From 52db5a1076e81a9d1f8181e15ae4d0050712a2c9 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Tue, 1 Aug 2023 08:45:37 -0400 Subject: [PATCH] Initial commit: rescuing PP from disappearance --- CHANGES | 462 + COVER-LETTER | 417 + Chans/822-local/Makefile | 244 + Chans/822-local/ckmf.c | 303 + Chans/822-local/code.c | 563 ++ Chans/822-local/lex.l | 152 + Chans/822-local/loc.h | 58 + Chans/822-local/loc.y | 128 + Chans/822-local/loc_child.c | 894 ++ Chans/822-local/loc_parent.c | 468 + Chans/822-local/mailfilter | 25 + Chans/822-local/make | 2 + Chans/822-local/parse_hdr.c | 124 + Chans/Makefile | 49 + Chans/decnet/Makefile | 200 + Chans/decnet/de_wtmail.c | 380 + Chans/decnet/decnet.c | 681 ++ Chans/decnet/decnetsrvr.c | 665 ++ Chans/decnet/make | 2 + Chans/dr2rfc/Makefile | 188 + Chans/dr2rfc/dr2rfc.c | 483 + Chans/dr2rfc/make | 2 + Chans/dr2rfc/write_queue.c | 148 + Chans/dr2rfc/write_report.c | 1748 ++++ Chans/fax/Makefile | 99 + Chans/fax/dexNet200/Makefile | 86 + Chans/fax/dexNet200/dexnet.h | 134 + Chans/fax/dexNet200/dexnet_conv.c | 239 + Chans/fax/dexNet200/dexnet_intf.c | 479 + Chans/fax/dexNet200/dexnet_util.c | 789 ++ Chans/fax/dexNet200/make | 2 + Chans/fax/fax_in.c | 567 ++ Chans/fax/fax_out.c | 929 ++ Chans/fax/faxgeneric.h | 121 + Chans/fax/make | 2 + Chans/fax/ps250/Makefile | 133 + Chans/fax/ps250/error_codes.c | 113 + Chans/fax/ps250/make | 2 + Chans/fax/ps250/ps250.h | 230 + Chans/fax/ps250/ps250_basic.c | 207 + Chans/fax/ps250/ps250_intf.c | 629 ++ Chans/fax/ps250/ps250_manage.c | 241 + Chans/fax/ps250/ps250_stat.c | 401 + Chans/fax/ps250/ps250_trans.c | 238 + Chans/fax/ps250/ps250_util.c | 629 ++ Chans/fax/ps250/tools/Makefile | 95 + Chans/fax/ps250/tools/fax_print.c | 480 + Chans/fax/ps250/tools/faxenq1.c | 171 + Chans/fax/ps250/tools/faxid.c | 162 + Chans/fax/ps250/tools/make | 2 + Chans/fax/ps250/tools/setid.c | 185 + Chans/filtercontrol/Makefile | 150 + Chans/filtercontrol/filtercont.c | 703 ++ Chans/filtercontrol/make | 2 + Chans/filtercontrol/removebp.sh | 12 + Chans/grey/Makefile | 242 + Chans/grey/README | 20 + Chans/grey/io_grey.c | 858 ++ Chans/grey/make | 2 + Chans/grey/ppp.c | 947 ++ Chans/grey/tgreyin.c | 86 + Chans/lists/Makefile | 564 ++ Chans/lists/READ-ME | 123 + Chans/lists/dish.c | 93 + Chans/lists/dl.c | 1919 ++++ Chans/lists/dl.py | 44 + Chans/lists/dl_permit.c | 182 + Chans/lists/dl_util.c | 581 ++ Chans/lists/dl_x500.c | 755 ++ Chans/lists/dlist.h | 62 + Chans/lists/hack.c | 258 + Chans/lists/init.c | 118 + Chans/lists/list.c | 1301 +++ Chans/lists/lmnpq_dish.c | 78 + Chans/lists/make | 2 + Chans/lists/md.py | 93 + Chans/lists/or2addr.c | 128 + Chans/lists/syn_oraddr.c | 177 + Chans/lists/syn_orname.c | 142 + Chans/lists/syn_permit.c | 196 + Chans/lists/syn_policy.c | 215 + Chans/make | 2 + Chans/msg-clean/Makefile | 146 + Chans/msg-clean/make | 2 + Chans/msg-clean/msg-clean.c | 216 + Chans/qmgr-load/Makefile | 200 + Chans/qmgr-load/make | 2 + Chans/qmgr-load/qmgr-load.c | 292 + Chans/qmgr-load/qmgr-start.c | 271 + Chans/qmgr-load/ryinitiator.c | 375 + Chans/qmgr-load/ryinitiator.h | 44 + Chans/qmgr-load/ryresponder.c | 410 + Chans/qmgr-load/ryresponder.h | 38 + Chans/shell/Makefile | 144 + Chans/shell/README | 2 + Chans/shell/make | 2 + Chans/shell/prog.h | 40 + Chans/shell/shell.c | 789 ++ Chans/shell/tb_getprog.c | 131 + Chans/slocal/Makefile | 134 + Chans/slocal/alert-script | 40 + Chans/slocal/loc_proto.c | 532 ++ Chans/slocal/local.c | 390 + Chans/slocal/make | 2 + Chans/slocal/slocal.c | 646 ++ Chans/smtp/Makefile | 274 + Chans/smtp/make | 2 + Chans/smtp/sm_ns.c | 474 + Chans/smtp/sm_wtmail.c | 603 ++ Chans/smtp/smtp.c | 622 ++ Chans/smtp/smtp.start | 2 + Chans/smtp/smtpd.c | 380 + Chans/smtp/smtpsrvr.c | 1121 +++ Chans/splitter/Makefile | 112 + Chans/splitter/make | 2 + Chans/splitter/splitter.c | 409 + Chans/testchan/Makefile | 140 + Chans/testchan/README | 4 + Chans/testchan/dogen | 34 + Chans/testchan/make | 2 + Chans/testchan/testchan.c | 606 ++ Chans/timeout/Makefile | 145 + Chans/timeout/make | 2 + Chans/timeout/timeout.c | 199 + Chans/trashman/Makefile | 142 + Chans/trashman/make | 2 + Chans/trashman/trash.c | 299 + Chans/uucp/Makefile | 214 + Chans/uucp/make | 2 + Chans/uucp/rfc8222uu.c | 249 + Chans/uucp/rmail.c | 1286 +++ Chans/uucp/t-rfc8222uu.c | 44 + Chans/uucp/uucp_out.c | 630 ++ Chans/warnings/Makefile | 134 + Chans/warnings/make | 2 + Chans/warnings/warnings.c | 628 ++ Chans/x40084/Makefile | 377 + Chans/x40084/P1_in.py | 929 ++ Chans/x40084/P1_out.py | 1112 +++ Chans/x40084/P1_print.py | 599 ++ Chans/x40084/Rts_posy.py | 30 + Chans/x40084/make | 2 + Chans/x40084/ut_logs.c | 231 + Chans/x40084/ut_misc.c | 90 + Chans/x40084/ut_rts.c | 399 + Chans/x40084/x400in84.c | 622 ++ Chans/x40084/x400out84.c | 1211 +++ Chans/x40084/x400topp.c | 579 ++ Chans/x40088/Makefile | 373 + Chans/x40088/make | 2 + Chans/x40088/p88.c | 153 + Chans/x40088/pptox400.c | 2760 ++++++ Chans/x40088/tasn.c | 240 + Chans/x40088/ut_misc.c | 67 + Chans/x40088/ut_rts.c | 491 + Chans/x40088/util.c | 178 + Chans/x40088/x400in88.c | 718 ++ Chans/x40088/x400inext.c | 1016 +++ Chans/x40088/x400inmsg.c | 499 ++ Chans/x40088/x400out88.c | 1596 ++++ Chans/x40088/x400outext.c | 1382 +++ Chans/x40088/x400topp.c | 2045 +++++ Format/Makefile | 46 + Format/ascii2fax/Makefile | 192 + Format/ascii2fax/X2PPbitmap.c | 146 + Format/ascii2fax/Xfont2PPfont.c | 224 + Format/ascii2fax/bitmap_util.c | 150 + Format/ascii2fax/char_util.c | 64 + Format/ascii2fax/font_util.c | 84 + Format/ascii2fax/fonts.h | 47 + Format/ascii2fax/g3.h | 242 + Format/ascii2fax/hdr2fax.c | 891 ++ Format/ascii2fax/ia52fax.c | 204 + Format/ascii2fax/image2fax.c | 322 + Format/ascii2fax/make | 2 + Format/ascii2fax/pg_sizes.h | 42 + Format/ascii2fax/str_util.c | 147 + Format/asn/Makefile | 217 + Format/asn/asn.c | 77 + Format/asn/asn.h | 52 + Format/asn/asn1/Makefile | 111 + Format/asn/asn1/extdefbp.py | 39 + Format/asn/asn1/gentxt.py | 46 + Format/asn/asn1/make | 2 + Format/asn/asn_charset.c | 97 + Format/asn/asn_dec.c | 83 + Format/asn/asn_enc.c | 119 + Format/asn/asn_proc.c | 58 + Format/asn/asn_rd.c | 126 + Format/asn/doc/asn.aux | 6 + Format/asn/doc/asn.dvi | Bin 0 -> 5396 bytes Format/asn/doc/asn.tex | 146 + Format/asn/f_6937.c | 113 + Format/asn/f_gentxt.c | 122 + Format/asn/f_teletex.c | 112 + Format/asn/make | 2 + Format/asn/oid.h | 19 + Format/asn/opt_cmdln.c | 165 + Format/asn/opt_functs.c | 107 + Format/asn/ut_asn.c | 71 + Format/asn/ut_ext.c | 198 + Format/asn/ut_f.c | 288 + Format/charset/Makefile | 101 + Format/charset/README | 16 + Format/charset/conv.c | 130 + Format/charset/copyright | 20 + Format/charset/design | 161 + Format/charset/doc/charset.tex | 229 + Format/charset/doc/notforPPdoc/design.more | 13 + Format/charset/doc/notforPPdoc/uclstuff | 160 + Format/charset/make | 2 + Format/charset/test/files/dotranslate | 17 + Format/charset/test/files/keld | 6 + Format/charset/test/files/orig.czeck | 17 + Format/charset/test/files/orig.english | 3 + Format/charset/test/files/orig.italian | 14 + Format/charset/test/files/t.61-8.1 | 2 + Format/charset/test/files/t.61-8.all | 18 + Format/charset/test/progs/Makefile | 85 + Format/charset/test/progs/bit2ch | Bin 0 -> 16384 bytes Format/charset/test/progs/bit2ch.c | 64 + Format/charset/test/progs/ch255 | Bin 0 -> 16384 bytes Format/charset/test/progs/ch255.c | 34 + Format/charset/test/progs/ch2val | Bin 0 -> 16384 bytes Format/charset/test/progs/ch2val.c | 54 + Format/charset/test/progs/make | 2 + Format/charset/test/progs/translate.c | 72 + Format/make | 2 + Format/p2explode/Makefile | 173 + Format/p2explode/explode_chan.c | 328 + Format/p2explode/explode_only.c | 47 + Format/p2explode/make | 2 + Format/p2explode/p2explode.c | 868 ++ Format/p2flatten/Makefile | 149 + Format/p2flatten/flatten_chan.c | 316 + Format/p2flatten/flatten_only.c | 47 + Format/p2flatten/make | 2 + Format/p2flatten/p2flatten.c | 990 +++ Format/p2norm/Makefile | 99 + Format/p2norm/make | 2 + Format/p2norm/p2norm.c | 442 + Format/p2norm/pac | Bin 0 -> 499 bytes Format/rfc1148/Makefile | 303 + Format/rfc1148/P2toRFC.c | 2487 ++++++ Format/rfc1148/RFCtoP2.c | 1311 +++ Format/rfc1148/c-P2toRFC.c | 704 ++ Format/rfc1148/c-RFCtoP2.c | 617 ++ Format/rfc1148/f-P2toRFC.c | 87 + Format/rfc1148/f-RFCtoP2.c | 83 + Format/rfc1148/make | 2 + Format/rfc1148/oids.h | 26 + Format/rfc1148/rfc-hdr.h | 48 + Format/rfc1148/t-P2toRFC.c | 125 + Format/rfc1148/t-RFCtoP2.c | 117 + Format/rfc822norm/Makefile | 123 + Format/rfc822norm/make | 2 + Format/rfc822norm/rfc822norm.c | 1649 ++++ Format/rfc934/Makefile | 150 + Format/rfc934/do-rfc934.c | 585 ++ Format/rfc934/make | 2 + Format/rfc934/rfc934.c | 332 + Lib/Makefile | 68 + Lib/addr/Makefile | 214 + Lib/addr/ap_1adr.c | 670 ++ Lib/addr/ap_dmflip.c | 50 + Lib/addr/ap_equ.c | 85 + Lib/addr/ap_file.c | 113 + Lib/addr/ap_lex.c | 381 + Lib/addr/ap_lex_tb.c | 101 + Lib/addr/ap_norm.c | 399 + Lib/addr/ap_p2s.c | 684 ++ Lib/addr/ap_s2p.c | 83 + Lib/addr/ap_s2s.c | 35 + Lib/addr/ap_s2t.c | 88 + Lib/addr/ap_t2p.c | 179 + Lib/addr/ap_t2s.c | 67 + Lib/addr/ap_ut.c | 487 + Lib/addr/ap_val2str.c | 189 + Lib/addr/make | 2 + Lib/charset/Make.defs | 40 + Lib/charset/Makefile | 143 + Lib/charset/README | 16 + Lib/charset/charset_conf.c | 43 + Lib/charset/copyright | 20 + Lib/charset/design | 161 + Lib/charset/gc.c | 184 + Lib/charset/make | 2 + Lib/charset/master/CHARSETS | 1630 ++++ Lib/charset/master/CHARSETS_PP | 22 + Lib/charset/master/CONTROL | 204 + Lib/charset/master/ISO_10646 | 1507 ++++ Lib/charset/master/OTHER | 68 + Lib/charset/strcnv.c | 431 + Lib/format/Makefile | 438 + Lib/format/UTC2rfc.c | 132 + Lib/format/adr2rfc.c | 193 + Lib/format/domsinfo2rfc.c | 132 + Lib/format/globalid2rfc.c | 49 + Lib/format/make | 2 + Lib/format/msgid2rfc.c | 57 + Lib/format/reprecip2rfc.c | 163 + Lib/format/rfc2UTC.c | 261 + Lib/format/rfc2domsinfo.c | 162 + Lib/format/rfc2encinfo.c | 52 + Lib/format/rfc2globalid.c | 120 + Lib/format/rfc2msgid.c | 70 + Lib/format/rfc2reprecip.c | 316 + Lib/format/rfc2trace.c | 56 + Lib/format/rfc2x400trc.c | 202 + Lib/format/rfctxtfold.c | 92 + Lib/format/trace2rfc.c | 47 + Lib/format/x400trc2rfc.c | 227 + Lib/io/Makefile | 365 + Lib/io/io_lib.c | 777 ++ Lib/io/make | 2 + Lib/io/rd_adr.c | 81 + Lib/io/rd_buf.c | 123 + Lib/io/rd_dr.c | 35 + Lib/io/rd_msg.c | 239 + Lib/io/rd_prm.c | 82 + Lib/io/rd_q.c | 82 + Lib/io/wr_adr.c | 49 + Lib/io/wr_dr.c | 40 + Lib/io/wr_drfile.c | 104 + Lib/io/wr_prm.c | 39 + Lib/io/wr_q.c | 49 + Lib/io/wr_q2drfile.c | 244 + Lib/make | 2 + Lib/or/Makefile | 313 + Lib/or/make | 2 + Lib/or/or2pe.py | 198 + Lib/or/or_add.c | 247 + Lib/or/or_asc2ps.c | 81 + Lib/or/or_basic.c | 152 + Lib/or/or_blank.c | 60 + Lib/or/or_buildpn.c | 95 + Lib/or/or_check.c | 390 + Lib/or/or_default.c | 122 + Lib/or/or_dmn2or.c | 88 + Lib/or/or_downgrade.c | 144 + Lib/or/or_getpn.c | 83 + Lib/or/or_init.c | 59 + Lib/or/or_misc.c | 161 + Lib/or/or_or2dmn.c | 94 + Lib/or/or_or2rbits.c | 343 + Lib/or/or_or2rfc.c | 197 + Lib/or/or_or2std.c | 91 + Lib/or/or_ps2asc.c | 114 + Lib/or/or_rbits2or.c | 147 + Lib/or/or_rfc2or.c | 240 + Lib/or/or_search.c | 240 + Lib/or/or_std2or.c | 271 + Lib/or/or_tables.c | 209 + Lib/or/or_up_bnds.c | 75 + Lib/or/or_util.c | 283 + Lib/or/or_valid.c | 399 + Lib/or/orn-dec.c | 529 ++ Lib/or/orn-enc.c | 1002 +++ Lib/or/orn-util.c | 95 + Lib/or/pe2or.py | 300 + Lib/parse/Makefile | 352 + Lib/parse/ad_getlocal.c | 73 + Lib/parse/ad_local.c | 568 ++ Lib/parse/ad_parse.c | 499 ++ Lib/parse/aparse_norm.c | 615 ++ Lib/parse/make | 2 + Lib/parse/rfc822_dnorm.c | 82 + Lib/parse/rfc822_parse.c | 193 + Lib/parse/rfc822_val.c | 192 + Lib/parse/rfc822_x400.c | 61 + Lib/parse/x400_parse.c | 48 + Lib/parse/x400_rfc822.c | 70 + Lib/parse/x400_val.c | 174 + Lib/pp/Makefile | 1001 +++ Lib/pp/adr2txt.c | 618 ++ Lib/pp/chan_acheck.c | 120 + Lib/pp/conf.c | 53 + Lib/pp/dchan_acheck.c | 163 + Lib/pp/dr2txt.c | 317 + Lib/pp/get_dr.c | 52 + Lib/pp/lchan_acheck.c | 134 + Lib/pp/list_bpt.c | 139 + Lib/pp/list_rchan.c | 141 + Lib/pp/make | 2 + Lib/pp/msg2file.c | 36 + Lib/pp/mta2txt.c | 402 + Lib/pp/p32txt.c | 87 + Lib/pp/pps_mail.c | 436 + Lib/pp/prm2txt.c | 101 + Lib/pp/q2txt.c | 416 + Lib/pp/set_1dr.c | 213 + Lib/pp/static.c | 129 + Lib/pp/tb_a.c | 201 + Lib/pp/tb_bpt84.c | 52 + Lib/pp/tb_bpt88.c | 55 + Lib/pp/tb_dr.c | 139 + Lib/pp/tb_misc.c | 46 + Lib/pp/tb_p1.c | 93 + Lib/pp/tb_p3prm.c | 35 + Lib/pp/tb_prm.c | 43 + Lib/pp/tb_q.c | 85 + Lib/pp/txt2adr.c | 573 ++ Lib/pp/txt2dr.c | 323 + Lib/pp/txt2mta.c | 477 + Lib/pp/txt2p3.c | 67 + Lib/pp/txt2prm.c | 100 + Lib/pp/txt2q.c | 384 + Lib/pp/ut_a.c | 151 + Lib/pp/ut_aparse.c | 196 + Lib/pp/ut_com.c | 74 + Lib/pp/ut_dlh.c | 75 + Lib/pp/ut_dr.c | 93 + Lib/pp/ut_fn.c | 52 + Lib/pp/ut_free.c | 86 + Lib/pp/ut_gldm.c | 53 + Lib/pp/ut_mm2p1.c | 76 + Lib/pp/ut_mpduid.c | 50 + Lib/pp/ut_msg.c | 356 + Lib/pp/ut_p12mm.c | 63 + Lib/pp/ut_p1_st.c | 96 + Lib/pp/ut_postie.c | 84 + Lib/pp/ut_prm.c | 44 + Lib/pp/ut_q.c | 159 + Lib/pp/ut_qid.c | 157 + Lib/pp/ut_redirect.c | 98 + Lib/pp/ut_trace.c | 118 + Lib/pp/wr_stat.c | 112 + Lib/qmgr/Makefile | 264 + Lib/qmgr/chan_control.c | 435 + Lib/qmgr/chan_debug.c | 153 + Lib/qmgr/comms.c | 623 ++ Lib/qmgr/cons-misc.c | 200 + Lib/qmgr/consblk.c | 59 + Lib/qmgr/consblk.h | 22 + Lib/qmgr/make | 2 + Lib/qmgr/op_chan.c | 206 + Lib/qmgr/op_filter.c | 165 + Lib/qmgr/op_msg.c | 471 + Lib/qmgr/op_mta.c | 198 + Lib/qmgr/op_que.c | 116 + Lib/qmgr/order.c | 186 + Lib/qmgr/qmgr.ry | 576 ++ Lib/qmgr/qstruct2qmgr.c | 579 ++ Lib/qmgr/recipstate.c | 137 + Lib/qmgr/submit2qmgr.c | 454 + Lib/table/Makefile | 266 + Lib/table/ch_nm2struct.c | 73 + Lib/table/make | 2 + Lib/table/tb_1148gate.c | 65 + Lib/table/tb_checkauth.c | 72 + Lib/table/tb_dbm.c | 212 + Lib/table/tb_getalias.c | 126 + Lib/table/tb_getauth.c | 604 ++ Lib/table/tb_getchan.c | 175 + Lib/table/tb_getdl.c | 328 + Lib/table/tb_getdomain.c | 687 ++ Lib/table/tb_getlocal.c | 319 + Lib/table/tb_getuser.c | 89 + Lib/table/tb_k2val.c | 191 + Lib/table/tb_nm2struct.c | 36 + Lib/table/tb_rtsparams.c | 323 + Lib/tai/Makefile | 139 + Lib/tai/init_chan.c | 21 + Lib/tai/init_tai.c | 370 + Lib/tai/init_uip.c | 21 + Lib/tai/make | 2 + Lib/tai/pp_setuserid.c | 46 + Lib/tai/tai_chan.c | 525 ++ Lib/tai/tai_sys.c | 487 + Lib/tai/tai_tb.c | 162 + Lib/util/Makefile | 208 + Lib/util/arg2str.c | 172 + Lib/util/check_close.c | 33 + Lib/util/cmdbsrch.c | 46 + Lib/util/compress.c | 52 + Lib/util/diskfull.c | 119 + Lib/util/err_abrt.c | 50 + Lib/util/expand.c | 144 + Lib/util/flip_bits.c | 43 + Lib/util/getfpath.c | 47 + Lib/util/hier_scanQ.c | 132 + Lib/util/lock.c | 187 + Lib/util/lstr2oid.c | 42 + Lib/util/make | 2 + Lib/util/multcat.c | 44 + Lib/util/multcpy.c | 37 + Lib/util/oid2lstr.c | 83 + Lib/util/pe_fragment.c | 107 + Lib/util/prefix.c | 31 + Lib/util/recrm.c | 89 + Lib/util/rename_log.c | 28 + Lib/util/rp_valstr.c | 106 + Lib/util/siginit.c | 80 + Lib/util/str2arg.c | 206 + Lib/util/sys5_regex.c | 75 + Lib/util/timeout.c | 54 + Lib/util/timer.c | 68 + Lib/util/tryfork.c | 28 + Lib/util/utctime.c | 90 + Lib/version.major | 1 + Lib/version.minor | 1 + Lib/version.sh | 48 + Lib/x400/Makefile | 341 + Lib/x400/Rts_posy.py | 30 + Lib/x400/authen.py | 199 + Lib/x400/enctypes2mem.c | 151 + Lib/x400/extent.py | 329 + Lib/x400/fixorig.c | 67 + Lib/x400/iob.py | 573 ++ Lib/x400/make | 2 + Lib/x400/mta.ry | 1056 +++ Lib/x400/rasn.c | 484 + Lib/x400/tokens.py | 132 + Lib/x400/transfer.py | 56 + Makefile | 76 + README | 330 + Src/LINEconsole/Makefile | 204 + Src/LINEconsole/assoc.c | 634 ++ Src/LINEconsole/badness.c | 738 ++ Src/LINEconsole/channels.c | 965 ++ Src/LINEconsole/console.h | 177 + Src/LINEconsole/drive.c | 478 + Src/LINEconsole/heuristics.c | 20 + Src/LINEconsole/io.c | 544 ++ Src/LINEconsole/make | 2 + Src/LINEconsole/misc.c | 746 ++ Src/LINEconsole/msgs.c | 1339 +++ Src/LINEconsole/mtas.c | 1089 +++ Src/LINEconsole/status.c | 151 + Src/LINEconsole/tai_defs.inc | 31 + Src/MTAconsole/.MTAconsole | 8 + Src/MTAconsole/.MTAconsole~ | 7 + Src/MTAconsole/Makefile | 226 + Src/MTAconsole/Mtaconsole.ad | 670 ++ Src/MTAconsole/README | 10 + Src/MTAconsole/assoc.c | 1227 +++ Src/MTAconsole/auto.c | 450 + Src/MTAconsole/back.bit | 8 + Src/MTAconsole/badness.c | 956 ++ Src/MTAconsole/bops.c | 1400 +++ Src/MTAconsole/console.h | 264 + Src/MTAconsole/create.c | 2030 +++++ Src/MTAconsole/data.c | 746 ++ Src/MTAconsole/display.c | 1990 +++++ Src/MTAconsole/drive.c | 347 + Src/MTAconsole/make | 2 + Src/MTAconsole/misc.c | 277 + Src/MTAconsole/ops.c | 766 ++ Src/MTAconsole/parse.c | 275 + Src/MTAconsole/popup.c | 300 + Src/MTAconsole/tai_defs.inc | 31 + Src/MTAconsole/workops.c | 1026 +++ Src/Makefile | 28 + Src/lconsole/Makefile | 135 + Src/lconsole/channel.c | 275 + Src/lconsole/functions.c | 965 ++ Src/lconsole/lconsole.c | 301 + Src/lconsole/lconsole.h | 56 + Src/lconsole/make | 2 + Src/lconsole/msgs.c | 204 + Src/lconsole/mtas.c | 181 + Src/lconsole/show.c | 171 + Src/make | 2 + Src/pptsapd/Makefile | 106 + Src/pptsapd/make | 2 + Src/pptsapd/pptsapd-stat.c | 444 + Src/pptsapd/pptsapd.c | 411 + Src/qmgr/Makefile | 307 + Src/qmgr/assoc.c | 178 + Src/qmgr/chans.c | 2365 +++++ Src/qmgr/make | 2 + Src/qmgr/misc.c | 78 + Src/qmgr/qmgr.c | 465 + Src/qmgr/ryresponder.c | 599 ++ Src/qmgr/ryresponder.h | 37 + Src/qmgr/structs.c | 788 ++ Src/qmgr/tables.c | 2083 +++++ Src/qmgr/types.h | 313 + Src/submit/Makefile | 589 ++ Src/submit/ad_mgt.c | 824 ++ Src/submit/auth.c | 1281 +++ Src/submit/auth_logs.c | 306 + Src/submit/auth_tb.c | 63 + Src/submit/auth_ut.c | 232 + Src/submit/ch_bind.c | 803 ++ Src/submit/gen_io2dr.c | 143 + Src/submit/gen_ndr.c | 172 + Src/submit/gen_probedr.c | 102 + Src/submit/gen_warn.c | 280 + Src/submit/make | 2 + Src/submit/rd_rfchdr.c | 1136 +++ Src/submit/submit.c | 598 ++ Src/submit/submit_chk.c | 478 + Src/submit/submit_mgt.c | 336 + Src/submit/submit_prm.c | 77 + Src/submit/submit_que.c | 359 + Src/submit/submit_srvr.c | 162 + Src/submit/submit_txt.c | 489 + Src/submit/t-auth.c | 103 + Src/submit/t-rd_rfchdr.c | 40 + Src/submit/t-tracecheck.c | 114 + Tools/Makefile | 38 + Tools/bin2ascii/Makefile | 92 + Tools/bin2ascii/bin2ascii.c | 281 + Tools/bin2ascii/make | 2 + Tools/bin2hex/Makefile | 90 + Tools/bin2hex/bin2hex.c | 68 + Tools/bin2hex/make | 2 + Tools/ckadr/Makefile | 137 + Tools/ckadr/ckadr.c | 188 + Tools/ckadr/make | 2 + Tools/ckchan/Makefile | 154 + Tools/ckchan/ckchan.c | 844 ++ Tools/ckchan/make | 2 + Tools/ckchan/qcheck.c | 190 + Tools/ckconfig/Makefile | 122 + Tools/ckconfig/ckconfig.c | 1330 +++ Tools/ckconfig/make | 2 + Tools/ckmail/Makefile | 150 + Tools/ckmail/ckmail.c | 771 ++ Tools/ckmail/make | 2 + Tools/ckmail/ryinitiator.c | 330 + Tools/ckmail/ryinitiator.h | 44 + Tools/ckor/Makefile | 118 + Tools/ckor/make | 2 + Tools/ckor/or2rfc.c | 105 + Tools/ckor/rfc2or.c | 101 + Tools/dbmbuild/Makefile | 100 + Tools/dbmbuild/dbmbuild.c | 742 ++ Tools/dbmbuild/make | 2 + Tools/dbmedit/Makefile | 97 + Tools/dbmedit/dbmedit.c | 436 + Tools/dbmedit/make | 2 + Tools/dbmunbuild/Makefile | 101 + Tools/dbmunbuild/dbmunbuild.c | 371 + Tools/dbmunbuild/make | 2 + Tools/ean2real/Makefile | 99 + Tools/ean2real/ean2real.c | 232 + Tools/ean2real/make | 2 + Tools/hex2bin/Makefile | 92 + Tools/hex2bin/hex2bin.c | 102 + Tools/hex2bin/make | 2 + Tools/make | 2 + Tools/make-lists/Makefile | 82 + Tools/make-lists/README | 9 + Tools/make-lists/make | 2 + Tools/make-lists/make-lists.8 | 61 + Tools/make-lists/make-lists.c | 472 + Tools/misc/Makefile | 331 + Tools/misc/README | 20 + Tools/misc/make | 2 + Tools/misc/t-chkpe.c | 120 + Tools/misc/t-conf.c | 40 + Tools/misc/t-norm.c | 95 + Tools/misc/t-pefrag.c | 108 + Tools/misc/t-prf.c | 44 + Tools/misc/t-rdmsg.c | 49 + Tools/misc/t-rtime.c | 36 + Tools/misc/t-single.c | 265 + Tools/misc/t-time.c | 36 + Tools/misc/t-txt2dr.c | 55 + Tools/mkpasswd/Makefile | 82 + Tools/mkpasswd/make | 2 + Tools/mkpasswd/mkpasswd.c | 78 + Tools/mlist/Makefile | 122 + Tools/mlist/make | 2 + Tools/mlist/mlist.c | 1621 ++++ Tools/mpp84/Makefile | 122 + Tools/mpp84/P1.py | 641 ++ Tools/mpp84/P2.py | 400 + Tools/mpp84/P3.py | 63 + Tools/mpp84/SFD.py | 110 + Tools/mpp84/T73.py | 34 + Tools/mpp84/UNIV.py | 121 + Tools/mpp84/make | 2 + Tools/mpp84/mpp84.py | 285 + Tools/mpp88/Makefile | 101 + Tools/mpp88/make | 2 + Tools/mpp88/mpp88.py | 272 + Tools/mu/Makefile | 129 + Tools/mu/README | 5 + Tools/mu/argh.c | 636 ++ Tools/mu/make | 2 + Tools/mu/mu.c | 1247 +++ Tools/mu/mu.defaults | 4 + Tools/nsapexpand/Makefile | 85 + Tools/nsapexpand/make | 2 + Tools/nsapexpand/nsapexpand.c | 106 + Tools/ntail/Makefile | 92 + Tools/ntail/README | 49 + Tools/ntail/entryfuncs.c | 237 + Tools/ntail/make | 2 + Tools/ntail/miscfuncs.c | 240 + Tools/ntail/ntail.c | 401 + Tools/ntail/ntail.h | 248 + Tools/ppbm/Makefile | 97 + Tools/ppbm/make | 2 + Tools/ppbm/pp-bench.awk | 52 + Tools/ppbm/pp-benchmarks.tbl | 251 + Tools/ppbm/ppbm.8 | 63 + Tools/ppbm/ppbm.c | 417 + Tools/ppls/Makefile | 83 + Tools/ppls/make | 2 + Tools/ppls/ppls.c | 151 + Tools/probe/Makefile | 144 + Tools/probe/make | 2 + Tools/probe/p_stdin.c | 148 + Tools/probe/p_ut.c | 130 + Tools/probe/probe.c | 311 + Tools/splat/Makefile | 99 + Tools/splat/make | 2 + Tools/splat/ps2pe.c | 264 + Tools/splat/splat.c | 300 + Tools/statgen/Makefile | 83 + Tools/statgen/README | 2 + Tools/statgen/line.nawk | 188 + Tools/statgen/make | 2 + Tools/statgen/rare.nawk | 220 + Tools/statgen/slowhosts.awk | 143 + Tools/statgen/statp.c | 406 + Tools/tables/Makefile | 45 + Tools/tables/abbrev/Makefile | 90 + Tools/tables/abbrev/abbrev.c | 226 + Tools/tables/abbrev/make | 2 + Tools/tables/compat/Makefile | 66 + Tools/tables/compat/ali_o2n | 38 + Tools/tables/compat/dom_o2n | 46 + Tools/tables/compat/make | 2 + Tools/tables/compat/que_o2n | 31 + Tools/tables/domain/Makefile | 61 + Tools/tables/domain/make | 2 + Tools/tables/domain/t-getdomain.c | 108 + Tools/tables/make | 2 + Tools/tables/pp-rfc987/Makefile | 71 + Tools/tables/pp-rfc987/awk.or2rfc | 62 + Tools/tables/pp-rfc987/awk.rfc2or | 57 + Tools/tables/pp-rfc987/make | 2 + Tools/tables/rfc987-pp/Makefile | 78 + Tools/tables/rfc987-pp/awk.rfc987.pac | 57 + Tools/tables/rfc987-pp/make | 2 + Tools/tables/tjoin/Makefile | 99 + Tools/tables/tjoin/lex.l | 79 + Tools/tables/tjoin/make | 2 + Tools/tables/tjoin/tjoin.y | 115 + Tools/tables/tjoin/tjoin1.c | 200 + Tools/tables/tjoin/tjoin2.c | 599 ++ Tools/tables/tjoin/tjoin3.c | 498 ++ Uip/Makefile | 40 + Uip/mail/Makefile | 97 + Uip/mail/mail.c | 230 + Uip/mail/make | 2 + Uip/make | 2 + Uip/misc/Makefile | 157 + Uip/misc/X400_addr.c | 78 + Uip/misc/flock.c | 83 + Uip/misc/make | 2 + Uip/misc/strip_addr.c | 79 + Uip/rcvalert/Makefile | 225 + Uip/rcvalert/README | 14 + Uip/rcvalert/XAlert.ad | 134 + Uip/rcvalert/data.h | 29 + Uip/rcvalert/dirsbr.c | 1136 +++ Uip/rcvalert/flagmail.c | 255 + Uip/rcvalert/image.h | 24 + Uip/rcvalert/make | 2 + Uip/rcvalert/parsesbr.c | 220 + Uip/rcvalert/rttyalert | 40 + Uip/rcvalert/ttyalert.c | 113 + Uip/rcvalert/ttybiff.c | 122 + Uip/rcvalert/ttysbr.c | 113 + Uip/rcvalert/udpsbr.c | 170 + Uip/rcvalert/xalert.c | 731 ++ Uip/rcvtrip/Makefile | 106 + Uip/rcvtrip/make | 2 + Uip/rcvtrip/rcvtrip.c | 749 ++ Uip/resend/Makefile | 107 + Uip/resend/make | 2 + Uip/resend/resend.c | 261 + Uip/sendmail/Makefile | 108 + Uip/sendmail/make | 2 + Uip/sendmail/sendmail.c | 520 ++ config/OPTIONS.h | 22 + config/OPTIONS.make | 153 + config/README | 7 + config/drs6000.h | 29 + config/drs6000.make | 175 + config/hpux.h | 29 + config/hpux.make | 145 + config/pp.start | 8 + config/pp.startaspp | 15 + config/s5r4.h | 28 + config/s5r4.make | 181 + config/sun.h | 35 + config/sun.make | 182 + config/vax.h | 36 + config/vax.make | 181 + doc/Makefile | 51 + doc/README | 37 + doc/funet91/Makefile | 96 + doc/funet91/bcustom.bib | 39 + doc/funet91/bof-slides.tex | 139 + doc/funet91/captcont.sty | 16 + doc/funet91/figure1.pic | 52 + doc/funet91/figure1.tex | 317 + doc/funet91/figure2.pic | 15 + doc/funet91/figure2.tex | 123 + doc/funet91/jpo.bib | 65 + doc/funet91/lcustom.tex | 350 + doc/funet91/make | 2 + doc/funet91/networking.bib | 1768 ++++ doc/funet91/pp-slides.aux | 1 + doc/funet91/pp-slides.tex | 456 + doc/funet91/pp.aux | 39 + doc/funet91/pp.bbl | 40 + doc/funet91/pp.major | 1 + doc/funet91/pp.minor | 1 + doc/funet91/pp.tex | 571 ++ doc/funet91/pp.vrsn | 6 + doc/funet91/queuefig.fig | 47 + doc/funet91/sfwdoc.bib | 346 + doc/funet91/software.bib | 345 + doc/funet91/trademark.tex | 75 + doc/funet91/version.sh | 19 + doc/ifip6.5-88/Makefile | 39 + doc/ifip6.5-88/make | 2 + doc/ifip6.5-88/paper.psc | 8846 +++++++++++++++++++ doc/ifip6.5-88/slides/Makefile | 35 + doc/ifip6.5-88/slides/dir.fig | 57 + doc/ifip6.5-88/slides/dir.pic | 62 + doc/ifip6.5-88/slides/dir.tex | 131 + doc/ifip6.5-88/slides/ifip88-pp.tex | 381 + doc/ifip6.5-88/slides/structure.fig | 28 + doc/ifip6.5-88/slides/structure.pic | 51 + doc/ifip6.5-88/slides/structure.tex | 127 + doc/make | 2 + doc/manual/Make.defs | 30 + doc/manual/Makefile | 37 + doc/manual/README | 18 + doc/manual/book-changes.ms | 22 + doc/manual/make | 10 + doc/manual/ps/README | 3 + doc/manual/texinputs/a4.sty | 23 + doc/manual/texinputs/bcustom.bib | 37 + doc/manual/texinputs/captcont.sty | 16 + doc/manual/texinputs/dist-params.tex | 12 + doc/manual/texinputs/grindefs | 49 + doc/manual/texinputs/grindefs.sty | 21 + doc/manual/texinputs/lcustom.tex | 350 + doc/manual/texinputs/networking.bib | 1574 ++++ doc/manual/texinputs/pp.bib | 89 + doc/manual/texinputs/sfwdoc.bib | 346 + doc/manual/texinputs/sfwmac.sty | 66 + doc/manual/texinputs/tgrind.sty | 203 + doc/manual/texinputs/trademark.tex | 82 + doc/manual/volume0/COVER-LETTER.aux | 1 + doc/manual/volume0/COVER-LETTER.tex | 10 + doc/manual/volume0/COVER-TXT | 417 + doc/manual/volume0/COVER-TXT.aux | 1 + doc/manual/volume0/COVER-TXT.tex | 12 + doc/manual/volume0/Makefile | 125 + doc/manual/volume0/announce.tex | 22 + doc/manual/volume0/contents.tex | 70 + doc/manual/volume0/distrib.tex | 206 + doc/manual/volume0/highlights.tex | 23 + doc/manual/volume0/make | 11 + doc/manual/volume0/real.aux | 50 + doc/manual/volume0/real.tex | 253 + doc/manual/volume0/version.sh | 19 + doc/manual/volume0/volume0.aux | 2 + doc/manual/volume0/volume0.bbl | 39 + doc/manual/volume0/volume0.major | 1 + doc/manual/volume0/volume0.minor | 1 + doc/manual/volume0/volume0.tex | 56 + doc/manual/volume0/volume0.toc | 10 + doc/manual/volume0/volume0.vrsn | 6 + doc/manual/volume1/Makefile | 151 + doc/manual/volume1/addon.aux | 49 + doc/manual/volume1/addon.tex | 466 + doc/manual/volume1/alias.tex | 16 + doc/manual/volume1/appendix.aux | 38 + doc/manual/volume1/appendix.tex | 21 + doc/manual/volume1/argh.tex | 245 + doc/manual/volume1/asnfilter.tai | 22 + doc/manual/volume1/asnfilter.tex | 23 + doc/manual/volume1/auth.tex | 244 + doc/manual/volume1/chan-examp.tai | 19 + doc/manual/volume1/chan-examp.tex | 20 + doc/manual/volume1/chantbl.tex | 25 + doc/manual/volume1/chanx400examp.tex | 11 + doc/manual/volume1/chx400out.tex | 43 + doc/manual/volume1/configure.aux | 84 + doc/manual/volume1/configure.tex | 1865 ++++ doc/manual/volume1/console_tai.tex | 24 + doc/manual/volume1/domain.tex | 8 + doc/manual/volume1/dreport.tex | 13 + doc/manual/volume1/exampleortbl.tex | 41 + doc/manual/volume1/exampleortbl2.tex | 43 + doc/manual/volume1/faxTable.tai | 18 + doc/manual/volume1/faxTable.tex | 19 + doc/manual/volume1/faxtai.tai | 18 + doc/manual/volume1/faxtai.tex | 19 + doc/manual/volume1/filt-examp.tai | 11 + doc/manual/volume1/filt-examp.tex | 12 + doc/manual/volume1/general.aux | 42 + doc/manual/volume1/general.tex | 189 + doc/manual/volume1/idx2ind | 53 + doc/manual/volume1/install.aux | 45 + doc/manual/volume1/install.tex | 537 ++ doc/manual/volume1/lists-examp.tex | 11 + doc/manual/volume1/log-examp.tai | 13 + doc/manual/volume1/log-examp.tex | 14 + doc/manual/volume1/logx400-examp.tex | 14 + doc/manual/volume1/make | 11 + doc/manual/volume1/management.aux | 87 + doc/manual/volume1/management.tex | 1746 ++++ doc/manual/volume1/mu.aux | 30 + doc/manual/volume1/mu.tex | 223 + doc/manual/volume1/musub.c | 23 + doc/manual/volume1/musub.tex | 24 + doc/manual/volume1/or.tex | 30 + doc/manual/volume1/or2rfc.tex | 19 + doc/manual/volume1/pac.dvi | Bin 0 -> 88296 bytes doc/manual/volume1/pp_nightly.sh | 46 + doc/manual/volume1/pp_nightly.tex | 47 + doc/manual/volume1/pp_start.csh | 20 + doc/manual/volume1/pp_start.sh | 22 + doc/manual/volume1/pp_start.tex | 23 + doc/manual/volume1/pptables.aux | 22 + doc/manual/volume1/pptables.tex | 0 doc/manual/volume1/preface.aux | 21 + doc/manual/volume1/preface.tex | 18 + doc/manual/volume1/program.tex | 76 + doc/manual/volume1/qfile.tex | 37 + doc/manual/volume1/qmgrproto.aux | 26 + doc/manual/volume1/qmgrproto.tex | 5 + doc/manual/volume1/qmgrros.ry | 527 ++ doc/manual/volume1/qmgrros.tex | 528 ++ doc/manual/volume1/rfc1148g.tex | 4 + doc/manual/volume1/rfc2or.tex | 21 + doc/manual/volume1/shelfilt.sh | 11 + doc/manual/volume1/shelfilt.tex | 12 + doc/manual/volume1/shell-examp.tex | 10 + doc/manual/volume1/shellfilt.sh | 11 + doc/manual/volume1/table-examp.tai | 9 + doc/manual/volume1/table-examp.tex | 10 + doc/manual/volume1/tableauthreasons.tex | 30 + doc/manual/volume1/tableconsole_accels.tex | 18 + doc/manual/volume1/tableconsole_mapping.tex | 26 + doc/manual/volume1/tableinfo_expan.tex | 35 + doc/manual/volume1/tablemakedefs1.tex | 46 + doc/manual/volume1/tablemakedefs2.tex | 38 + doc/manual/volume1/tablemuflags.tex | 22 + doc/manual/volume1/tables.aux | 89 + doc/manual/volume1/tables.tex | 1616 ++++ doc/manual/volume1/tables.tex.aux | 20 + doc/manual/volume1/tableshellexp.tex | 29 + doc/manual/volume1/tablewarn.tex | 32 + doc/manual/volume1/tablewarnexp.tex | 30 + doc/manual/volume1/tablex400info1.tex | 12 + doc/manual/volume1/tablex400info2.tex | 15 + doc/manual/volume1/tailor.tai | 425 + doc/manual/volume1/tailor.tex | 426 + doc/manual/volume1/users.tex | 12 + doc/manual/volume1/version.sh | 19 + doc/manual/volume1/volume1.aux | 24 + doc/manual/volume1/volume1.bbl | 57 + doc/manual/volume1/volume1.idx | 824 ++ doc/manual/volume1/volume1.ind | 381 + doc/manual/volume1/volume1.lof | 47 + doc/manual/volume1/volume1.lot | 24 + doc/manual/volume1/volume1.major | 1 + doc/manual/volume1/volume1.minor | 1 + doc/manual/volume1/volume1.tex | 98 + doc/manual/volume1/volume1.toc | 184 + doc/manual/volume1/volume1.vrsn | 6 + doc/manual/volume1/x400in-examp.tex | 11 + doc/manual/volume1/x400in-examp2.tex | 27 + doc/manual/volume1/x400links.aux | 55 + doc/manual/volume1/x400links.tex | 481 + doc/manual/volume1/x400out-examp.tex | 12 + doc/manual/volume1/x400tables.aux | 24 + doc/manual/volume1/x400tables.tex | 88 + doc/manual/volume2/Makefile | 119 + doc/manual/volume2/adrstruct.h | 126 + doc/manual/volume2/adrstruct.tex | 127 + doc/manual/volume2/channels.aux | 51 + doc/manual/volume2/channels.tex | 732 ++ doc/manual/volume2/delivery.aux | 25 + doc/manual/volume2/delivery.tex | 16 + doc/manual/volume2/delv-rep.c | 14 + doc/manual/volume2/delv-rep.tex | 15 + doc/manual/volume2/eit.h | 4 + doc/manual/volume2/eit.tex | 5 + doc/manual/volume2/general.aux | 37 + doc/manual/volume2/general.tex | 361 + doc/manual/volume2/idx2ind | 53 + doc/manual/volume2/io.c | 56 + doc/manual/volume2/io.tex | 57 + doc/manual/volume2/make | 11 + doc/manual/volume2/outbound.c | 111 + doc/manual/volume2/outbound.tex | 112 + doc/manual/volume2/preface.aux | 20 + doc/manual/volume2/preface.tex | 13 + doc/manual/volume2/prmstruct.h | 7 + doc/manual/volume2/prmstruct.tex | 8 + doc/manual/volume2/qmgrif.h | 29 + doc/manual/volume2/qmgrif.tex | 30 + doc/manual/volume2/qstruct.h | 90 + doc/manual/volume2/qstruct.tex | 91 + doc/manual/volume2/rchan.h | 13 + doc/manual/volume2/rchan.tex | 14 + doc/manual/volume2/rpbstruct.h | 6 + doc/manual/volume2/rpbstruct.tex | 7 + doc/manual/volume2/submission.aux | 66 + doc/manual/volume2/submission.tex | 1010 +++ doc/manual/volume2/tablecrit.tex | 11 + doc/manual/volume2/tablediag.tex | 33 + doc/manual/volume2/tableexplicit.tex | 27 + doc/manual/volume2/tablelog.tex | 13 + doc/manual/volume2/tablemuflags.tex | 20 + doc/manual/volume2/tablereason.tex | 24 + doc/manual/volume2/tablerpcodes.tex | 38 + doc/manual/volume2/version.sh | 19 + doc/manual/volume2/volume2.aux | 5 + doc/manual/volume2/volume2.idx | 175 + doc/manual/volume2/volume2.ind | 188 + doc/manual/volume2/volume2.lof | 13 + doc/manual/volume2/volume2.lot | 8 + doc/manual/volume2/volume2.major | 1 + doc/manual/volume2/volume2.minor | 1 + doc/manual/volume2/volume2.tex | 79 + doc/manual/volume2/volume2.toc | 56 + doc/manual/volume2/volume2.vrsn | 6 + doc/manual/volume2/xx.dvi | Bin 0 -> 14656 bytes doc/manual/volume3/Makefile | 120 + doc/manual/volume3/idx2ind | 53 + doc/manual/volume3/intro.aux | 23 + doc/manual/volume3/intro.tex | 60 + doc/manual/volume3/lists.aux | 40 + doc/manual/volume3/lists.tex | 544 ++ doc/manual/volume3/local-bnf.bnf | 39 + doc/manual/volume3/local-bnf.tex | 40 + doc/manual/volume3/local-examp.tex | 24 + doc/manual/volume3/local.aux | 45 + doc/manual/volume3/local.tex | 746 ++ doc/manual/volume3/make | 11 + doc/manual/volume3/utility.aux | 25 + doc/manual/volume3/utility.tex | 62 + doc/manual/volume3/version.sh | 19 + doc/manual/volume3/volume3.aux | 5 + doc/manual/volume3/volume3.idx | 153 + doc/manual/volume3/volume3.ind | 105 + doc/manual/volume3/volume3.lof | 6 + doc/manual/volume3/volume3.lot | 4 + doc/manual/volume3/volume3.major | 1 + doc/manual/volume3/volume3.minor | 1 + doc/manual/volume3/volume3.tex | 77 + doc/manual/volume3/volume3.toc | 38 + doc/manual/volume3/volume3.vrsn | 6 + doc/nordunet/Makefile | 92 + doc/nordunet/captcont.sty | 16 + doc/nordunet/console.wd.Z | 68 + doc/nordunet/figure1.pic | 52 + doc/nordunet/figure1.tex | 317 + doc/nordunet/figure2.pic | 15 + doc/nordunet/figure2.tex | 123 + doc/nordunet/lcustom.tex | 350 + doc/nordunet/make | 2 + doc/nordunet/pp-slides.aux | 1 + doc/nordunet/pp-slides.tex | 281 + doc/nordunet/pp.aux | 36 + doc/nordunet/pp.bbl | 40 + doc/nordunet/pp.major | 1 + doc/nordunet/pp.minor | 1 + doc/nordunet/pp.tex | 361 + doc/nordunet/pp.vrsn | 6 + doc/nordunet/trademark.tex | 75 + doc/nordunet/version.sh | 19 + doc/sun-89/Makefile | 89 + doc/sun-89/captcont.sty | 16 + doc/sun-89/console.wd | Bin 0 -> 49811 bytes doc/sun-89/figure1.pic | 52 + doc/sun-89/figure1.tex | 38 + doc/sun-89/figure2.pic | 15 + doc/sun-89/figure2.tex | 123 + doc/sun-89/lcustom.tex | 350 + doc/sun-89/make | 2 + doc/sun-89/pp-slides.aux | 1 + doc/sun-89/pp-slides.tex | 253 + doc/sun-89/pp.aux | 36 + doc/sun-89/pp.bbl | 40 + doc/sun-89/pp.major | 1 + doc/sun-89/pp.minor | 1 + doc/sun-89/pp.tex | 346 + doc/sun-89/pp.vrsn | 6 + doc/sun-89/trademark.tex | 75 + doc/sun-89/version.sh | 19 + doc/tailor/Makefile | 91 + doc/tailor/make | 2 + doc/tailor/tailor.tex | 203 + doc/tailor/version.sh | 21 + doc/uknet90/Makefile | 93 + doc/uknet90/bcustom.bib | 39 + doc/uknet90/captcont.sty | 16 + doc/uknet90/figure1.pic | 52 + doc/uknet90/figure1.tex | 317 + doc/uknet90/figure2.pic | 15 + doc/uknet90/figure2.tex | 123 + doc/uknet90/jpo.bib | 65 + doc/uknet90/lcustom.tex | 350 + doc/uknet90/make | 2 + doc/uknet90/networking.bib | 1768 ++++ doc/uknet90/pp-slides.aux | 1 + doc/uknet90/pp-slides.tex | 455 + doc/uknet90/pp.aux | 39 + doc/uknet90/pp.bbl | 40 + doc/uknet90/pp.major | 1 + doc/uknet90/pp.minor | 1 + doc/uknet90/pp.tex | 570 ++ doc/uknet90/pp.vrsn | 6 + doc/uknet90/queuefig.fig | 46 + doc/uknet90/sfwdoc.bib | 346 + doc/uknet90/software.bib | 345 + doc/uknet90/trademark.tex | 75 + doc/uknet90/version.sh | 19 + doc/unix-niftp/Makefile | 13 + doc/unix-niftp/make | 2 + doc/unix-niftp/unix-niftp-pp.ms | 258 + examples/INTERNET/Makefile | 114 + examples/INTERNET/make | 2 + examples/JANET/Makefile | 114 + examples/JANET/make | 2 + examples/LOCALSMTP/Makefile | 114 + examples/LOCALSMTP/make | 2 + examples/Makefile | 37 + examples/README | 21 + examples/make | 2 + examples/master/Makefile | 79 + examples/master/README | 1 + examples/master/README-master | 189 + examples/master/aliases | 23 + examples/master/auth.channel | 5 + examples/master/auth.mta | 5 + examples/master/auth.qmgr | 7 + examples/master/auth.user | 5 + examples/master/ch.list | 12 + examples/master/ch.local | 18 + examples/master/ch.shell | 5 + examples/master/ch.uucp | 5 + examples/master/ch.x400in84 | 5 + examples/master/ch.x400in88 | 5 + examples/master/ch.x400out84 | 5 + examples/master/ch.x400out88 | 5 + examples/master/channel-I | 48 + examples/master/channel-J | 59 + examples/master/channel-L | 50 + examples/master/domain-I | 51 + examples/master/domain-J | 64 + examples/master/domain-L | 51 + examples/master/foo | 1 + examples/master/isoentities.add | 23 + examples/master/make | 2 + examples/master/or | 5 + examples/master/or2rfc | 5 + examples/master/rfc1148gate | 1 + examples/master/rfc2or | 5 + examples/master/tailor-I.head | 53 + examples/master/tailor-J.head | 53 + examples/master/tailor-L.head | 54 + examples/master/tailor.common | 188 + examples/master/users | 15 + examples/master/warning.1 | 16 + examples/master/warning.2 | 15 + examples/master/x500.sample | 5 + examples/xtel/Make.defs | 188 + examples/xtel/Makefile | 77 + examples/xtel/aliases | 176 + examples/xtel/auth.channel | 22 + examples/xtel/auth.mta | 16 + examples/xtel/auth.qmgr | 18 + examples/xtel/auth.user | 20 + examples/xtel/ch.fax | 57 + examples/xtel/ch.list | 34 + examples/xtel/ch.local | 34 + examples/xtel/ch.mslocal | 29 + examples/xtel/ch.shell | 17 + examples/xtel/ch.uucp | 5 + examples/xtel/ch.x400in84 | 9 + examples/xtel/ch.x400in88 | 12 + examples/xtel/ch.x400out84 | 21 + examples/xtel/ch.x400out88 | 24 + examples/xtel/channel | 500 ++ examples/xtel/config.h | 47 + examples/xtel/domain | 500 ++ examples/xtel/make | 2 + examples/xtel/or | 248 + examples/xtel/or2rfc | 500 ++ examples/xtel/rfc1148gate | 10 + examples/xtel/rfc2or | 500 ++ examples/xtel/tailor | 439 + examples/xtel/users | 88 + examples/xtel/warning.1 | 16 + examples/xtel/warning.2 | 15 + h/adr.h | 241 + h/alias.h | 35 + h/ap.h | 140 + h/ap_lex.h | 54 + h/aparse.h | 96 + h/argh.h | 104 + h/auth.h | 147 + h/ch_bind.h | 48 + h/chan.h | 126 + h/charset.h | 69 + h/dbase.h | 73 + h/dl.h | 44 + h/dlist.h | 62 + h/dr.h | 170 + h/expand.h | 25 + h/extension.h | 139 + h/head.h | 39 + h/list_bpt.h | 37 + h/list_rchan.h | 52 + h/ll_log.h | 128 + h/loc_user.h | 42 + h/mta.h | 112 + h/or.h | 248 + h/ppp.h | 30 + h/prm.h | 39 + h/q.h | 134 + h/qmgr-int.h | 188 + h/qmgr.h | 43 + h/retcode.h | 250 + h/rtsparams.h | 53 + h/sys.file.h | 47 + h/table.h | 55 + h/tb_a.h | 77 + h/tb_auth.h | 33 + h/tb_bpt84.h | 45 + h/tb_bpt88.h | 48 + h/tb_com.h | 33 + h/tb_dr.h | 48 + h/tb_p1.h | 56 + h/tb_p3prm.h | 26 + h/tb_prm.h | 26 + h/tb_q.h | 59 + h/tjoin.h | 77 + h/util.h | 190 + h/x400_ub.h | 69 + make | 2 + man/Makefile | 46 + man/inst-man.sh | 166 + man/make | 2 + man/man1/Makefile | 56 + man/man1/ckmail.1 | 36 + man/man1/ckmf.1 | 39 + man/man1/dl.1 | 106 + man/man1/flagmail.1 | 78 + man/man1/flock.1 | 30 + man/man1/mail.1 | 38 + man/man1/make | 2 + man/man1/malias.1 | 28 + man/man1/mlist.1 | 37 + man/man1/mu.1 | 151 + man/man1/ntail.1 | 53 + man/man1/rcvtrip.1 | 75 + man/man1/resend.1 | 41 + man/man1/strip_addr.1 | 37 + man/man1/ttyalert.1 | 58 + man/man1/ttybiff.1 | 53 + man/man1/xalert.1 | 82 + man/man3/Makefile | 41 + man/man3/make | 2 + man/man3/or.3 | 216 + man/man8/MTAconsole.8 | 69 + man/man8/Makefile | 62 + man/man8/abbrev.8 | 42 + man/man8/ckadr.8 | 58 + man/man8/ckchan.8 | 44 + man/man8/ckconfig.8 | 69 + man/man8/dbmbuild.8 | 49 + man/man8/dbmedit.8 | 118 + man/man8/dbmunbuild.8 | 49 + man/man8/lconsole.8 | 77 + man/man8/make | 2 + man/man8/mpp84.8 | 56 + man/man8/mpp88.8 | 52 + man/man8/pp-gen.8 | 284 + man/man8/pptsapd.8 | 40 + man/man8/probe.8 | 59 + man/man8/qmgr.8 | 79 + man/man8/rmail.8 | 21 + man/man8/sendmail.8 | 26 + man/man8/smtpd.8 | 47 + man/man8/smtpsrvr.8 | 41 + man/man8/tjoin.8 | 57 + pp-changes.ms | 306 + template/README | 32 + template/template.bug-report | 22 + template/template.c | 12 + template/template.chan | 228 + template/template.h | 8 + template/template.man | 5 + template/template.mk | 56 + template/template.py | 13 + template/template.sh | 11 + 1305 files changed, 254721 insertions(+) create mode 100644 CHANGES create mode 100644 COVER-LETTER create mode 100644 Chans/822-local/Makefile create mode 100644 Chans/822-local/ckmf.c create mode 100644 Chans/822-local/code.c create mode 100644 Chans/822-local/lex.l create mode 100644 Chans/822-local/loc.h create mode 100644 Chans/822-local/loc.y create mode 100644 Chans/822-local/loc_child.c create mode 100644 Chans/822-local/loc_parent.c create mode 100644 Chans/822-local/mailfilter create mode 100755 Chans/822-local/make create mode 100644 Chans/822-local/parse_hdr.c create mode 100644 Chans/Makefile create mode 100644 Chans/decnet/Makefile create mode 100644 Chans/decnet/de_wtmail.c create mode 100644 Chans/decnet/decnet.c create mode 100644 Chans/decnet/decnetsrvr.c create mode 100755 Chans/decnet/make create mode 100644 Chans/dr2rfc/Makefile create mode 100644 Chans/dr2rfc/dr2rfc.c create mode 100755 Chans/dr2rfc/make create mode 100644 Chans/dr2rfc/write_queue.c create mode 100644 Chans/dr2rfc/write_report.c create mode 100644 Chans/fax/Makefile create mode 100644 Chans/fax/dexNet200/Makefile create mode 100644 Chans/fax/dexNet200/dexnet.h create mode 100644 Chans/fax/dexNet200/dexnet_conv.c create mode 100644 Chans/fax/dexNet200/dexnet_intf.c create mode 100644 Chans/fax/dexNet200/dexnet_util.c create mode 100755 Chans/fax/dexNet200/make create mode 100644 Chans/fax/fax_in.c create mode 100644 Chans/fax/fax_out.c create mode 100644 Chans/fax/faxgeneric.h create mode 100755 Chans/fax/make create mode 100644 Chans/fax/ps250/Makefile create mode 100644 Chans/fax/ps250/error_codes.c create mode 100755 Chans/fax/ps250/make create mode 100644 Chans/fax/ps250/ps250.h create mode 100644 Chans/fax/ps250/ps250_basic.c create mode 100644 Chans/fax/ps250/ps250_intf.c create mode 100644 Chans/fax/ps250/ps250_manage.c create mode 100644 Chans/fax/ps250/ps250_stat.c create mode 100644 Chans/fax/ps250/ps250_trans.c create mode 100644 Chans/fax/ps250/ps250_util.c create mode 100644 Chans/fax/ps250/tools/Makefile create mode 100644 Chans/fax/ps250/tools/fax_print.c create mode 100644 Chans/fax/ps250/tools/faxenq1.c create mode 100644 Chans/fax/ps250/tools/faxid.c create mode 100755 Chans/fax/ps250/tools/make create mode 100644 Chans/fax/ps250/tools/setid.c create mode 100644 Chans/filtercontrol/Makefile create mode 100644 Chans/filtercontrol/filtercont.c create mode 100755 Chans/filtercontrol/make create mode 100755 Chans/filtercontrol/removebp.sh create mode 100644 Chans/grey/Makefile create mode 100644 Chans/grey/README create mode 100644 Chans/grey/io_grey.c create mode 100755 Chans/grey/make create mode 100644 Chans/grey/ppp.c create mode 100644 Chans/grey/tgreyin.c create mode 100644 Chans/lists/Makefile create mode 100644 Chans/lists/READ-ME create mode 100644 Chans/lists/dish.c create mode 100644 Chans/lists/dl.c create mode 100644 Chans/lists/dl.py create mode 100644 Chans/lists/dl_permit.c create mode 100644 Chans/lists/dl_util.c create mode 100644 Chans/lists/dl_x500.c create mode 100644 Chans/lists/dlist.h create mode 100644 Chans/lists/hack.c create mode 100644 Chans/lists/init.c create mode 100644 Chans/lists/list.c create mode 100644 Chans/lists/lmnpq_dish.c create mode 100755 Chans/lists/make create mode 100644 Chans/lists/md.py create mode 100644 Chans/lists/or2addr.c create mode 100644 Chans/lists/syn_oraddr.c create mode 100644 Chans/lists/syn_orname.c create mode 100644 Chans/lists/syn_permit.c create mode 100644 Chans/lists/syn_policy.c create mode 100755 Chans/make create mode 100644 Chans/msg-clean/Makefile create mode 100755 Chans/msg-clean/make create mode 100644 Chans/msg-clean/msg-clean.c create mode 100644 Chans/qmgr-load/Makefile create mode 100755 Chans/qmgr-load/make create mode 100644 Chans/qmgr-load/qmgr-load.c create mode 100644 Chans/qmgr-load/qmgr-start.c create mode 100644 Chans/qmgr-load/ryinitiator.c create mode 100644 Chans/qmgr-load/ryinitiator.h create mode 100644 Chans/qmgr-load/ryresponder.c create mode 100644 Chans/qmgr-load/ryresponder.h create mode 100644 Chans/shell/Makefile create mode 100644 Chans/shell/README create mode 100755 Chans/shell/make create mode 100644 Chans/shell/prog.h create mode 100644 Chans/shell/shell.c create mode 100644 Chans/shell/tb_getprog.c create mode 100644 Chans/slocal/Makefile create mode 100755 Chans/slocal/alert-script create mode 100644 Chans/slocal/loc_proto.c create mode 100644 Chans/slocal/local.c create mode 100755 Chans/slocal/make create mode 100644 Chans/slocal/slocal.c create mode 100644 Chans/smtp/Makefile create mode 100755 Chans/smtp/make create mode 100644 Chans/smtp/sm_ns.c create mode 100644 Chans/smtp/sm_wtmail.c create mode 100644 Chans/smtp/smtp.c create mode 100755 Chans/smtp/smtp.start create mode 100644 Chans/smtp/smtpd.c create mode 100644 Chans/smtp/smtpsrvr.c create mode 100644 Chans/splitter/Makefile create mode 100755 Chans/splitter/make create mode 100644 Chans/splitter/splitter.c create mode 100644 Chans/testchan/Makefile create mode 100644 Chans/testchan/README create mode 100755 Chans/testchan/dogen create mode 100755 Chans/testchan/make create mode 100644 Chans/testchan/testchan.c create mode 100644 Chans/timeout/Makefile create mode 100755 Chans/timeout/make create mode 100644 Chans/timeout/timeout.c create mode 100644 Chans/trashman/Makefile create mode 100755 Chans/trashman/make create mode 100644 Chans/trashman/trash.c create mode 100644 Chans/uucp/Makefile create mode 100755 Chans/uucp/make create mode 100644 Chans/uucp/rfc8222uu.c create mode 100644 Chans/uucp/rmail.c create mode 100644 Chans/uucp/t-rfc8222uu.c create mode 100644 Chans/uucp/uucp_out.c create mode 100644 Chans/warnings/Makefile create mode 100755 Chans/warnings/make create mode 100644 Chans/warnings/warnings.c create mode 100644 Chans/x40084/Makefile create mode 100644 Chans/x40084/P1_in.py create mode 100644 Chans/x40084/P1_out.py create mode 100644 Chans/x40084/P1_print.py create mode 100644 Chans/x40084/Rts_posy.py create mode 100755 Chans/x40084/make create mode 100644 Chans/x40084/ut_logs.c create mode 100644 Chans/x40084/ut_misc.c create mode 100644 Chans/x40084/ut_rts.c create mode 100644 Chans/x40084/x400in84.c create mode 100644 Chans/x40084/x400out84.c create mode 100644 Chans/x40084/x400topp.c create mode 100644 Chans/x40088/Makefile create mode 100755 Chans/x40088/make create mode 100644 Chans/x40088/p88.c create mode 100644 Chans/x40088/pptox400.c create mode 100644 Chans/x40088/tasn.c create mode 100644 Chans/x40088/ut_misc.c create mode 100644 Chans/x40088/ut_rts.c create mode 100644 Chans/x40088/util.c create mode 100644 Chans/x40088/x400in88.c create mode 100644 Chans/x40088/x400inext.c create mode 100644 Chans/x40088/x400inmsg.c create mode 100644 Chans/x40088/x400out88.c create mode 100644 Chans/x40088/x400outext.c create mode 100644 Chans/x40088/x400topp.c create mode 100644 Format/Makefile create mode 100644 Format/ascii2fax/Makefile create mode 100644 Format/ascii2fax/X2PPbitmap.c create mode 100644 Format/ascii2fax/Xfont2PPfont.c create mode 100644 Format/ascii2fax/bitmap_util.c create mode 100644 Format/ascii2fax/char_util.c create mode 100644 Format/ascii2fax/font_util.c create mode 100644 Format/ascii2fax/fonts.h create mode 100644 Format/ascii2fax/g3.h create mode 100644 Format/ascii2fax/hdr2fax.c create mode 100644 Format/ascii2fax/ia52fax.c create mode 100644 Format/ascii2fax/image2fax.c create mode 100755 Format/ascii2fax/make create mode 100644 Format/ascii2fax/pg_sizes.h create mode 100644 Format/ascii2fax/str_util.c create mode 100644 Format/asn/Makefile create mode 100644 Format/asn/asn.c create mode 100644 Format/asn/asn.h create mode 100644 Format/asn/asn1/Makefile create mode 100644 Format/asn/asn1/extdefbp.py create mode 100644 Format/asn/asn1/gentxt.py create mode 100755 Format/asn/asn1/make create mode 100644 Format/asn/asn_charset.c create mode 100644 Format/asn/asn_dec.c create mode 100644 Format/asn/asn_enc.c create mode 100644 Format/asn/asn_proc.c create mode 100644 Format/asn/asn_rd.c create mode 100644 Format/asn/doc/asn.aux create mode 100644 Format/asn/doc/asn.dvi create mode 100644 Format/asn/doc/asn.tex create mode 100644 Format/asn/f_6937.c create mode 100644 Format/asn/f_gentxt.c create mode 100644 Format/asn/f_teletex.c create mode 100755 Format/asn/make create mode 100644 Format/asn/oid.h create mode 100644 Format/asn/opt_cmdln.c create mode 100644 Format/asn/opt_functs.c create mode 100644 Format/asn/ut_asn.c create mode 100644 Format/asn/ut_ext.c create mode 100644 Format/asn/ut_f.c create mode 100644 Format/charset/Makefile create mode 100644 Format/charset/README create mode 100644 Format/charset/conv.c create mode 100644 Format/charset/copyright create mode 100644 Format/charset/design create mode 100644 Format/charset/doc/charset.tex create mode 100644 Format/charset/doc/notforPPdoc/design.more create mode 100644 Format/charset/doc/notforPPdoc/uclstuff create mode 100755 Format/charset/make create mode 100755 Format/charset/test/files/dotranslate create mode 100644 Format/charset/test/files/keld create mode 100644 Format/charset/test/files/orig.czeck create mode 100644 Format/charset/test/files/orig.english create mode 100644 Format/charset/test/files/orig.italian create mode 100644 Format/charset/test/files/t.61-8.1 create mode 100644 Format/charset/test/files/t.61-8.all create mode 100644 Format/charset/test/progs/Makefile create mode 100755 Format/charset/test/progs/bit2ch create mode 100644 Format/charset/test/progs/bit2ch.c create mode 100755 Format/charset/test/progs/ch255 create mode 100644 Format/charset/test/progs/ch255.c create mode 100755 Format/charset/test/progs/ch2val create mode 100644 Format/charset/test/progs/ch2val.c create mode 100755 Format/charset/test/progs/make create mode 100644 Format/charset/test/progs/translate.c create mode 100755 Format/make create mode 100644 Format/p2explode/Makefile create mode 100644 Format/p2explode/explode_chan.c create mode 100644 Format/p2explode/explode_only.c create mode 100755 Format/p2explode/make create mode 100644 Format/p2explode/p2explode.c create mode 100644 Format/p2flatten/Makefile create mode 100644 Format/p2flatten/flatten_chan.c create mode 100644 Format/p2flatten/flatten_only.c create mode 100755 Format/p2flatten/make create mode 100644 Format/p2flatten/p2flatten.c create mode 100644 Format/p2norm/Makefile create mode 100755 Format/p2norm/make create mode 100644 Format/p2norm/p2norm.c create mode 100644 Format/p2norm/pac create mode 100644 Format/rfc1148/Makefile create mode 100644 Format/rfc1148/P2toRFC.c create mode 100644 Format/rfc1148/RFCtoP2.c create mode 100644 Format/rfc1148/c-P2toRFC.c create mode 100644 Format/rfc1148/c-RFCtoP2.c create mode 100644 Format/rfc1148/f-P2toRFC.c create mode 100644 Format/rfc1148/f-RFCtoP2.c create mode 100755 Format/rfc1148/make create mode 100644 Format/rfc1148/oids.h create mode 100644 Format/rfc1148/rfc-hdr.h create mode 100644 Format/rfc1148/t-P2toRFC.c create mode 100644 Format/rfc1148/t-RFCtoP2.c create mode 100644 Format/rfc822norm/Makefile create mode 100755 Format/rfc822norm/make create mode 100644 Format/rfc822norm/rfc822norm.c create mode 100644 Format/rfc934/Makefile create mode 100644 Format/rfc934/do-rfc934.c create mode 100755 Format/rfc934/make create mode 100644 Format/rfc934/rfc934.c create mode 100644 Lib/Makefile create mode 100644 Lib/addr/Makefile create mode 100644 Lib/addr/ap_1adr.c create mode 100644 Lib/addr/ap_dmflip.c create mode 100644 Lib/addr/ap_equ.c create mode 100644 Lib/addr/ap_file.c create mode 100644 Lib/addr/ap_lex.c create mode 100644 Lib/addr/ap_lex_tb.c create mode 100644 Lib/addr/ap_norm.c create mode 100644 Lib/addr/ap_p2s.c create mode 100644 Lib/addr/ap_s2p.c create mode 100644 Lib/addr/ap_s2s.c create mode 100644 Lib/addr/ap_s2t.c create mode 100644 Lib/addr/ap_t2p.c create mode 100644 Lib/addr/ap_t2s.c create mode 100644 Lib/addr/ap_ut.c create mode 100644 Lib/addr/ap_val2str.c create mode 100755 Lib/addr/make create mode 100644 Lib/charset/Make.defs create mode 100644 Lib/charset/Makefile create mode 100644 Lib/charset/README create mode 100644 Lib/charset/charset_conf.c create mode 100644 Lib/charset/copyright create mode 100644 Lib/charset/design create mode 100644 Lib/charset/gc.c create mode 100755 Lib/charset/make create mode 100644 Lib/charset/master/CHARSETS create mode 100644 Lib/charset/master/CHARSETS_PP create mode 100644 Lib/charset/master/CONTROL create mode 100644 Lib/charset/master/ISO_10646 create mode 100644 Lib/charset/master/OTHER create mode 100644 Lib/charset/strcnv.c create mode 100644 Lib/format/Makefile create mode 100644 Lib/format/UTC2rfc.c create mode 100644 Lib/format/adr2rfc.c create mode 100644 Lib/format/domsinfo2rfc.c create mode 100644 Lib/format/globalid2rfc.c create mode 100755 Lib/format/make create mode 100644 Lib/format/msgid2rfc.c create mode 100644 Lib/format/reprecip2rfc.c create mode 100644 Lib/format/rfc2UTC.c create mode 100644 Lib/format/rfc2domsinfo.c create mode 100644 Lib/format/rfc2encinfo.c create mode 100644 Lib/format/rfc2globalid.c create mode 100644 Lib/format/rfc2msgid.c create mode 100644 Lib/format/rfc2reprecip.c create mode 100644 Lib/format/rfc2trace.c create mode 100644 Lib/format/rfc2x400trc.c create mode 100644 Lib/format/rfctxtfold.c create mode 100644 Lib/format/trace2rfc.c create mode 100644 Lib/format/x400trc2rfc.c create mode 100644 Lib/io/Makefile create mode 100644 Lib/io/io_lib.c create mode 100755 Lib/io/make create mode 100644 Lib/io/rd_adr.c create mode 100644 Lib/io/rd_buf.c create mode 100644 Lib/io/rd_dr.c create mode 100644 Lib/io/rd_msg.c create mode 100644 Lib/io/rd_prm.c create mode 100644 Lib/io/rd_q.c create mode 100644 Lib/io/wr_adr.c create mode 100644 Lib/io/wr_dr.c create mode 100644 Lib/io/wr_drfile.c create mode 100644 Lib/io/wr_prm.c create mode 100644 Lib/io/wr_q.c create mode 100644 Lib/io/wr_q2drfile.c create mode 100755 Lib/make create mode 100644 Lib/or/Makefile create mode 100755 Lib/or/make create mode 100644 Lib/or/or2pe.py create mode 100644 Lib/or/or_add.c create mode 100644 Lib/or/or_asc2ps.c create mode 100644 Lib/or/or_basic.c create mode 100644 Lib/or/or_blank.c create mode 100644 Lib/or/or_buildpn.c create mode 100644 Lib/or/or_check.c create mode 100644 Lib/or/or_default.c create mode 100644 Lib/or/or_dmn2or.c create mode 100644 Lib/or/or_downgrade.c create mode 100644 Lib/or/or_getpn.c create mode 100644 Lib/or/or_init.c create mode 100644 Lib/or/or_misc.c create mode 100644 Lib/or/or_or2dmn.c create mode 100644 Lib/or/or_or2rbits.c create mode 100644 Lib/or/or_or2rfc.c create mode 100644 Lib/or/or_or2std.c create mode 100644 Lib/or/or_ps2asc.c create mode 100644 Lib/or/or_rbits2or.c create mode 100644 Lib/or/or_rfc2or.c create mode 100644 Lib/or/or_search.c create mode 100644 Lib/or/or_std2or.c create mode 100644 Lib/or/or_tables.c create mode 100644 Lib/or/or_up_bnds.c create mode 100644 Lib/or/or_util.c create mode 100644 Lib/or/or_valid.c create mode 100644 Lib/or/orn-dec.c create mode 100644 Lib/or/orn-enc.c create mode 100644 Lib/or/orn-util.c create mode 100644 Lib/or/pe2or.py create mode 100644 Lib/parse/Makefile create mode 100644 Lib/parse/ad_getlocal.c create mode 100644 Lib/parse/ad_local.c create mode 100644 Lib/parse/ad_parse.c create mode 100644 Lib/parse/aparse_norm.c create mode 100755 Lib/parse/make create mode 100644 Lib/parse/rfc822_dnorm.c create mode 100644 Lib/parse/rfc822_parse.c create mode 100644 Lib/parse/rfc822_val.c create mode 100644 Lib/parse/rfc822_x400.c create mode 100644 Lib/parse/x400_parse.c create mode 100644 Lib/parse/x400_rfc822.c create mode 100644 Lib/parse/x400_val.c create mode 100644 Lib/pp/Makefile create mode 100644 Lib/pp/adr2txt.c create mode 100644 Lib/pp/chan_acheck.c create mode 100644 Lib/pp/conf.c create mode 100644 Lib/pp/dchan_acheck.c create mode 100644 Lib/pp/dr2txt.c create mode 100644 Lib/pp/get_dr.c create mode 100644 Lib/pp/lchan_acheck.c create mode 100644 Lib/pp/list_bpt.c create mode 100644 Lib/pp/list_rchan.c create mode 100755 Lib/pp/make create mode 100644 Lib/pp/msg2file.c create mode 100644 Lib/pp/mta2txt.c create mode 100644 Lib/pp/p32txt.c create mode 100644 Lib/pp/pps_mail.c create mode 100644 Lib/pp/prm2txt.c create mode 100644 Lib/pp/q2txt.c create mode 100644 Lib/pp/set_1dr.c create mode 100644 Lib/pp/static.c create mode 100644 Lib/pp/tb_a.c create mode 100644 Lib/pp/tb_bpt84.c create mode 100644 Lib/pp/tb_bpt88.c create mode 100644 Lib/pp/tb_dr.c create mode 100644 Lib/pp/tb_misc.c create mode 100644 Lib/pp/tb_p1.c create mode 100644 Lib/pp/tb_p3prm.c create mode 100644 Lib/pp/tb_prm.c create mode 100644 Lib/pp/tb_q.c create mode 100644 Lib/pp/txt2adr.c create mode 100644 Lib/pp/txt2dr.c create mode 100644 Lib/pp/txt2mta.c create mode 100644 Lib/pp/txt2p3.c create mode 100644 Lib/pp/txt2prm.c create mode 100644 Lib/pp/txt2q.c create mode 100644 Lib/pp/ut_a.c create mode 100644 Lib/pp/ut_aparse.c create mode 100644 Lib/pp/ut_com.c create mode 100644 Lib/pp/ut_dlh.c create mode 100644 Lib/pp/ut_dr.c create mode 100644 Lib/pp/ut_fn.c create mode 100644 Lib/pp/ut_free.c create mode 100644 Lib/pp/ut_gldm.c create mode 100644 Lib/pp/ut_mm2p1.c create mode 100644 Lib/pp/ut_mpduid.c create mode 100644 Lib/pp/ut_msg.c create mode 100644 Lib/pp/ut_p12mm.c create mode 100644 Lib/pp/ut_p1_st.c create mode 100644 Lib/pp/ut_postie.c create mode 100644 Lib/pp/ut_prm.c create mode 100644 Lib/pp/ut_q.c create mode 100644 Lib/pp/ut_qid.c create mode 100644 Lib/pp/ut_redirect.c create mode 100644 Lib/pp/ut_trace.c create mode 100644 Lib/pp/wr_stat.c create mode 100644 Lib/qmgr/Makefile create mode 100644 Lib/qmgr/chan_control.c create mode 100644 Lib/qmgr/chan_debug.c create mode 100644 Lib/qmgr/comms.c create mode 100644 Lib/qmgr/cons-misc.c create mode 100644 Lib/qmgr/consblk.c create mode 100644 Lib/qmgr/consblk.h create mode 100755 Lib/qmgr/make create mode 100644 Lib/qmgr/op_chan.c create mode 100644 Lib/qmgr/op_filter.c create mode 100644 Lib/qmgr/op_msg.c create mode 100644 Lib/qmgr/op_mta.c create mode 100644 Lib/qmgr/op_que.c create mode 100644 Lib/qmgr/order.c create mode 100644 Lib/qmgr/qmgr.ry create mode 100644 Lib/qmgr/qstruct2qmgr.c create mode 100644 Lib/qmgr/recipstate.c create mode 100644 Lib/qmgr/submit2qmgr.c create mode 100644 Lib/table/Makefile create mode 100644 Lib/table/ch_nm2struct.c create mode 100755 Lib/table/make create mode 100644 Lib/table/tb_1148gate.c create mode 100644 Lib/table/tb_checkauth.c create mode 100644 Lib/table/tb_dbm.c create mode 100644 Lib/table/tb_getalias.c create mode 100644 Lib/table/tb_getauth.c create mode 100644 Lib/table/tb_getchan.c create mode 100644 Lib/table/tb_getdl.c create mode 100644 Lib/table/tb_getdomain.c create mode 100644 Lib/table/tb_getlocal.c create mode 100644 Lib/table/tb_getuser.c create mode 100644 Lib/table/tb_k2val.c create mode 100644 Lib/table/tb_nm2struct.c create mode 100644 Lib/table/tb_rtsparams.c create mode 100644 Lib/tai/Makefile create mode 100644 Lib/tai/init_chan.c create mode 100644 Lib/tai/init_tai.c create mode 100644 Lib/tai/init_uip.c create mode 100755 Lib/tai/make create mode 100644 Lib/tai/pp_setuserid.c create mode 100644 Lib/tai/tai_chan.c create mode 100644 Lib/tai/tai_sys.c create mode 100644 Lib/tai/tai_tb.c create mode 100644 Lib/util/Makefile create mode 100644 Lib/util/arg2str.c create mode 100644 Lib/util/check_close.c create mode 100644 Lib/util/cmdbsrch.c create mode 100644 Lib/util/compress.c create mode 100644 Lib/util/diskfull.c create mode 100644 Lib/util/err_abrt.c create mode 100644 Lib/util/expand.c create mode 100644 Lib/util/flip_bits.c create mode 100644 Lib/util/getfpath.c create mode 100644 Lib/util/hier_scanQ.c create mode 100644 Lib/util/lock.c create mode 100644 Lib/util/lstr2oid.c create mode 100755 Lib/util/make create mode 100644 Lib/util/multcat.c create mode 100644 Lib/util/multcpy.c create mode 100644 Lib/util/oid2lstr.c create mode 100644 Lib/util/pe_fragment.c create mode 100644 Lib/util/prefix.c create mode 100644 Lib/util/recrm.c create mode 100644 Lib/util/rename_log.c create mode 100644 Lib/util/rp_valstr.c create mode 100644 Lib/util/siginit.c create mode 100644 Lib/util/str2arg.c create mode 100644 Lib/util/sys5_regex.c create mode 100644 Lib/util/timeout.c create mode 100644 Lib/util/timer.c create mode 100644 Lib/util/tryfork.c create mode 100644 Lib/util/utctime.c create mode 100644 Lib/version.major create mode 100644 Lib/version.minor create mode 100755 Lib/version.sh create mode 100644 Lib/x400/Makefile create mode 100644 Lib/x400/Rts_posy.py create mode 100644 Lib/x400/authen.py create mode 100644 Lib/x400/enctypes2mem.c create mode 100644 Lib/x400/extent.py create mode 100644 Lib/x400/fixorig.c create mode 100644 Lib/x400/iob.py create mode 100755 Lib/x400/make create mode 100644 Lib/x400/mta.ry create mode 100644 Lib/x400/rasn.c create mode 100644 Lib/x400/tokens.py create mode 100644 Lib/x400/transfer.py create mode 100644 Makefile create mode 100644 README create mode 100644 Src/LINEconsole/Makefile create mode 100644 Src/LINEconsole/assoc.c create mode 100644 Src/LINEconsole/badness.c create mode 100644 Src/LINEconsole/channels.c create mode 100644 Src/LINEconsole/console.h create mode 100644 Src/LINEconsole/drive.c create mode 100644 Src/LINEconsole/heuristics.c create mode 100644 Src/LINEconsole/io.c create mode 100755 Src/LINEconsole/make create mode 100644 Src/LINEconsole/misc.c create mode 100644 Src/LINEconsole/msgs.c create mode 100644 Src/LINEconsole/mtas.c create mode 100644 Src/LINEconsole/status.c create mode 100644 Src/LINEconsole/tai_defs.inc create mode 100644 Src/MTAconsole/.MTAconsole create mode 100644 Src/MTAconsole/.MTAconsole~ create mode 100644 Src/MTAconsole/Makefile create mode 100644 Src/MTAconsole/Mtaconsole.ad create mode 100644 Src/MTAconsole/README create mode 100644 Src/MTAconsole/assoc.c create mode 100644 Src/MTAconsole/auto.c create mode 100644 Src/MTAconsole/back.bit create mode 100644 Src/MTAconsole/badness.c create mode 100644 Src/MTAconsole/bops.c create mode 100644 Src/MTAconsole/console.h create mode 100644 Src/MTAconsole/create.c create mode 100644 Src/MTAconsole/data.c create mode 100644 Src/MTAconsole/display.c create mode 100644 Src/MTAconsole/drive.c create mode 100755 Src/MTAconsole/make create mode 100644 Src/MTAconsole/misc.c create mode 100644 Src/MTAconsole/ops.c create mode 100644 Src/MTAconsole/parse.c create mode 100644 Src/MTAconsole/popup.c create mode 100644 Src/MTAconsole/tai_defs.inc create mode 100644 Src/MTAconsole/workops.c create mode 100644 Src/Makefile create mode 100644 Src/lconsole/Makefile create mode 100644 Src/lconsole/channel.c create mode 100644 Src/lconsole/functions.c create mode 100644 Src/lconsole/lconsole.c create mode 100644 Src/lconsole/lconsole.h create mode 100755 Src/lconsole/make create mode 100644 Src/lconsole/msgs.c create mode 100644 Src/lconsole/mtas.c create mode 100644 Src/lconsole/show.c create mode 100755 Src/make create mode 100644 Src/pptsapd/Makefile create mode 100755 Src/pptsapd/make create mode 100644 Src/pptsapd/pptsapd-stat.c create mode 100644 Src/pptsapd/pptsapd.c create mode 100644 Src/qmgr/Makefile create mode 100644 Src/qmgr/assoc.c create mode 100644 Src/qmgr/chans.c create mode 100755 Src/qmgr/make create mode 100644 Src/qmgr/misc.c create mode 100644 Src/qmgr/qmgr.c create mode 100644 Src/qmgr/ryresponder.c create mode 100644 Src/qmgr/ryresponder.h create mode 100644 Src/qmgr/structs.c create mode 100644 Src/qmgr/tables.c create mode 100644 Src/qmgr/types.h create mode 100644 Src/submit/Makefile create mode 100644 Src/submit/ad_mgt.c create mode 100644 Src/submit/auth.c create mode 100644 Src/submit/auth_logs.c create mode 100644 Src/submit/auth_tb.c create mode 100644 Src/submit/auth_ut.c create mode 100644 Src/submit/ch_bind.c create mode 100644 Src/submit/gen_io2dr.c create mode 100644 Src/submit/gen_ndr.c create mode 100644 Src/submit/gen_probedr.c create mode 100644 Src/submit/gen_warn.c create mode 100755 Src/submit/make create mode 100644 Src/submit/rd_rfchdr.c create mode 100644 Src/submit/submit.c create mode 100644 Src/submit/submit_chk.c create mode 100644 Src/submit/submit_mgt.c create mode 100644 Src/submit/submit_prm.c create mode 100644 Src/submit/submit_que.c create mode 100644 Src/submit/submit_srvr.c create mode 100644 Src/submit/submit_txt.c create mode 100644 Src/submit/t-auth.c create mode 100644 Src/submit/t-rd_rfchdr.c create mode 100644 Src/submit/t-tracecheck.c create mode 100644 Tools/Makefile create mode 100644 Tools/bin2ascii/Makefile create mode 100644 Tools/bin2ascii/bin2ascii.c create mode 100755 Tools/bin2ascii/make create mode 100644 Tools/bin2hex/Makefile create mode 100644 Tools/bin2hex/bin2hex.c create mode 100755 Tools/bin2hex/make create mode 100644 Tools/ckadr/Makefile create mode 100644 Tools/ckadr/ckadr.c create mode 100755 Tools/ckadr/make create mode 100644 Tools/ckchan/Makefile create mode 100644 Tools/ckchan/ckchan.c create mode 100755 Tools/ckchan/make create mode 100644 Tools/ckchan/qcheck.c create mode 100644 Tools/ckconfig/Makefile create mode 100644 Tools/ckconfig/ckconfig.c create mode 100755 Tools/ckconfig/make create mode 100644 Tools/ckmail/Makefile create mode 100644 Tools/ckmail/ckmail.c create mode 100755 Tools/ckmail/make create mode 100644 Tools/ckmail/ryinitiator.c create mode 100644 Tools/ckmail/ryinitiator.h create mode 100644 Tools/ckor/Makefile create mode 100755 Tools/ckor/make create mode 100644 Tools/ckor/or2rfc.c create mode 100644 Tools/ckor/rfc2or.c create mode 100644 Tools/dbmbuild/Makefile create mode 100644 Tools/dbmbuild/dbmbuild.c create mode 100755 Tools/dbmbuild/make create mode 100644 Tools/dbmedit/Makefile create mode 100644 Tools/dbmedit/dbmedit.c create mode 100755 Tools/dbmedit/make create mode 100644 Tools/dbmunbuild/Makefile create mode 100644 Tools/dbmunbuild/dbmunbuild.c create mode 100755 Tools/dbmunbuild/make create mode 100644 Tools/ean2real/Makefile create mode 100644 Tools/ean2real/ean2real.c create mode 100755 Tools/ean2real/make create mode 100644 Tools/hex2bin/Makefile create mode 100644 Tools/hex2bin/hex2bin.c create mode 100755 Tools/hex2bin/make create mode 100755 Tools/make create mode 100644 Tools/make-lists/Makefile create mode 100644 Tools/make-lists/README create mode 100755 Tools/make-lists/make create mode 100644 Tools/make-lists/make-lists.8 create mode 100644 Tools/make-lists/make-lists.c create mode 100644 Tools/misc/Makefile create mode 100644 Tools/misc/README create mode 100755 Tools/misc/make create mode 100644 Tools/misc/t-chkpe.c create mode 100644 Tools/misc/t-conf.c create mode 100644 Tools/misc/t-norm.c create mode 100644 Tools/misc/t-pefrag.c create mode 100644 Tools/misc/t-prf.c create mode 100644 Tools/misc/t-rdmsg.c create mode 100644 Tools/misc/t-rtime.c create mode 100644 Tools/misc/t-single.c create mode 100644 Tools/misc/t-time.c create mode 100644 Tools/misc/t-txt2dr.c create mode 100644 Tools/mkpasswd/Makefile create mode 100755 Tools/mkpasswd/make create mode 100644 Tools/mkpasswd/mkpasswd.c create mode 100644 Tools/mlist/Makefile create mode 100755 Tools/mlist/make create mode 100644 Tools/mlist/mlist.c create mode 100644 Tools/mpp84/Makefile create mode 100644 Tools/mpp84/P1.py create mode 100644 Tools/mpp84/P2.py create mode 100644 Tools/mpp84/P3.py create mode 100644 Tools/mpp84/SFD.py create mode 100644 Tools/mpp84/T73.py create mode 100644 Tools/mpp84/UNIV.py create mode 100755 Tools/mpp84/make create mode 100644 Tools/mpp84/mpp84.py create mode 100644 Tools/mpp88/Makefile create mode 100755 Tools/mpp88/make create mode 100644 Tools/mpp88/mpp88.py create mode 100644 Tools/mu/Makefile create mode 100644 Tools/mu/README create mode 100644 Tools/mu/argh.c create mode 100755 Tools/mu/make create mode 100644 Tools/mu/mu.c create mode 100644 Tools/mu/mu.defaults create mode 100644 Tools/nsapexpand/Makefile create mode 100755 Tools/nsapexpand/make create mode 100644 Tools/nsapexpand/nsapexpand.c create mode 100644 Tools/ntail/Makefile create mode 100644 Tools/ntail/README create mode 100644 Tools/ntail/entryfuncs.c create mode 100755 Tools/ntail/make create mode 100644 Tools/ntail/miscfuncs.c create mode 100644 Tools/ntail/ntail.c create mode 100644 Tools/ntail/ntail.h create mode 100644 Tools/ppbm/Makefile create mode 100755 Tools/ppbm/make create mode 100755 Tools/ppbm/pp-bench.awk create mode 100644 Tools/ppbm/pp-benchmarks.tbl create mode 100644 Tools/ppbm/ppbm.8 create mode 100644 Tools/ppbm/ppbm.c create mode 100644 Tools/ppls/Makefile create mode 100755 Tools/ppls/make create mode 100644 Tools/ppls/ppls.c create mode 100644 Tools/probe/Makefile create mode 100755 Tools/probe/make create mode 100644 Tools/probe/p_stdin.c create mode 100644 Tools/probe/p_ut.c create mode 100644 Tools/probe/probe.c create mode 100644 Tools/splat/Makefile create mode 100755 Tools/splat/make create mode 100644 Tools/splat/ps2pe.c create mode 100644 Tools/splat/splat.c create mode 100644 Tools/statgen/Makefile create mode 100644 Tools/statgen/README create mode 100755 Tools/statgen/line.nawk create mode 100755 Tools/statgen/make create mode 100755 Tools/statgen/rare.nawk create mode 100755 Tools/statgen/slowhosts.awk create mode 100644 Tools/statgen/statp.c create mode 100644 Tools/tables/Makefile create mode 100644 Tools/tables/abbrev/Makefile create mode 100644 Tools/tables/abbrev/abbrev.c create mode 100755 Tools/tables/abbrev/make create mode 100644 Tools/tables/compat/Makefile create mode 100755 Tools/tables/compat/ali_o2n create mode 100755 Tools/tables/compat/dom_o2n create mode 100755 Tools/tables/compat/make create mode 100755 Tools/tables/compat/que_o2n create mode 100644 Tools/tables/domain/Makefile create mode 100755 Tools/tables/domain/make create mode 100644 Tools/tables/domain/t-getdomain.c create mode 100755 Tools/tables/make create mode 100644 Tools/tables/pp-rfc987/Makefile create mode 100755 Tools/tables/pp-rfc987/awk.or2rfc create mode 100755 Tools/tables/pp-rfc987/awk.rfc2or create mode 100755 Tools/tables/pp-rfc987/make create mode 100644 Tools/tables/rfc987-pp/Makefile create mode 100755 Tools/tables/rfc987-pp/awk.rfc987.pac create mode 100755 Tools/tables/rfc987-pp/make create mode 100644 Tools/tables/tjoin/Makefile create mode 100644 Tools/tables/tjoin/lex.l create mode 100755 Tools/tables/tjoin/make create mode 100644 Tools/tables/tjoin/tjoin.y create mode 100644 Tools/tables/tjoin/tjoin1.c create mode 100644 Tools/tables/tjoin/tjoin2.c create mode 100644 Tools/tables/tjoin/tjoin3.c create mode 100644 Uip/Makefile create mode 100644 Uip/mail/Makefile create mode 100644 Uip/mail/mail.c create mode 100755 Uip/mail/make create mode 100755 Uip/make create mode 100644 Uip/misc/Makefile create mode 100644 Uip/misc/X400_addr.c create mode 100644 Uip/misc/flock.c create mode 100755 Uip/misc/make create mode 100644 Uip/misc/strip_addr.c create mode 100644 Uip/rcvalert/Makefile create mode 100644 Uip/rcvalert/README create mode 100644 Uip/rcvalert/XAlert.ad create mode 100644 Uip/rcvalert/data.h create mode 100644 Uip/rcvalert/dirsbr.c create mode 100644 Uip/rcvalert/flagmail.c create mode 100644 Uip/rcvalert/image.h create mode 100755 Uip/rcvalert/make create mode 100644 Uip/rcvalert/parsesbr.c create mode 100755 Uip/rcvalert/rttyalert create mode 100644 Uip/rcvalert/ttyalert.c create mode 100644 Uip/rcvalert/ttybiff.c create mode 100644 Uip/rcvalert/ttysbr.c create mode 100644 Uip/rcvalert/udpsbr.c create mode 100644 Uip/rcvalert/xalert.c create mode 100644 Uip/rcvtrip/Makefile create mode 100755 Uip/rcvtrip/make create mode 100644 Uip/rcvtrip/rcvtrip.c create mode 100644 Uip/resend/Makefile create mode 100755 Uip/resend/make create mode 100644 Uip/resend/resend.c create mode 100644 Uip/sendmail/Makefile create mode 100755 Uip/sendmail/make create mode 100644 Uip/sendmail/sendmail.c create mode 100644 config/OPTIONS.h create mode 100644 config/OPTIONS.make create mode 100644 config/README create mode 100644 config/drs6000.h create mode 100644 config/drs6000.make create mode 100644 config/hpux.h create mode 100644 config/hpux.make create mode 100755 config/pp.start create mode 100755 config/pp.startaspp create mode 100644 config/s5r4.h create mode 100644 config/s5r4.make create mode 100644 config/sun.h create mode 100644 config/sun.make create mode 100644 config/vax.h create mode 100644 config/vax.make create mode 100644 doc/Makefile create mode 100644 doc/README create mode 100644 doc/funet91/Makefile create mode 100644 doc/funet91/bcustom.bib create mode 100644 doc/funet91/bof-slides.tex create mode 100644 doc/funet91/captcont.sty create mode 100644 doc/funet91/figure1.pic create mode 100644 doc/funet91/figure1.tex create mode 100644 doc/funet91/figure2.pic create mode 100644 doc/funet91/figure2.tex create mode 100644 doc/funet91/jpo.bib create mode 100644 doc/funet91/lcustom.tex create mode 100755 doc/funet91/make create mode 100644 doc/funet91/networking.bib create mode 100644 doc/funet91/pp-slides.aux create mode 100644 doc/funet91/pp-slides.tex create mode 100644 doc/funet91/pp.aux create mode 100644 doc/funet91/pp.bbl create mode 100644 doc/funet91/pp.major create mode 100644 doc/funet91/pp.minor create mode 100644 doc/funet91/pp.tex create mode 100644 doc/funet91/pp.vrsn create mode 100644 doc/funet91/queuefig.fig create mode 100644 doc/funet91/sfwdoc.bib create mode 100644 doc/funet91/software.bib create mode 100644 doc/funet91/trademark.tex create mode 100755 doc/funet91/version.sh create mode 100644 doc/ifip6.5-88/Makefile create mode 100755 doc/ifip6.5-88/make create mode 100644 doc/ifip6.5-88/paper.psc create mode 100644 doc/ifip6.5-88/slides/Makefile create mode 100644 doc/ifip6.5-88/slides/dir.fig create mode 100644 doc/ifip6.5-88/slides/dir.pic create mode 100644 doc/ifip6.5-88/slides/dir.tex create mode 100644 doc/ifip6.5-88/slides/ifip88-pp.tex create mode 100644 doc/ifip6.5-88/slides/structure.fig create mode 100644 doc/ifip6.5-88/slides/structure.pic create mode 100644 doc/ifip6.5-88/slides/structure.tex create mode 100755 doc/make create mode 100644 doc/manual/Make.defs create mode 100644 doc/manual/Makefile create mode 100644 doc/manual/README create mode 100644 doc/manual/book-changes.ms create mode 100755 doc/manual/make create mode 100644 doc/manual/ps/README create mode 100644 doc/manual/texinputs/a4.sty create mode 100644 doc/manual/texinputs/bcustom.bib create mode 100644 doc/manual/texinputs/captcont.sty create mode 100644 doc/manual/texinputs/dist-params.tex create mode 100644 doc/manual/texinputs/grindefs create mode 100644 doc/manual/texinputs/grindefs.sty create mode 100644 doc/manual/texinputs/lcustom.tex create mode 100644 doc/manual/texinputs/networking.bib create mode 100644 doc/manual/texinputs/pp.bib create mode 100644 doc/manual/texinputs/sfwdoc.bib create mode 100644 doc/manual/texinputs/sfwmac.sty create mode 100644 doc/manual/texinputs/tgrind.sty create mode 100644 doc/manual/texinputs/trademark.tex create mode 100644 doc/manual/volume0/COVER-LETTER.aux create mode 100644 doc/manual/volume0/COVER-LETTER.tex create mode 100644 doc/manual/volume0/COVER-TXT create mode 100644 doc/manual/volume0/COVER-TXT.aux create mode 100644 doc/manual/volume0/COVER-TXT.tex create mode 100644 doc/manual/volume0/Makefile create mode 100644 doc/manual/volume0/announce.tex create mode 100644 doc/manual/volume0/contents.tex create mode 100644 doc/manual/volume0/distrib.tex create mode 100644 doc/manual/volume0/highlights.tex create mode 100755 doc/manual/volume0/make create mode 100644 doc/manual/volume0/real.aux create mode 100644 doc/manual/volume0/real.tex create mode 100755 doc/manual/volume0/version.sh create mode 100644 doc/manual/volume0/volume0.aux create mode 100644 doc/manual/volume0/volume0.bbl create mode 100644 doc/manual/volume0/volume0.major create mode 100644 doc/manual/volume0/volume0.minor create mode 100644 doc/manual/volume0/volume0.tex create mode 100644 doc/manual/volume0/volume0.toc create mode 100644 doc/manual/volume0/volume0.vrsn create mode 100644 doc/manual/volume1/Makefile create mode 100644 doc/manual/volume1/addon.aux create mode 100644 doc/manual/volume1/addon.tex create mode 100644 doc/manual/volume1/alias.tex create mode 100644 doc/manual/volume1/appendix.aux create mode 100644 doc/manual/volume1/appendix.tex create mode 100644 doc/manual/volume1/argh.tex create mode 100644 doc/manual/volume1/asnfilter.tai create mode 100644 doc/manual/volume1/asnfilter.tex create mode 100644 doc/manual/volume1/auth.tex create mode 100644 doc/manual/volume1/chan-examp.tai create mode 100644 doc/manual/volume1/chan-examp.tex create mode 100644 doc/manual/volume1/chantbl.tex create mode 100644 doc/manual/volume1/chanx400examp.tex create mode 100644 doc/manual/volume1/chx400out.tex create mode 100644 doc/manual/volume1/configure.aux create mode 100644 doc/manual/volume1/configure.tex create mode 100644 doc/manual/volume1/console_tai.tex create mode 100644 doc/manual/volume1/domain.tex create mode 100644 doc/manual/volume1/dreport.tex create mode 100644 doc/manual/volume1/exampleortbl.tex create mode 100644 doc/manual/volume1/exampleortbl2.tex create mode 100644 doc/manual/volume1/faxTable.tai create mode 100644 doc/manual/volume1/faxTable.tex create mode 100644 doc/manual/volume1/faxtai.tai create mode 100644 doc/manual/volume1/faxtai.tex create mode 100644 doc/manual/volume1/filt-examp.tai create mode 100644 doc/manual/volume1/filt-examp.tex create mode 100644 doc/manual/volume1/general.aux create mode 100644 doc/manual/volume1/general.tex create mode 100755 doc/manual/volume1/idx2ind create mode 100644 doc/manual/volume1/install.aux create mode 100644 doc/manual/volume1/install.tex create mode 100644 doc/manual/volume1/lists-examp.tex create mode 100644 doc/manual/volume1/log-examp.tai create mode 100644 doc/manual/volume1/log-examp.tex create mode 100644 doc/manual/volume1/logx400-examp.tex create mode 100755 doc/manual/volume1/make create mode 100644 doc/manual/volume1/management.aux create mode 100644 doc/manual/volume1/management.tex create mode 100644 doc/manual/volume1/mu.aux create mode 100644 doc/manual/volume1/mu.tex create mode 100644 doc/manual/volume1/musub.c create mode 100644 doc/manual/volume1/musub.tex create mode 100644 doc/manual/volume1/or.tex create mode 100644 doc/manual/volume1/or2rfc.tex create mode 100644 doc/manual/volume1/pac.dvi create mode 100644 doc/manual/volume1/pp_nightly.sh create mode 100644 doc/manual/volume1/pp_nightly.tex create mode 100644 doc/manual/volume1/pp_start.csh create mode 100644 doc/manual/volume1/pp_start.sh create mode 100644 doc/manual/volume1/pp_start.tex create mode 100644 doc/manual/volume1/pptables.aux create mode 100644 doc/manual/volume1/pptables.tex create mode 100644 doc/manual/volume1/preface.aux create mode 100644 doc/manual/volume1/preface.tex create mode 100644 doc/manual/volume1/program.tex create mode 100644 doc/manual/volume1/qfile.tex create mode 100644 doc/manual/volume1/qmgrproto.aux create mode 100644 doc/manual/volume1/qmgrproto.tex create mode 100644 doc/manual/volume1/qmgrros.ry create mode 100644 doc/manual/volume1/qmgrros.tex create mode 100644 doc/manual/volume1/rfc1148g.tex create mode 100644 doc/manual/volume1/rfc2or.tex create mode 100644 doc/manual/volume1/shelfilt.sh create mode 100644 doc/manual/volume1/shelfilt.tex create mode 100644 doc/manual/volume1/shell-examp.tex create mode 100644 doc/manual/volume1/shellfilt.sh create mode 100644 doc/manual/volume1/table-examp.tai create mode 100644 doc/manual/volume1/table-examp.tex create mode 100644 doc/manual/volume1/tableauthreasons.tex create mode 100644 doc/manual/volume1/tableconsole_accels.tex create mode 100644 doc/manual/volume1/tableconsole_mapping.tex create mode 100644 doc/manual/volume1/tableinfo_expan.tex create mode 100644 doc/manual/volume1/tablemakedefs1.tex create mode 100644 doc/manual/volume1/tablemakedefs2.tex create mode 100644 doc/manual/volume1/tablemuflags.tex create mode 100644 doc/manual/volume1/tables.aux create mode 100644 doc/manual/volume1/tables.tex create mode 100644 doc/manual/volume1/tables.tex.aux create mode 100644 doc/manual/volume1/tableshellexp.tex create mode 100644 doc/manual/volume1/tablewarn.tex create mode 100644 doc/manual/volume1/tablewarnexp.tex create mode 100644 doc/manual/volume1/tablex400info1.tex create mode 100644 doc/manual/volume1/tablex400info2.tex create mode 100644 doc/manual/volume1/tailor.tai create mode 100644 doc/manual/volume1/tailor.tex create mode 100644 doc/manual/volume1/users.tex create mode 100755 doc/manual/volume1/version.sh create mode 100644 doc/manual/volume1/volume1.aux create mode 100644 doc/manual/volume1/volume1.bbl create mode 100644 doc/manual/volume1/volume1.idx create mode 100644 doc/manual/volume1/volume1.ind create mode 100644 doc/manual/volume1/volume1.lof create mode 100644 doc/manual/volume1/volume1.lot create mode 100644 doc/manual/volume1/volume1.major create mode 100644 doc/manual/volume1/volume1.minor create mode 100644 doc/manual/volume1/volume1.tex create mode 100644 doc/manual/volume1/volume1.toc create mode 100644 doc/manual/volume1/volume1.vrsn create mode 100644 doc/manual/volume1/x400in-examp.tex create mode 100644 doc/manual/volume1/x400in-examp2.tex create mode 100644 doc/manual/volume1/x400links.aux create mode 100644 doc/manual/volume1/x400links.tex create mode 100644 doc/manual/volume1/x400out-examp.tex create mode 100644 doc/manual/volume1/x400tables.aux create mode 100644 doc/manual/volume1/x400tables.tex create mode 100644 doc/manual/volume2/Makefile create mode 100644 doc/manual/volume2/adrstruct.h create mode 100644 doc/manual/volume2/adrstruct.tex create mode 100644 doc/manual/volume2/channels.aux create mode 100644 doc/manual/volume2/channels.tex create mode 100644 doc/manual/volume2/delivery.aux create mode 100644 doc/manual/volume2/delivery.tex create mode 100644 doc/manual/volume2/delv-rep.c create mode 100644 doc/manual/volume2/delv-rep.tex create mode 100644 doc/manual/volume2/eit.h create mode 100644 doc/manual/volume2/eit.tex create mode 100644 doc/manual/volume2/general.aux create mode 100644 doc/manual/volume2/general.tex create mode 100755 doc/manual/volume2/idx2ind create mode 100644 doc/manual/volume2/io.c create mode 100644 doc/manual/volume2/io.tex create mode 100755 doc/manual/volume2/make create mode 100644 doc/manual/volume2/outbound.c create mode 100644 doc/manual/volume2/outbound.tex create mode 100644 doc/manual/volume2/preface.aux create mode 100644 doc/manual/volume2/preface.tex create mode 100644 doc/manual/volume2/prmstruct.h create mode 100644 doc/manual/volume2/prmstruct.tex create mode 100644 doc/manual/volume2/qmgrif.h create mode 100644 doc/manual/volume2/qmgrif.tex create mode 100644 doc/manual/volume2/qstruct.h create mode 100644 doc/manual/volume2/qstruct.tex create mode 100644 doc/manual/volume2/rchan.h create mode 100644 doc/manual/volume2/rchan.tex create mode 100644 doc/manual/volume2/rpbstruct.h create mode 100644 doc/manual/volume2/rpbstruct.tex create mode 100644 doc/manual/volume2/submission.aux create mode 100644 doc/manual/volume2/submission.tex create mode 100644 doc/manual/volume2/tablecrit.tex create mode 100644 doc/manual/volume2/tablediag.tex create mode 100644 doc/manual/volume2/tableexplicit.tex create mode 100644 doc/manual/volume2/tablelog.tex create mode 100644 doc/manual/volume2/tablemuflags.tex create mode 100644 doc/manual/volume2/tablereason.tex create mode 100644 doc/manual/volume2/tablerpcodes.tex create mode 100755 doc/manual/volume2/version.sh create mode 100644 doc/manual/volume2/volume2.aux create mode 100644 doc/manual/volume2/volume2.idx create mode 100644 doc/manual/volume2/volume2.ind create mode 100644 doc/manual/volume2/volume2.lof create mode 100644 doc/manual/volume2/volume2.lot create mode 100644 doc/manual/volume2/volume2.major create mode 100644 doc/manual/volume2/volume2.minor create mode 100644 doc/manual/volume2/volume2.tex create mode 100644 doc/manual/volume2/volume2.toc create mode 100644 doc/manual/volume2/volume2.vrsn create mode 100644 doc/manual/volume2/xx.dvi create mode 100644 doc/manual/volume3/Makefile create mode 100755 doc/manual/volume3/idx2ind create mode 100644 doc/manual/volume3/intro.aux create mode 100644 doc/manual/volume3/intro.tex create mode 100644 doc/manual/volume3/lists.aux create mode 100644 doc/manual/volume3/lists.tex create mode 100644 doc/manual/volume3/local-bnf.bnf create mode 100644 doc/manual/volume3/local-bnf.tex create mode 100644 doc/manual/volume3/local-examp.tex create mode 100644 doc/manual/volume3/local.aux create mode 100644 doc/manual/volume3/local.tex create mode 100755 doc/manual/volume3/make create mode 100644 doc/manual/volume3/utility.aux create mode 100644 doc/manual/volume3/utility.tex create mode 100755 doc/manual/volume3/version.sh create mode 100644 doc/manual/volume3/volume3.aux create mode 100644 doc/manual/volume3/volume3.idx create mode 100644 doc/manual/volume3/volume3.ind create mode 100644 doc/manual/volume3/volume3.lof create mode 100644 doc/manual/volume3/volume3.lot create mode 100644 doc/manual/volume3/volume3.major create mode 100644 doc/manual/volume3/volume3.minor create mode 100644 doc/manual/volume3/volume3.tex create mode 100644 doc/manual/volume3/volume3.toc create mode 100644 doc/manual/volume3/volume3.vrsn create mode 100644 doc/nordunet/Makefile create mode 100644 doc/nordunet/captcont.sty create mode 100644 doc/nordunet/console.wd.Z create mode 100644 doc/nordunet/figure1.pic create mode 100644 doc/nordunet/figure1.tex create mode 100644 doc/nordunet/figure2.pic create mode 100644 doc/nordunet/figure2.tex create mode 100644 doc/nordunet/lcustom.tex create mode 100755 doc/nordunet/make create mode 100644 doc/nordunet/pp-slides.aux create mode 100644 doc/nordunet/pp-slides.tex create mode 100644 doc/nordunet/pp.aux create mode 100644 doc/nordunet/pp.bbl create mode 100644 doc/nordunet/pp.major create mode 100644 doc/nordunet/pp.minor create mode 100644 doc/nordunet/pp.tex create mode 100644 doc/nordunet/pp.vrsn create mode 100644 doc/nordunet/trademark.tex create mode 100755 doc/nordunet/version.sh create mode 100644 doc/sun-89/Makefile create mode 100644 doc/sun-89/captcont.sty create mode 100644 doc/sun-89/console.wd create mode 100644 doc/sun-89/figure1.pic create mode 100644 doc/sun-89/figure1.tex create mode 100644 doc/sun-89/figure2.pic create mode 100644 doc/sun-89/figure2.tex create mode 100644 doc/sun-89/lcustom.tex create mode 100755 doc/sun-89/make create mode 100644 doc/sun-89/pp-slides.aux create mode 100644 doc/sun-89/pp-slides.tex create mode 100644 doc/sun-89/pp.aux create mode 100644 doc/sun-89/pp.bbl create mode 100644 doc/sun-89/pp.major create mode 100644 doc/sun-89/pp.minor create mode 100644 doc/sun-89/pp.tex create mode 100644 doc/sun-89/pp.vrsn create mode 100644 doc/sun-89/trademark.tex create mode 100755 doc/sun-89/version.sh create mode 100644 doc/tailor/Makefile create mode 100755 doc/tailor/make create mode 100644 doc/tailor/tailor.tex create mode 100755 doc/tailor/version.sh create mode 100644 doc/uknet90/Makefile create mode 100644 doc/uknet90/bcustom.bib create mode 100644 doc/uknet90/captcont.sty create mode 100644 doc/uknet90/figure1.pic create mode 100644 doc/uknet90/figure1.tex create mode 100644 doc/uknet90/figure2.pic create mode 100644 doc/uknet90/figure2.tex create mode 100644 doc/uknet90/jpo.bib create mode 100644 doc/uknet90/lcustom.tex create mode 100755 doc/uknet90/make create mode 100644 doc/uknet90/networking.bib create mode 100644 doc/uknet90/pp-slides.aux create mode 100644 doc/uknet90/pp-slides.tex create mode 100644 doc/uknet90/pp.aux create mode 100644 doc/uknet90/pp.bbl create mode 100644 doc/uknet90/pp.major create mode 100644 doc/uknet90/pp.minor create mode 100644 doc/uknet90/pp.tex create mode 100644 doc/uknet90/pp.vrsn create mode 100644 doc/uknet90/queuefig.fig create mode 100644 doc/uknet90/sfwdoc.bib create mode 100644 doc/uknet90/software.bib create mode 100644 doc/uknet90/trademark.tex create mode 100755 doc/uknet90/version.sh create mode 100644 doc/unix-niftp/Makefile create mode 100755 doc/unix-niftp/make create mode 100644 doc/unix-niftp/unix-niftp-pp.ms create mode 100644 examples/INTERNET/Makefile create mode 100755 examples/INTERNET/make create mode 100644 examples/JANET/Makefile create mode 100755 examples/JANET/make create mode 100644 examples/LOCALSMTP/Makefile create mode 100755 examples/LOCALSMTP/make create mode 100644 examples/Makefile create mode 100644 examples/README create mode 100755 examples/make create mode 100644 examples/master/Makefile create mode 100644 examples/master/README create mode 100644 examples/master/README-master create mode 100644 examples/master/aliases create mode 100644 examples/master/auth.channel create mode 100644 examples/master/auth.mta create mode 100644 examples/master/auth.qmgr create mode 100644 examples/master/auth.user create mode 100644 examples/master/ch.list create mode 100644 examples/master/ch.local create mode 100644 examples/master/ch.shell create mode 100644 examples/master/ch.uucp create mode 100644 examples/master/ch.x400in84 create mode 100644 examples/master/ch.x400in88 create mode 100644 examples/master/ch.x400out84 create mode 100644 examples/master/ch.x400out88 create mode 100644 examples/master/channel-I create mode 100644 examples/master/channel-J create mode 100644 examples/master/channel-L create mode 100644 examples/master/domain-I create mode 100644 examples/master/domain-J create mode 100644 examples/master/domain-L create mode 100644 examples/master/foo create mode 100644 examples/master/isoentities.add create mode 100755 examples/master/make create mode 100644 examples/master/or create mode 100644 examples/master/or2rfc create mode 100644 examples/master/rfc1148gate create mode 100644 examples/master/rfc2or create mode 100644 examples/master/tailor-I.head create mode 100644 examples/master/tailor-J.head create mode 100644 examples/master/tailor-L.head create mode 100644 examples/master/tailor.common create mode 100644 examples/master/users create mode 100644 examples/master/warning.1 create mode 100644 examples/master/warning.2 create mode 100644 examples/master/x500.sample create mode 100644 examples/xtel/Make.defs create mode 100644 examples/xtel/Makefile create mode 100644 examples/xtel/aliases create mode 100644 examples/xtel/auth.channel create mode 100644 examples/xtel/auth.mta create mode 100644 examples/xtel/auth.qmgr create mode 100644 examples/xtel/auth.user create mode 100644 examples/xtel/ch.fax create mode 100644 examples/xtel/ch.list create mode 100644 examples/xtel/ch.local create mode 100644 examples/xtel/ch.mslocal create mode 100644 examples/xtel/ch.shell create mode 100644 examples/xtel/ch.uucp create mode 100644 examples/xtel/ch.x400in84 create mode 100644 examples/xtel/ch.x400in88 create mode 100644 examples/xtel/ch.x400out84 create mode 100644 examples/xtel/ch.x400out88 create mode 100644 examples/xtel/channel create mode 100644 examples/xtel/config.h create mode 100644 examples/xtel/domain create mode 100755 examples/xtel/make create mode 100644 examples/xtel/or create mode 100644 examples/xtel/or2rfc create mode 100644 examples/xtel/rfc1148gate create mode 100644 examples/xtel/rfc2or create mode 100644 examples/xtel/tailor create mode 100644 examples/xtel/users create mode 100644 examples/xtel/warning.1 create mode 100644 examples/xtel/warning.2 create mode 100644 h/adr.h create mode 100644 h/alias.h create mode 100644 h/ap.h create mode 100644 h/ap_lex.h create mode 100644 h/aparse.h create mode 100644 h/argh.h create mode 100644 h/auth.h create mode 100644 h/ch_bind.h create mode 100644 h/chan.h create mode 100644 h/charset.h create mode 100644 h/dbase.h create mode 100644 h/dl.h create mode 100644 h/dlist.h create mode 100644 h/dr.h create mode 100644 h/expand.h create mode 100644 h/extension.h create mode 100644 h/head.h create mode 100644 h/list_bpt.h create mode 100644 h/list_rchan.h create mode 100644 h/ll_log.h create mode 100644 h/loc_user.h create mode 100644 h/mta.h create mode 100644 h/or.h create mode 100644 h/ppp.h create mode 100644 h/prm.h create mode 100644 h/q.h create mode 100644 h/qmgr-int.h create mode 100644 h/qmgr.h create mode 100644 h/retcode.h create mode 100644 h/rtsparams.h create mode 100644 h/sys.file.h create mode 100644 h/table.h create mode 100644 h/tb_a.h create mode 100644 h/tb_auth.h create mode 100644 h/tb_bpt84.h create mode 100644 h/tb_bpt88.h create mode 100644 h/tb_com.h create mode 100644 h/tb_dr.h create mode 100644 h/tb_p1.h create mode 100644 h/tb_p3prm.h create mode 100644 h/tb_prm.h create mode 100644 h/tb_q.h create mode 100644 h/tjoin.h create mode 100644 h/util.h create mode 100644 h/x400_ub.h create mode 100755 make create mode 100644 man/Makefile create mode 100755 man/inst-man.sh create mode 100755 man/make create mode 100644 man/man1/Makefile create mode 100644 man/man1/ckmail.1 create mode 100644 man/man1/ckmf.1 create mode 100644 man/man1/dl.1 create mode 100644 man/man1/flagmail.1 create mode 100644 man/man1/flock.1 create mode 100644 man/man1/mail.1 create mode 100755 man/man1/make create mode 100644 man/man1/malias.1 create mode 100644 man/man1/mlist.1 create mode 100644 man/man1/mu.1 create mode 100644 man/man1/ntail.1 create mode 100644 man/man1/rcvtrip.1 create mode 100644 man/man1/resend.1 create mode 100644 man/man1/strip_addr.1 create mode 100644 man/man1/ttyalert.1 create mode 100644 man/man1/ttybiff.1 create mode 100644 man/man1/xalert.1 create mode 100644 man/man3/Makefile create mode 100755 man/man3/make create mode 100644 man/man3/or.3 create mode 100644 man/man8/MTAconsole.8 create mode 100644 man/man8/Makefile create mode 100644 man/man8/abbrev.8 create mode 100644 man/man8/ckadr.8 create mode 100644 man/man8/ckchan.8 create mode 100644 man/man8/ckconfig.8 create mode 100644 man/man8/dbmbuild.8 create mode 100644 man/man8/dbmedit.8 create mode 100644 man/man8/dbmunbuild.8 create mode 100644 man/man8/lconsole.8 create mode 100755 man/man8/make create mode 100644 man/man8/mpp84.8 create mode 100644 man/man8/mpp88.8 create mode 100644 man/man8/pp-gen.8 create mode 100644 man/man8/pptsapd.8 create mode 100644 man/man8/probe.8 create mode 100644 man/man8/qmgr.8 create mode 100644 man/man8/rmail.8 create mode 100644 man/man8/sendmail.8 create mode 100644 man/man8/smtpd.8 create mode 100644 man/man8/smtpsrvr.8 create mode 100644 man/man8/tjoin.8 create mode 100644 pp-changes.ms create mode 100644 template/README create mode 100755 template/template.bug-report create mode 100644 template/template.c create mode 100644 template/template.chan create mode 100644 template/template.h create mode 100644 template/template.man create mode 100644 template/template.mk create mode 100644 template/template.py create mode 100644 template/template.sh diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..17a627b --- /dev/null +++ b/CHANGES @@ -0,0 +1,462 @@ + + + + + + + + + + Changes from PP version 5.2 to 6.0 + + + + + +_1. _O_v_e_r_v_i_e_w + +This short document is a description of the more +user/administrator visible changes that have taken place in +PP between the last interim version (5.2) and the beta ver- +sion (6.0). This document is not exhaustive or complete but +is a guide to what to look out for. In general the following +may be assumed. + +o+ The Queue files are compatible between 5.2 and 6.0. + Note however that the Queue structure has changed. Old + channels will have to be recompiled to recognise the + new format, but new channels will read old queue files. + +o+ The qmgr protocol is compatible between 5.2 and 6.0 + +o+ The syntax of some of the table files has changed. + Where appropriate conversion scripts are provided. + +o+ Some procedure calls have been changed or have dif- + ferent parameters. + +o+ the libdsap.a library is now required for compilation. + +In summary, you should be careful when upgrading to the 6.0 +release. It will not work by just replacing the 5.2 +binaries with 6.0. For definite the domain table will HAVE +to be changed. + +_2. _D_e_t_a_i_l_e_d _c_h_a_n_g_e_s + +This list is in no particular order of preference or impor- +tance. + +Domain Table + The domain table syntax has been changed to be more + explicit and has been brought into line with the OR + table syntax. We feel this is clearer and more logical. + Tools that process the domain table have been taught + the new format and there are scripts in + Tools/tables/compat to convert between the old and new + formats. There is NO backwards compatibility here. Old + format tables will just plain not work. + +Aliases Table + + + + December 18, 1991 + + + + + + - 2 - + + + The aliases table syntax has changed to a main choice + of synonym or alias with further qualifiers specifying + the address type of the synonym or alias. The changes + are + + x:alias y x:alias y + x:synonym y x:synonym y + x:822-synonym y x:synonym y 822 + x:x400-synonym y x:synonym y x400 + x:822 y x:alias y 822 + x:x400 y x:alias y x400 + where any white space in y must be quoted using a + backslash There is also a "external" qualifier. This + disables further lookups of synonyms and aliases and + can be used for a main site mail hub mapping from + site_wide_name@localsite to + local_machine_name@localmachine and vice versa. The + use of external stops the looping alias problem which + would otherwise occur. + +Return of Contents + Return of contents is now supported. This is a side + effect and part of the work on routing of delivery + reports. + +Use of pepsy + Use of the PEPSY ASN.1 compiler rather than PEPY/POSY + is now used in many places. This makes for smaller + binaries and much quicker compilation. + +ISODE 7.0 + PP 6.0 is aligned to ISODE 7.0. It will not work under + ISODE 6.0. If you are using the 6.0 release you should + be using ISODE 7.0. It should however work under ISODE + 6.8. + +Tailor file + There have been many changes to the tailor file. The + introduction of several new variables and the splitting + up of header and body part types. These are + + dap_user Directory username for DS lookups + dap_passwd Directory Passwd for same + fsync disable use of fsync(2) + headertype list of headers c.f. bodypart + queuestruct use hierarchical queue structure + submit_addr call submit over network + diskuse limit the disk space consumed by PP + + Channel tailoring also has a number of new variables + + drchan replaces old outchan + hdrin headers inbound + hdrout headers outbound + + + + December 18, 1991 + + + + + + - 3 - + + + ininfo inbound channel info + inadr inbound channel addr type + insubadr inbound channel sub address type + intable inbound channel table + key give alternative names to channel + mtatable list of known mtas for channel binding + outinfo outbound channel info + outsubadr outbound channel sub address + outtable outbound channel table + solo-proc channel requires address one at a time + bad-sender-policyset the policy for unroutable senders + check set the checking mode of the channel + +Channel pairing + Channels may now be explicitly paired together. This + allows one definition to specify both an inbound and an + outbound channel. It also allows several logical chan- + nels for one inbound protocol by selecting a channel + per MTA. + +Timezones + Many more lettered timezones are recognised. This list + is ambiguous at best and numeric forms should really be + used except at user interfaces. + +Delivery Reports + Delivery reports are now routed back to their origina- + tor. In 5.2 they were returned directly down the chan- + nel they arrived on. This allows for one way links in + general makes things easier. It also allows protocol + conversion so that, for instance, a delivery report on + an X.400 message may go back via an RFC-822 if that is + the only option. A side effect of this is the channel + variable outchan has been renamed drchan and has dif- + ferent semantics attached to it (see the manual). + +Header parts + Separation of headers and bodyparts for each channel. + This is mainly a syntactic change but will allow more + flexibility later. The upshot is you may need both + bptin/bptout and hdrin/hdrout types in channel defini- + tions. + +Local delivery + The local channel table (ch.local) has had a change of + syntax. The old format should still work, but the new + format (which is key=value) based allows much more + flexibility and setting of options for mail managers. + +MTA Console + The MTA Console has been changed to show more statis- + tics and has a new heuristics for showing just channel + and MTA summary information. This is useful for very + large queues. + + + + December 18, 1991 + + + + + + - 4 - + + +Line Console + Two line based console programs have been provided. + These give some of the functionality of the MTA console + for dumb terminals. + +Directory lists + The directory list program has been improved more. It + now has several associated tools to convert file based + lists into directory based lists. There is also a + checkup tool. + +Performance + Some work has been done on general performance. In gen- + eral the system should run slightly faster and have + less problems with large queues. + +X.400(88) OIDs + One of the X.400(1988) object identifiers was + incorrect. Originally the code used the object identif- + ier designated in the Blue Book. It now uses the one + given in the implementors guide. + +Mail 11 + Our thanks must go to Nigel Titley of British Telecom + for the donation of a Decnet Mail-11 channel. This + allows interworking with DECNET and PP. + +G3Fax channel + A skeleton outbound G3 Fax channel is included. There + are currently two drivers written using this skeleton, + one for the Fujitsu dexNet200 modem and one for the + Panasonic SystemFax 250 machine. These channels enable + PP to send appropriately encoded messages via fax. + There are a couple of reformatter filters which convert + an hdr.822 to a fax coverpage and an ia5 bodypart to a + g3fax bodypart. These reformatters produce X.400 g3fax + bodyparts and so are general use and are not dependent + on any fax machine. + +Splitter Channel + A Splitter channel is included. This channel together + with the presence of solo-proc=yes in channel entries + in the tailor file enables exclusive processing for + specified recipients. This was introduced for the fax + reformatter channels. + +Address Parsing + The address parsing code has been restructured exten- + sively. This should be more efficient in many cases. + +X.400 Extensions + X.400(88) address extensions are now recognised. + +X.400 addresses + + + + December 18, 1991 + + + + + + - 5 - + + + Address parsing recognises A as ADMD and P as PRMD in + RFC1148 encoded X.400 addresses. These are converted to + the form given in RFC1148. + +Multi level queue + For very large system (queues in excess of about 4000 + messages) a multi-level queue can be used. if this is + in effect messages are placed at random in subdirec- + tories of the main queue to reduce the time required by + the system to locate files. + +Authorisation Warnings + Authorisation warnings are now implemented. If a mes- + sage fails authorisation, a warning can be optionally + sent to the originator and/or the recipient. + +Delayed delivery warning + Warnings of delays in delivery are now sent to the ori- + ginator of the message if the message cannot be + delivered in a timely fashion. + +Submit daemon + Submit can be run as a daemon in addition to its normal + directly executed form. This may give performance + improvements for inbound messages. + +administrator assigned alternate recipient + The system manager can direct bad address to a default + mailbox, where numerous actions may be attempted (such + as returning helpful messages about approximate match- + ings etc.) + +X.400(88) downgrading + A filter to downgrade X.400(88) P2 headers to X.400(84) + P2 headers has been provided. Similarly downgrading of + P1 is done in the appropriate channels. This new + filter may also be used to normalise OR addresses in + these headers. + +Body part support + Support of a number of different body types, including + ISO-6937, ISO-8859, and T.61 character sets. + +New queue format + A new queue format has been introduced. We believe this + will give greater reliability and flexibility. There + are now no special subdirectories of the queue, every- + thing is directly under the queue directory. There is a + utility to convert the old format into the new format + (Tools/tables/compat/que_o2n). New format for the + internal structure of the message queue has also been + added in a backwards compatible way. + +ckadr + + + + December 18, 1991 + + + + + + - 6 - + + + ckadr no longer guesses which format of addressing an + address is (x400 or rfc822). Explicit choice should be + made via the -x and -r flags (-r is default) It also no + longer checks for UK domain ordering by default i.e. + will only identify US domain ordering). Checking for + UK ordering can be done via the -b flag. + +Disk checking + Submit can be tailored to check the amount of free + space available on disk and not submit messages if this + is below some threshold. This is not supported on all + systems. + +Control of header type + The specification of a nondefault header type in the + inbound channel will override the default header types + such as hdr.822 and hdr.p2. This will enable a site to + minimise the header manipulation/normalisation done. + +Bad senders + The system manager can control the policy for dealing + with bad senders on an inbound channel basis. + +X.400(88) Extensions + X.400(88) O/R Address extensions have been implemented + and are useable for routing. + +loc_dom_mta, loc_dom_site + Previously these two values were magically recognised + as local when normalising and routing RFC 822 + addresses. This magic has been removed and now you + need explicit entries for these in the domain table + +redirection history + X.400 redirection history is now supported. This shows + up a bug in PP 5.* which may cause PP 5.* MTA to break + when interworking over x400 with a PP 6.0 MTA. Note + that aliases are implemented as redirects. + +table overrides + Tables may been overriden by explicit key/value pairs + given in the tailor file. + +_3. _U_p_g_r_a_d_e _p_a_t_h + + This is the basics of how to upgrade from PP 5.2 to +6.0. + +Compile + Compile pp-6.0 and install. + +domain table + Convert the domain table into the new format. There are + some tools under Tools/tables/compat to aid in this, + + + + December 18, 1991 + + + + + + - 7 - + + + but you may want to rethink how you generate these a + little. This is the major change in this version. Also + check that the relevant entries for loc_dom_site and + loc_dom_mta are present in the domain table as they are + no longer magically recognised. + +alias table + This should be altered into the new format. The conver- + sion routine in Tools/tables/compat may help again. + +local table + This should be backwards compatible, but you may want + to change to the new format anyway. + +Queue + Any files in the queue should be converted to the new + format. This can be done by the following: + + + +Tailoring + Change the tailor file to use the new keys and values. + +Checkup + Run ckconfig and see that everything is sensible. + +restart + Rebuild the database and restart. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + December 18, 1991 + + diff --git a/COVER-LETTER b/COVER-LETTER new file mode 100644 index 0000000..73d8548 --- /dev/null +++ b/COVER-LETTER @@ -0,0 +1,417 @@ + + + + + A N N O U N C E M E N T + + +The next release of PP will be available on December 20, 1991. This +release will be known as + + + PP 6.0 + + +PP is a Message Transfer Agent, intended for high volume message +switching, protocol conversion, and format conversion. It is targeted for +use in an operational environment, but is also be useful for investigating +message related applications. Good management features are a major +aspect of this system. PP supports the 1984 and 1988 versions of the +CCITT X.400 / ISO 10021 services and protocols. Many existing RFC 822 +based protocols are supported, along with RFC 1148bis conversion to +X.400. PP is an appropriate replacement for MMDF or Sendmail. +This is the second public release of PP, and includes substantial changes +based on feedback from using PP on many sites. + + + o PP is not proprietary and can be used for any purpose. The only + restriction is that suing of the authors for any damage the code may + cause is not allowed. + + + o PP runs on a range of UNIX and UNIX-like operating systems, + including SUNOS, Ultrix, and BSD. A full list of platforms on which + PP is know to run is included in the distribution. + + + o Current modules include: + + + - X.400 (1984) P1 protocol. + + - X.400 (1988) P1 protocol. + + - Simple mail transfer protocol (SMTP), conformant to host + requirements. + + - JNT mail (grey book) Protocol. + + - UUCP mail transfer. + + - DECNET Mail-11 transfer + + - Distribution list expansion and maintenance, using either a file + based mechanism or an X.500 directory. + + - RFC 822-based local delivery. + + - Delivery time processing of messages. + + - Conversion between X.400 and RFC 822 according to the latest + revision of RFC 1148, known as RFC 1148bis. + + - Conversion support for reformatting body parts and headers. + + - X-Window and line-based management console. + + - Message Authorisation checking. + + - Reformatting support for "mail hub" operation. + + - X.500-based distribution list facility using the QUIPU directory. + + + + 1 + + + + + - FAX interworking + + + o No User Agents (UAs) are included with PP. However, procedural + access to the MTA is documented, to encourage others to write or to + port UAs. Several existing UAs, such as MH, may be used with PP. + + + o It is expected that a Message Store to be used in conjunction with + PP (PPMS), and an associated X-Windows User Agent (XUA) will + be released on beta test in first quarter 92. + + + o The core routing of PP 6.0 is table based. DNS is used by the SMTP + channel. The next version of PP will support Directory Based + routing, which may use X.500 or DNS. + + + o PP 6.0 requires ISODE 7.0. + + + o X-Windows release X11R4 (or greater) is needed by some of the + management tools. PP can be operated without these tools. + + + o Although PP is not "supported" per se (but see later), it does have a + problem reporting address: + + + + RFC 822: PP-SUPPORT@CS.UCL.AC.UK + + + X.400: S=PP-Support; OU=CS; O=UCL; + PRMD=UK.AC; ADMD= ; C=GB; + + + + Bug reports (and fixes) are welcome. + + + o The discussion group PP-PEOPLE@CS.UCL.AC.UK is used as an + open forum on PP; Contact + PP-PEOPLE-REQUEST@CS.UCL.AC.UK to be added to this list. + + + o The primary documentation for this release consists of a three and a + half volume User's Manual (approx. 300 pages) and a set of UNIX + manual pages. The sources to the User's Manual are in LaTeX + format. + + +For more information, contact: + + + Steve Kille + Department of Computer Science + University College London + Gower Street + London + WC1E 6BT + England + + + + 2 + + + + +DISTRIBUTION SITES + + +NIFTP + + +If you run NIFTP over the public X.25 or over Janet, and are registered in +the NRS at Salford, you can use NIFTP with username "guest" and your +own name as password, to access UK.AC.UCL.CS to retrieve the file +pp/pp-6.tar. The file pp-6.tar.Z is the tar image after being run +through the compress program (approx 3Mb). + + + +FTP + + +If you can FTP to the Internet from outside Europe, then use anonymous +FTP to uu.psi.com [136.161.128.3] to retrieve the file pp-6.tar.Z in binary +mode from the isode/ directory. This file is the tar image after being run +through the compress program and is approximately 3Mb in size. + +If you can FTP to the Internet from Europe, then use anonymous FTP to +archive.eu.net [192.16.202.1] to retrieve the file pp-6.tar.Z in binary mode +from the network/isode/ directory. This file is the tar image after being +run through the compress program and is approximately 3Mb in size. + + + +EUROPE (tape and documentation) + + +For mailings in EUROPE, send a cheque or bankers draft and a purchase +order for 200 Pounds Sterling to: + + + Postal address: Department of Computer Science + Attn: Natalie May/Dawn Bailey + University College London + Gower Street + London, WC1E 6BT + UK + + +For information only: + + + Telephone: +44 71-380-7214 + Fax: +44 71-387-1397 + Telex: 28722 + Internet: natalie@cs.ucl.ac.uk + dawn@cs.ucl.ac.uk + + +Specify one: + + + 1. 1600bpi 1/2-inch tape, or + + + 2. Sun 1/4-inch cartridge tape. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + + 3 + + + + +EUROPE (tape only) + + +Tapes without hardcopy documentation can be obtained via the software +distribution service of the European UNIX User group (EUUG). The PP +6.0 distribution is called "EUUGD22 - PP (6.0)". + + + Postal address: EUUG Software Distributions + c/o Frank Kuiper + Centrum voor Wiskunde en Informatica + Kruislaan 413 + 1098 SJ Amsterdam + The Netherlands + + + For information only: + Telephone: +31 20-5924121 + (or +31 20-5929333) + Telex: 12571 mactr nl + Telefax: +31-20-5924199 + Internet: euug-tapes@cwi.nl + + +Specify one: + + + 1. 1600bpi 1/2-inch tape: 130 Dutch guilders. + + + 2. 800bpi 1/2-inch tape: 150 Dutch guilders. + + + 3. Sun 1/4-inch cartridge tape (QIC-24 format): 190 Dutch guilders. + + + 4. Sun 1/4-inch cartridge tape (QIC-11 format): 215 Dutch guilders. + + +If you require DHL, this is possible and will be billed through. Note that if +you are not a member of EUUG, then there is an additional handling fee of +300 Dutch guilders (please enclose a copy of your membership or +contribution payment form when ordering). Do not send money, cheques, +tapes or envelopes; you will be invoiced. + + + +NORTH AMERICA + + +For mailings in NORTH AMERICA, send a check for 375 US dollars to: + + + Postal address: University of Pennsylvania + Department of Computer and Information Science + Moore School + Attn: David J. Farber (PP Distribution) + 200 South 33rd Street + Philadelphia, PA 19104-6314 + U.S.A. + + + Telephone: +1 215-898-8560 + + +Specify one: + + + 1. 1600bpi 1/2-inch tape, or + + + + 4 + + + + + 2. Sun 1/4-inch cartridge tape. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + +AUSTRALIA and NEW ZEALAND + + +For mailings in AUSTRALIA and NEW ZEALAND, + + + 1. If you already have ISODE 7.0, send a cheque for 100 dollars + Australian to the following address. You will recieve only the PP + manuals and a PP tape. Clearly specify on the cheque and + order that you only want PP 6.0. + + + 2. If you do not have ISODE 7.0, send a cheque for 350 dollars + Australian to the following address. You will recieve a tape + containing both ISODE 7.0 and PP 6.0, together with manuals for + both ISODE 7.0 and PP 6.0. + + + + Postal address: CSIRO DIT + Attn: Andrew Waugh (ISODE Distribution) + 723 Swanston St + Carlton, 3053 + Australia + + +For information only: + + + Telephone: +61 3-282-2615 + Fax: +61 3-282-2600 + Internet: ajw@mel.dit.csiro.au + + +Specify one: + + + 1. 1600/3200/6250bpi 1/2-inch tape, or + + + 2. Sun 1/4-inch cartridge tape in either QIC-11, QIC-24 or QIC-150 + format. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + +FTAM on Janet or PSS + + +The source code is available by FTAM at the University College London +over X.25 using Janet (DTE 00000511160013), PSS (DTE +23421920030013) or IXI (DTE 20433450420113) with Transport +Selector 259 (ASCII encoding). Use the "anon" user-identity and retrieve +the file pp-6.tar. The file pp-6.tar.Z is the tar image after being run +through the compress program (3Mb). + + + + 5 + + + + +FTAM on the Internet + + +The source code is available by FTAM over the Internet at host +osi.nyser.net [192.33.4.10] (TCP port 102 selects the OSI transport +service) with Transport Selector 259 (numeric encoding). Use the "anon" +user-identity, supply any password, and retrieve pp-6.tar.Z from the +isode/ directory. This file is the tar image after being run through the +compress program and is approximately 3Mb in size. + + + +Online Postscript + + +For distributions via FTAM, the file service is provided by the FTAM +implementation in ISODE 5.0 or later (IS FTAM). +For distributions via either FTAM or FTP, there are additional files +available for retrieval, called pp-6-ps-a4.tar.Z and pp-6-ps-us.tar.Z +which are compressed tar images (1.5MB) containing the entire +documentation set in PostScript format, for A4 and US paper respectively. + + + +SUPPORT + + +A UK company has been set up to provide support for the ISODE, PP, +and associated packages: X-Tel Services Ltd. This company provides an +update service, general assistance and site specific support. This company +is closely associated with the development of PP. + + + Postal Address: X-Tel Services Ltd. + Nottingham University + Nottingham, NG7 2RD + UK + Telephone: +44 602-412648 + Fax: +44 602-790278 + Internet: support@xtel.co.uk + + + + 6 diff --git a/Chans/822-local/Makefile b/Chans/822-local/Makefile new file mode 100644 index 0000000..905e6f3 --- /dev/null +++ b/Chans/822-local/Makefile @@ -0,0 +1,244 @@ +# Local delivery channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/Makefile,v 6.0 1991/12/18 20:04:31 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:04:31 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ckmf.c code.c lex.c loc.c loc_child.c loc_parent.c parse_hdr.c +OBJS = + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xlocal xckmf + +default: $(PROGS) + +install: inst-dir inst-local inst-ckmf + +############################################################ +# +# Ckmf - check mailfilter file +# +############################################################ + +CHKOBJS = ckmf.o loc.o code.o parse_hdr.o +CHKSRCS = ckmf.c loc.c code.c parse_hdr.c + +inst-ckmf: $(USRBINDIR)/ckmf + +$(USRBINDIR)/ckmf: xckmf + -$(BACKUP) $@ zxckmf + rm -f $@ + $(INSTALL) xckmf $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "mailfilter check program installed normally"; echo "" + +ckmf: xckmf + +xckmf: $(CHKOBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(CHKOBJS) $(LIBPP) $(LIBSYS) -o $@ + +loc.o: lex.c + +loc.o code.o: loc.h + +loc.c: loc.y + $(YACC) loc.y + mv y.tab.c $@ + +l-ckmf: $(CHKSRCS) lex.c + $(LINT) $(LLFLAGS) $(CHKSRCS) $(LINTLIBS) + +############################################################ +# +# local delivery channel +# +############################################################ + +LOCOBJS = loc_parent.o loc_child.o code.o loc.o parse_hdr.o +LOCSRCS = loc_parent.c loc_child.c code.c loc.c parse_hdr.c + + +inst-local: $(CHANDIR)/local +$(CHANDIR)/local: xlocal + -$(BACKUP) $@ zxlocal + rm -f $@ + $(INSTALL) xlocal $@ + -$(CHOWN) $(ROOTUSER) $@ + -$(CHMOD) 4755 $@ + -@ls -ls $@ + -@echo "local channel installed normally"; echo "" + +local: xlocal + +xlocal: $(LOCOBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(LOCOBJS) $(LIBPP) $(LIBSYS) -o $@ + +saber_src: $(LOCSRCS) + #load -C $(CFLAGS) $(LOCSRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(LOCOBJS) + #load -C $(LOCOBJS) $(LIBPP) $(LIBSYS) + +loc_parent.o: loc_parent.c ../../Make.defs + $(CC) $(CFLAGS) -c -DUSRPATH='"$(USRBINDIR)"' loc_parent.c +l-local: $(LOCSRCS) lex.c + $(LINT) $(LLFLAGS) $(LOCSRCS) $(LINTLIBS) + +############################################################ +# +# misc stuff +# +############################################################ + +clean: tidy + rm -f $(OBJS) *.o lex.c loc.c + +tidy: + rm -f $(PROGS) core a.out *old *.BAK zx* + +lint: l-local l-ckmf + + + +inst-dir: $(CHANDIR) + +depend: $(SRCS) + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ckmf.o: ckmf.c +ckmf.o: ../../h/util.h +ckmf.o: ../../h/config.h +ckmf.o: ../../h/ll_log.h +ckmf.o: ../../h/expand.h +ckmf.o: ../../h/retcode.h +code.o: code.c +code.o: ../../h/util.h +code.o: ../../h/config.h +code.o: ../../h/ll_log.h +code.o: loc.h +code.o: ../../h/retcode.h +code.o: ../../h/expand.h +lex.o: lex.c +loc.o: loc.c +loc.o: ../../h/util.h +loc.o: ../../h/config.h +loc.o: ../../h/ll_log.h +loc.o: loc.h +loc.o: lex.c +loc_child.o: loc_child.c +loc_child.o: ../../h/util.h +loc_child.o: ../../h/config.h +loc_child.o: ../../h/ll_log.h +loc_child.o: ../../h/qmgr.h +loc_child.o: ../../h/Qmgr-types.h +loc_child.o: ../../h/Qmgr-ops.h +loc_child.o: ../../h/sys.file.h +loc_child.o: ../../h/retcode.h +loc_child.o: ../../h/expand.h +loc_child.o: ../../h/q.h +loc_child.o: ../../h/adr.h +loc_child.o: ../../h/list_rchan.h +loc_child.o: ../../h/chan.h +loc_child.o: ../../h/table.h +loc_child.o: ../../h/list_bpt.h +loc_child.o: ../../h/auth.h +loc_child.o: ../../h/list_bpt.h +loc_child.o: ../../h/extension.h +loc_child.o: ../../h/mta.h +loc_child.o: ../../h/adr.h +loc_child.o: ../../h/list_bpt.h +loc_child.o: ../../h/aparse.h +loc_child.o: ../../h/ap.h +loc_child.o: ../../h/util.h +loc_child.o: ../../h/or.h +loc_child.o: ../../h/chan.h +loc_child.o: ../../h/auth.h +loc_child.o: ../../h/list_rchan.h +loc_child.o: ../../h/mta.h +loc_child.o: ../../h/loc_user.h +loc_child.o: ../../h/ap.h +loc_parent.o: loc_parent.c +loc_parent.o: ../../h/util.h +loc_parent.o: ../../h/config.h +loc_parent.o: ../../h/ll_log.h +loc_parent.o: ../../h/retcode.h +loc_parent.o: ../../h/prm.h +loc_parent.o: ../../h/q.h +loc_parent.o: ../../h/adr.h +loc_parent.o: ../../h/list_rchan.h +loc_parent.o: ../../h/chan.h +loc_parent.o: ../../h/table.h +loc_parent.o: ../../h/list_bpt.h +loc_parent.o: ../../h/auth.h +loc_parent.o: ../../h/list_bpt.h +loc_parent.o: ../../h/extension.h +loc_parent.o: ../../h/mta.h +loc_parent.o: ../../h/adr.h +loc_parent.o: ../../h/list_bpt.h +loc_parent.o: ../../h/aparse.h +loc_parent.o: ../../h/ap.h +loc_parent.o: ../../h/util.h +loc_parent.o: ../../h/or.h +loc_parent.o: ../../h/chan.h +loc_parent.o: ../../h/auth.h +loc_parent.o: ../../h/list_rchan.h +loc_parent.o: ../../h/mta.h +loc_parent.o: ../../h/dr.h +loc_parent.o: ../../h/extension.h +loc_parent.o: ../../h/mta.h +loc_parent.o: ../../h/qmgr.h +loc_parent.o: ../../h/Qmgr-types.h +loc_parent.o: ../../h/Qmgr-ops.h +loc_parent.o: ../../h/loc_user.h +parse_hdr.o: parse_hdr.c +parse_hdr.o: ../../h/util.h +parse_hdr.o: ../../h/config.h +parse_hdr.o: ../../h/ll_log.h +parse_hdr.o: ../../h/expand.h +parse_hdr.o: loc.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/822-local/ckmf.c b/Chans/822-local/ckmf.c new file mode 100644 index 0000000..6453df4 --- /dev/null +++ b/Chans/822-local/ckmf.c @@ -0,0 +1,303 @@ +/* chkmf.c: check local delivery file stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/ckmf.c,v 6.0 1991/12/18 20:04:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/ckmf.c,v 6.0 1991/12/18 20:04:31 jpo Rel $ + * + * $Log: ckmf.c,v $ + * Revision 6.0 1991/12/18 20:04:31 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "expand.h" +#include "retcode.h" +#include +#include +#include /* getlocalhost defn */ + +#define PROTMODE (0022) + +#define MAXVARS 100 +Expand variables[MAXVARS]; +int nvars; +static int fakeuserid; +static int change_user = 0; + +char *myname; +extern int debug, yydebug; +void adios (), advise (); + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + extern FILE *yyin; + int opt; + int n; + char msg_size[20]; + struct stat st; + + myname = argv[0]; + while((opt = getopt(argc, argv, "du:i:")) != EOF) + switch (opt) { + case 'd': + yydebug = debug = 1; + break; + + case 'u': + { + struct passwd *pwd; + + if ((pwd = getpwnam (optarg)) == NULL) { + fprintf (stderr, + "Unknown user name %s", + optarg); + exit (1); + } + fakeuserid = pwd -> pw_uid; + change_user = 1; + } + break; + case 'i': + fakeuserid = atoi(optarg); + change_user = 1; + break; + + default: + fprintf (stderr, "Usage: %s [-d] mailfilter\n", + myname); + break; + } + argc -= optind; + argv += optind; + if (change_user) + do_the_change (fakeuserid); + + if (argc != 1) + adios (NULLCP, "Usage: %s [-d] mailfilter", myname); + if ((yyin = fopen (argv[0], "r")) == NULL) + adios (argv[0], "Can't open file"); + if (fstat (fileno (yyin), &st) == NOTOK) + adios (argv[0], "Can't fstat file"); + if (st.st_mode & PROTMODE) { + fprintf (stderr, "File %s has wrong mode (%o)\n", + argv[0], st.st_mode & 0777); + fprintf (stderr, + "Should not have group or general write permission\n"); + } + + initialise (); + + yyparse(); + + if (fstat (0, &st) == -1) + (void) strcpy (msg_size, "???"); + else (void) sprintf (msg_size, "%d", st.st_size); + + n = 0; + variables[n].macro = strdup("size"); + variables[n].expansion = strdup (msg_size); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("return-path"); + variables[n].expansion = strdup ("sender@remote"); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("mailbox"); + variables[n].expansion = strdup ("themailbox"); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("recipient"); + variables[n].expansion = strdup ("therecipient"); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("userid"); + if (getenv ("USER")) + variables[n].expansion = strdup (getenv("USER")); + else { + (void) sprintf (msg_size, "%d", getuid ()); + variables[n].expansion = strdup (msg_size); + } + create_var (&variables[n]); + n ++; + + (void) sprintf (msg_size, "%d", getgid ()); + variables[n].macro = strdup ("groupid"); + variables[n].expansion = strdup (msg_size); + create_var (&variables[n]); + n ++; + + variables[n].macro = strdup ("channelname"); + variables[n].expansion = strdup ("thechannel"); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("hostname"); + variables[n].expansion = strdup (getlocalhost ()); + create_var (&variables[n]); + n ++; + + + nvars = parse_hdr (0, variables + 3, MAXVARS - 3) + 3; + + switch (run ()) { + case RP_OK: + printf ("Result: delivered OK\n"); + break; + case RP_BAD: + printf ("Result: delivery failed (permanently)\n"); + break; + case RP_AGN: + printf ("Result: delivered failed (temporarily)\n"); + break; + case RP_NOOP: + printf ("Result: no delivery - other methods will be tried\n"); + break; + default: + printf ("Result: Dunno!\n"); + break; + } + + exit (0); + /* NOTREACHED */ +} + +do_the_change (id) +int id; +{ + int myuid = getuid (); + struct passwd *pwd; + extern char *pplogin; + + pwd = getpwnam (pplogin); + if (myuid == 0 || + (pwd && myuid == pwd -> pw_uid)) { +#ifdef BSD42 + if (setreuid (id, id) == NOTOK) +#else + if (setuid (id) == NOTOK) +#endif + adios ("setreuid", "Can't set ids to %d", id); + } + else + adios (NULLCP, "Not running as root or PP"); +} + + +#ifndef lint +static void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + +putunixfile (str) +char *str; +{ + char buf[BUFSIZ]; + expand (buf, str, variables); + printf ("append to file (sendmail format) '%s'\n", buf); + return RP_OK; +} + +putfile (str) +char *str; +{ + char buf[BUFSIZ]; + expand (buf, str, variables); + printf ("append to file '%s'\n", buf); + return RP_OK; +} + +putpipe (str) +char *str; +{ + char buf[BUFSIZ]; + + install_vars (variables, nvars, MAXVARS); + expand (buf, str, variables); + printf ("pipe into process '%s'\n", buf); + return RP_OK; +} + +printit (s) +char *s; +{ + fputs (s, stdout); +} diff --git a/Chans/822-local/code.c b/Chans/822-local/code.c new file mode 100644 index 0000000..efa51e9 --- /dev/null +++ b/Chans/822-local/code.c @@ -0,0 +1,563 @@ +/* code.c: interpreter code */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/code.c,v 6.0 1991/12/18 20:04:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/code.c,v 6.0 1991/12/18 20:04:31 jpo Rel $ + * + * $Log: code.c,v $ + * Revision 6.0 1991/12/18 20:04:31 jpo + * Release 6.0 + * + */ + + + +/* This stuff based heavily on Kernigan & Pike's hoc */ + +#include "util.h" +#include "loc.h" +#include "retcode.h" +#include "expand.h" +#include + +#ifndef NULLCP +#define NULLCP ((char *)0) +#endif +#define NSTACK 1024 +static Datum stack[NSTACK]; +static Datum *stackp; + +#define NPROG 2000 +Inst prog[NPROG]; +Inst *progp, *pc; + +static char true[] = "true", false[] = "", rp_agn[] = "again", + delivered[] = "delivered", permfail[] = "perm"; +#define istrue(x) (*x) + +int lineno; +int debug = 0; + +static struct { + char *name; + char *val; +} consts[] = { + "TRUE", true, + "FALSE", false, + "OK", true, + "PERMFAIL", permfail, + "TEMPFAIL", rp_agn, + 0, 0 +}; + +static CMD_TABLE tbl_codes[] = { + true, RP_OK, + rp_agn, RP_AGN, + false, RP_NOOP, + permfail, RP_BAD, + 0, -1 +}; + +static int exiting; +extern char *strdup (); + +initialise () +{ + Symbol *sp; + int i; + + stackp = stack; + progp = prog; + if (!lookup (delivered)) { + sp = install (delivered, strvar); + sp -> str = false; + for (i = 0; consts[i].name; i++) { + sp = install (consts[i].name, constant); + sp -> str = consts[i].val; + } + } + exiting = 0; +} + +#ifdef DISASS +static CMD_TABLE procs[] = { + "ifcode", (int) ifcode, + "eq", (int) eq, + "ne", (int) ne, + "or", (int) or, + "and", (int) and, + "stringpush", (int) stringpush, + "tofile", (int) tofile, + "topipe", (int) topipe, + "exitproc", (int) exitproc, + "varpush", (int) varpush, + "setdeliver", (int) setdeliver, + "eval", (int) eval, + "defexitproc", (int) defexitproc, + "not", (int) not, + "unixmail", (int) tounixfile, + "STOP", 0, + 0, -1 +}; +#endif + +run () +{ + Symbol *sp; + int retval; +#ifdef DISASS + Inst *p; + char *cp; + + for (p = prog; p < progp; p++) + if (cp = rcmd_srch (*p, procs)) + PP_TRACE (("%d %s", p - prog, cp)); + else + PP_TRACE (("%d %x", p - prog, *p)); + +#endif + execute (prog); + + sp = lookup (delivered); + if (sp == NULL) + adios (NULLCP, "symbol %s not defined!!", delivered); + switch (retval = cmd_srch (sp -> str, tbl_codes)) { + case RP_AGN: + case RP_BAD: + case RP_OK: + case RP_NOOP: + break; + + default: + adios (NULLCP, "Unknown return state '%s'", sp -> str); + } + return retval; +} + +execute (p) +Inst *p; +{ + Inst tmppc; + + for (pc = p; *pc != STOP && !exiting; ) { + tmppc = *pc ++; /* work around ultrix bug */ + (*tmppc) (); + } +} + +Datum pop () +{ + if (stackp == stack) + adios (NULLCP, "stack underflow"); + return *--stackp; +} + +push (d) +Datum d; +{ + if (stackp >= &stack[NSTACK]) + adios (NULLCP, "stack overflow"); + *stackp++ = d; +} + +Inst *code (f) +Inst f; +{ + Inst *oprogp = progp; + + if (progp >= &prog[NPROG]) + adios (NULLCP, "program too big"); + *progp++ = f; + return oprogp; +} + +void or () +{ + Datum d1, d2; + + d1 = pop (); + d2 = pop (); + PP_TRACE (("%s or %s", d1.str, d2.str)); + d1.str = (istrue(d1.str) || istrue(d2.str) ? true : false); + push (d1); +} + +void and () +{ + Datum d1, d2; + + d1 = pop (); + d2 = pop (); + PP_TRACE (("%s and %s", d1.str, d2.str)); + d1.str = (istrue(d1.str) && istrue(d2.str) ? true : false); + push (d1); +} + + +void eq () +{ + Datum d1, d2; + + d2 = pop (); + d1 = pop (); + PP_TRACE (("%s eq %s", d1.str, d2.str)); + d1.str = (lexequ (d1.str, d2.str) == 0 ? true : false); + push (d1); +} + +void ne () +{ + PP_TRACE (("not (psuedo)")); + eq (); + not (); +} + +void req () +{ + Datum d1, d2; + char *cp, *dp, *re_comp (); + static char *rbuf; + static int rbsize; + int s; + + d2 = pop (); + d1 = pop (); + + PP_TRACE (("%s req %s", d1.str, d2.str)); + if (cp = re_comp (d2.str)) + adios (NULLCP, "Bad re expression %s: %s", d2.str, cp); + s = strlen (d1.str); + if (rbuf == NULLCP) + rbuf = malloc ((unsigned)(rbsize = (s + 1))); + else if (s + 1 > rbsize) + rbuf = realloc (rbuf, (unsigned) (rbsize = s + 1)); + for (cp = d1.str, dp = rbuf; *cp; cp ++) { + if (isascii (*cp) && isupper (*cp)) + *dp++ = tolower (*cp); + else *dp ++ = *cp; + } + *dp = '\0'; + + if (re_exec (rbuf)) + d1.str = true; + else d1.str = false; + push (d1); +} + +void not () +{ + Datum d; + + d = pop (); + PP_TRACE (("not %s", d.str)); + d.str = istrue(d.str) ? false : true; + push (d); +} + +void eval () +{ + Datum d; + + d = pop (); + + PP_TRACE (("eval %s", d.sym -> str ? d.sym -> str : + "")); + if (d.sym -> str == (char *)0) + d.str = false; + else d.str = d.sym -> str; + push(d); +} + +void stringpush () +{ + Datum d; + + d.str = (char *)*pc ++; + PP_TRACE (("stringpush %s", d.str)); + push (d); +} + +void varpush () +{ + Datum d; + + d.sym = (Symbol *)(*pc ++); + PP_TRACE (("varpush %s", d.sym -> str)); + push (d); +} + +void ifcode () +{ + Datum d; + Inst *savepc = pc; + + PP_TRACE (("ifcode")); + execute (savepc+3); /* then part */ + + d = pop (); + if (istrue(d.str)) { + PP_TRACE (("then code")); + execute (*((Inst **)(savepc))); + } + else if (*((Inst **)(savepc+1))) { /* else part */ + PP_TRACE (("else code")); + execute (*((Inst **)(savepc + 1))); + } + PP_TRACE (("endif")); + if (!exiting) + pc = *((Inst **)(savepc + 2)); /* next statement */ +} + +void tofile () +{ + Datum d; + + d = pop (); + PP_TRACE (("tofile %s", d.str)); + switch (putfile (d.str)) { + case RP_OK: + d.str = true; + break; + case RP_AGN: + d.str = rp_agn; + break; + default: + case RP_BAD: + d.str = false; + break; + } + push (d); +} + +void tounixfile () +{ + Datum d; + + d = pop (); + PP_TRACE (("tounixfile %s", d.str)); + switch (putunixfile (d.str)) { + case RP_OK: + d.str = true; + break; + case RP_AGN: + d.str = rp_agn; + break; + default: + case RP_BAD: + d.str = false; + break; + } + push (d); +} + +void topipe () +{ + Datum d; + + d = pop (); + PP_TRACE (("topipe %s", d.str)); + switch (putpipe (d.str)) { + case RP_OK: + d.str = true; + break; + case RP_BAD: + d.str = false; + break; + default: + case RP_AGN: + d.str = rp_agn; + break; + } + PP_TRACE (("topipe = %s", d.str)); + push (d); +} + +void setdeliver () +{ + Datum d; + Symbol *sym; + + d = pop (); + PP_TRACE (("setdelivered %s", d.str)); + sym = lookup (delivered); + if (sym == NULL) + adios (NULLCP, "symbol %s not defined!!", delivered); + sym -> str = d.str; + if (lexequ (d.str, rp_agn) == 0) + exiting = 1; + push (d); +} + +void exitproc () +{ + Datum d; + Symbol *sym; + + d = pop (); + PP_TRACE (("exitproc %s", d.str)); + sym = lookup (delivered); + if (sym == NULL) + adios (NULLCP, "symbol %s not defined!!", delivered); + sym -> str = d.str; + exiting = 1; +} + +void defexitproc () +{ + Symbol *sym; + Datum d; + + PP_TRACE (("defexitproc")); + sym = lookup (delivered); + if (sym == NULL) + adios (NULLCP, "symbol %s not defined!!", delivered); + d.str = sym -> str; + push (d); + exiting = 1; +} + +void prexpr () +{ + Datum d; + + d = pop (); + printit (d.str); +} + +void assign () +{ + Datum d1, d2; + + d1 = pop (); + d2 = pop (); + if (d1.sym -> type != strvar) + adios (NULLCP, "assignment to non-variable '%s'", + d1.sym -> name); + PP_TRACE (("%s = %s", d1.sym -> name, d2.str)); + d1.sym -> str = d2.str; + push (d2); +} + +checkmacro (s) +char *s; +{ + char *p, *q; + + for (q = s; p = index(q, '$'); q = p + 1) { + if (p[1] == '(') { + char *cp, buf[1024]; + + for (p += 2, cp = buf; *p; p++) + if (*p == ')') + break; + else *cp ++ = *p; + *cp = 0; + if (lookup (buf) == (Symbol *)0) + install (strdup (buf), field); + } + } +} + +static Symbol *symlist; + + +Symbol *lookup (s) +char *s; +{ + Symbol *sp; + + for (sp = symlist; sp; sp = sp -> next) + if (strcmp (sp -> name, s) == 0) + return sp; + return 0; +} + + +Symbol *install (str, t) +char *str; +stype t; +{ + Symbol *sp; + + PP_TRACE (("Install %s",str)); + sp = (Symbol *) smalloc (sizeof *sp); + sp -> name = str; + sp -> type = t; + sp -> str = false; + + sp -> next = symlist; + symlist = sp; + return sp; +} + +reset_syms () +{ + Symbol **spp, *sp; + + PP_TRACE (("reset symbols")); + for (spp = &symlist; *spp; ) { /* half hearted free attempt */ + sp = *spp; + spp = &(*spp) -> next; + if (sp -> name && *sp -> name) + free (sp -> name); + free ((char *)sp); + } + symlist = 0; +} + +int yywrap () +{ + return 1; +} + +yyerror (s) +char *s; +{ + extern char yytext[]; + + adios (NULLCP, "%s near line %d (last token was '%s')", + s, lineno, yytext); +} + +fillin_var (str, dest) +char *str; +char dest[]; +{ + Symbol *sp; + + if (sp = lookup (str)) + (void) sprintf (dest, "PATH=%s", sp -> str); +} + +install_vars (vars, n, maxv) +Expand vars[]; +int n; +int maxv; +{ + int i; + Symbol *sp; + + for (i = n, sp = symlist; i < maxv && sp; + sp = sp -> next) { + if (sp -> type == field) + continue; + vars[i].macro = strdup (sp -> name); + vars[i].expansion = strdup (sp -> str); + i++; + } + vars[i].macro = vars[i].expansion = NULLCP; + +} + +void create_var (var) +Expand *var; +{ + Symbol *sp; + + if ((sp = lookup (var -> macro)) == NULL) + sp = install (var -> macro, field); + sp -> str = var -> expansion; +} diff --git a/Chans/822-local/lex.l b/Chans/822-local/lex.l new file mode 100644 index 0000000..58932c1 --- /dev/null +++ b/Chans/822-local/lex.l @@ -0,0 +1,152 @@ +%{ +static CMD_TABLE keywds[] = { + "if", IF, + "else", ELSE, + "exit", EXIT, + "ignore", IGNORE, + "file", TOFILE, + "pipe", TOPIPE, + "unixfile", TOUNIXFILE, + "print", PRINT, + 0, -1 +}; + +extern int lineno; +%} + +%% +[ \t]+ {;} +\n { lineno ++; } +"!=" { return NE; } +"==" { return EQ; } +"&&" { return AND; } +"||" { return OR; } +"!" { return NOT; } +[0-9]+ { + yylval.yy_n = atoi (yytext); + return NUMBER; + } +"#".* {;} +"$("[a-z][-a-z0-9]*")" { + yytext[strlen(yytext)-1] = 0; + if ((yylval.yy_sym = lookup (yytext+2)) == NULL) + yylval.yy_sym = install (strdup (yytext+2), + field); + return FIELD; + } +[A-Za-z][A-Za-z0-9]* { + int n; + + if ((n = cmd_srch (yytext, keywds)) != -1) + return n; + if ((yylval.yy_sym = lookup (yytext)) == NULL) + yylval.yy_sym = install (strdup(yytext), strvar); + return VARIABLE; + } + +\" { + int c; + char *cp, *pp, *ep; + int len; + + pp = smalloc (len = 20); + + for (ep = (cp = pp) + len - 1;; ) { + if ((c = input ()) == NULL) + yyerror ("end-of-file while reading string"); + if (c == '\n') + yyerror ("newline in string"); + if (c == '"') { + *cp = NULL; + yylval.yy_str = pp; + return STRING; + } + if (c == '\\') { + switch (c = input()) { + case 0: + yyerror ("end-of-file while reading string"); + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + default: + break; + } + } + if (cp >= ep) { + register int curlen = cp - pp; + register char *dp; + + if ((dp = realloc (pp, + (unsigned) (len *= 2))) + == NULL) + yyerror ("out of memory"); + cp = dp + curlen; + ep = (pp = dp) + len - 1; + } + *cp ++ = c; + } + } +"/" { + int c; + char *cp, *pp, *ep; + int len; + + pp = smalloc (len = 20); + + for (ep = (cp = pp) + len - 1;; ) { + if ((c = input ()) == NULL) + yyerror ("end-of-file while reading regexp"); + if (c == '\n') + yyerror ("newline in regexp"); + if (c == '/') { + *cp = NULL; + yylval.yy_str = pp; + return REGEXP; + } + if (c == '\\') { + switch (c = input()) { + case 0: + yyerror ("end-of-file while reading string"); + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + default: + break; + } + } + if (cp >= ep) { + register int curlen = cp - pp; + register char *dp; + + if ((dp = realloc (pp, + (unsigned) (len *= 2))) + == NULL) + yyerror ("out of memory"); + cp = dp + curlen; + ep = (pp = dp) + len - 1; + } + *cp ++ = c; + } + } +. { return yytext[0]; } + diff --git a/Chans/822-local/loc.h b/Chans/822-local/loc.h new file mode 100644 index 0000000..05a81e1 --- /dev/null +++ b/Chans/822-local/loc.h @@ -0,0 +1,58 @@ +/* loc.h: 822-local definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/loc.h,v 6.0 1991/12/18 20:05:47 jpo Rel $ + * + * $Log: loc.h,v $ + * Revision 6.0 1991/12/18 20:05:47 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_822LOCAL_LOC +#define _H_822LOCAL_LOC + + +typedef enum { strvar = 1, field, constant } stype; + + +typedef struct Symbol { + char *name; + stype type; + char *str; + struct Symbol *next; +} Symbol; + + +Symbol *install(), *lookup(); + + + +typedef union { + char *str; + Symbol *sym; +} Datum; + +extern Datum pop(); + + + +typedef void (*Inst)(); +#define STOP ((Inst)0) + + +extern Inst prog[]; +extern Inst *progp; +extern Inst *code(); + +extern void ifcode(), eq(), ne(), or(), and(), stringpush(), + tofile(), topipe(), ignore(), exitproc(), varpush(), + setdeliver(), eval(), defexitproc(), not(), req(), + prexpr(), assign(), tounixfile(); +extern void adios(), advise(); + + +#endif diff --git a/Chans/822-local/loc.y b/Chans/822-local/loc.y new file mode 100644 index 0000000..eba0e54 --- /dev/null +++ b/Chans/822-local/loc.y @@ -0,0 +1,128 @@ +%{ +#include "util.h" +#include +#include +#include "loc.h" + +#define YYDEBUG 1 +#define code2(c1,c2) code (c1); (void) code (c2) +#define code3(c1,c2,c3) code (c1); (void) code (c2); (void) code(c3) +%} + +%union { + char *yy_str; + int yy_n; + Inst *yy_inst; + Symbol *yy_sym; +} + +%token IF ELSE TOFILE TOPIPE IGNORE EXIT PRINT TOUNIXFILE +%token VARIABLE FIELD +%token STRING REGEXP +%token NUMBER +%type if end condition expression statement statementlist prexp +%type ignore + +%right '=' +%left OR +%left AND +%left EQ NE +%left NOT + +%% + +list: statementlist { code (STOP); } + ; + +statementlist: /* empty */ { $$ = progp; } + | statementlist statement + ; + +statement: expression ';' { code ((Inst)pop); } + | ';' { $$ = progp; } + | PRINT prexp ';' { $$ = $2; } + | if condition statement end { + ($1)[1] = (Inst)$3; + ($1)[3] = (Inst)$4; + } + | if condition statement end ELSE statement end { + ($1)[1] = (Inst)$3; + ($1)[2] = (Inst)$6; + ($1)[3] = (Inst)$7; + } + | '{' statementlist '}' { $$ = $2; } + ; + +if : IF { $$ = code (ifcode); code3 (STOP, STOP, STOP); } + ; + +end : /* nothing */ { code (STOP); $$ = progp; } + ; + +condition: '(' expression ')' { code(STOP); $$ = $2; } + ; + +expression: '(' expression ')' { $$ = $2; } + | expression EQ REGEXP { + char *cp, *re_comp(); + char buf[256]; + if (cp = re_comp ($3)) { + (void) sprintf (buf, "bad RE '%s': %s", + $3, cp); + yyerror (buf); + } + code3 (stringpush, (Inst)$3, req); + } + | expression NE REGEXP { + char *cp, *re_comp (); + char buf[256]; + if (cp = re_comp ($3)) { + (void) sprintf (buf, "bad RE '%s': %s", + $3, cp); + yyerror (buf); + } + code2 (stringpush, (Inst)$3); + code2 (req, not); + } + | VARIABLE '=' expression { code3 (varpush, (Inst)$1, assign); } + | expression EQ expression { code (eq); } + | expression NE expression { code (ne); } + | expression OR expression { code (or); } + | expression AND expression { code (and); } + | NOT expression { $$ = $2; code (not); } + | ignore TOFILE STRING { + checkmacro ($3); + $$ = code3(stringpush, (Inst)$3, tofile); + if ($1) + code (setdeliver); + } + | ignore TOPIPE STRING { + checkmacro ($3); + $$ = code3(stringpush, (Inst)$3, topipe); + if ($1) + code (setdeliver); + } + | ignore TOUNIXFILE STRING { + checkmacro ($3); + $$ = code3 (stringpush, (Inst)$3, tounixfile); + if ($1) + code (setdeliver); + } + | EXIT { $$ = code2(defexitproc, STOP); } + | EXIT '(' expression ')' { $$ = $3; code2(exitproc, STOP); } + | FIELD { $$ = code3 (varpush, (Inst)$1, eval); } + | VARIABLE { $$ = code3 (varpush, (Inst)$1, eval); } + | STRING { $$ = code2 (stringpush, (Inst)$1); } + ; + +ignore: /* empty */ { $$ = 1; } + | IGNORE { $$ = 0; } + ; + +prexp: expression { code(prexpr); } + | prexp ',' expression { code(prexpr); } + ; + +%% + +#include "lex.c" diff --git a/Chans/822-local/loc_child.c b/Chans/822-local/loc_child.c new file mode 100644 index 0000000..6025b2d --- /dev/null +++ b/Chans/822-local/loc_child.c @@ -0,0 +1,894 @@ +/* loc_child.c: do the actual delivery */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/loc_child.c,v 6.0 1991/12/18 20:04:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/loc_child.c,v 6.0 1991/12/18 20:04:31 jpo Rel $ + * + * $Log: loc_child.c,v $ + * Revision 6.0 1991/12/18 20:04:31 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "qmgr.h" +#include +#include +#include "sys.file.h" +#include "retcode.h" +#include +#include +#include "expand.h" +#include "q.h" +#include "loc_user.h" +#include "ap.h" +#ifdef SYS5 +#ifdef vfork +#undef vfork +#endif +#include +#endif + + +#ifndef L_INCR +#define L_INCR SEEK_CUR +#endif +#ifndef L_SET +#define L_SET SEEK_SET +#endif + +#ifndef WCOREDUMP +#define WCOREDUMP(x) (((union wait *)&(x))->w_coredump) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif +#ifndef WTERMSIG +#define WTERMSIG(x) (((union wait *)&(x)) -> w_termsig) +#endif + +#define PROTMODE (0022) +#ifdef notdef +#define TESTVERSION /* do setuid'ing */ +#endif + +extern char *mailfilter, *sysmailfilter; +extern char *delim1, *delim2, *mboxname; +extern char *envp[]; +extern char env_path[]; +extern char *local_user; +extern long message_size; +extern Q_struct Qstruct; +extern CHAN *mychan; +extern void create_var (); +void adios (), advise (); + +static char msg_size[20]; + +static int hdr_fd, body_fd; + +static int restrict; /* >0 -> restricted access */ + +static void setstatus (), cleanup (), suckuperrors (); + +static int copy (), copynofrom (), readinfile (); +static int do_mailfilter (); +static char *returnpath, *localhost; +static char *lowerfy (); +static char *return_path (); +static LocUser *this_user_opts; + +#define MAXVARS 100 +static Expand variables[MAXVARS]; +static int nvars; + +int child_process (loc, h_fd, b_fd) +LocUser *loc; +int h_fd, b_fd; +{ + int childpid, pid; +#ifdef SVR4 + int status; +#else + union wait status; +#endif + + PP_TRACE (("child_process (loc, %d, %d)", h_fd, b_fd)); + + if ((childpid = tryfork ()) == NOTOK) + return NOTOK; + + if (childpid) { /* parent */ +#ifdef SVR4 + while ((pid = wait(&status)) != childpid && pid != -1) +#else + while ((pid = wait(&status.w_status)) != childpid && pid != -1) +#endif + continue; + if (pid == -1) { + PP_LOG (LLOG_EXCEPTIONS, ("Pid == -1 something bad")); + return NOTOK; + } + if (WIFEXITED(status)) + return WEXITSTATUS(status); + PP_LOG (LLOG_EXCEPTIONS, ("processed killed %s", + WCOREDUMP(status) ? "core dumped" : + "")); + return NOTOK; + } + + /* child */ + hdr_fd = h_fd; + body_fd = b_fd; + this_user_opts = loc; + +#ifndef TESTVERSION + if (loc -> username && + initgroups (loc -> username, loc -> gid) == NOTOK) + PP_SLOG (LLOG_EXCEPTIONS, loc -> username, + ("Cant initilize groups list for")); +#ifdef SYS5 + if (setgid (loc->gid) == -1 || + setuid (loc->uid) == -1) { +#else + if (setregid (loc -> gid, loc -> gid) == NOTOK || + setreuid (loc -> uid, loc -> uid) == NOTOK) { +#endif + PP_SLOG (LLOG_EXCEPTIONS, + (loc -> username ? loc -> username : ""), + ("Can't set uid (channel not setuid?) for uid-=%d id", + loc-> uid )); + _exit (int_Qmgr_status_mtaFailure); + } +#endif + PP_TRACE (("Changing directory to %s", loc -> directory)); + if (chdir (loc -> directory) == NOTOK) { + PP_SLOG(LLOG_EXCEPTIONS, loc -> directory, + ("Can't change to directory")); + _exit (int_Qmgr_status_mtaFailure); + } + + returnpath = return_path (Qstruct.Oaddress -> ad_r822adr); + localhost = getlocalhost (); + + if (loc -> mailfilter) + setstatus (do_mailfilter (loc -> mailfilter, 0, loc)); + + if (loc -> sysmailfilter) + setstatus (do_mailfilter (loc -> sysmailfilter, 1, loc)); + + switch (loc -> mailformat) { + case MF_PP: + setstatus (putfile (loc -> mailbox)); + break; + case MF_UNIX: + setstatus (putunixfile (loc -> mailbox)); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown default mbox format %d", + loc -> mailformat)); + break; + } + _exit (int_Qmgr_status_messageFailure); + return NOTOK; +} + + +static void setstatus (retval) +int retval; +{ + PP_TRACE (("setstatus (%s)", rp_valstr(retval))); + if (rp_isgood (retval)) { + PP_TRACE (("Delivery done")); + _exit (int_Qmgr_status_success); + } + else if (retval == RP_NOOP) { + PP_TRACE (("Trying next method")); + return; + } + else if (retval == RP_AGN) { + PP_TRACE (("Retry later")); + _exit (int_Qmgr_status_messageFailure); + } + PP_TRACE (("Failed")); + _exit (int_Qmgr_status_negativeDR); +} + +static char *return_path (str) +char *str; +{ + extern int ap_outtype; + char *newaddr = NULLCP; + AP_ptr tree = NULLAP, + group = NULLAP, + name = NULLAP, + local = NULLAP, + domain = NULLAP, + route = NULLAP; + + switch (mychan -> ch_ad_order) { + case CH_UK_ONLY: + case CH_UK_PREF: + ap_outtype = AP_PARSE_822 | AP_PARSE_BIG; + break; + + default: + return strdup (str); + } + + if (ap_s2p (str, &tree, &group, &name, &local, &domain, &route) + == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to parse (s2p) Recipient addr %s", str)); + return NULLCP; + } + + + if ((newaddr = ap_p2s (group, name, local, domain, route)) + == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to parse (p2s) Recipient addr %s", str)); + newaddr = NULLCP; + } + + ap_free (tree); + + return lowerfy(newaddr); +} + +static jmp_buf jbuf; + +static int do_mailfilter (file, sysflg, loc) +char *file; +int sysflg; +LocUser *loc; +{ + struct stat statbuf; + static int n; + char gbuf[30]; + + PP_TRACE (("do_mailfilter (%s, %d)", file, sysflg)); + + if (stat (file, &statbuf) == NOTOK) { + PP_TRACE (("No file %s...", file)); + return RP_NOOP; + } + + if (statbuf.st_mode & PROTMODE) { + PP_NOTICE (("File %s has wrong modes", file)); + return RP_NOOP; + } + if (statbuf.st_uid != 0 && + (sysflg == 0 && statbuf.st_uid != loc -> uid)) { + PP_NOTICE (("File %s not owned by owner or root", file)); + return RP_NOOP; + } + + if (setjmp (jbuf) == DONE) + return RP_AGN; + + reset_syms (); + initialise (); + zapvars (variables, MAXVARS); + + if (readinfile (file) != OK) + return RP_AGN; + + n = 0; + (void) sprintf (msg_size, "%d", message_size); + variables[n].macro = strdup("size"); + variables[n].expansion = strdup (msg_size); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("return-path"); + variables[n].expansion = + strdup (returnpath); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("mailbox"); + variables[n].expansion = strdup (loc -> mailbox); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("recipient"); + variables[n].expansion = strdup (local_user); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("userid"); + if (loc -> username) + variables[n].expansion = strdup (loc -> username); + else { + (void) sprintf (gbuf, "%d", loc -> uid); + variables[n].expansion = strdup (gbuf); + } + create_var (&variables[n]); + n ++; + + variables[n].macro = strdup ("groupid"); + (void) sprintf (gbuf, "%d", loc -> gid); + variables[n].expansion = strdup (gbuf); + create_var (&variables[n]); + n ++; + + variables[n].macro = strdup ("channelname"); + variables[n].expansion = strdup (mychan -> ch_name); + create_var (&variables[n]); + n++; + + variables[n].macro = strdup ("hostname"); + variables[n].expansion = strdup (localhost); + create_var (&variables[n]); + n ++; + + nvars = parse_hdr (hdr_fd, variables + n, MAXVARS - n) + n; + + return run (); +} + +static int sigpiped, sigalarmed; + +int putfile (file) +char *file; +{ + FILE *fp; + off_t oldlen; + int n; + int exists; + char buffer[BUFSIZ]; + + install_vars (variables, nvars, MAXVARS); + expand (buffer, file, variables); + PP_TRACE (("putfile %s", buffer)); + + sigalarmed = sigpiped = 0; + + if (lseek (hdr_fd, 0L, L_SET) == NOTOK || + lseek (body_fd, 0L, L_SET) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "failed", ("lseek")); + return RP_AGN; + } + + exists = access (buffer, 0) == 0; + + if ((fp = flckopen (buffer, "a")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, buffer, ("Can't open file")); + return RP_AGN; + } + if (!exists) + (void) fchmod (fileno (fp), 0600); + + oldlen = lseek (fileno (fp), 0L, L_INCR); + if (oldlen < 0) { + (void) flckclose (fp); + return RP_AGN; + } + + n = strlen (delim1); + if (fwrite (delim1, 1, n, fp) != n) { + cleanup (fp, oldlen); + return RP_AGN; + } + + fprintf (fp, "Return-Path: <%s>\n", + returnpath); + if (copy (hdr_fd, fp) == NOTOK) { + cleanup (fp, oldlen); + return RP_AGN; + } + + putc ('\n', fp); + + if (copy (body_fd, fp) == NOTOK) { + cleanup (fp, oldlen); + return RP_AGN; + } + + n = strlen (delim2); + if (fwrite (delim2, 1, n, fp) != n) { + cleanup (fp, oldlen); + return RP_AGN; + } + + if (flckclose (fp) != OK) { + cleanup (fp, oldlen); + return RP_AGN; + } + + PP_TRACE (("Message written to file %s", buffer)); + return RP_OK; +} + +int putunixfile (file) +char *file; +{ + FILE *fp; + time_t now; + char *tstr; + off_t oldlen; + int n; + int exists; + char buf[BUFSIZ]; + char buffer[BUFSIZ]; + time_t time (); + + install_vars (variables, nvars, MAXVARS); + expand (buffer, file, variables); + + sigalarmed = sigpiped = 0; + + PP_TRACE (("putunixfile %s", buffer)); + + if (lseek (hdr_fd, 0L, L_SET) == NOTOK || + lseek (body_fd, 0L, L_SET) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "failed", ("lseek")); + return RP_AGN; + } + + exists = access (buffer, 0) == 0; + + if ((fp = flckopen (buffer, "a")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, buffer, ("Can't open file")); + return RP_AGN; + } + if (!exists) + (void) fchmod (fileno (fp), 0600); + + oldlen = lseek (fileno (fp), 0L, L_INCR); + if (oldlen < 0) { + (void) flckclose (fp); + return RP_AGN; + } + + (void) time (&now); + tstr = ctime (&now); + (void) sprintf (buf, "From %s %s", + returnpath, tstr); + + n = strlen (buf); + if (fwrite (buf, 1, n, fp) != n) { + cleanup (fp, oldlen); + return RP_AGN; + } + + fprintf (fp, "Return-Path: <%s>\n", + returnpath); + if (copynofrom (hdr_fd, fp) == NOTOK) { + cleanup (fp, oldlen); + return RP_AGN; + } + + putc ('\n', fp); + + if (copynofrom (body_fd, fp) == NOTOK) { + cleanup (fp, oldlen); + return RP_AGN; + } + putc ('\n', fp); + + if (fflush (fp) != OK) { + cleanup (fp, oldlen); + return RP_AGN; + } + (void) flckclose (fp); + + PP_TRACE (("Message written to file %s", buffer)); + return RP_OK; +} + +static void cleanup (fp, len) +FILE *fp; +off_t len; +{ + int fd; + + fd = dup (fileno (fp)); + (void) flckclose (fp); + + (void) ftruncate (fd, len); /* attempt to undo the damage */ + + (void) close (fd); +} + +static SFD alarmed (), piped(); +static jmp_buf pipe_arlm_jmp; + +putpipe (proc) +char *proc; +{ + int pid, cpid; + int retval; + SFP oldalarm, oldpipe; + int tofds[2], fromfds[2]; + char buffer[BUFSIZ]; + int killed = 0; + FILE *fp; +#ifdef SVR4 + int status; +#else + union wait status; +#endif + + PP_TRACE(("putpipe (%s)", proc)); + + if (lseek (hdr_fd, 0L, L_SET) == NOTOK || + lseek (body_fd, 0L, L_SET) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "failed", ("lseek")); + return RP_AGN; + } + + if (pipe (tofds) == NOTOK) + return RP_AGN; + if (pipe (fromfds) == NOTOK) { + (void) close (tofds[0]); + (void) close (tofds[1]); + return RP_AGN; + } + + if ((pid = tryfork ()) == NOTOK) { /* argggh! So near */ + (void) close (tofds[0]); + (void) close (tofds[1]); + (void) close (fromfds[0]); + (void) close (fromfds[1]); + return RP_AGN; + } + + if (pid == 0) { /* kid */ + int i; + + install_vars (variables, nvars, MAXVARS); + (void) expand (buffer, proc, variables); + PP_TRACE (("exec %s", buffer)); + if (restrict <= 0) + fillin_var ("PATH", env_path); + + (void) close (tofds[1]); + (void) dup2 (tofds[0], 0); + (void) close (tofds[0]); + + (void) close (fromfds[0]); + (void) dup2 (fromfds[1], 1); + (void) dup2 (fromfds[1], 2); + (void) close (fromfds[1]); + for (i = getdtablesize (); i > 2; i--) + (void) close (i); +#ifndef SYS5 + (void) setpgrp (0, getpid ()); +#endif +#ifdef TIOCNOTTY + if ((i = open ("/dev/tty", O_RDWR, 0)) >= 0) { + (void) ioctl (i, TIOCNOTTY, 0); + (void) close (i); + } +#endif + if (restrict > 0) { + char pathname[BUFSIZ]; + char *argv[50]; + sstr2arg (buffer, 50, argv, " \t\n"); + if (index (argv[0], '/')) { + PP_LOG (LLOG_EXCEPTIONS, + ("argv[0] contains a '/' '%s'", + argv[0])); + _exit (1); + } + (void) sprintf (pathname, "%s/%s", + this_user_opts -> searchpath, argv[0]); + (void) execve (pathname, argv, envp); + _exit (1); + } + (void) execle ("/bin/sh", "sh", "-c", buffer, NULLCP, envp); + _exit (1); + } + + (void) close (tofds[0]); + (void) close (fromfds[1]); + fp = fdopen (tofds[1], "w"); + + oldalarm = signal (SIGALRM, alarmed); + oldpipe = signal (SIGPIPE, piped); + sigpiped = 0; + sigalarmed = 0; + + (void) alarm ((unsigned)(300 + message_size/20)); + PP_TRACE (("alarm set for %d secs", 300 + message_size/20)); + + if (setjmp (pipe_arlm_jmp) != DONE) { + fprintf (fp, "Return-Path: <%s>\n", + returnpath); + if (copy (hdr_fd, fp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("copy error")); + sigpiped = 1; /* pretend it failed - it probably did */ + } + if (!sigpiped) { + fputs ("\n", fp); + + if (copy (body_fd, fp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("copy error")); + sigpiped = 1; + } + } + } + else { + if (sigalarmed) + PP_TRACE (("alarm went off")); + if (sigpiped) + PP_TRACE (("pipe went off")); + } + + if (sigpiped) { /* pipe died - reset for timeout */ + sigpiped = 0; + if (setjmp (pipe_arlm_jmp) == DONE) + PP_TRACE (("Timeout")); + } + + if (sigalarmed) { /* alarm went off - shoot it dead! */ + PP_NOTICE (("Process taking too long ... killing")); + killed = 1; + (void) killpg (pid, SIGTERM); + sleep (2); + (void) killpg (pid, SIGKILL); + } + if (fp) { + (void) fclose (fp); + fp = NULL; + } + + suckuperrors (fromfds[0]); + +#ifdef SVR4 + while ((cpid = wait (&status)) != pid && pid != -1) +#else + while ((cpid = wait (&status.w_status)) != pid && pid != -1) +#endif + PP_TRACE (("proc %d", cpid)); + + PP_TRACE (("pid %d returned term=%d, retcode=%d core=%d killed =%d", + pid, WTERMSIG(status), WEXITSTATUS(status), + WCOREDUMP(status), killed)); + (void) alarm (0); + suckuperrors (fromfds[0]); + + if (!killed && cpid == pid && WIFEXITED (status)) { + if (WEXITSTATUS(status) == 0) + retval = RP_OK; + else if (rp_gbval(WEXITSTATUS(status)) == RP_BNO) + retval = RP_BAD; + else retval = RP_AGN; + } + else retval = RP_AGN; + + /* restore status */ + (void) close (fromfds[0]); + (void) signal (SIGPIPE, oldpipe); + (void) signal (SIGALRM, oldalarm); + + return retval; +} + +static SFD alarmed () +{ + sigalarmed = 1; + longjmp (pipe_arlm_jmp, DONE); +} + +static SFD piped () +{ + sigpiped = 1; + longjmp (pipe_arlm_jmp, DONE); +} + +static int copy (fd, fp) +int fd; +FILE *fp; +{ + char buf[BUFSIZ]; + int n = 0; + char lastc = '\n'; + struct stat st; + int count; + + if (fstat (fd, &st) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "", ("Can't stat file")); + return NOTOK; + } + count = st.st_size; + + PP_TRACE (("copy (%d -> %d) %d bytes", fd, fileno (fp), count)); + while (!sigpiped && !sigalarmed && + (n = read (fd, buf, sizeof buf)) > 0) { + count -= n; + lastc = buf[n-1]; + if (fwrite (buf, 1, n, fp) != n) + return NOTOK; + } + if (n >= 0 && !sigalarmed && !sigpiped && count > 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("File copy not correct %d bytes left", count)); + return NOTOK; + } + + + if (n >= 0 && lastc != '\n') + (void) putc ('\n', fp); + return n < 0 || fflush(fp) == EOF || ferror(fp) ? NOTOK : OK; +} + +static int copynofrom (fd, fp) +int fd; +FILE *fp; +{ + char buf[BUFSIZ]; + int n; + FILE *fp2; + char lastc = '\n'; + + if ((fp2 = fdopen (dup(fd), "r")) == NULL) + return NOTOK; + + PP_TRACE (("copy (%d -> %d)", fd, fileno (fp))); + while (!sigpiped && !sigalarmed && + fgets (buf, sizeof buf, fp2)) { + if (strncmp (buf, "From ", 5) == 0) + putc ('>', fp); + if (fputs (buf, fp) == EOF) { + (void) fclose (fp2); + return NOTOK; + } + lastc = buf[strlen(buf) -1]; + } + if (lastc != '\n') + (void) putc ('\n', fp); + n = ferror (fp2) || ferror (fp) ? NOTOK : OK; + if (fclose (fp2) == NOTOK) + return NOTOK; + return n; +} + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + char buffer[BUFSIZ]; + + va_start (ap); + + asprintf (buffer, ap); + ll_log (pp_log_norm, LLOG_EXCEPTIONS, NULLCP, "%s", buffer); + + va_end (ap); + longjmp (jbuf, DONE); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + +static int readinfile (file) +char *file; +{ + extern FILE *yyin; + + PP_TRACE (("readinfile (%s)", file)); + if ((yyin = fopen (file, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, file, ("Can't open file")); + return NOTOK; + } + + yyparse (); + + (void) fclose (yyin); + return OK; +} + +static void suckuperrors (fd) +int fd; +{ + fd_set rfds, ifds; + char buf[80]; /* smallish */ + int n; + struct timeval timer; + + timerclear(&timer); + + PP_TRACE (("suckuperrors (%d)", fd)); + FD_ZERO (&rfds); + FD_SET (fd, &rfds); + +#define the_universe_exists 1 + + while (the_universe_exists) { + ifds = rfds; + + if (select (fd + 1, &ifds, NULLFD, NULLFD, &timer) <= 0) + break; + + PP_TRACE (("select fired")); + if (FD_ISSET (fd, &ifds)) { + if((n = read (fd, buf, sizeof buf - 1)) > 0) { + buf[n] = 0; + PP_LOG (LLOG_EXCEPTIONS, + ("Output from process '%s'", buf)); + } + else break; + } + else break; + } + PP_TRACE (("suckuperrors - done")); +} + +zapvars (vp, mvp) +Expand *vp; +int mvp; +{ + while (mvp --) { + if (vp -> macro) { + free (vp -> macro); + vp -> macro = NULL; + } + if (vp -> expansion) { + free (vp -> expansion); + vp -> expansion = NULL; + } + vp ++; + } +} + +/* ARGSUSED */ +printit (s) +char *s; +{ + return; +} + +static char *lowerfy (s) +char *s; +{ + register char *cp; + + for (cp = s;*cp; cp++) + if (isupper(*cp)) + *cp = tolower(*cp); + return s; +} + diff --git a/Chans/822-local/loc_parent.c b/Chans/822-local/loc_parent.c new file mode 100644 index 0000000..fe0d79a --- /dev/null +++ b/Chans/822-local/loc_parent.c @@ -0,0 +1,468 @@ +/* loc_parent.c: local delivery channel - parent process */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/loc_parent.c,v 6.0 1991/12/18 20:04:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/loc_parent.c,v 6.0 1991/12/18 20:04:31 jpo Rel $ + * + * $Log: loc_parent.c,v $ + * Revision 6.0 1991/12/18 20:04:31 jpo + * Release 6.0 + * + */ + + + +/* + Works as parent & child. New child for each message. Child does + actual delivery of message, parent interacts with PP. +*/ + +#include "util.h" +#include "retcode.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include +#include +#include +#include +#include "loc_user.h" + +#ifndef USRPATH +#define USRPATH "." +#endif + +extern char *quedfldir; +extern CHAN *ch_nm2struct (); +extern char *delim1; +extern char *delim2; +extern char *hdr_822_bp; +extern char *ad_getlocal (); +extern void chan_init(), err_abrt(), rd_end(); +CHAN *mychan; +static char *this_msg; + +static int initproc (); +static int douser (); +static int deliver (); +static void dirinit (); +static struct type_Qmgr_DeliveryStatus *process (); +Q_struct Qstruct; + +static char env_user[LINESIZE]; +static char env_shell[LINESIZE]; +static char env_home[LINESIZE]; +char env_path[LINESIZE]; +char *envp[] = { + env_user, env_shell, env_home, env_path, NULLCP +}; + +long message_size; +int firstSuccessDR, firstFailDR; +char *local_user; + +/* --------------------- Begin Routines --------------------------------- */ + +main (argc, argv) +int argc; +char **argv; +{ + char *p; + + if ((p = rindex(argv[0], '/')) != NULLCP) + p++; + else p = argv[0]; + + /* -- Init the channel - and find out who we are -- */ + chan_init (p); + + + dirinit (); +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, + initproc, process, NULLIFP); + else +#endif + channel_control (argc, argv, initproc, process, NULLIFP); + exit (0); + /* NOTREACHED */ +} + + + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + char *p; + + p = qb2str (arg); + + PP_TRACE (("initproc (%s)", p)); + if ((mychan = ch_nm2struct (p)) == NULLCHAN) + err_abrt (RP_PARM, "Channel '%s' not known", p); + + PP_NOTICE (("Starting %s (%s)", + mychan -> ch_name, mychan -> ch_show)); + + (void) signal (SIGCHLD, SIG_DFL); + + if (p) + free (p); + + return OK; +} + + + + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + struct prm_vars prm; + Q_struct *qp = &Qstruct; + ADDR *ad_sendr = NULL, + *ad_recip = NULL; + int ad_count, + retval; + + + bzero ((char *)&prm, sizeof prm); + bzero ((char *)qp, sizeof *qp); + firstFailDR = TRUE; + firstSuccessDR = TRUE; + if (this_msg) + free (this_msg); + + this_msg = qb2str (arg -> qid); + + PP_NOTICE (("Processing msg %s", this_msg)); + + delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg err: %s", this_msg)); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + for (up = arg -> users; up; up = up -> next) + douser ((int)up -> RecipientId -> parm, ad_recip); + + rd_end(); + prm_free (&prm); + q_free (qp); + + return deliverystate; +} + + + +/* +Change into pp queue space +*/ + +static void dirinit () +{ + PP_TRACE (("dirinit ()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Uanble to change directory to '%s'", + quedfldir); +} + + +/* + * process one extension-id for this message + */ + +static int douser (rno, ad_recip) +int rno; +ADDR *ad_recip; +{ + ADDR *ap; + + for (ap = ad_recip; ap ; ap = ap->ad_next) { + if (rno != ap -> ad_no) + continue; + if (lchan_acheck (ap, mychan, 1, NULLVP) == NOTOK) + return; + else { + deliver (ap); + return; + } + } + + PP_LOG (LLOG_EXCEPTIONS, + ("user not recipient of %s", this_msg)); + + delivery_setstate (rno, int_Qmgr_status_messageFailure, + "user is not a recipient"); +} + + +static char *formatdir = NULLCP; + +/* +Do the delivery +*/ +static int deliver (ap) +ADDR *ap; +{ + char buffer[BUFSIZ], + filename[MAXPATHLENGTH]; + int hdr_fd, body_fd, + retval; + LocUser *loc; + char *cp; + int size; + struct stat st; + + if (local_user) + free(local_user); + if ((local_user = ad_getlocal (ap -> ad_r822adr, AD_822_TYPE, 1)) == NULLCP) { + (void) sprintf (buffer, "User %s not local!", + ap -> ad_r822adr); + PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + return RP_USER; + } + + if ((loc = tb_getlocal (local_user, mychan)) == NULL) { + (void) sprintf (buffer, + "User %s not registered in channel table %s", + local_user, mychan -> ch_name); + PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) { + delivery_set (ap -> ad_no, + (firstFailDR == TRUE) ? + int_Qmgr_status_negativeDR : + int_Qmgr_status_failureSharedDR); + firstFailDR = FALSE; + } + return RP_USER; + } + if (loc -> searchpath == NULLCP) + loc -> searchpath = strdup (USRPATH); + + PP_TRACE(( +"Found entry for '%s' uid %d, gid %d, user '%s' dir '%s' mailbox '%s', \ +shell %s, home %s, format %d, restrict %d, filter %s, sysfilter %s, \ +PATH %s, opts `%s'", + ap -> ad_r822adr, + loc -> uid, + loc -> gid, + (loc -> username) ? loc -> username : "", + (loc -> directory) ? loc -> directory : "", + (loc -> mailbox) ? loc -> mailbox : "", + (loc -> shell) ? loc -> shell : "", + (loc -> home) ? loc -> home : "", + loc -> mailformat, + loc -> restricted, + (loc -> mailfilter) ? loc -> mailfilter : "", + (loc -> sysmailfilter) ? loc -> sysmailfilter : "", + (loc -> searchpath) ? loc -> searchpath : "", + (loc -> opts) ? loc -> opts : "")); + + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't locate message %s", this_msg)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, + "Can't find the message"); + return RP_MECH; + } + if (rp_isbad (retval = msg_rinit (formatdir))) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit can't init %s", + formatdir)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, + "can't read the body"); + return RP_MECH; + } + if (msg_rfile (filename) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise hdr")); + delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, + "No message header"); + msg_rend (); + return RP_MECH; + } + if ((cp = rindex (filename, '/')) != NULLCP) + cp ++; + else cp = filename; + if (lexnequ (cp, hdr_822_bp, strlen (hdr_822_bp)) != 0) { + PP_LOG (LLOG_EXCEPTIONS, ("Bad header type, %s", cp)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_IMPLICITCONV_NOTREGISTERED, + "Header of message is not RFC-822 based"); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); + msg_rend (); + return RP_MECH; + } + + if ((hdr_fd = open (filename, O_RDONLY, 0)) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, filename, + ("Can't open file")); + (void) sprintf (buffer, "Can't open file %s", filename); + delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + buffer); + return RP_MECH; + } + if (fstat (hdr_fd, &st) != NOTOK) + size = st.st_size; + + switch (msg_rfile (filename)) { + case RP_OK: + if ((body_fd = open (filename, O_RDONLY, 0)) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, filename, + ("Can't open file")); + (void) sprintf (buffer, "Can't open file %s", + filename); + delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + buffer); + (void) close (hdr_fd); + msg_rend (); + return RP_MECH; + } + if (fstat (body_fd, &st) != NOTOK) + size += st.st_size; + break; + + case RP_DONE: + PP_NOTICE (("Message with header part only")); + if ((body_fd = open ("/dev/null", O_RDONLY, 0)) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, "/dev/null", + ("Can't open file")); + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + (void) close (hdr_fd); + msg_rend (); + return RP_MECH; + } + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise body")); + delivery_setstate (ap -> ad_no, int_Qmgr_status_messageFailure, + "Can't initialise body"); + (void) close (hdr_fd); + msg_rend (); + return RP_MECH; + } + + if (msg_rfile (filename) != RP_DONE) { + PP_LOG (LLOG_EXCEPTIONS, ("Extra body parts in message %s", + this_msg)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_IMPLICITCONV_NOTREGISTERED, + "Extra body part that has not been converted to 822"); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); + (void) close (hdr_fd); + (void) close (body_fd); + msg_rend (); + return RP_USER; + } + msg_rend (); + + /* set up the env */ + (void) sprintf (env_home, "HOME=%s", loc -> home ? loc -> home : + (loc -> directory ? loc -> directory : ".")); + (void) sprintf (env_shell, "SHELL=%s", + loc -> shell ? loc -> shell : "/bin/sh"); + (void) sprintf (env_user, "USER=%s", + loc -> username ? loc -> username : local_user); + + (void) sprintf (env_path, "PATH=%s", USRPATH); + size += 1 + strlen (Qstruct.Oaddress -> ad_r822adr); + message_size = size; + retval = child_process (loc, hdr_fd, body_fd); + (void) close (hdr_fd); + (void) close (body_fd); + switch (retval) { + case int_Qmgr_status_negativeDR: + { + char buf[LINESIZE]; + + (void) sprintf (buf, "Delivery to %s (%d) failed", + loc -> username ? + loc -> username : local_user, + loc -> uid); + + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_TRANSFER_FAILURE, + DRD_UA_UNAVAILABLE, buf); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) { + delivery_set (ap -> ad_no, + (firstFailDR == TRUE) ? + retval : + int_Qmgr_status_failureSharedDR); + firstFailDR = FALSE; + } + free_loc_user (loc); + } + return RP_MECH; + + case int_Qmgr_status_success: + break; + + case int_Qmgr_status_mtaFailure: + case int_Qmgr_status_messageFailure: + case int_Qmgr_status_mtaAndMessageFailure: + delivery_set (ap -> ad_no, retval); + free_loc_user (loc); + return RP_MECH; + + case NOTOK: + default: + PP_LOG (LLOG_EXCEPTIONS, + ("child process failed")); + delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + "Child process failed"); + free_loc_user (loc); + return RP_MECH; + } + + if (loc -> username) + PP_NOTICE ((">>> local : Message delivered to %s (%s)", + local_user, loc -> username)); + else + PP_NOTICE ((">>> local: Message delivered to %s (id %d/%d)", + local_user, loc -> uid, loc -> gid)); + free_loc_user (loc); + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_NO_REASON, + -1, NULLCP); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) { + delivery_set (ap -> ad_no, + (firstSuccessDR == TRUE) ? + int_Qmgr_status_positiveDR : + int_Qmgr_status_successSharedDR); + firstSuccessDR = FALSE; + } + } + else { + (void) wr_ad_status (ap, AD_STAT_DONE); + (void) wr_stat (ap, &Qstruct, this_msg, (int)message_size); + delivery_set (ap -> ad_no, int_Qmgr_status_success); + } + return RP_OK; +} diff --git a/Chans/822-local/mailfilter b/Chans/822-local/mailfilter new file mode 100644 index 0000000..e0e45ba --- /dev/null +++ b/Chans/822-local/mailfilter @@ -0,0 +1,25 @@ +# +# This is a comment +# +print $(to); +if ($(to) == /jpo/ ) { + pipe "rcvstore +to"; + ignore pipe "rcvalert 'to folder $(subject)'"; + delivered = TEMPFAIL; + exit ; +} +else if ($(to) == /jpo/ && $(from) == /pp-workers/) { + pipe "rcvalert +pp"; + ignore pipe "rcvalert 'PP folder'"; + exit(OK); +} +else if ($(sender) == /mmdf/) + pipe "rcvstore +mmdf2"; +else { + pipe "rcvstore +inbox"; + pipe "rcvalert 'foo'"; +} +if ( ! delivered) { + pipe "rcvstore +inbox"; + ignore pipe "rcvalert 'inbox folder'"; +} diff --git a/Chans/822-local/make b/Chans/822-local/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/822-local/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/822-local/parse_hdr.c b/Chans/822-local/parse_hdr.c new file mode 100644 index 0000000..8c7caca --- /dev/null +++ b/Chans/822-local/parse_hdr.c @@ -0,0 +1,124 @@ +/* parse_hdr: attempt to parse a header file */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/822-local/RCS/parse_hdr.c,v 6.0 1991/12/18 20:04:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/822-local/RCS/parse_hdr.c,v 6.0 1991/12/18 20:04:31 jpo Rel $ + * + * $Log: parse_hdr.c,v $ + * Revision 6.0 1991/12/18 20:04:31 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "expand.h" +#include "loc.h" + +extern void compress(); + +parse_hdr (fd, vars, maxvp) +int fd; +Expand vars[]; +int maxvp; +{ + FILE *fp; + Symbol *sp; + char *name, *contents; + int vp = 0; + + PP_TRACE (("parse_hdr (%d, vars, %d)", fd, maxvp)); + + fp = fdopen (dup(fd), "r"); + + while (hdr_read (fp, &name, &contents) == OK) { + if ((sp = lookup (name)) != NULL && sp -> type == field) { + if (vp >= maxvp) + adios (NULLCP, "More than %s variables!", + maxvp); + if (contents == NULLCP) + contents = ""; + if (sp -> str && *sp -> str) { + char *cp; + int i; + + cp = smalloc (strlen (sp -> str) + + strlen (contents) + 2); + (void) strcpy (cp, sp -> str); + (void) strcat (cp, " "); + (void) strcat (cp, contents); + free (sp -> str); + sp -> str = cp; + for (i = 0; i < vp; i++) + if (lexequ (vars[i].macro, name) == 0) { + vars[i].expansion = sp -> str; + break; + } + if (i >= vp) { + vars[vp].macro = strdup (name); + vars[vp++].expansion = sp -> str; + } + } + else { + sp -> str = strdup (contents); + vars[vp].macro = strdup (name); + vars[vp++].expansion = sp -> str; + } + } + } + fclose (fp); + return vp; +} + +hdr_read (fp, np, cp) +FILE *fp; +char **np, **cp; +{ + int c; + static char mybuf[8192]; + char *p; + + PP_TRACE (("hdr_read (fp, np, cp)")); + + *cp = NULLCP; + *np = mybuf; + + for (p = mybuf; (c = getc (fp)) != EOF;) { + if (c == '\n') { + if ((c = getc(fp)) == ' ' || c == '\t') + continue; + else { + ungetc (c, fp); + break; + } + } + else if (c == ':' && *cp == NULLCP) { + *cp = p + 1; + *p++ = '\0'; + continue; + } + if (p - mybuf < sizeof(mybuf) - 3) + *p++ = c; + + } + if (c == EOF && p == mybuf) + return DONE; + else if (p == mybuf) + return DONE; + + *p = 0; + compress (mybuf, mybuf); + if (*cp != NULLCP) + (void) compress (*cp, *cp); + + for (p = *np; *p; p++) + if (isupper(*p)) + *p = tolower (*p); + + PP_TRACE (("hdr_read field=%s contents=%s", *np, *cp)); + return OK; +} diff --git a/Chans/Makefile b/Chans/Makefile new file mode 100644 index 0000000..154226d --- /dev/null +++ b/Chans/Makefile @@ -0,0 +1,49 @@ +# Channel master makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/RCS/Makefile,v 6.0 1991/12/18 20:03:15 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:03:15 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +BASIC = dr2rfc filtercontrol msg-clean qmgr-load timeout trashman \ + splitter warnings +SUBDIRS = $(BASIC) $(OPTIONALCHANS) +ALLDIRS = $(BASIC) 822-local grey lists shell slocal \ + smtp uucp x40084 x40088 fax decnet testchan + +############################################################ +# +# Building Rules +# +############################################################ + +target: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +install: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + + +tidy define depend clean lint: + @for i in ${ALLDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Chans/decnet/Makefile b/Chans/decnet/Makefile new file mode 100644 index 0000000..6a4cf61 --- /dev/null +++ b/Chans/decnet/Makefile @@ -0,0 +1,200 @@ +# Decnet(mail11) channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/decnet/RCS/Makefile,v 6.0 1991/12/18 20:06:35 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:06:35 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = decnet.c de_wtmail.c decnetsrvr.c +OBJS = decnet.o de_wtmail.o decnetsrvr.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS=xdecnet xdecnetsrvr + +default: all + +all: $(PROGS) + +lint: l-decnet l-decnetsrvr + +decnet: xdecnet + +xdecnet: decnet.o de_wtmail.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ decnet.o de_wtmail.o \ + $(LIBPP) $(LIBRESOLV) $(LIBSYS) + +l-decnet: decnet.c de_wtmail.c + $(LINT) $(LLFLAGS) decnet.c de_wtmail.c $(LINTLIBS) + +decnetsrvr: xdecnetsrvr + +xdecnetsrvr: decnetsrvr.o $(LIBPP) + $(CC) $(LDFLAGS) decnetsrvr.o $(LIBPP) $(LIBSYS) $(LIBRESOLV) -o xdecnetsrvr + +l-decnetsrvr: decnetsrvr.c + $(LINT) $(LLFLAGS) decnetsrvr.c $(LINTLIBS) + + +install: inst-dir inst-decnet inst-decnetsrvr + +inst-dir: $(CHANDIR) + +inst-decnet: $(CHANDIR)/decnet + +$(CHANDIR)/decnet: xdecnet + -$(BACKUP) $@ zxdecnet + rm -f $@ + $(INSTALL) xdecnet $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "decnet channel installed normally"; echo "" + +inst-decnetsrvr: $(CHANDIR)/decnetsrvr + +$(CHANDIR)/decnetsrvr: xdecnetsrvr + -$(BACKUP) $@ zxdecnetsrvr + rm -f $@ + $(INSTALL) xdecnetsrvr $@ + -$(CHOWN) $(PPUSER) $@ + -$(CHMOD) 4755 $@ + -@ls -ls $@ + -@echo "you must now do whatever is necessary on your" + -@echo "system to enable $@ to be called when an incoming" + -@echo "mail11 connection comes in" + -@echo "decnet server installed normally"; echo " " + +test: test.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ test.o \ + $(LIBPP) $(LIBRESOLV) $(LIBSYS) + + +clean: tidy + rm -f $(OBJS) $(PROGS) core a.out *old *.BAK zx* + +tidy: + rm -f $(PROGS) zx* core a.out *old *.BAK + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + + + ############################################################ + # + # End of Building Rules + # + ############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +decnet.o: decnet.c +decnet.o: ../../h/head.h +decnet.o: ../../h/util.h +decnet.o: ../../h/config.h +decnet.o: ../../h/ll_log.h +decnet.o: ../../h/retcode.h +decnet.o: ../../h/chan.h +decnet.o: ../../h/table.h +decnet.o: ../../h/list_bpt.h +decnet.o: ../../h/prm.h +decnet.o: ../../h/q.h +decnet.o: ../../h/adr.h +decnet.o: ../../h/list_rchan.h +decnet.o: ../../h/chan.h +decnet.o: ../../h/auth.h +decnet.o: ../../h/list_bpt.h +decnet.o: ../../h/extension.h +decnet.o: ../../h/mta.h +decnet.o: ../../h/adr.h +decnet.o: ../../h/list_bpt.h +decnet.o: ../../h/aparse.h +decnet.o: ../../h/ap.h +decnet.o: ../../h/util.h +decnet.o: ../../h/or.h +decnet.o: ../../h/chan.h +decnet.o: ../../h/auth.h +decnet.o: ../../h/list_rchan.h +decnet.o: ../../h/mta.h +decnet.o: ../../h/dr.h +decnet.o: ../../h/extension.h +decnet.o: ../../h/mta.h +decnet.o: ../../h/qmgr.h +decnet.o: ../../h/Qmgr-types.h +decnet.o: ../../h/Qmgr-ops.h +de_wtmail.o: de_wtmail.c +de_wtmail.o: ../../h/util.h +de_wtmail.o: ../../h/config.h +de_wtmail.o: ../../h/ll_log.h +de_wtmail.o: ../../h/retcode.h +de_wtmail.o: ../../h/chan.h +de_wtmail.o: ../../h/table.h +de_wtmail.o: ../../h/list_bpt.h +de_wtmail.o: ../../h/ap.h +de_wtmail.o: ../../h/util.h +decnetsrvr.o: decnetsrvr.c +decnetsrvr.o: ../../h/head.h +decnetsrvr.o: ../../h/util.h +decnetsrvr.o: ../../h/config.h +decnetsrvr.o: ../../h/ll_log.h +decnetsrvr.o: ../../h/retcode.h +decnetsrvr.o: ../../h/chan.h +decnetsrvr.o: ../../h/table.h +decnetsrvr.o: ../../h/list_bpt.h +decnetsrvr.o: ../../h/prm.h +decnetsrvr.o: ../../h/q.h +decnetsrvr.o: ../../h/adr.h +decnetsrvr.o: ../../h/list_rchan.h +decnetsrvr.o: ../../h/chan.h +decnetsrvr.o: ../../h/auth.h +decnetsrvr.o: ../../h/list_bpt.h +decnetsrvr.o: ../../h/extension.h +decnetsrvr.o: ../../h/mta.h +decnetsrvr.o: ../../h/adr.h +decnetsrvr.o: ../../h/list_bpt.h +decnetsrvr.o: ../../h/aparse.h +decnetsrvr.o: ../../h/ap.h +decnetsrvr.o: ../../h/util.h +decnetsrvr.o: ../../h/or.h +decnetsrvr.o: ../../h/chan.h +decnetsrvr.o: ../../h/auth.h +decnetsrvr.o: ../../h/list_rchan.h +decnetsrvr.o: ../../h/mta.h +decnetsrvr.o: ../../h/ap.h +decnetsrvr.o: ../../h/retcode.h +decnetsrvr.o: ../../h/list_rchan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/decnet/de_wtmail.c b/Chans/decnet/de_wtmail.c new file mode 100644 index 0000000..208f389 --- /dev/null +++ b/Chans/decnet/de_wtmail.c @@ -0,0 +1,380 @@ +/* de_wtmail.c: nitty gritty of decnet */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/decnet/RCS/de_wtmail.c,v 6.0 1991/12/18 20:06:35 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/decnet/RCS/de_wtmail.c,v 6.0 1991/12/18 20:06:35 jpo Rel $ + * + * $Log: de_wtmail.c,v $ + * Revision 6.0 1991/12/18 20:06:35 jpo + * Release 6.0 + * + */ + +/* + * This module contains all the nitty gritty stuff which actually + * does the decnet communications + */ + +#include "util.h" +#include "retcode.h" +#include "chan.h" +#include "ap.h" +#include +#include +#include +#include +#include + +#define DEC_OK 0x01000000 +#define CC 0x10 +#define CC_OK 0x20 +#define MAXDNIBYTES 128 /* Maximum bytes in a line */ +#define NET_TIMEOUT 120 /* Timeout for net reads/writes */ + +/* Externals */ + +extern int de_fd; +extern int mrgate; +extern int cc_ok; +extern int map_space; +extern char space_char; +extern char toupper(); +char de_status_text[BUFSIZ]; + +/* Internals */ +char *user_addr(), *rfc_de(); + +/* This routine opens a logical link */ + +de_nopen(host, err) +char *host; +char *err; +{ + struct ses_io_type sesopts; + OpenBlock ob; + static OpenBlock template = + { + "", /* Host name (filled in later) */ + "", /* Task name */ + 27, /* Mail 11 */ + "", /* Userid */ + "", /* Account */ + "", /* Password */ + { /* Connect data */ + 16, /* 16 bytes of data */ + 3, /* protocol version 3 */ + 0, /* ECO level 0 */ + 0, /* Customer ECO level 0 */ + 0, /* OS type (other) */ + 0,0,0,0,/* No options */ + CC, /* Send CC: line */ + 0, /* Reserved */ + 0, /* reserved */ + 0, /* Reserved */ + 0, /* RMS RFM transfer mode */ + 0, /* RMS RAT type */ + 0, /* Reserved */ + 0 /* Reserved */ + } + }; + + PP_NOTICE(("opening connection to [%s]", host)); + + /* First open the logical link device */ + PP_DBG(("attempting to open logical link device")); + if ((de_fd = open("/dev/dni", O_RDWR)) < 0) + { + strcpy(err, "failed to open logical link device"); + return RP_LIO; + } + + /* Now set up I/O options. We need record mode */ + sesopts.io_flags = SES_IO_RECORD_MODE; + PP_DBG(("attempting to set record mode")); + if (ioctl(de_fd, SES_IO_TYPE, &sesopts) < 0) + { + strcpy(err, "failed to set i/o options"); + return RP_LIO; + } + + /* Now request link, including requesting CC: mode */ + ob = template; + strcpy(ob.op_node_name, host); + if (ioctl(de_fd, SES_LINK_ACCESS, &ob) < 0) + { + switch (errno & 0xff) + { + case FAILED: /* Connection failed */ + case NODE_UNREACH: /* Node unreacheable */ + sprintf(err, "failed to connect to host [%s], unreacheable", host); + return RP_NIO; + case BAD_NAME: /* Invalid host name */ + case NODE_NAME:/* Unrecognised node name */ + sprintf(err, "failed to connect to host [%s], bad host", host); + return RP_NO; + case BAD_OBJECT:/* Mail11 object does not exist */ + case OBJ_NAME: /* Ditto */ + sprintf(err, "failed to connect to host [%s], mail object not present", host); + return RP_NIO; + case BY_OBJECT: /* Mail 11 won't talk to us */ + sprintf(err, "failed to connect to host [%s], mail object not communicating", host); + return RP_NIO; + default: + sprintf(err, "failed to connect to host [%s], error = %d", host, errno & 0xff); + return RP_NIO; + } + } + + /* Check if CC: is aceptable */ + PP_TRACE(("connection data 0x%x(%d)", ob.op_opt_data.im_data[8], ob.op_opt_data.im_length)); + if (ob.op_opt_data.im_length == 0) + cc_ok = FALSE; + else + cc_ok = (ob.op_opt_data.im_data[8] & CC_OK) == CC_OK; + + PP_NOTICE(("connection open")); + strcpy(err, "connection open"); + return RP_OK; +} + +/* This routine closes a logical link */ + +de_nclose(type) +int type; +{ + SessionData sd; + + PP_NOTICE(("closing connection")); + sd.sd_reason = 0; + sd.sd_data.im_length = 0; + if (ioctl(de_fd, SES_DISCONNECT, &sd) < 0) + { + PP_NOTICE(("failed to close connection, so aborting link")); + ioctl(de_fd, SES_ABORT, &sd); + } + close(de_fd); + PP_TRACE(("connection closed")); +} + +/* This routine sends a `mark', used to delimit various parts of the protocol */ + +de_mark() +{ + char mark = 0; + + PP_TRACE(("de_mark()")); + if (timeout(NET_TIMEOUT)) + { + PP_NOTICE(("timed out while sending mark")); + return RP_NIO; + } + if (write(de_fd, &mark, 1) < 0) + { + timeout(0); + PP_NOTICE(("failed to transmit mark")); + return RP_NIO; + } + timeout(0); + return RP_OK; +} + +/* this routine sends a single address and returns a success (or otherwise) + code */ + +int de_wto(adr) +char *adr; +{ + + PP_TRACE(("de_wto(%s)", adr)); + + /* Extract the user part and send it */ + if (de_send(user_addr(adr)) != RP_OK) + return RP_NIO; + + switch (de_status()) + { + case RP_NIO: + return RP_NIO; + case RP_OK: + return RP_AOK; + case RP_NO: + return RP_USER; + default: + return RP_NO; + } +} + + +/* This routine sends a single, null terminated string to the decnet link */ + +de_send(buf) +char *buf; +{ + int size = strlen(buf); + + PP_TRACE(("de_send(%s)", buf)); + /* If size is greater than the maximum that the remote system + can handle (usually about 127 bytes) then truncate */ + if (size > MAXDNIBYTES) size = MAXDNIBYTES; + if (timeout(NET_TIMEOUT)) + { + PP_NOTICE(("connection timed out")); + return RP_NIO; + } + if (write(de_fd, buf, size) < 0) + { + timeout(0); + PP_NOTICE(("failed to transmit data, errno = %d", errno & 0xff)); + PP_NOTICE(("data was `%s'", buf)); + return RP_NIO; + } + timeout(0); + return RP_OK; +} + +/* This routine gets a status code from the decnet connection */ + +int de_status() +{ + char txt[LINESIZE]; + long status; + int len; + + PP_TRACE(("de_status()")); + + strcpy(de_status_text, ""); + if (timeout(NET_TIMEOUT)) + { + PP_NOTICE(("timeout while transmitting status")); + return RP_NIO; + } + if (read(de_fd, (char *)&status, sizeof(status)) < sizeof(status)) + { + timeout(0); + return (RP_NIO); + } + timeout(0); + PP_DBG(("got 0x%lx", status)); + + /* If bit 0 is set then good status */ + if ((status & DEC_OK) == DEC_OK) + { + return (RP_OK); + } + else + { + if (timeout(NET_TIMEOUT)) + { + PP_NOTICE(("timeout while reading status")); + return RP_NIO; + } + while ((len = read(de_fd, txt, sizeof(txt))) >= 0) + { + if (len == 1 && txt[0] == 0) + { + timeout(0); + return RP_NO; + } + else + { + txt[len] = '\0'; + if (sizeof(de_status_text) - strlen(de_status_text) > len) + { + strcat(de_status_text, txt); + strcat(de_status_text, "\n"); + } + } + } + /* If we get here, the connection has dropped */ + timeout(0); + return (RP_NIO); + } +} + +/* This routine takes an RFC822 message and returns the user part forced + to upper case, `_' mapped to space if necessary */ + +char *user_addr(addr) +char *addr; +{ + AP_ptr tree, group, name, local, domain, route; + char *s; + char *final; + + PP_DBG(("user_addr(%s)", addr)); + if (ap_s2p(addr, &tree, &group, &name, &local, &domain, &route) == (char *)NOTOK) + { + return "Orphanage"; + } + for (s = local->ap_obvalue; *s = toupper(*s); s++) + { + if (map_space && *s == space_char) *s = ' '; + } + + /* Allocate enough space for string + MRGATE:: if needed */ + final = malloc(strlen(local->ap_obvalue) + 10); + + /* Tack on an MRGATE if talking to one */ + strcpy(final, (mrgate) ? "MRGATE::" : ""); + strcat(final, local->ap_obvalue); + + PP_DBG(("returns: %s", final)); + return (final); +} + +/* This procedure takes an RFC822 string and converts it to DecNet format */ + +char *rfc_de(addr) +char *addr; +{ + AP_ptr tree, group, name, local, domain, route, a; + char *final; + int size = 0; + + PP_DBG(("rfc_de(%s)", addr)); + if (ap_s2p(addr, &tree, &group, &name, &local, &domain, &route) == (char *)NOTOK) + { + return "Orphanage"; + } + + /* OK, now troll down the tree adding up the sizes so we can alloc + a big enough string */ + + for (a = tree; a ; a = a->ap_next) + { + switch(a->ap_obtype) + { + case AP_MAILBOX: + size += strlen(a->ap_obvalue) + 1; + break; + case AP_DOMAIN: + size += strlen(a->ap_obvalue) + 2; + break; + } + } + + /* Allocate the space */ + final = malloc(size); + + /* Now build the decnet address */ + + for (a = tree, strcpy(final, ""); a ; a = a->ap_next) + { + if (a->ap_obtype == AP_DOMAIN) + { + strcat(final, a->ap_obvalue); + strcat(final, "::"); + } + } + for (a = tree; a ; a = a->ap_next) + { + if (a->ap_obtype == AP_MAILBOX) + strcat(final, a->ap_obvalue); + } + + PP_TRACE(("returns: %s", final)); + return (final); +} diff --git a/Chans/decnet/decnet.c b/Chans/decnet/decnet.c new file mode 100644 index 0000000..73e17bb --- /dev/null +++ b/Chans/decnet/decnet.c @@ -0,0 +1,681 @@ +/* decnet.c: main decnet program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/decnet/RCS/decnet.c,v 6.0 1991/12/18 20:06:35 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/decnet/RCS/decnet.c,v 6.0 1991/12/18 20:06:35 jpo Rel $ + * + * $Log: decnet.c,v $ + * Revision 6.0 1991/12/18 20:06:35 jpo + * Release 6.0 + * + */ + +/* + * Mail11 channel for PP + */ + +#include "head.h" +#include "chan.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include + +/* Externs */ +extern char *quedfldir; +extern void rd_end(), chan_init(), err_abrt(), timer_start(), timer_end(); +FILE *msg_fp; +extern char *rfc_de(); +extern char de_status_text[]; + +/* Local variables */ +CHAN *mychan; /* Our channel structure */ +char *sender; /* Message sender */ +char *this_msg; /* Message id */ +char *cur_host = NULLCP; /* Current host */ +char *open_host = NULLCP; +char bp_name[MAXPATHLENGTH]; /* Body part file name */ +FILE *bp; /* Body part file descriptor */ +int strip = 0; /* If true then strip headers */ +int cc_ok = 0; /* If true then may send cc line */ +int mrgate = 0; /* If true then talking to MRGATE */ +int map_space = 0; /* If true then map to ' ' */ +char space_char = '_'; /* Character which will be substituted by ' ' */ +int de_fd; /* File descriptor for decnet */ +int open_state; /* defines meaning of open_host */ +#define STATE_INITIAL 0 +#define STATE_OPEN 1 +#define STATE_BAD_HOST 2 +#define STATE_TIMED_OUT 3 + +/* Local Procedures */ +char *fix_header(); +void dirinit(); +int chaninit(), + endproc(); +struct type_Qmgr_DeliveryStatus *process(); +static int data_bytes; + +main(argc, argv) +int argc; +char **argv; +{ + + /* First initialise the channel */ + + chan_init(argv[0]); + + /* Go to correct directory */ + + dirinit(); + +#ifdef PP_DEBUG + if (argc > 1 && strcmp(argv[1], "debug") == 0) + debug_channel_control(argc, argv, chaninit, process, endproc); + else +#endif + channel_control(argc, argv, chaninit, process, endproc); + exit(0); +} + +static int chaninit(arg) +struct type_Qmgr_Channel *arg; +{ + extern char *strstr(); + char *p = qb2str(arg); + + /* Check channel OK */ + if ((mychan = ch_nm2struct(p)) == (CHAN *)0) + err_abrt(RP_PARM, "Channel `%s' not known", p); + /* Do any initialising */ + + rename_log(p); + PP_NOTICE (("starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); + + /* Check the config options */ + strip = (strstr(mychan->ch_out_info, "strip") != NULLCP); + mrgate = (strstr(mychan->ch_out_info, "mrgate") != NULLCP); + map_space = (strstr(mychan->ch_out_info, "map_space") != NULLCP); + + PP_TRACE (("options: strip(%d) mrgate(%d) map_space(%d)", strip, mrgate, map_space)); + + free(p); + return (OK); +} + +static int endproc() +{ + PP_TRACE(("endproc()")); +} + +static struct type_Qmgr_DeliveryStatus *process(arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + struct type_Qmgr_UserList *up; + Q_struct Qstruct, *qp = &Qstruct; + int retval; + ADDR *ap, + *ad_sendr = NULLADDR, + *ad_recip = NULLADDR, + *alp, + *ad_list = NULLADDR; + int ad_count; + + PP_TRACE(("process()")); + if (this_msg) free(this_msg); + + this_msg = qb2str (arg -> qid); + + PP_TRACE(("process msg %s", this_msg)); + + memset((char *)&prm, 0, sizeof(prm)); + memset((char *)qp, 0, sizeof(*qp)); + + (void) delivery_init(arg->users); + + retval = rd_msg(this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + + if (rp_isbad(retval)) + { + PP_LOG(LLOG_EXCEPTIONS,("rd_msg err: %s", this_msg)); + return delivery_setall(int_Qmgr_status_messageFailure); + } + + sender = ad_sendr->ad_r822adr; + PP_TRACE(("sender: %s", sender)); + + for (ap = ad_recip; ap; ap = ap->ad_next) + { + for (up = arg->users; up; up = up->next) + { + if (up->RecipientId->parm != ap->ad_no) + continue; + switch (chan_acheck (ap, mychan, + ad_list == NULLADDR, &cur_host)) { + default: + case NOTOK: + continue; + + case OK: + break; + } + break; + } + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + { + PP_DBG(("allocating ad_list and alp")); + ad_list = alp = (ADDR *)calloc(1, sizeof(*alp)); + } + else + { + PP_DBG(("allocating alp")); + alp->ad_next = (ADDR *)calloc(1, sizeof(*alp)); + alp = alp->ad_next; + } + *alp = *ap; + alp->ad_next = NULLADDR; + } + + if (ad_list == NULLADDR) + { + PP_LOG(LLOG_EXCEPTIONS, ("No recipients in user list")); + rd_end(); + q_free (qp); + return deliverystate; + } + + PP_NOTICE (("processing msg %s to %s", this_msg, cur_host)); + + deliver(ad_list, qp); + + q_free (qp); + rd_end(); + + return deliverystate; +} + +/* Do delivery of message */ + +deliver(ad_list, qp) +ADDR *ad_list; +Q_struct *qp; +{ + ADDR *ap; + int naddrs, good_cnt, bad_cnt; + char buf [LINESIZE]; + struct timeval data_time; + + PP_TRACE(("deliver()")); + + if (lexequ (cur_host, open_host) != 0) + { + /* Brand new host */ + + if (open_host != NULLCP) + { + free (open_host); + if (open_state == STATE_OPEN) + de_nclose (OK); + } + open_host = strdup (cur_host); + + switch (de_nopen (cur_host, buf)) + { + case RP_OK: + open_state = STATE_OPEN; + break; + case RP_NO: + open_state = STATE_BAD_HOST; + break; + default: + open_state = STATE_TIMED_OUT; + break; + } + } + + switch (open_state) + { + case STATE_OPEN: + break; /* just carry on */ + case STATE_BAD_HOST: + PP_NOTICE ((buf)); + set_all_dr (qp, ad_list, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + buf); + wr_q2dr (qp, this_msg); + (void) delivery_setall (int_Qmgr_status_negativeDR); + return; + case STATE_TIMED_OUT: + PP_NOTICE (("Connection failed to '%s': %s", + cur_host, buf)); + (void) delivery_setallstate + (int_Qmgr_status_mtaFailure, + buf); + return; + } + + naddrs = 0; + + if (do_sender (ad_list, sender) == NOTOK) + return; + + for (ap = ad_list; ap; ap = ap -> ad_next) { + switch (do_recip (ap, qp) ){ + case OK: + naddrs ++; + break; + + case NOTOK: + break; + + default: + return; + } + } + + if (naddrs == 0) { + (void) reset (); + wr_q2dr (qp, this_msg); + PP_NOTICE ((">>> Message %s transfered to no recipients", + this_msg, naddrs)); + delivery_setall (int_Qmgr_status_negativeDR); + return; + } + /* Terminate list of addressees */ + de_mark(); + + data_bytes = 0; + timer_start (&data_time); + + /* Send To: Cc: and Subj: headers */ + if (rp_isbad(de_headers(ad_list))) + { + PP_NOTICE((">>> Message %s failed during header transfer", + this_msg)); + msg_rend(); + return; + } + + /* Send message body */ + if (rp_isbad(de_txt())) + { + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "failure during body transfer"); + PP_NOTICE((">>> Message %s failed during body transfer", + this_msg)); + (void) reset(); + msg_rend(); + return; + } + + /* Sit and receive the status codes */ + bad_cnt = good_cnt = 0; + for (ap = ad_list; ap; ap = ap->ad_next) + { + if (ap->ad_resp) + { + switch (de_status()) + { + case RP_NIO: + delivery_setstate (ap -> ad_no, int_Qmgr_status_mtaAndMessageFailure, "channel failure during final status phase"); + bad_cnt++; + break; + case RP_OK: + (void) wr_ad_status (ap, AD_STAT_DONE); + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) + { + set_1dr (qp, ap -> ad_no, this_msg, + DRR_NO_REASON, -1, NULLCP); + delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + } + else { + delivery_set (ap -> ad_no, int_Qmgr_status_success); + wr_stat (ap, qp, this_msg, data_bytes); + } + good_cnt++; + break; + case RP_NO: + set_1dr (qp, ap->ad_no, this_msg, + DRR_TRANSFER_FAILURE, + DRD_MTA_CONGESTION, + de_status_text); + delivery_setstate (ap -> ad_no, + int_Qmgr_status_negativeDR, + "message transfer failed during final status phase"); + bad_cnt++; + break; + default: + set_1dr (qp, ap->ad_no, this_msg, + DRR_TRANSFER_FAILURE, + DRD_MTA_CONGESTION, + "final status failure (unknown reason)"); + delivery_setstate (ap -> ad_no, int_Qmgr_status_negativeDR, "internal MTA failure during final status phase"); + bad_cnt++; + break; + } + } + } + timer_end (&data_time, data_bytes, "Data Transfered"); + + wr_q2dr (qp, this_msg); + PP_NOTICE ((">>> Message %s transferred to %d recipients, failed on %d recipients", + this_msg, good_cnt, bad_cnt)); + /* Unlock the message files */ + msg_rend(); +} + +/* Change in PP queue space */ + +static void dirinit() +{ + if (chdir(quedfldir) < 0) + err_abrt(RP_LIO, "Unable to change directory to `%s'", quedfldir); +} + +/* Send the `sender field' */ + +do_sender(ap, sndr) +ADDR *ap; +char *sndr; +{ + char *formatdir; + char buf[LINESIZE]; + char *from = NULLCP; + + PP_TRACE(("do_sender()")); + + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message %s", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't find message"); + (void) reset (); + return NOTOK; + } + + if (rp_isbad (msg_rinit (formatdir))) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't read message %s files", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + reset (); + return NOTOK; + } + + /* Get the first file (which will be the header) */ + + if (rp_isbad (msg_rfile (bp_name))) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't initialise message %s files", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message file name"); + reset (); + return NOTOK; + } + + PP_TRACE(("message file (%s)", bp_name)); + /* open the file */ + if ((bp = fopen(bp_name, "r")) == 0) + { + PP_LOG (LLOG_EXCEPTIONS, ("Can't open bp %s file", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't open bp file"); + reset (); + return NOTOK; + } + + /* Now extract the From: line (removing the terminating + newline */ + while (fgets(buf, sizeof(buf), bp) != 0) + { + buf[strlen(buf) - 1] = '\0'; + if (strncmp(buf, "From:", 5) == 0) + { + from = strdup(fix_header(buf)); + break; + } + } + + /* Check if we are sending to a mail router. If so then we have + to make the sender address look as VMSish as possible */ + if (mrgate) + { + return (de_send((from) ? rfc_de(from) : rfc_de(sndr))); + } + + /* Check and see if the sender needs quotes to protect it from the + depredations of VMS */ + + if (strpbrk((from) ? from : sndr, "@%:,") != 0) + sprintf(buf, "\"%s\"", (from) ? from : sndr); + else + strcpy(buf, (from) ? from: sndr); + + return (de_send(buf)); +} + +/* This routine passes over a single recipient address */ + +do_recip (ap, qp) +ADDR *ap; +Q_struct *qp; +{ + char errbuf[BUFSIZ]; + + PP_NOTICE (("Recipient %s", ap -> ad_r822adr)); + + switch (de_wto (ap ->ad_r822adr)) + { + case RP_AOK: + ap -> ad_resp = 1; + return OK; + + case RP_NIO: + (void) delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + "network error"); + PP_LOG (LLOG_EXCEPTIONS, ("Temporary failure: %s", + "network error")); + ap -> ad_resp = 0; + return NOTOK; + + case RP_USER: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + (void) sprintf (errbuf, + "MTA '%s' rejects address %s", + cur_host, ap->ad_r822adr); + PP_LOG (LLOG_EXCEPTIONS, ("User error: %s", errbuf)); + set_1dr (qp, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + errbuf); + ap -> ad_resp = 0; + return NOTOK; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Message failure: %s", + "unknown error")); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "unknown error"); + (void) reset (); + return DONE; + } +} + +/* This routine gets and sends the header lines */ + +de_headers(ap) +ADDR *ap; +{ + char line[BUFSIZ]; + char *to = NULLCP, + *subject = NULLCP, + *cc = NULLCP; + + PP_TRACE(("de_headers()")); + + /* Rewind the header file (opened by de_from) */ + rewind(bp); + + /* Now extract the To:, Cc: and Subject lines (removing the terminating + newline */ + while (fgets(line, sizeof(line), bp) != 0) + { + line[strlen(line) - 1] = '\0'; + if (strncmp(line, "To:", 3) == 0) + { + to = strdup(line); + } + else if (strncmp(line, "Subject:", 8) == 0) + { + subject = strdup(line); + } + else if (strncmp(line, "Cc:", 3) == 0) + { + cc = strdup(line); + } + } + + /* Send the various fields */ + if (rp_isbad(de_send((to) ? fix_header(to) : "(Unknown)")) + || (cc_ok && rp_isbad(de_send((cc) ? fix_header(cc) : ""))) + || rp_isbad(de_send((subject) ? fix_header(subject) : "(None)"))) + { + (void) delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + "network error"); + PP_LOG (LLOG_EXCEPTIONS, ("Temporary failure: %s", + "network error")); + return NOTOK; + } + + /* Clean up */ + if (to) free(to); + if (subject) free(subject); + if (cc) free(cc); + + return OK; +} + +/* This routine gets and sends the message text */ + +de_txt() +{ + char line[BUFSIZ]; + int n; + + PP_TRACE(("de_txt()")); + /* If we have set header stripping then close the header */ + if (strip) + { + fclose(bp); + /* If there is no more body parts, just wrap up */ + if (msg_rfile(bp_name) == RP_DONE) + { + de_mark(); + return OK; + } + /* other wise open the next body part */ + if ((bp = fopen(bp_name, "r")) == 0) + { + PP_LOG (LLOG_EXCEPTIONS, ("Can't open bp %s file", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't open bp file"); + reset (); + return NOTOK; + } + } + else + { + rewind(bp); + } + + /* Now iterate through the body parts */ + while (1) + { + /* Send a body part */ + while (fgets(line, sizeof(line), bp) != 0) + { + line[(n = strlen(line)) - 1] = '\0'; + n--; + data_bytes += n; + if (rp_isbad(de_send(line))) + { + return NOTOK; + } + } + /* Send a blank line to seperate the body parts */ + de_send(""); + + /* Close it and get the next one */ + fclose(bp); + + /* If there is no more body parts, just wrap up */ + if (msg_rfile(bp_name) == RP_DONE) + break; + + /* other wise open the next body part */ + if ((bp = fopen(bp_name, "r")) == 0) + { + PP_LOG (LLOG_EXCEPTIONS, ("Can't open bp %s file", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't open bp file"); + reset (); + return NOTOK; + } + } + de_mark(); + return OK; +} + +/* This is the equivalent of the `reset' function. However, since mail11 + doesn't have the ability to reset, we have to close down the connection + */ + +reset() +{ + PP_TRACE(("reset()")); + + if (open_host != NULLCP) + { + free (open_host); + if (open_state == STATE_OPEN) + de_nclose (OK); + open_host = NULLCP; + } +} + +/* This trivial little function takes a header line and returns a pointer + to the first non space character after the first `:' + */ + +char *fix_header(h) +char *h; +{ + char *s; + extern char *strchr(); + + if ((s = strchr(h, ':')) != NULL) + { + while (*++s == ' '); + return s; + } + return h; + +} diff --git a/Chans/decnet/decnetsrvr.c b/Chans/decnet/decnetsrvr.c new file mode 100644 index 0000000..b70fdc1 --- /dev/null +++ b/Chans/decnet/decnetsrvr.c @@ -0,0 +1,665 @@ +/* decnectsrvr.c: DecNet Server */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/decnet/RCS/decnetsrvr.c,v 6.0 1991/12/18 20:06:35 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/decnet/RCS/decnetsrvr.c,v 6.0 1991/12/18 20:06:35 jpo Rel $ + * + * $Log: decnetsrvr.c,v $ + * Revision 6.0 1991/12/18 20:06:35 jpo + * Release 6.0 + * + */ + +/* decnet server designed to be started by dniserver (sunlink DNI) + + Unfortunately there seems to be no way of passing parameters + in to the slave process from dniserver, so we cannot pass in the + channel name. This is thus hardwired in as `decnet-in'. + + Sorry folks... + + Some design philosophy: we accept all recipient addresses, no matter + how preposterous. We then generate non-delivery reports. This means + that users of All-in-One and Mail Router actually get failure reports + in a timely fashion, rather than several days later which is what happens + if we reject the recipient addresses at the mail11 protocol level. Of course + it means that users of straight VMS mail have to wait a few extra seconds + for their failure notification, but what the hell, they shouldn't be + using it anyway. + + Mail11 To: and Cc: lines are accepted and mapped to X-Vms-To: and X-Vms-Cc: + in order to save us the possibly fruitless task of trying to parse and + convert what the incoming mailer dumps into these records. All recipients + are treated as primary recipients and inserted into a proper To: line + + We map the sender address into a From: line, after having been converted to + RFC822. Personal names are mapped into comments, as we cannot guarantee + the contents of the mail11 personal name data (and it is easier anyway). + + We add a Date: field. This of course is date of acceptance at the incoming + interface and bears no resemblance to actual date of posting. + + */ + +#include "head.h" +#include "chan.h" +#include "prm.h" +#include "q.h" +#include "ap.h" +#include "retcode.h" +#include "list_rchan.h" + +#include +#include +#include + +#define DEC_OK 0x01000000 +#define MAXLINE 78 /* Max characters on header line */ +#define NET_TIMEOUT 120 /* Timeout for net reads/writes */ + + +/* Externals */ +extern char *cont_822; + +/* Internals */ +char *decnet_in = "decnet-in"; /* Name of this channel */ +char *remote_host; /* name of the remote host */ +CHAN *mychan; +int de_fd = 3; /* The decnet file descriptor */ +int cc_ok = 0; /* CC line OK */ +int map_space = 0; /* Do we want to map spaces? */ +char *de_s2s(); +ADDR *to_first = 0; /* Will contain list of recipients */ +ADDR *ad_sender; /* Will contain sender */ + + +/* ARGSUSED */ +main(argc, argv) +int argc; +char *argv[]; +{ + int state = 0; + int addrs, mark; + RP_Buf rp; + char record[BUFSIZ]; + + /* First initialise the channel */ + chan_init(decnet_in); + + /* Do any initialisation */ + chaninit(); + + /* Now start the real work */ + while (rp_isgood(de_get(record, sizeof(record), &mark))) + { + switch (state) + { + case 0: /* Start of a message, getting sender */ + do_sender(record); + addrs = 0; + state = 1; + break; + case 1: /* Process addressees */ + if (!mark) + { + do_recip(record); + addrs++; + } + else + { + if (rp_isbad(io_adend(&rp)) + || rp_isbad(io_tinit(&rp)) + || rp_isbad(io_tpart("hdr.822", 0, &rp))) + error(rp.rp_line); + state = 2; + } + break; + case 2: /* Now get To: line */ + do_to(record); + if (cc_ok) + state = 3; + else + state = 4; + break; + case 3: /* Now get Cc: line if allowed */ + do_cc(record); + state = 4; + break; + case 4: /* Now get Subject: line */ + do_subject(record); + if (rp_isbad(io_tdend(&rp)) + || rp_isbad(io_tpart("2.ia5", 0, &rp))) + error(rp.rp_line); + state = 5; + break; + case 5: /* Now do the text */ + if (!mark) + do_txt(record); + else + { + if (rp_isbad(io_tdend(&rp)) + || rp_isbad(io_tend(&rp))) + error(rp.rp_line); + do_status(addrs); + state = 0; + PP_NOTICE((">>> Message sent to %d recipients", addrs)); + } + break; + } + } + + /* If here then connection has failed for some reason. + This may be normal */ + if (state == 0) + { + PP_NOTICE(("Channel terminating normally")); + io_end(OK); + } + else + { + PP_NOTICE(("Channel terminated abnormally (state %d)", state)); + io_end(NOTOK); + } + exit(0); +} + +/* This procedure does any initialisation. This includes accepting the + decnet connection */ + +chaninit() +{ + extern char *strstr(); + SessionData sd; + OpenBlock ob; + struct prm_vars prm; + RP_Buf rp; + + PP_TRACE(("chaninit()")); + + /* Get access info */ + if (ioctl(de_fd, SES_GET_AI, &ob) < 0) + error("failed to get access information"); + remote_host = strdup(ob.op_node_name); + + /* Check channel OK */ + if ((mychan = ch_mta2struct(decnet_in, remote_host)) == (CHAN *)0) + error("Channel not known"); + + /* Do any initialising */ + rename_log(mychan -> ch_name); + PP_NOTICE (("Connection from [%s] on channel %s", remote_host, + mychan -> ch_name)); + + /* Accept the connection */ + sd.sd_data.im_length = 0; + if (ioctl(de_fd, SES_ACCEPT, &sd) < 0) + error("decnet accept failed"); + + /* Initialise IO system */ + setuid(geteuid()); + if (rp_isbad(io_init(&rp))) + error("failed to initialise incoming decnet channel"); + + /* Set up the management parameters */ + prm_init(&prm); + prm.prm_opts = PRM_ACCEPTALL; + if (rp_isbad(io_wprm(&prm, &rp))) + error("failed to set management parameters"); + prm_free(&prm); + + /* Check config options */ + map_space = (strstr(mychan->ch_in_info, "map_space") != NULLCP); + + PP_TRACE(("options: map_space(%d)", map_space)); + +} + +/* This procedure takes a string containing the sender name in DEC format + and starts the message submission process + */ + +do_sender(sender) +char *sender; +{ + char *cp; + Q_struct qp; + RP_Buf rp; + char lcl_sender[BUFSIZ]; + + PP_TRACE(("do_sender(%s)", sender)); + + /* Set up the per message parameters */ + PP_TRACE(("set up message parameters")); + q_init(&qp); + /* qp.cont_type = strdup(cont_822); */ + txt2listbpt(&qp.encodedinfo.eit_types, cp = strdup("ia5,hdr.822")); + free (cp); + qp.inbound = list_rchan_new(remote_host, mychan -> ch_name); + if (rp_isbad(io_wrq(&qp, &rp))) + error(rp.rp_line); + q_free(&qp); + + /* Set up the sender address */ + PP_TRACE(("set up sender address")); + sprintf(lcl_sender, "%s::%s", remote_host, sender); + ad_sender = adr_new(de_s2s(lcl_sender), AD_ANY_TYPE, 0); + if (rp_isbad(io_wadr(ad_sender, AD_ORIGINATOR, &rp))) + error(rp.rp_line); + +} + +/* This procedure takes one recipient address, submits it, and returns + the DECnet status value. Note that we always accept addresses. If the + address is incorrect we return a non-delivery report. This is for the + benefit of the cretinous behaviour of VMS MRgate software which just + keeps on resubmitting failed mail at short intervals until it times out, + several days later. + + A To: line is built up at the same time. + + */ + +do_recip(recip) +char *recip; +{ + ADDR *ad_recip; + RP_Buf rp; + + PP_TRACE(("do_recip(%s)", recip)); + + /* If we get a failure from io_wadr then this is fairly major, + as we have asked submit to handle non-delivery reports */ + + ad_recip = adr_new(de_s2s(recip), AD_ANY_TYPE, 1); + if (rp_isbad(io_wadr(ad_recip, AD_RECIPIENT, &rp))) + error(rp.rp_line); + adr_add(&to_first, ad_recip); + + de_send_status(OK); +} + +/* This procedure takes a Cc: line and maps it to an X-Vms-Cc: line in the + header + */ + +do_cc(cc) +char *cc; +{ + char line[BUFSIZ]; + + PP_TRACE(("do_cc(%s)", cc)); + sprintf(line, "X-Vms-Cc: %s\n", cc); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write Cc: line"); + +} + +/* This procedure takes a To: line and maps it to a X-Vms-To: line in the + header. It also creates a new To: line out of the list of recipients + built by do_recip and a From: line out of ad_sender + */ + +do_to(to) +char *to; +{ + char line[BUFSIZ]; + ADDR *ad; + + PP_TRACE(("do_to(%s)", to)); + sprintf(line, "X-Vms-To: %s\n", to); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write X-Vms-To: line"); + + for (ad = to_first, strcpy(line, "To: "); ad; ad = ad->ad_next) + { + if ((strlen(line) + strlen(ad->ad_value) + 4) > MAXLINE) + { + strcat(line, "\n"); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write To: line"); + strcpy(line, " "); + } + strcat(line, ", "); + strcat(line, ad->ad_value); + } + strcat(line, "\n"); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write To: line"); + sprintf(line, "From: %s\n", ad_sender->ad_value); + PP_NOTICE(("From %s", ad_sender->ad_value)); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write From: line"); + +} + +/* This procedure takes a Subject: line and inserts it into the header + * also inserts Date: line + */ + +do_subject(subject) +char *subject; +{ + char line[BUFSIZ], buf[BUFSIZ]; + UTC ut, lt; + extern UTC utclocalise(); + + PP_TRACE(("do_subject(%s)", subject)); + sprintf(line, "Subject: %s\n", subject); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write Subject: line"); + + /* Do date */ + ut = utcnow(); + lt = utclocalise(ut); + + UTC2rfc(lt, buf); + sprintf(line, "Date: %s\n", buf); + if (rp_isbad(io_tdata(line, strlen(line)))) + error("failed to write Date: line"); + free ((char *)ut); + free ((char *)lt); + +} + +/* This procedure takes a single text record and inserts it into the body + */ + +do_txt(line) +char *line; +{ + PP_TRACE(("do_txt(%s)", line)); + + if ((strlen(line) && rp_isbad(io_tdata(line, strlen(line)))) + || rp_isbad(io_tdata("\n", 1))) + error("failed to write text line"); + +} + +/* This procedure sends `n' OK status messages back to DECnet */ + +do_status(n) +int n; +{ + + PP_TRACE(("do_status(%d)", n)); + + for ( ; n > 0 ; n--) + de_send_status(OK); + +} + +/* This procedure winds up in the event of error. It prints a notice in the + log, aborts the decnet connection (if still extant), aborts the message + submission process, and exits. It will be called in the event of any + failure in the protocol, as there is *no* recovery mechanism. + */ + +error(s) +char *s; +{ + SessionData sd; + + PP_NOTICE(("error exit [%s]", s)); + + /* Abort the DECnet link (don't bother to check return status) */ + sd.sd_reason = 0; + sd.sd_data.im_length = 0; + ioctl(de_fd, SES_ABORT, &sd); + + /* Abort message submission process */ + io_end(NOTOK); + + /* Farewell */ + exit(1); + +} + +/* This procedure sends a status to the DECnet */ + +de_send_status(value) +int value; +{ + long status; + + PP_TRACE(("de_send_status(%d)", value)); + + status = DEC_OK; + if (timeout(NET_TIMEOUT)) + { + error("decnet timeout in write"); + } + if (write(de_fd, (char *)&status, sizeof(status)) != sizeof(status)) + error("failed to write status value"); + timeout(0); + +} + +/* This procedure takes an address in DECNet form and returns a parse tree. + Mail11 personal names are converted to comments. If the address + is surrounded by quotes then we assume it is not for conversion and feed + it into the normal address parser. We also force the address (not the + comments) into lower case, as I hate machines that SHOUT at me. Internal + (to the address) quotes are removed, as these seem to be generated by + MRGATE somewhat gratuitously. + */ + +AP_ptr de_s2t(s) +char *s; +{ + AP_ptr ap, + ap_start, + local_host = NULLAP, + route_host = NULLAP, + personal = NULLAP; + int state = 0; + char *t, *token, *token_end, *last_token; + + PP_TRACE(("de_s2t(%s)", s)); + for (ap_start = ap = ap_alloc(), t = s; *t; t++) + { + switch (state) + { + case 0: /* Start of things. Looking for non_space */ + if (*t == '"') /* Assume RFC822 address */ + { + token = t + 1; + state = 5; + } + else + { + *t = tolower(*t); + token = t; + state = 1; + last_token = 0; + } + break; + case 1: /* Looking at host names or mailbox names */ + if (*t == ':') /* Could be start of a :: */ + { + state = 2; + } + else if (*t == ' ') /* Could be mailbox */ + { + token_end = t; + state = 3; + } + else + { + *t = tolower(*t); + } + break; + case 2: /* Just got a :, looking for the next */ + if (*t == ':') /* Bingo! Got a :: */ + { + *(t - 1) = '\0'; + + /* Now tack it into the parse tree */ + if (strstr(token, "mrgate") == 0 && + strstr(token, "a1") == 0 && + !( last_token && strstr(token, last_token))) + { + ap_fllnode(ap, AP_DOMAIN, token); + route_host = local_host; + local_host = ap; + ap->ap_next = ap_alloc(); + ap->ap_ptrtype = AP_PTR_MORE; + ap = ap->ap_next; + last_token = token; + } + token = t + 1; + state = 1; + } + else /* Error */ + { + return (BADAP); + } + break; + case 3: /* May be end of user name */ + if (*t == '"') /* personal name */ + { + *token_end = '\0'; + ap_fllnode(ap, AP_MAILBOX, token); + token = t + 1; + state = 4; + } + else if (*t != ' ') /* Bother, not finished */ + { + *t = tolower(*t); + state = 1; + } + break; + case 4: /* Collecting personal name */ + break; + case 5: /* processing quoted address */ + if (*t == '"') + *t = '\0'; + break; + } + } + /* Finish off if necessary */ + if (state == 3) + *token_end = '\0'; + if ((state == 1 || state == 3) && + !(last_token && strstr(token, last_token))) + ap_fllnode(ap, AP_MAILBOX, token); + if (state == 4) + { + *(t - 1) = '\0'; + personal = ap_new(AP_COMMENT, token); + } + + /* If state 5 then was processing RFC address */ + if (state == 5) + ap_start = ap_s2t(token); + else /* We have to take last host and put after mailbox */ + { + if (route_host) + { + ap_move(route_host, local_host); + if (personal) + ap_insert(local_host, AP_PTR_MORE, personal); + } + else if (local_host) + { + ap->ap_next = local_host; + ap->ap_ptrtype = AP_PTR_MORE; + local_host->ap_next = NULLAP; + local_host->ap_ptrtype = AP_PTR_NIL; + ap_start = ap; + if (personal) + ap_insert(local_host, AP_PTR_MORE, personal); + } + else if (personal) + ap_insert(ap, AP_PTR_MORE, personal); + + } + + /* Last of all we cruise down the tree removing spurious "s + in DOMAIN and MAILBOX tokens. Also at this point we map ' ' to '_' + if required */ + for (ap = ap_start; ap; ap = ap->ap_next) + { + if (ap->ap_obtype == AP_DOMAIN || ap->ap_obtype == AP_MAILBOX) + { + char *s1, *d; + + for (s1 = d = ap->ap_obvalue; *s1; s1++) + if (map_space && *s1 == ' ') *d++ = '_'; + else if (*s1 != '"') *d++ = *s1; + *d = '\0'; + } + } + + return (ap_start); +} + +/* This procedure takes a decnet address and returns it mapped to RFC822 + */ + +char *de_s2s(de) +char *de; +{ + AP_ptr tree; + char *rfc; + + PP_TRACE(("de_s2s(%s)", de)); + ap_norm_all_domains(); + if ((tree = de_s2t(de)) != BADAP) + { + ap_t2s(ap_normalize(tree, mychan->ch_ad_order), &rfc); + PP_TRACE(("returns: `%s'", rfc)); + return (rfc); + } + PP_TRACE(("returns (fail): `%s'", de)); + return (de); +} + +/* This procedure gets a single decnet record, null terminates it (stripping + off terminating carriage control if present). It sets mark if the mark + record was read. + */ + +de_get(s, n, m) +char *s; +int n, *m; +{ + int no_read; + + PP_TRACE(("de_get()")); + + /* Read a record */ + if (timeout(NET_TIMEOUT)) + { + PP_NOTICE(("read timed out")); + return RP_NIO; + } + if ((no_read = read(de_fd, s, n - 1)) < 0) + { + PP_DBG(("read failed [%d]", errno)); + return RP_NIO; + } + timeout(0); + + /* Is it a mark? */ + if (no_read == 1 && s[0] == '\0') + { + *m = TRUE; + PP_DBG(("returns `mark'")); + return RP_OK; + } + + /* terminate it, removing \r\n if present */ + if (no_read >= 2 && s[no_read - 2] == '\r' && s[no_read - 1] == '\n') + s[no_read - 2] = '\0'; + else + s[no_read] = '\0'; + + /* clear mark and return */ + *m = 0; + PP_DBG(("returns `%s'", s)); + return RP_OK; + +} diff --git a/Chans/decnet/make b/Chans/decnet/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/decnet/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/dr2rfc/Makefile b/Chans/dr2rfc/Makefile new file mode 100644 index 0000000..c98eb62 --- /dev/null +++ b/Chans/dr2rfc/Makefile @@ -0,0 +1,188 @@ +# PP Delivery Notification to RFC channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/Makefile,v 6.0 1991/12/18 20:06:58 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:06:58 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = dr2rfc.c write_queue.c write_report.c +OBJS = dr2rfc.o write_queue.o write_report.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS= ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xdr2rfc + +default: $(PROGS) + +dr2rfc: $(PROGS) + +xdr2rfc: ${OBJS} $(LIBPP) + ${CC} ${LDFLAGS} ${OBJS} ${LIBPP} ${LIBSYS} -o $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +clean: tidy + rm -f ${OBJS} $(PROGS) core a.out *.old *.BAK + +tidy: + rm -f $(PROGS) core a.out *old *.BAK zxdr2rfc + +lint: l-dr2rfc +l-dr2rfc: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + + +install: inst-dir inst-dr2rfc +inst-dr2rfc: $(CHANDIR)/dr2rfc +$(CHANDIR)/dr2rfc: xdr2rfc + -$(BACKUP) $@ zxdr2rfc + rm -f $@ + $(INSTALL) xdr2rfc $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dr2rfc channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of Building Rules +# +############################################################ + + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +dr2rfc.o: dr2rfc.c +dr2rfc.o: ../../h/head.h +dr2rfc.o: ../../h/util.h +dr2rfc.o: ../../h/config.h +dr2rfc.o: ../../h/ll_log.h +dr2rfc.o: ../../h/retcode.h +dr2rfc.o: ../../h/prm.h +dr2rfc.o: ../../h/qmgr.h +dr2rfc.o: ../../h/Qmgr-types.h +dr2rfc.o: ../../h/Qmgr-ops.h +dr2rfc.o: ../../h/q.h +dr2rfc.o: ../../h/adr.h +dr2rfc.o: ../../h/list_rchan.h +dr2rfc.o: ../../h/chan.h +dr2rfc.o: ../../h/table.h +dr2rfc.o: ../../h/list_bpt.h +dr2rfc.o: ../../h/auth.h +dr2rfc.o: ../../h/list_bpt.h +dr2rfc.o: ../../h/extension.h +dr2rfc.o: ../../h/mta.h +dr2rfc.o: ../../h/adr.h +dr2rfc.o: ../../h/list_bpt.h +dr2rfc.o: ../../h/aparse.h +dr2rfc.o: ../../h/ap.h +dr2rfc.o: ../../h/util.h +dr2rfc.o: ../../h/or.h +dr2rfc.o: ../../h/chan.h +dr2rfc.o: ../../h/auth.h +dr2rfc.o: ../../h/list_rchan.h +dr2rfc.o: ../../h/mta.h +dr2rfc.o: ../../h/tb_a.h +dr2rfc.o: ../../h/ap.h +write_queue.o: write_queue.c +write_queue.o: ../../h/head.h +write_queue.o: ../../h/util.h +write_queue.o: ../../h/config.h +write_queue.o: ../../h/ll_log.h +write_queue.o: ../../h/retcode.h +write_queue.o: ../../h/prm.h +write_queue.o: ../../h/q.h +write_queue.o: ../../h/adr.h +write_queue.o: ../../h/list_rchan.h +write_queue.o: ../../h/chan.h +write_queue.o: ../../h/table.h +write_queue.o: ../../h/list_bpt.h +write_queue.o: ../../h/auth.h +write_queue.o: ../../h/list_bpt.h +write_queue.o: ../../h/extension.h +write_queue.o: ../../h/mta.h +write_queue.o: ../../h/adr.h +write_queue.o: ../../h/list_bpt.h +write_queue.o: ../../h/aparse.h +write_queue.o: ../../h/ap.h +write_queue.o: ../../h/util.h +write_queue.o: ../../h/or.h +write_queue.o: ../../h/chan.h +write_queue.o: ../../h/auth.h +write_queue.o: ../../h/list_rchan.h +write_queue.o: ../../h/mta.h +write_queue.o: ../../h/tb_a.h +write_queue.o: ../../h/tb_q.h +write_queue.o: ../../h/tb_p1.h +write_report.o: write_report.c +write_report.o: ../../h/head.h +write_report.o: ../../h/util.h +write_report.o: ../../h/config.h +write_report.o: ../../h/ll_log.h +write_report.o: ../../h/retcode.h +write_report.o: ../../h/q.h +write_report.o: ../../h/adr.h +write_report.o: ../../h/list_rchan.h +write_report.o: ../../h/chan.h +write_report.o: ../../h/table.h +write_report.o: ../../h/list_bpt.h +write_report.o: ../../h/auth.h +write_report.o: ../../h/list_bpt.h +write_report.o: ../../h/extension.h +write_report.o: ../../h/mta.h +write_report.o: ../../h/adr.h +write_report.o: ../../h/list_bpt.h +write_report.o: ../../h/aparse.h +write_report.o: ../../h/ap.h +write_report.o: ../../h/util.h +write_report.o: ../../h/or.h +write_report.o: ../../h/chan.h +write_report.o: ../../h/auth.h +write_report.o: ../../h/list_rchan.h +write_report.o: ../../h/mta.h +write_report.o: ../../h/or.h +write_report.o: ../../h/dr.h +write_report.o: ../../h/extension.h +write_report.o: ../../h/mta.h +write_report.o: ../../h/tb_bpt84.h +write_report.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/dr2rfc/dr2rfc.c b/Chans/dr2rfc/dr2rfc.c new file mode 100644 index 0000000..1980480 --- /dev/null +++ b/Chans/dr2rfc/dr2rfc.c @@ -0,0 +1,483 @@ +/* dr2rfc.c - The PP DR structure to an RFC message */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/dr2rfc.c,v 6.0 1991/12/18 20:06:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/dr2rfc.c,v 6.0 1991/12/18 20:06:58 jpo Rel $ + * + * $Log: dr2rfc.c,v $ + * Revision 6.0 1991/12/18 20:06:58 jpo + * Release 6.0 + * + */ + + + +/****************************************************************************\ +* * +* The following checks are done: * +* - The message should not as yet be delivered. * +* - The Recipient number has a DR associated with it. * +* - All specified recipients have the same DR number. * +* * +\****************************************************************************/ + + + + +#include +#include "head.h" +#include "prm.h" +#include "qmgr.h" +#include "q.h" +#include "tb_a.h" +#include "ap.h" + +extern char *quedfldir; +extern void rd_end(), chan_init(), err_abrt(), or_myinit(); + +/* -- static variables -- */ +static Q_struct Qstruct; +Q_struct *PPQuePtr = &Qstruct; +static struct prm_vars PRMstruct; +static int DRno = 0; +char *this_msg = NULLCP; +int order_pref; +int io_running; +int linked = TRUE; +extern int ap_outtype; +static int initproc (); +static int endfunc(); +static void dirinit (); +static struct type_Qmgr_DeliveryStatus *process (); +static int adr_checks (); +static int Deliver (); +static void display_ProcMsg (); +char error[BUFSIZ]; +/* -- used by other files -- */ +CHAN *mychan; + +#define DEFAULT_MAX_INCLUDE 5000 +#define DEFAULT_NUM_INCLUDE_LINES 10 + +long max_include_msg = DEFAULT_MAX_INCLUDE; +int num_include_lines = DEFAULT_NUM_INCLUDE_LINES; +int include_all = FALSE; +int include_admin = FALSE; + +/* --------------------- Begin Routines -------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + char *myname = argv[0]; + + if (*myname == '/') { + myname = rindex (myname, '/'); + myname++; + } + + /* -- read pp tailor file -- */ + chan_init (myname); + + /* -- needed for oid_table -- */ + dsap_init ((char ***) NULL, (int *) NULL); + + /* -- check that the Q dirs are ok -- */ + dirinit(); + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, initproc, process, endfunc); + else +#endif + channel_control (argc, argv, initproc, process, endfunc); + + + exit (0); +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void dirinit() /* -- Change into pp queue space -- */ +{ + PP_TRACE (("dirinit()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change to dir '%s'", quedfldir); +} + +static void do_ch_info_flags(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + if ((margc = sstr2arg(info_copy, 20, margv, "= \t,")) > 0) { + for (ix = 0; ix < margc; ix++) { + if (lexequ(margv[ix], "order") == 0) { + if (lexequ(margv[ix+1], "uk") == 0) { + order_pref = CH_UK_PREF; + ap_outtype |= AP_PARSE_BIG; + } + ix ++; + } else if (lexequ(margv[ix], "submit") == 0) { + if (lexequ(margv[ix+1], "linked") == 0) + linked = TRUE; + else if (lexequ(margv[ix+1], "copy") == 0) + linked = FALSE; + ix ++; + } else if (lexequ(margv[ix], "admininfo") == 0) { + if (lexequ(margv[ix+1], "true") == 0) + include_admin = TRUE; + else if (lexequ(margv[ix+1], "false") == 0) + include_admin = FALSE; + ix++; + } else if (lexequ(margv[ix], "return") == 0) { + if (lexequ(margv[ix+1], "all") == 0) + include_all = TRUE; + else { + /* number letter */ + char *ich = margv[ix+1]; + + while (isdigit(*ich)) ich++; + + switch (*ich) { + case 'l': + case 'L': + if (*ich == margv[ix+1][0]) + num_include_lines = 1; + else + num_include_lines = + atoi(margv[ix+1]); + break; + + case 'K': + case 'k': + if (*ich == margv[ix+1][0]) + max_include_msg = (long) 1000; + else + max_include_msg = + (long) atoi(margv[ix+1]) * (long) 1000; + break; + + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to parse LHS as numberletter '%s=%s'", margv[ix], margv[ix+1])); + } + } + ix++; + } else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown info flag '%s'", + margv[ix])); + } + } + free(info_copy); +} + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + char *myname = qb2str (arg); + RP_Buf rps, *rp = &rps; + + PP_TRACE (("initproc (%s)", myname)); + + if ((mychan = ch_nm2struct (myname)) == NULLCHAN) + err_abrt (RP_PARM, "Channel '%s' not known", myname); + + + /* -- other initialisations -- */ + order_pref = CH_USA_PREF; + ap_outtype = AP_PARSE_SAME; + linked = TRUE; + max_include_msg = DEFAULT_MAX_INCLUDE; + num_include_lines = DEFAULT_NUM_INCLUDE_LINES; + include_all = FALSE; + include_admin = FALSE; + + if (mychan->ch_out_info != NULLCP) + do_ch_info_flags(mychan->ch_out_info); + + pp_setuserid(); + + or_myinit(); + + if (rp_isbad (io_init(rp))) + err_abrt (RP_PARM, "io_init err %s", rp -> rp_line); + else + io_running = TRUE; + + PP_NOTICE (("Channel %s initialised", myname)); + free (myname); + q_init (PPQuePtr); + prm_init (&PRMstruct); + return OK; +} + +/* ARGSUSED */ +static int endfunc (arg) +struct type_Qmgr_Channel *arg; +{ + if (io_running == TRUE) + io_end(OK); + io_running = FALSE; +} + +stop_io() +{ + if (io_running == TRUE) + io_end(NOTOK); + io_running = FALSE; +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + + struct type_Qmgr_UserList *up; + ADDR *ad_list = NULLADDR, + *ad_sender = NULLADDR, + *ad_recip = NULLADDR, + *alp = NULLADDR, + *ap = NULLADDR; + int naddrs = 0, + ad_count, + retval; + + if (this_msg) + free (this_msg); + + this_msg = qb2str (arg->qid); + PP_TRACE (("process (msg = '%s')", this_msg)); + (void) delivery_init (arg->users); + (void) delivery_setall (int_Qmgr_status_messageFailure); + +#ifdef PP_DEBUG + display_ProcMsg (arg); +#endif + + + /* -- Initialisation --*/ + + DRno = 0; + q_init (PPQuePtr); + prm_init (&PRMstruct); + + + /* -- read the addr control file -- */ + + retval = rd_msg (this_msg, &PRMstruct, PPQuePtr, + &ad_sender, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + rd_end(); + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg error: %s", this_msg)); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + + + /* -- create a new recip list + perform addr check -- */ + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + for (up = arg->users; up; up = up->next) { + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + if (adr_checks (ap) != OK) + break; + + if (ad_list == NULLADDR) + ad_list = alp = + (ADDR *) calloc(1, sizeof *alp); + else { + alp -> ad_next = + (ADDR *) calloc(1, sizeof *alp); + alp = alp -> ad_next; + } + + /* -- struct copy -- */ + *alp = *ap; + alp -> ad_next = NULLADDR; + naddrs++; + break; + } + } + + + if (naddrs == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients in the user list")); + rd_end (); + return deliverystate; + } + + + /* -- deliverystate set in deliver -- */ + if (Deliver (ad_sender, ad_list) != RP_OK) + PP_LOG (LLOG_EXCEPTIONS, ("resubmission failed")); + rd_end(); + + /* -- free ad_list -- */ + for (alp = ad_list; alp; alp = ap) { + ap = alp -> ad_next; + free ((char *)alp); + } + + q_free (PPQuePtr); + prm_free (&PRMstruct); + + return deliverystate; +} + + + + +static int adr_checks (ap) +ADDR *ap; +{ + PP_TRACE (("adr_checks (%s)", ap->ad_value)); + + switch (ap->ad_status) { + case AD_STAT_DRWRITTEN: + break; + case AD_STAT_DONE: + (void) delivery_set(ap->ad_no, + int_Qmgr_status_success); + return NOTOK; + default: + PP_LOG (LLOG_EXCEPTIONS, ("adr_checks - wrong status")); + (void) delivery_setstate(ap->ad_no, + int_Qmgr_status_messageFailure, + "adr_checks - wrong status"); + return NOTOK; + } + + if (ap -> ad_resp == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("responsibility bit not set for addr %d", + ap -> ad_no)); + (void) delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + "responsibility bit not set for addr"); + return NOTOK; + } + + + if (DRno == 0) + DRno = ap->ad_no; + return OK; +} + + + + +static int Deliver (orig, recip) +ADDR *orig; +ADDR *recip; +{ + int retval = RP_BAD; + int value = int_Qmgr_status_messageFailure; + ADDR *ap; + RP_Buf rps, *rp = &rps; + PP_TRACE (("Deliver (%s)", orig->ad_value)); + error[0] = '\0'; + if (orig->ad_outchan && + orig->ad_outchan->li_chan && + orig->ad_outchan->li_chan->ch_name && + lexequ(orig->ad_outchan->li_chan->ch_name, mychan->ch_name) == 0) { + + if (io_running == FALSE) + if (rp_isbad(io_init(rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("io_init err %s", rp -> rp_line)); + (void) sprintf (error, + "io_init error [%s]", + rp -> rp_line); + goto Deliver_free; + } else + io_running = TRUE; + + if (rp_isbad (write_queue (orig))) + goto Deliver_free; + + if (rp_isbad (write_report (orig, DRno, recip))) + goto Deliver_free; + + + value = int_Qmgr_status_success; + retval = RP_OK; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal setting of outbound channel for addr %d", + orig->ad_no)); + (void) sprintf (error, + "Illegal setting of outbound channel"); + } + + Deliver_free: ; + for (ap = recip; ap; ap = ap -> ad_next) { + if (ap -> ad_resp) { + (void) delivery_setstate (ap -> ad_no, value, error); + if (value == int_Qmgr_status_success) + wr_ad_status (ap, AD_STAT_DONE); + } + + } + + if (retval == RP_OK) { + PP_NOTICE (("Wrote DR to '%s'", orig->ad_value)); + PP_NOTICE ((">>> %s %s done", mychan -> ch_name, this_msg)); + } + else { + PP_OPER (NULLCP, ("dr2rfc has failed for %s", this_msg)); + PP_NOTICE ((">>> %s %s has not been done", + mychan -> ch_name, this_msg)); + stop_io (); + } + + return retval; +} + + + + +/* -------------------- Debug Proceedures ------------------------------ */ + + + + +#ifdef PP_DEBUG +static void display_ProcMsg (pm) +struct type_Qmgr_ProcMsg *pm; +{ + char *str; + struct type_Qmgr_UserList *pmu; + + str = qb2str (pm -> qid); + + for (pmu = pm -> users; pmu; pmu = pmu -> next) + PP_TRACE (("%s: user(%d)", + str, pmu -> RecipientId->parm)); + + if (str) free (str); + + return; +} +#endif diff --git a/Chans/dr2rfc/make b/Chans/dr2rfc/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/dr2rfc/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/dr2rfc/write_queue.c b/Chans/dr2rfc/write_queue.c new file mode 100644 index 0000000..730c64c --- /dev/null +++ b/Chans/dr2rfc/write_queue.c @@ -0,0 +1,148 @@ +/* write_queue.c - Creates & submits a Q_struct for a DR Msg */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_queue.c,v 6.0 1991/12/18 20:06:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_queue.c,v 6.0 1991/12/18 20:06:58 jpo Rel $ + * + * $Log: write_queue.c,v $ + * Revision 6.0 1991/12/18 20:06:58 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "tb_a.h" +#include "tb_q.h" +#include "tb_p1.h" +#include + +extern CHAN *mychan; +extern char *loc_dom_site; +extern char *getpostmaster(), + *hdr_822_bp, + *ia5_bp, error[]; +extern ADDR *adr_new (); +extern CMD_TABLE qtbl_con_type[]; +extern LIST_BPT *list_bpt_dup(); + +/* --------------------- Begin Routines --------------------------------- */ + +char *recip_err; + + +write_queue (to) +ADDR *to; +{ + struct prm_vars prm; + Q_struct QNewStruct, + *qp = &QNewStruct; + EncodedIT *ep = &qp -> encodedinfo; + RP_Buf rps, *rp = &rps; + + + PP_TRACE (("dr2rfc/write_queue()")); + + if (to->ad_r822adr == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("%s%s", + "dr2rfc/write_queue - no rfc822 ", + "recipient address has been specified")); + (void) sprintf(error, + "no rfc822 recipient address has been specified"); + return RP_BAD; + } + + + /* -- initialize prm and Q fields -- */ + prm_init (&prm); + q_init (qp); + qp -> msgtype = MT_UMPDU; + qp -> inbound = list_rchan_new (loc_dom_site, + mychan->ch_name); + ep->eit_types = NULL; + list_bpt_add(&ep->eit_types, list_bpt_new(hdr_822_bp)); + list_bpt_add(&ep->eit_types, list_bpt_new(ia5_bp)); + + + MPDUid_new (&qp -> msgid); + + /* -- create the ADDR struct for orig and recipient -- */ + qp->Oaddress = adr_new (getpostmaster(AD_822_TYPE), + AD_822_TYPE, 0); + qp->Raddress = adr_new ((isstr(to->ad_r822DR)) ? + to->ad_r822DR : to->ad_r822adr, + AD_822_TYPE, 1); + + + if (rp_isbad (io_wprm (&prm, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/io_wprm err %s", + rp -> rp_line)); + stop_io(); + (void) sprintf (error, + "io_wprm error [%s]", + rp -> rp_line); + return RP_BAD; + } + + + if (rp_isbad (io_wrq (qp, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/io_wrq err %s", + rp -> rp_line)); + stop_io(); + (void) sprintf (error, + "io_wrq error [%s]", + rp -> rp_line); + return RP_BAD; + } + + + if (rp_isbad (io_wadr (qp -> Oaddress, AD_ORIGINATOR, rp))) { + PP_OPER (NULLCP, ("dr2rfc/io_wadr originator/postmaster err %s", + rp -> rp_line)); + stop_io(); + (void) sprintf (error, + "io_wadr originator/postmaster error [%s]", + rp -> rp_line); + return RP_BAD; + } + + + if (rp_isbad (io_wadr (qp -> Raddress, AD_RECIPIENT, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/io_wadr recipient err %s", + rp -> rp_line)); + recip_err = strdup(rp->rp_line); + if (rp_isbad(io_wadr(qp -> Oaddress, AD_RECIPIENT, rp))) { + PP_OPER (NULLCP, ("dr2rfc/io_wadr originator/postmaster err %s", + rp -> rp_line)); + (void) sprintf (error, + "io_wadr originator/postmaster error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + } else + recip_err = NULLCP; + + + if (rp_isbad (io_adend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/io_adend err %s", + rp -> rp_line)); + stop_io(); + (void) sprintf (error, + "io_adend error [%s]", + rp -> rp_line); + return RP_BAD; + } + + /* -- frees the structure -- */ + q_free (qp); + return RP_OK; + +} + diff --git a/Chans/dr2rfc/write_report.c b/Chans/dr2rfc/write_report.c new file mode 100644 index 0000000..88a4fdb --- /dev/null +++ b/Chans/dr2rfc/write_report.c @@ -0,0 +1,1748 @@ +/* write_report.c - Writes the DR struct as a Message -- */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_report.c,v 6.0 1991/12/18 20:06:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/dr2rfc/RCS/write_report.c,v 6.0 1991/12/18 20:06:58 jpo Rel $ + * + * $Log: write_report.c,v $ + * Revision 6.0 1991/12/18 20:06:58 jpo + * Release 6.0 + * + */ + + + +/* --- *** --- + * These routines create 2 text files containing body part info: + * The files are called "hdr.822.uk" and "1.ia5". These files are + * placed by submit into the $Q/msg directory + * --- *** --- */ + + +#include "head.h" +#include "q.h" +#include "or.h" +#include "dr.h" +#include "tb_bpt84.h" +#include +#include +#include "sys.file.h" +#include + +extern CHAN *mychan; +extern CMD_TABLE bptbl_body_parts84 [/* body part types */]; +extern char *this_msg, + *loc_or, + *loc_dom, + *loc_dom_mta, + *loc_dom_site, + *postmaster, + *hdr_822_bp, + *ia5_bp, + *recip_err, + *cont_822, error[]; +extern Q_struct *PPQuePtr; +extern int order_pref, linked; +extern int msgid2rfc(), reprecip2rfc(), + globalid2rfc(), x400eits2rfc(), include_admin; +extern void rfctxtfold(); +extern UTC utclocalise(); +static int wr_hdr_rest (); +static int get_DR (); +static int end_admin_info(), start_admin_info(); +static int wr_hdr_end (); +static int wr_body (); +static int copy (); +static int DR_print (); +static int DR_write (); +static DRmpdu DRstruct; +static char *getSubject(); +static int write_start(), write_cont(), write_end(); +static ADDR *to; +static int linecopy(); +static int do_subject_intermediate_trace(); +static int get822Mailbox(); +static char message[BUFSIZ*2]; /* -- holds the Recip info -- */ +static long return_size; +extern CMD_TABLE rr_rcode[], + rr_dcode[], + rr_tcode[]; +int forwarded; + +static int allSameType(), allSameMta(); + +static CMD_TABLE rr_dcode_eng [] = { /* -- diagnostic-codes -- */ + +"Unknown Address", +DRD_UNRECOGNISED_OR, + +"Ambiguous Address", +DRD_AMBIGUOUS_OR, + +"Message rejected due to congestion", +DRD_MTA_CONGESTION, + +"Message looping detected (please contact local administrator)", +DRD_LOOP_DETECTED, + +"Recipient's Mailbox unavailable", +DRD_UA_UNAVAILABLE, + +"Message timed out", +DRD_MAX_TIME_EXPIRED, + +"Some of your message could not be displayed by the recipient's system", +DRD_ENCINFOTYPES_NOTSUPPORTED, + +"The message is too big for delivery", +DRD_CONTENT_TOO_LONG, + +"Unable to perform the conversion required for delivery", +DRD_CONVERSION_IMPRACTICAL, + +"Not allowed to perform the conversion required for delivery", +DRD_CONVERSION_PROHIBITED, + +"Don't know how to convert for delivery", +DRD_IMPLICITCONV_NOTREGISTERED, + +"One or more of the message parameters is invalid", +DRD_INVALID_PARAMETERS, + +"A syntax error was detected in the header of the message", +DRD_CONTENT_SYNTAX_ERROR, + +"X.400 protocol error - constraint violation (please contact local administrator)", +DRD_SIZE_CONSTRAINT_VIOLATION, + +"X.400 protocol error - missing argument (please contact local administrator)", +DRD_PROTOCOL_VIOLATION, + +"The recipient site could not handle the content type of the message", +DRD_CONTENT_TYPE_NOT_SUPPORTED, + +"The message specified too many recipients for the system to cope with", +DRD_TOO_MANY_RECIPIENTS, + +"Incompatibility between two sites on the route of the message (please contact local administrator)", +DRD_NO_BILATERAL_AGREEMENT, + +"A critical function required for the transfer or delivery of the message is not supported by the originating site of this report", +DRD_UNSUPPORTED_CRITICAL_FUNCTION, + +"Not allowed to perform the conversion required for delivery as it would result in loss of information", +DRD_CONVERSION_WITH_LOSS_PROHIBITED, + +"Some lines of the message were too long to be delivered", +DRD_LINE_TOO_LONG, + +"Some pages of the message were too long to be delivered", +DRD_PAGE_SPLIT, + +"Some pictorial symbols would have been lost if the message was delivered", +DRD_PICTORIAL_SYMBOL_LOSS, + +"Some punctuation symbols would have been lost if the message was delivered", +DRD_PUNCTUATION_SYMBOL_LOSS, + +"Some alphabetic characters would have been lost if the message was delivered", +DRD_ALPHABETIC_CHARACTER_LOSS, + +"Some information would have been lost if the message was delivered", +DRD_MULTIPLE_INFORMATION_LOSS, + +"The message could not be delivered because the originator of the message prohibited redirection", +DRD_RECIPIENT_REASSIGNMENT_PROHIBITED, + +"The message could not be redirected to an alternate recipient because that recipient had previously redirected the message (redirection loop)", +DRD_REDIRECTION_LOOP_DETECTED, + +"The message could not be delivered because the originator of the message prohibited the expansion of distribution lists", +DRD_DL_EXPANSION_PROHIBITED, + +"The originator of the message does not have permission to submit messages to the recipient distribution list", +DRD_NO_DL_SUBMIT_PERMISSION, + +"The expansion of a distribution list could not be completed", +DRD_DL_EXPANSION_FAILURE, + +"The postal access unit does not support the physical format required", +DRD_PHYSICAL_RENDITION_ATTRIBUTES_NOT_SUPPORTED, + +"The message was undeliverable because the specified recipient postal address was incorrect", +DRD_UNDLIV_PD_ADDRESS_INCORRECT, + +"The message was undeliverable because the physical delivery office identified by the specified postal address was incorrect or invalid", +DRD_UNDLIV_PD_OFFICE_INCORRECT_OR_INVALID, + +"The message was undeliverable because the specified recipient postal address was incompletely specified", +DRD_UNDLIV_PD_ADDRESS_INCOMPLETE, + +"The message was undeliverable because the recipient specified in the postal address was not known at that address", +DRD_UNDLIV_RECIPIENT_UNKNOWN, + +"The message was undeliverable because the recipient specified in the postal address is deceased", +DRD_UNDLIV_RECIPIENT_DECEASED, + +"The message was undeliverable because the recipient organization specified in the postal address is no longer registered", +DRD_UNDLIV_ORGANIZATION_EXPIRED, + +"The message was undeliverable because the recipient specified in the postal address refused to accept it", +DRD_UNDLIV_RECIPIENT_REFUSED_TO_ACCEPT, + +"The message was undeliverable because the recipient specified in the postal address did not collect the mail", +DRD_UNDLIV_RECIPIENT_DID_NOT_CLAIM, + +"The message was undeliverable because the recipient specified in the postal address had changed address permanently ('moved') and forwarding was not applicable", +DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_PERMANENTLY, + +"The message was undeliverable because the recipient specified in the postal address had changed address temporarily ('on holiday') and forwarding was not applicable", +DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_TEMPORARILY, + +"The message was undeliverable because the recipient specified in the postal address had changed temporary address ('departed') and forwarding was not applicable", +DRD_UNDLIV_RECIPIENT_CHANGED_TEMPORARY_ADDRESS, + +"The message was undeliverable because the recipient has moved and the recipient's new address is unknown", +DRD_UNDLIV_NEW_ADDRESS_UNKNOWN, + +"The message was undeliverable because delivery would have required physical forwarding which the recipient did not want", +DRD_UNDLIV_RECIPIENT_DID_NOT_WANT_FORWARDING, + +"The physical forwarding required for the message to be delivered has been prohibited by the originator of the message", +DRD_UNDLIV_ORIGINATOR_PROHIBITED_FORWARDING, + +"The message could not be progressed because it would violate the security policy in force", +DRD_SECURE_MESSAGING_ERROR, + +"The downgrading of the message's content required for delivery could not be performed", +DRD_UNABLE_TO_DOWNGRADE, + 0, -1 +}; + +int dirlen; + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +write_report (ap, DRno, recip) +ADDR *ap; +int DRno; +ADDR *recip; +{ + int retval = RP_BAD; + + PP_TRACE (("write_report: %s (%d) (%s)", + ap->ad_value, DRno, this_msg)); + + if (ap == NULLADDR) + return retval; + else + to = ap; + + /* -- initialise -- */ + bzero (message, sizeof (message)); + dr_init (&DRstruct); + + if (rp_isbad (get_DR (DRno))) + goto write_report_end; + + if (rp_isbad (wr_hdr_start())) + goto write_report_end; + + if (rp_isbad (wr_hdr_rest())) + goto write_report_end; + + if (rp_isbad (wr_hdr_end())) + goto write_report_end; + + if (rp_isbad (wr_body(ap, recip))) + goto write_report_end; + + retval = RP_OK; + +write_report_end: ; + dr_free (&DRstruct); + if (recip_err) { + free(recip_err); + recip_err = NULLCP; + } + return retval; + +} + + + + +/* -------------------- Static Routines ------------------------------- */ + + +static int write_p1_trace (trace) +Trace *trace; +{ + char abuf[BUFSIZ]; + + if (trace == NULL) + return RP_OK; + if (rp_isbad(write_p1_trace (trace -> trace_next))) + return RP_BAD; + if (x400trace2rfc (trace, abuf) == NOTOK) + return RP_BAD; + if (rp_isbad(DR_write("X400-Received: ",abuf))) + return RP_BAD; + return RP_OK; +} + +wr_postmaster_hdr(useDR) +int useDR; +{ + char buf[BUFSIZ], + temp[BUFSIZ], + part[BUFSIZ]; + RP_Buf rps, + *rp = &rps; + UTC now, localnow; + + PP_TRACE(("dr2rfc/wr_postmaster_hdr()")); + + if (rp_isbad (io_tpart (hdr_822_bp, FALSE, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("dr2rfc/wr_hdr/io_tpart blows %s", rp -> rp_line)); + stop_io(); + (void) sprintf (error, + "io_tpart error [%s]", + rp -> rp_line); + return RP_BAD; + } + + if (rp_isbad (DR_write ("From: ", postmaster))) + return RP_BAD; + + + /* -- To -- */ + if (useDR == TRUE && isstr(to->ad_r822DR)) { + char *tmp; + tmp = to->ad_r822adr; + to->ad_r822adr = to->ad_r822DR; + if (adr2rfc (to, temp, order_pref) == RP_BAD) + return RP_BAD; + if (rp_isbad (DR_write ("To: ", temp))) + return RP_BAD; + to->ad_r822adr = tmp; + } else { + if (rp_isbad (DR_write ("To: ", postmaster))) + return RP_BAD; + } + + /* -- Subject -- */ + if (adr2rfc (to, temp, order_pref) == RP_BAD) + return RP_BAD; + + (void) sprintf (buf, + "Unable to send delivery report to %s", + temp); + + if (rp_isbad (DR_write ("Subject: ", buf))) + return RP_BAD; + + if (rp_isbad(DR_write("Message-Type: ", "Delivery Report"))) + return RP_BAD; + + now = utcnow(); + localnow = utclocalise(now); + if (UTC2rfc(localnow, buf) == NOTOK) + return RP_BAD; + if (now) free((char *) now); + if (localnow) free((char *) localnow); + + if (rp_isbad (DR_write ("Date: ", buf))) + return RP_BAD; + + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("dr2rfc/wr_hdr_end/tdend blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tdend error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + + (void) sprintf(part, "1.%s", ia5_bp); + + if (rp_isbad (io_tpart (part, FALSE, rp))) { + PP_TRACE (("dr2rfc/wr_body/tpart blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tpart error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + + if (useDR == TRUE) + (void) sprintf (buf, "The originally sender '%s' can not be reached from %s\nThe delivery report follows:\n\n", + to->ad_value, loc_dom_site); + else + (void) sprintf(buf, "%s was unable to construct a delivery report\n\taddressed to '%s'.\nThe reason given was '%s'.\n\nThe delivery report follows:\n\n", + mychan->ch_name, + temp, + recip_err); + if (rp_isbad(io_tdata (buf, strlen(buf)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + (void) sprintf(error, + "io_tdata error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails")); + (void) sprintf (error, + "io_tdend error"); + stop_io(); + return RP_BAD; + } + + return RP_OK; +} + +wr_hdr_start () +{ + RP_Buf rps, *rp = &rps; + char buffer[BUFSIZ], part[BUFSIZ], + *pmailbox; + UTC now, localnow; + Rrinfo *ix; + if (rp_isbad (io_tinit (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("dr2rfc/wr_hdr/tinit blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tinit error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + + if (recip_err != NULLCP) { + if (rp_isbad(wr_postmaster_hdr(FALSE))) + return RP_BAD; + (void) sprintf(part, "2.ipm/%s", hdr_822_bp); + forwarded = TRUE; + } else if (isstr(to->ad_r822DR)) { + if (rp_isbad(wr_postmaster_hdr(TRUE))) + return RP_BAD; + (void) sprintf(part, "2.ipm/%s", hdr_822_bp); + forwarded = TRUE; + } else { + (void) sprintf(part, "%s", hdr_822_bp); + forwarded = FALSE; + } + + if (rp_isbad (io_tpart (part, FALSE, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("dr2rfc/wr_hdr/io_tpart blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tpart error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + + if (DRstruct.dr_trace != NULL + && DRstruct.dr_trace -> trace_next != NULL) + /* not local (x400 ?) */ + if (rp_isbad(write_p1_trace(DRstruct.dr_trace))) + return RP_BAD; + + /* -- From -- */ + if (rp_isbad (DR_write ("From: ", postmaster))) + return RP_BAD; + + + /* -- To -- */ + if (adr2rfc (to, buffer, order_pref) == RP_BAD) + return RP_BAD; + if (rp_isbad (DR_write ("To: ", buffer))) + return RP_BAD; + + /* -- Subject -- */ + (void) sprintf (buffer, "Delivery Report"); + + ix = DRstruct.dr_recip_list; + if (allSameType(ix, DR_REP_SUCCESS) == TRUE) + (void) sprintf (buffer, "%s (success)", buffer); + else if (allSameType(ix, DR_REP_FAILURE) == TRUE) + (void) sprintf (buffer, "%s (failure)", buffer); + else + (void) sprintf (buffer, "%s (success and failures)", buffer); + + if (ix && ix->rr_next == NULL + && !rp_isbad(get822Mailbox(ix, &pmailbox))) { + (void) sprintf (buffer, "%s for %s", + buffer, pmailbox); + free(pmailbox); + } else if (allSameMta(ix, &pmailbox) == TRUE) { + (void) sprintf (buffer, "%s for MTA %s", + buffer, pmailbox); + free(pmailbox); + } + + + if (rp_isbad (DR_write ("Subject: ", buffer))) + return RP_BAD; + + if (rp_isbad(DR_write("Message-Type: ", "Delivery Report"))) + return RP_BAD; + + now = utcnow(); + localnow = utclocalise(now); + if (UTC2rfc(localnow, buffer) == NOTOK) + return RP_BAD; + if (now) free((char *) now); + if (localnow) free((char *) localnow); + + if (rp_isbad (DR_write ("Date: ", buffer))) + return RP_BAD; + + return RP_OK; +} + + + + +static int wr_hdr_rest () +{ + char buffer [BUFSIZ], + fbuf [BUFSIZ]; + + PP_TRACE (("dr2rfc/wr_hdr_rest ()")); + + /* -- P1-Message-ID -- */ + if (DRstruct.dr_mpduid && DRstruct.dr_mpduid->mpduid_string) { + (void) sprintf (fbuf, "Message-ID: "); + (void) sprintf (buffer, "<\"%s\"@%s>", + DRstruct.dr_mpduid->mpduid_string, + loc_dom_site); + if (rp_isbad (DR_write (fbuf, buffer))) + return RP_BAD; + } + + /* -- UAContentId (optional) -- */ + if (PPQuePtr -> ua_id) { + (void) sprintf (fbuf, "Content-Identifier: "); + if (rp_isbad (DR_write (fbuf, PPQuePtr -> ua_id))) + return RP_BAD; + } + + return RP_OK; +} + +static int get_DR (DRno) +int DRno; +{ + int retval; + + PP_TRACE (("get_DR for %s (%d)", this_msg, DRno)); + + retval = get_dr (DRno, this_msg, &DRstruct); + if (rp_isbad(retval) && retval != RP_EOF) + goto get_DR_free; + + return (RP_OK); + +get_DR_free: ; + return RP_BAD; +} + + + + + +static wr_hdr_end() +{ + RP_Buf rps, + *rp = &rps; + + PP_TRACE (("dr2rfc/wr_hdr_end()")); + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("dr2rfc/wr_hdr_end/tdend blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tdend error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + return RP_OK; +} + +extern long max_include_msg; +extern int num_include_lines; +extern int include_all; + +static wr_body (ap, recip) +ADDR *ap; +ADDR *recip; +{ + RP_Buf rps, + *rp = &rps; + char *dir = NULLCP; + char filename[MAXPATHLENGTH], + *pmailbox, *cix, *str, + buffer[BUFSIZ], + buffer2[BUFSIZ], + part[BUFSIZ], + temp[BUFSIZ]; + int retval, avail, correlator, + nosubject = FALSE, allSuccess; + Rrinfo *ix; + ADDR *ad; + UTC now; + UTC loctime; + + if (forwarded == TRUE) + (void) sprintf(part, "2.ipm/1.%s", ia5_bp); + else + (void) sprintf(part, "1.%s", ia5_bp); + + if (rp_isbad (io_tpart (part, FALSE, rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line)); + (void) sprintf (error, + "io_tpart error [%s]", + rp -> rp_line); + stop_io(); + return RP_BAD; + } + +/* dr-summary */ + if (PPQuePtr -> pp_content_correlator == NULL + && PPQuePtr -> ua_id == NULL) + correlator = FALSE; + else + correlator = TRUE; + + if (correlator == TRUE) { + if (rp_isbad(write_start("This report relates to your message:", ""))) + return RP_BAD; + /* content correlator */ + + if (rp_isbad(pretty_output((PPQuePtr -> pp_content_correlator) ? PPQuePtr -> pp_content_correlator : PPQuePtr -> ua_id, 2))) + return RP_BAD; + + } else { + char *subject; + + if ((subject = getSubject(this_msg, recip)) != NULLCP) { + if (rp_isbad(write_start("This report relates to your message with subject:", subject))) + return RP_BAD; + free(subject); + } else if (rp_isbad(write_start("This report relates to your message", ""))) { + nosubject = TRUE; + return RP_BAD; + } + + } + if (DRstruct.dr_subject_intermediate_trace != NULL) { + Trace *tix = DRstruct.dr_subject_intermediate_trace; + while (tix->trace_next != NULL) + tix = tix->trace_next; + loctime = utclocalise(tix->trace_DomSinfo.dsi_time); + if (UTC2rfc(loctime, temp) == NOTOK) + return RP_BAD; + if (loctime) free((char *) loctime); + (void) sprintf(buffer, "of %s\n",temp); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } + if (nosubject == TRUE + && rp_isbad(write_cont("(no subject)", FALSE))) + return RP_BAD; + + if (rp_isbad(write_end())) + return RP_BAD; + + /* dr-recipients */ + ix = DRstruct.dr_recip_list; + allSuccess = TRUE; + + while (ix != NULL) { + if (rp_isbad(get822Mailbox(ix, &pmailbox))) + return RP_BAD; + if (ix -> rr_report.rep_type == DR_REP_SUCCESS) { + if (rp_isbad(write_start("Your message was successfully delivered to", ""))) + return RP_BAD; + if (rp_isbad(write_cont(pmailbox, FALSE))) + return RP_BAD; + if (ix-> rr_supplementary) { + (void) sprintf (buffer, "%s", ix -> rr_supplementary); + if (rp_isbad(write_cont(ix -> rr_supplementary, TRUE))) + return RP_BAD; + } + + if (ix -> rr_arrival) { + loctime = utclocalise(ix->rr_arrival); + if (UTC2rfc (loctime, temp) == NOTOK) + return RP_BAD; + if (loctime) free ((char *) loctime); + (void) sprintf(buffer, "at %s", temp); + if (rp_isbad(write_cont(temp, FALSE))) + return RP_BAD; + } + if (rp_isbad(write_cont("\n", FALSE))) + return RP_BAD; + if (rp_isbad(write_end())) + return RP_BAD; + } else { + char *diag; + allSuccess = FALSE; + if (rp_isbad(write_start("Your message was not delivered to ", ""))) + return RP_BAD; + if (rp_isbad(write_cont(pmailbox, FALSE))) + return RP_BAD; + if (rp_isbad(write_cont("for the following reason:", FALSE))) + return RP_BAD; + + if ((diag = rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_dcode, rr_dcode_eng)) != NULL) + (void) sprintf(buffer, "%s", diag); + else + (void) sprintf(buffer, "%s", + rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_rcode, rr_rcode)); + + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + + if (ix-> rr_supplementary) { + (void) sprintf (buffer, "%s", ix -> rr_supplementary); + if (rp_isbad(write_cont(ix -> rr_supplementary, TRUE))) + return RP_BAD; + } + if (rp_isbad(write_cont("\n", FALSE)) + || rp_isbad(write_end())) + return RP_BAD; + } + if (pmailbox != NULLCP) { + free(pmailbox); + pmailbox = NULLCP; + } + ix = ix -> rr_next; + } + +/* dr-adminstrator-info-envelope */ + if (allSuccess == FALSE + || include_admin == TRUE) { + start_admin_info(); + if (DRstruct.dr_trace != NULL) { + Trace *tix = DRstruct.dr_trace; + + if (tix -> trace_mta != NULL) { + (void) sprintf(buffer, "by: mta %s", + tix -> trace_mta); + if (rp_isbad(write_start("DR generated",buffer))) + return RP_BAD; + if (globalid2rfc(&(tix -> trace_DomId), + temp) == NOTOK) + return RP_BAD; + (void) sprintf(buffer, "in %s", temp); + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + } else { + if (globalid2rfc(&(tix -> trace_DomId), + temp) == NOTOK) + return RP_BAD; + (void) sprintf(buffer, "in %s", temp); + if (rp_isbad(write_start("DR generated",buffer))) + return RP_BAD; + } + + loctime = utclocalise (tix -> trace_DomSinfo.dsi_time); + if (UTC2rfc(loctime, temp) == NOTOK) + return RP_BAD; + if (loctime) free((char *) loctime); + + (void) sprintf(buffer,"at %s\n*",temp); + if (rp_isbad(write_cont(buffer, FALSE)) + || rp_isbad(write_end())) + return RP_BAD; + } + + now = utcnow(); + loctime = utclocalise(now); + if (UTC2rfc(loctime, temp) == NOTOK) + return RP_BAD; + if (now) free((char *) now); + if (loctime) free((char *) loctime); + + sprintf(buffer, "foo@%s", loc_dom_mta); + ap_s2s (buffer, &str, order_pref); + if (str != NULLCP + && (cix = index(str, '@')) != NULLCP) + (void) sprintf(buffer, "at %s", ++cix); + else + (void) sprintf(buffer, "at %s",loc_dom_mta); + if (str) free(str); + + if (rp_isbad(write_start("Converted to RFC 822", + buffer))) + return RP_BAD; + (void) sprintf(buffer, "at %s\n*", temp); + if (rp_isbad(write_cont(buffer, FALSE)) + || rp_isbad(write_end())) + return RP_BAD; + + /* dr-extra-information */ + (void) sprintf(buffer, "* Delivery Report Contents:\n*\n"); + if (rp_isbad(io_tdata (buffer, strlen(buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + (void) sprintf (error, + "io_tdata error"); + + stop_io(); + return RP_BAD; + } + + /* drc-field-list */ + if (globalid2rfc(&(PPQuePtr->msgid.mpduid_DomId), buffer2) == NOTOK) + return RP_BAD; + if (PPQuePtr->msgid.mpduid_string != NULL) + (void) sprintf(buffer, "[%s;%s]", + buffer2, + PPQuePtr->msgid.mpduid_string); + else + (void) sprintf(buffer, "[%s]", buffer2); + if (rp_isbad (DR_write("Subject-Submission-Identifier: ", + buffer))) + return RP_BAD; + + if (PPQuePtr -> ua_id != NULL + && rp_isbad (DR_print("Content-Identifier: ", + PPQuePtr -> ua_id))) + return RP_BAD; + + if (PPQuePtr -> cont_type != NULL + && strcmp(PPQuePtr -> cont_type, cont_822) != 0 + && rp_isbad (DR_print("Content-Type: ", + PPQuePtr -> cont_type))) + return RP_BAD; + + if (PPQuePtr -> orig_encodedinfo.eit_types != 0) { + if (x400eits2rfc (&(PPQuePtr -> orig_encodedinfo), &buffer[0]) == NOTOK) + return RP_BAD; + if (buffer[0] != '\0') + if (rp_isbad + (DR_print("Original-Encoded-Information-Types: ", + buffer))) + return RP_BAD; + } + + if (DRstruct.dr_subject_intermediate_trace != NULL) { + if (rp_isbad(do_subject_intermediate_trace(DRstruct.dr_subject_intermediate_trace))) + return RP_BAD; + } + + if (DRstruct.dr_dl_history != NULL) { + DLHistory *dlix = DRstruct.dr_dl_history; + buffer[0] = '\0'; + + if (rp_isbad(write_start("Originator-and-DL-Expansion-History: ", ""))) + return RP_BAD; + + while (dlix != NULL) { + if (dlix->dlh_next != NULL) { + (void) sprintf(buffer, "%s,", dlix -> dlh_addr); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } else if (rp_isbad(write_cont(dlix -> dlh_addr, FALSE))) + return RP_BAD; + dlix = dlix -> dlh_next; + } + if (rp_isbad(write_end())) + return RP_BAD; + } + + if (DRstruct.dr_reporting_dl_name != NULL + && DRstruct.dr_reporting_dl_name -> fn_addr != NULL + && rp_isbad(DR_print("Reporting-DL-Name: ", + DRstruct.dr_reporting_dl_name -> fn_addr))) + return RP_BAD; + + if (PPQuePtr -> pp_content_correlator != NULL + && (rp_isbad(write_start("Content-Correlator:", "")) + || rp_isbad(pretty_output(PPQuePtr -> pp_content_correlator, + strlen("Content-Correlator:"))))) + return RP_BAD; + + ix = DRstruct.dr_recip_list; + while (ix != NULL) { + char *str = NULLCP; + for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next) + if (ad -> ad_no == ix -> rr_recip) + break; + if (ad == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("unable to find recip '%d'", ix -> rr_recip)); + return RP_BAD; + } + ap_s2s(ad -> ad_r822adr, &str, order_pref); + if (str != NULLCP) { + (void) sprintf(buffer, "%s,", str); + free(str); + } else + (void) sprintf(buffer, "%s,", ad -> ad_r822adr); + if (rp_isbad(write_start("Recipient-Info:", buffer))) + return RP_BAD; + + (void) sprintf(buffer, "%s;", ad -> ad_r400adr); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + + if (ix -> rr_report.rep_type == DR_REP_SUCCESS) { + char delivered[BUFSIZ], + *type; + loctime = utclocalise (ix -> rr_report.rep.rep_dinfo.del_time); + if (UTC2rfc(loctime, delivered) == NOTOK) + return RP_BAD; + if (loctime) free ((char *) loctime); + (void) sprintf(buffer, "SUCCESS delivered at %s;", + delivered); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + + if (ix -> rr_report.rep.rep_dinfo.del_type != DRT_PUBLIC + && (type = rcmd_srch(ix -> rr_report.rep.rep_dinfo.del_type, rr_tcode)) != NULL) { + (void) sprintf(buffer, "type of MTS user %s (%d);", + type, + ix -> rr_report.rep.rep_dinfo.del_type); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } + } else { + char *diag; + + (void) sprintf(buffer, "FAILURE reason %s (%d);", + rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_rcode, rr_rcode), + ix -> rr_report.rep.rep_ndinfo.nd_rcode); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + if ((diag = rcmd_srch(ix -> rr_report.rep.rep_ndinfo.nd_dcode, rr_dcode)) != NULL) { + (void) sprintf(buffer,"diagnostic %s (%d);", + diag, + ix -> rr_report.rep.rep_ndinfo.nd_dcode); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } + } + + if (DRstruct.dr_subject_intermediate_trace != NULL) { + (void) sprintf(buffer,"last trace"); + if (PPQuePtr -> encodedinfo.eit_types != 0) { + if(x400eits2rfc(&PPQuePtr -> encodedinfo, + &(temp[0])) == NOTOK) + return RP_BAD; + (void) sprintf(buffer,"%s (%s)", buffer, temp); + } + loctime = utclocalise (DRstruct.dr_subject_intermediate_trace->trace_DomSinfo.dsi_time); + if (UTC2rfc(loctime, &temp[0]) == NOTOK) + return RP_BAD; + if (loctime) free ((char *) loctime); + + (void) sprintf(buffer,"%s %s;",buffer, temp); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } + + if (ix -> rr_converted != NULL) { + if (x400eits2rfc (ix -> rr_converted, &temp[0]) == NOTOK) + return RP_BAD; + if (temp[0] != '\0') { + (void) sprintf(buffer, "converted eits %s;", + temp); + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + } + } + + if (ix -> rr_originally_intended_recip != NULL) { + if (ix -> rr_originally_intended_recip -> fn_dn) + (void) sprintf(buffer, "originally intended recipient %s, %s;", + ix -> rr_originally_intended_recip -> fn_dn, + ix -> rr_originally_intended_recip -> fn_addr); + else + (void) sprintf(buffer, "originally intended recipient %s;", + ix -> rr_originally_intended_recip -> fn_addr); + + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + } + + if (ix -> rr_supplementary != NULL) { + (void) sprintf(buffer, "supplementary info \"%s\";", + ix -> rr_supplementary); + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + } + + if (ix -> rr_redirect_history != NULL) { + Redirection *rix = ix -> rr_redirect_history; + temp[0] = '\0'; + if (rp_isbad(write_cont("redirection history", FALSE))) + return RP_BAD; + while (rix != NULL) { + if (rix -> rd_next != NULL) + (void) sprintf(buffer, "%s,", rix -> rd_addr); + else + (void) sprintf(buffer, "%s;", rix -> rd_addr); + if (rp_isbad(write_cont(buffer, TRUE))) + return RP_BAD; + rix = rix -> rd_next; + } + } + + if (ix -> rr_physical_fwd_addr != NULL) { + (void) sprintf(buffer, "physical forwarding address %s;", + ix -> rr_physical_fwd_addr -> fn_addr); + if (rp_isbad(write_cont(buffer, FALSE))) + return RP_BAD; + } + if (rp_isbad(write_end())) + return RP_BAD; + ix = ix -> rr_next; + } + end_admin_info(); + } + + /* dr-content-return */ + + avail = FALSE; + if (allSuccess != TRUE && + PPQuePtr -> content_return_request == TRUE) { + if (qid2dir (this_msg, PPQuePtr->Oaddress, TRUE, &dir) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, ("qid2dir failed for originator")); + dir = NULLCP; + } else if (msg_rinit(dir) == NOTOK) + PP_LOG(LLOG_EXCEPTIONS, ("msg_rinit failed")); + else if ((retval = msg_rfile (filename)) == RP_OK) { + /* check for correct content type i.e presence of hdr.822 */ + if ((cix = rindex(filename, '/')) == NULLCP) + cix = filename; + else + cix++; + + if (strncmp(cix, + hdr_822_bp, + strlen(hdr_822_bp)) != 0) { + PP_LOG(LLOG_DEBUG, + ("Unable to find a hdr.822 in directory '%s'", dir)); + (void) msg_rend(); + } else + avail = TRUE; + } else + (void) msg_rend(); + } + + if (TRUE == allSuccess) + (void) sprintf(buffer, + "\nThe Original Message is not returned with positive reports\n"); + else if (avail == TRUE) { + dirlen = strlen(dir) + 1; + if (include_all == TRUE + || PPQuePtr -> msgsize <= max_include_msg) + (void) sprintf(buffer, "\nThe Original Message follows:\n\n"); + else + (void) sprintf(buffer, "\nThe Original Message follows but for size reasons has been truncated:\n\n"); + } else + (void) sprintf(buffer, "\nThe Original Message is not available\n"); + + if (avail == FALSE || allSuccess == TRUE) { + if (rp_isbad(io_tdata (buffer, strlen(buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + (void) sprintf(error, + "io_tdata error"); + stop_io(); + return RP_BAD; + } + } + + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails")); + (void) sprintf(error, + "io_tdend error"); + stop_io(); + return RP_BAD; + } + + if (avail == FALSE || allSuccess == TRUE) { + if (rp_isbad (io_tend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tend fails")); + (void) sprintf(error, + "io_tend error"); + stop_io(); + return RP_BAD; + } else + return RP_OK; + } + + return_size = 0; + + /* copy header no matter what size */ + if (rp_isbad (retval = copy (filename))) { + PP_LOG (LLOG_EXCEPTIONS, ("failed to copy header '%s'", filename)); + (void) sprintf (error, + "Failed to submit header '%s'", + filename); + return RP_BAD; + } + + if (allSuccess == FALSE) { + if (include_all == TRUE + || PPQuePtr -> msgsize <= max_include_msg) + while ((retval = msg_rfile (filename)) == RP_OK) { + if (rp_isbad (retval = copy (filename))) + break; + } + else { + int numLines = 0; + while ((retval = msg_rfile (filename)) == RP_OK + && numLines < num_include_lines + && return_size < max_include_msg) { + if (rp_isbad (retval = linecopy (filename, &numLines))) + break; + } + } + } + if (dir) free(dir); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("message copy failed")); + return RP_BAD; + } + + if (rp_isbad (retval = msg_rend ())) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_rend () failed")); + (void) sprintf (error, + "msg_rend failed"); + return RP_BAD; + } + + if (rp_isbad (io_tend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tend fails")); + (void) sprintf (error, + "io_tend failed"); + stop_io(); + return RP_BAD; + } + + return RP_OK; +} + +static int do_subject_intermediate_trace(trace) +Trace *trace; +{ + char *j, oldj, buffer[BUFSIZ]; + if (trace->trace_next != NULL + && rp_isbad(do_subject_intermediate_trace(trace->trace_next))) + return RP_BAD; + + if (trace2rfc(trace, buffer) == NOTOK) + return RP_BAD; + + j = buffer; + while (*j != '\0' && *j != ';') j++; + if (*j != '\0') j++; + oldj = *j; + *j = '\0'; + if (rp_isbad(write_start("Subject-Intermediate-Trace-Information: ", buffer))) + return RP_BAD; + if (oldj != '\0') { + *j = oldj; + if (rp_isbad(write_cont(j,FALSE))) + return RP_BAD; + } + if (rp_isbad(write_end())) + return RP_BAD; + return RP_OK; +} + +static int linecopy (file, pnumlines) +char *file; +int *pnumlines; +{ + FILE *fp; + RP_Buf rps, + *rp = &rps; + int retval = RP_OK; + char buf[BUFSIZ], *ix, *top; + + ix = strdup(file + dirlen); + + /* strip of following -us or -uk from hdr_822_bp's */ + if ((top = rindex(ix, '/')) == NULLCP) + top = ix; + else + top++; + + if (lexnequ(top, hdr_822_bp, strlen(hdr_822_bp)) == 0) + *(top+strlen(hdr_822_bp)) = '\0'; + + if (forwarded == TRUE) + (void) sprintf(buf, "2.ipm/2.ipm/%s", ix); + else + (void) sprintf(buf, "2.ipm/%s", ix); + + free(ix); + + if (rp_isbad(io_tpart (buf, FALSE, rp))) { + PP_TRACE (("dr2rfc/wr_body/tpart blows %s", rp -> rp_line)); + stop_io(); + return RP_BAD; + } + + if ((fp = fopen (file, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, file, + ("Can't open file")); + (void) sprintf (error, + "Can't open file '%s'", + file); + stop_io(); + return RP_FOPN; + } + + while (*pnumlines < num_include_lines + && return_size < max_include_msg + && fgets (buf, sizeof buf, fp) != NULL) { + if (io_tdata (buf, strlen(buf)) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + retval = RP_FIO; + break; + } + (*pnumlines)++; + return_size += strlen(buf); + } + + if (*pnumlines >= num_include_lines + || return_size >= max_include_msg) { + if (io_tdata("......(message truncated)\n", + strlen("......(message truncated)\n")) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + retval = RP_FIO; + } + } + + (void) fclose (fp); + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails")); + (void) sprintf (error, + "io_tdend fails"); + stop_io(); + return RP_BAD; + } + return retval; +} + +static int copy (file) +char *file; +{ + FILE *fp; + RP_Buf rps, + *rp = &rps; + int retval = RP_OK; + extern char *hdr_822_bp; + char buf[BUFSIZ], *ix, *top; + int n; + struct stat st; + + ix = strdup(file + dirlen); + + /* strip of following -us or -uk from hdr_822_bp's */ + if ((top = rindex(ix, '/')) == NULLCP) + top = ix; + else + top++; + + if (lexnequ(top, hdr_822_bp, strlen(hdr_822_bp)) == 0) + *(top+strlen(hdr_822_bp)) = '\0'; + + if (stat(file, &st) != 0) { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + return RP_BAD; + } + + if (linked == TRUE) { + if (forwarded == TRUE) + (void) sprintf(buf, "2.ipm/2.ipm/%s %s", ix, file); + else + (void) sprintf(buf, "2.ipm/%s %s", ix, file); + free(ix); + if (rp_isbad(io_tpart (buf, TRUE, rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line)); + stop_io(); + return RP_BAD; + } + } else { + if (forwarded == TRUE) + (void) sprintf(buf, "2.ipm/2.ipm/%s", ix); + else + (void) sprintf(buf, "2.ipm/%s", ix); + free(ix); + if (rp_isbad(io_tpart (buf, FALSE, rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("dr2rfc/wr_body/tpart blows %s", rp -> rp_line)); + stop_io(); + return RP_BAD; + } + + if ((fp = fopen (file, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, file, + ("Can't open file")); + (void) sprintf (error, + "Can't open file '%s'", + file); + stop_io(); + return RP_FOPN; + } + + while ((n = fread (buf, sizeof (char), sizeof buf, fp)) > 0) { + if (io_tdata (buf, n) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf(error, + "io_tdata error"); + stop_io(); + retval = RP_FIO; + break; + } + } + (void) fclose (fp); + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("dr2rfc/wr_body/io_tdend fails")); + (void) sprintf(error, + "io_tdend fails"); + stop_io(); + return RP_BAD; + } + } + + return_size += (long) st.st_size; + return retval; +} + +#define DEFAULT_FOLD_LENGTH 70 + +int chnum, tab = 8, foldlength = DEFAULT_FOLD_LENGTH; +static int admin_info = FALSE; + +static int start_admin_info () +{ + write_start ("***** The following information is directed towards the local administrator\n***** and is not intended for the end user\n*", ""); + write_end (); + admin_info = TRUE; +} + +static int end_admin_info() +{ + admin_info = FALSE; + write_start("****** End of administration information", ""); + write_end(); +} + +static int write_start(key, value) +char *key, + *value; +{ + int retval; + char buffer[BUFSIZ]; + if (key == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, ("Null key in output")); + return RP_BAD; + } + + (void) sprintf(buffer, "%s%s %s", + (admin_info == TRUE) ? "* " : "", + key, value); + if (rp_isbad(retval = io_tdata(buffer, strlen(buffer)))) { + PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf(error, + "io_tdata error"); + stop_io(); + } + chnum = strlen(buffer); + + return retval; +} + +static int write_cont(value, fold) +char *value; +int fold; +{ + int retval, len; + char buffer[BUFSIZ], *ix, *base, *lastix, *foldpt, savech; + + if (value == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, ("Null value in output")); + return RP_BAD; + } + + len = strlen(value); + + bzero(buffer, sizeof buffer); + + if (fold == FALSE) { + if (chnum + len > foldlength) { + (void) sprintf(buffer, "\n%s%*s%s", + (admin_info == TRUE) ? "* ": "", + tab, "", value); + chnum = tab; + } else + (void) sprintf(buffer, " %s", value); + chnum += len; + } else { + ix = lastix = base = value; + + /* write_cont assume big start new line */ + (void) sprintf (buffer, "\n%s%*s", + (admin_info == TRUE) ? "* " : "", + tab, ""); + chnum = tab; + + while (ix != NULLCP && *ix != '\0') { + while (*ix != '\0' && !isspace(*ix)) + ix++; + + if (chnum + (ix - base) > foldlength) { + /* need to fold */ + if (lastix == base) + foldpt = ix; + else + foldpt = lastix; + savech = *foldpt; + *foldpt = '\0'; + (void) sprintf (buffer, "%s%s\n%s%*s", + buffer, base, + (admin_info == TRUE) ? "* " : "", + tab, ""); + *foldpt = savech; + base = foldpt; + if (savech != '\0') + /* skip last space */ + base++; + chnum = tab; + } + lastix = ix; + if (*ix != '\0') ix++; + } + /* flush rest */ + if (base != ix) { + if (chnum + (ix - base) > foldlength) { + (void) sprintf(buffer, "%s\n%s%*s%s", + buffer, + (admin_info == TRUE) ? "* " : "", + tab, "", base); + chnum = tab; + } else + (void) strcat (buffer, base); + chnum += ix - base; + } + } + + if (rp_isbad(retval = io_tdata(buffer, strlen(buffer)))) { + PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf(error, + "io_tdata error"); + stop_io(); + } + return retval; +} + +static int write_end() +{ + int retval; + if (rp_isbad(retval = io_tdata("\n", strlen("\n")))) { + PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf(error, + "io_tdata error"); + stop_io(); + } + return retval; +} + +static int DR_write (key, value) +char *key; +char *value; +{ + char buffer[BUFSIZ]; + int retval; + + if (value == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("No value for key %s", key)); + return RP_BAD; + } + + bzero (buffer, sizeof buffer); + if (admin_info == TRUE) + (void) strcat (buffer, "* "); + if (key) + (void) strcat (buffer, key); + (void) strcat (buffer, value); + (void) strcat (buffer, "\n"); + if (rp_isbad (retval = io_tdata (buffer, strlen (buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + } + return retval; +} + + +static int DR_print (key, value) +char *key; +char *value; +{ + char buffer [BUFSIZ]; + char obuf[BUFSIZ]; + int retval; + + if (value == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("No value for key %s", key)); + return RP_BAD; + } + + bzero (buffer, sizeof buffer); + if (admin_info == TRUE) + (void) strcat (buffer, "* "); + if (key) + (void) strcat (buffer, key); + (void) strcat (buffer, value); + rfctxtfold (buffer, obuf, 66); + if (rp_isbad (retval = io_tdata (obuf, strlen (obuf)))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdata error")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + } + return retval; +} + +/* output string padding newlines with some indentation */ + +pretty_output(str, padding) +char *str; +int padding; +{ + char buffer[BUFSIZ]; + int i = 0, ix; + if (str == NULL) + return RP_BAD; + + while (*str != '\0') { + if (i == BUFSIZ-1) { + /* flush buffer */ + buffer[i] = '\0'; + if (rp_isbad(io_tdata(buffer, strlen(buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + return RP_BAD; + } + i = 0; + } + + buffer[i++] = *str; + + if (*str++ == '\n') { + if (i >= BUFSIZ - 3) { + /* flush buffer */ + buffer[i] = '\0'; + if (rp_isbad(io_tdata(buffer, strlen(buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + (void) sprintf (error, + "io_tdata error"); + stop_io(); + return RP_BAD; + } + i = 0; + } + + if (admin_info == TRUE) + buffer[i++] = '*'; + + /* pad newlines */ + for (ix = 0; ix < padding; ix++) + buffer[i++] = ' '; + } + + } + + if (i > 0) { + /* flush buffer */ + buffer[i] = '\0'; + if (rp_isbad(io_tdata(buffer, strlen(buffer)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Error writing message")); + stop_io(); + return RP_BAD; + } + } + + return RP_OK; +} + +/* */ + +static char *parseSubject(file) +char *file; +{ + char buf[BUFSIZ], *ret = NULLCP, *ix; + int subject = FALSE, len; + FILE *fd; + if ((fd = fopen(file, "r")) == NULL) + return NULLCP; + + while (subject == FALSE + && fgets(buf, BUFSIZ, fd) != NULLCP) { + if ((ix = index(buf, ':')) != NULLCP) { + *ix = '\0'; + if (lexequ("subject",buf) == 0) { + subject = TRUE; + ix++; + while (*ix && isspace(*ix)) ix++; + len = strlen(ix); + *(ix + len - 1) = '\0'; + ret = strdup(ix); + } + } + } + (void) fclose(fd); + return ret; +} + +extern char *hdr_822_bp; + +static int isHdr(entry) +struct dirent *entry; +{ + if (strncmp(entry->d_name, hdr_822_bp, strlen(hdr_822_bp)) == 0) + return 1; + return 0; +} + +static char *getSubject(msg_id, recip) +char *msg_id; +ADDR *recip; +{ + char *dir = NULLCP, hdr[MAXPATHLENGTH], *subject = NULLCP; + struct dirent **namelist = NULL; + int gothdr = FALSE, + rcnt = recip->ad_rcnt; + recip->ad_rcnt = 0; + while (gothdr == FALSE && recip->ad_rcnt <= rcnt) { + if (qid2dir(msg_id, recip, TRUE, &dir) == OK) { + if (_scandir(dir, &namelist, isHdr, NULLIFP) > 0) + gothdr = TRUE; + } + recip->ad_rcnt++; + } + + recip->ad_rcnt = rcnt; + if (gothdr == FALSE) + return NULLCP; + if ((*namelist)->d_name[0] != '/') + (void) sprintf(hdr, "%s/%s", dir, (*namelist)->d_name); + else + (void) strcpy(hdr, (*namelist)->d_name); + + subject = parseSubject(hdr); + free((char *) namelist); + free(dir); + return subject; +} + + +static int get822Mailbox(ix, pmailbox) +Rrinfo *ix; +char **pmailbox; +{ + ADDR *ad; + char buf[BUFSIZ]; + *pmailbox = NULLCP; + for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next) + if (ad -> ad_no == ix -> rr_recip) + break; + if (ad == NULL) + (void) sprintf(buf,"recipient %d", + ix -> rr_recip); + else if (ad -> ad_r822adr != NULL) { + char *str = NULLCP; + ap_s2s (ad -> ad_r822adr, &str, order_pref); + if (str != NULLCP && *str != '\0') { + (void) sprintf(buf, "%s", str); + free(str); + } else + (void) sprintf(buf, "%s", + ad -> ad_r822adr); + } else if (ad -> ad_value != NULL) + (void) sprintf(buf, "%s", ad -> ad_value); + else if (ad -> ad_type == AD_X400_TYPE + && ad -> ad_r400adr != NULL) + (void) sprintf(buf, "%s", ad -> ad_r400adr); + else { + PP_LOG (LLOG_EXCEPTIONS, ("Error no address string given for recip '%d'\n", ix -> rr_recip)); + return RP_BAD; + } + *pmailbox = strdup(buf); + return RP_OK; +} + +static int allSameType(ix, type) +Rrinfo *ix; +int type; +{ + if (ix == NULL) return FALSE; + while (ix != NULL && ix->rr_report.rep_type == type) + ix = ix -> rr_next; + if (ix == NULL) + return TRUE; + else + return FALSE; +} + +static int allSameMta(ix, pmta) +Rrinfo *ix; +char **pmta; +{ + ADDR *ad; + int first = TRUE, allSame = TRUE; + + + while (ix != NULL) { + for (ad = PPQuePtr -> Raddress; ad; ad = ad->ad_next) + if (ad -> ad_no == ix -> rr_recip) + break; + if (ad != NULL + && ad -> ad_outchan != NULL + && ad -> ad_outchan -> li_mta) { + if (first == TRUE) { + *pmta = strdup(ad -> ad_outchan -> li_mta); + first = FALSE; + } else if (lexequ(*pmta, ad -> ad_outchan -> li_mta) != 0) + allSame = FALSE; + } + ix = ix -> rr_next; + } + if (first == FALSE && allSame == TRUE) + return TRUE; + return FALSE; +} diff --git a/Chans/fax/Makefile b/Chans/fax/Makefile new file mode 100644 index 0000000..c28251d --- /dev/null +++ b/Chans/fax/Makefile @@ -0,0 +1,99 @@ +# Fax Channel Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/fax/RCS/Makefile,v 6.0 1991/12/18 20:07:09 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:07:09 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +PPTREE = ../.. + +PPOUTSRCS = fax_out.c +PPOUTOBJS = fax_out.o + +PPINSRCS = fax_in.c +PPINOBJS = fax_in.o + +SRCS = $(PPOUTSRCS) $(PPINSRCS) +OBJS = $(PPOUTOBJS) $(PPINOBJS) + +ALLDRIVERS = dexNet200 ps250 + +HEADERS = $(PPTREE)/h +LIBPP = $(PPTREE)/Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) $(PEPSYHEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = $(PPTREE)/Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + + +target: $(OBJS) + @sh -c "if [ -z \"$(FAXDRIVERS)\" ];\ + then echo \"No FAXDRIVERS variable defined - must be in Make.defs\";\ + exit 1;\ + fi" + @for i in $(FAXDRIVERS) ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE));\ + done + +install: $(OBJS) + @sh -c "if [ -z \"$(FAXDRIVERS)\" ];\ + then echo \"No FAXDRIVERS defined\"; exit 1;\ + fi" + @for i in ${FAXDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +clean: tidy + @for i in ${ALLDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +tidy: + rm -f $(OBJS) + @for i in ${ALLDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + @for i in ${ALLDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +define: + @for i in ${ALLDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +lint: l-out l-in l-subs + +l-out: + $(LINT) $(LLFLAGS) $(PPOUTSRCS) $(LINTLIBS) + +l-in: + $(LINT) $(LLFLAGS) $(PPINSRCS) $(LINTLIBS) + +l-subs: + @for i in ${ALLDRIVERS} ; \ + do (echo "cd $$i; $(MAKE) lint"; cd $$i; $(MAKE) lint); done + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow diff --git a/Chans/fax/dexNet200/Makefile b/Chans/fax/dexNet200/Makefile new file mode 100644 index 0000000..e1f703c --- /dev/null +++ b/Chans/fax/dexNet200/Makefile @@ -0,0 +1,86 @@ +# dexNet200 fax driver Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/Makefile,v 6.0 1991/12/18 20:08:53 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:08:53 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +PPOUTSRCS = ../fax_out.c +PPOUTOBJS = ../fax_out.o + +OUTSRCS = dexnet_intf.c dexnet_util.c dexnet_conv.c +OUTOBJS = dexnet_intf.o dexnet_util.o dexnet_conv.o + +HEADERS = ../../../h +LIBPP = ../../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xfax + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +install: inst-dir inst-out + +inst-dir: $(CHANDIR) + +lint: l-out + +############################################################ +# +# Fax channel +# +############################################################ + +xfax: $(OUTOBJS) $(PPOUTOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OUTOBJS) $(PPOUTOBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(OUTSRCS) $(PPOUTSRCS) + #load -C $(CFLAGS) $(OUTSRCS) $(PPOUTSRCS) $(LIBPP) $(LIBSYS) + +inst-out: $(CHANDIR)/dexNet200 +$(CHANDIR)/dexNet200: xfax + -$(BACKUP) $@ zxfax + rm -f $@ + $(INSTALL) xfax $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dexNet200 outbound fax channel installed normally"; echo "" +clean: tidy + rm -f $(PROGS) + +tidy: + rm -f $(OUTOBJS) core a.out Makefile.old + +l-out: $(OUTSRCS) $(PPOUTSRCS) + $(LINT) $(LLFLAGS) $(OUTSRCS) $(PPOUTSRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(OUTSRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Chans/fax/dexNet200/dexnet.h b/Chans/fax/dexNet200/dexnet.h new file mode 100644 index 0000000..60dc65a --- /dev/null +++ b/Chans/fax/dexNet200/dexnet.h @@ -0,0 +1,134 @@ +/* faxcodes.h: codes for the Fujitsu */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet.h,v 6.0 1991/12/18 20:08:53 jpo Rel $ + * + * $Log: dexnet.h,v $ + * Revision 6.0 1991/12/18 20:08:53 jpo + * Release 6.0 + * + * + */ + +/* + + This file contains the fax codes for the Fujitsu dexNet200. + + HISTORY: + + ?/?/? J. Knowles Created. + 3/24/91 S. Berdia Revamped. + 11/1/91 R. Hagens Rewacked + 12/4/91 P. Nikander Modified. +*/ +/* modem control codes */ +#define ANS_OFF {27,3,0} /* set answer mode off */ +#define IMAGE_MODE "\033\031\001" /* set image mode */ +#define TEXT_MODE "\033\031\000" /* set text mode */ +#define COMM_MODE "\033\031\002" /* set comm mode */ +#define CTS "\033\040\001" /* set CTS flow control */ +#define ZERO_RETRY "\033\144\000" /* set retries to zero */ +#define DIAL_NMBR "\033\002" /* dial number */ +#define END_OF_TRANS "\033\004" /* EOT string */ +#define ASK_STAT "\033\005" /* query fax status */ +#define BAUD_9600 "\033\022" /* set baud rate to 9600 */ +#define BAUD_19200 "\033\024" /* set baud rate to 19200 */ +#define FINE_RES "\033\033" /* set fine resolution */ +#define SEND_TTI "\033\034" /* send TTI for header */ +#define SEND_TIME "\033\036" /* send time for header */ +#define SEND_DATE "\033\037" /* send date for header */ +#define XON_XOFF "\033\040\001" /* set XON/XOFF flow control */ +#define FACTDEF "\033\364\033\360\033\365"/* reset factory deflt */ +#define RESET "\033\354" /* reset */ +#define NOSTEPUP "\033\026\000" /* disable STEUP on RTP */ +#define MH_START "\033\053" /* start of MH image */ +#define MH_END "\000\000" /* End of MH image */ +#define SEND_POLL "\033\027" /* Enable send polling */ +#define ASK_VERSION "\033\367\367" /* query version */ +#define MONITOR "\033\003\005" /* monitor line state */ +#define CUTPAGE "\033\014" /* cut page immediately */ +#define UNDERRUN "\033\003\127" /* turn on underrun diag */ + +#define SPEAKER_ON "\033\030\002" /* turn on speaker */ + +/* printer control codes */ +#define BOLD_EXPND "\033!4\r" /* set bold expand */ +#define THIN_LINE '\304' /* thin line char code */ +#define THICK_LINE '\337' /* thick line char code */ +#define EXP_COMP_OFF {27,87,0,'\222',12} /* expand/compress off, FF */ + + +#define ESC 0x1b +#define DLE 0x10 +#define BEL 0x07 +#define ACK 0x06 +#define NAK 0x15 +#define FS 0x1c +#define HT 0x09 +#define CR 0x0d +#define CAN 0x18 +#define XXON 0x11 +#define XXOFF 0x13 + +/* + * dexNET 200 error response + */ +#define dexUnknown 0 +#define dexNotReady 1 +#define dexReady 2 +#define dexConnected 3 +#define dexWaiting 4 +#define dexDialing 5 +#define dexSID 6 +#define dexTID 7 +#define dexStandardRes 8 +#define dexFineRes 9 +#define dexCallTerm 10 +#define dexAck 11 +#define dexNak 12 +#define dexRing 13 +#define dexBufferLow 14 +#define dex9600Baud 15 +#define dex7200Baud 16 +#define dex4800Baud 17 +#define dex2400Baud 18 +#define dexScanError 19 +#define dexVersion 20 +#define dexBusy 21 +#define dexNoResponse 22 +#define dexNotAFax 23 +#define dexDisconnect 24 +#define dexResError 25 +#define dexUnderrun 26 +#define dexBufFull 27 +#define dexBufEmpty 28 + +#define IssueCommand(fd, cmd, msg)\ + if (writeDexModem(fd, cmd, sizeof(cmd)-1, msg) == NOTOK)\ + return(NOTOK); + +#define IssueData(fd, cmd, len)\ + if (writeDexModem(fd, cmd, len, "IssueData") == NOTOK)\ + return(NOTOK); + +typedef struct _dexModem { + int fd; /* fd open to modem */ + char devName[255]; /* name of device */ + int highSpeed; /* true if talk at 19.2K baud */ + int xmitErrs; /* errors encountered during transmission */ + char msgBuf[255]; /* user readable error message stored here */ + char errBuf[255]; /* unix i.e., cryptic error message stored here */ + char stationId[25]; /* station identification */ + char terminalId[25]; /* terminal identification */ + int msgCode; /* code accompanies reason in msgBuf */ + + char tti[255]; /* outgoing tti */ + char *intlPrefix; /* international prefix */ + char *longdPrefix; /* long distance prefix */ + char *localPrefix; /* local access prefix (outside line) */ + char noLongDistance; /* access control */ + char noInternational;/* access control */ + int maxPages; /* limit number of pages sent */ +} DexModem; + +extern char *codeToString(); diff --git a/Chans/fax/dexNet200/dexnet_conv.c b/Chans/fax/dexNet200/dexnet_conv.c new file mode 100644 index 0000000..75f0e61 --- /dev/null +++ b/Chans/fax/dexNet200/dexnet_conv.c @@ -0,0 +1,239 @@ +/* dexnet_conv.c: convert g3 into Fujitsu */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_conv.c,v 6.0 1991/12/18 20:09:42 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_conv.c,v 6.0 1991/12/18 20:09:42 jpo Rel $ + * + * $Log: dexnet_conv.c,v $ + * Revision 6.0 1991/12/18 20:09:42 jpo + * Release 6.0 + * + */ + +/* fujicnvrt.c -- NASA Ames Research Center. + + Author: Jim Knowles + Internet: jknowles@trident.arc.nasa.gov + Sterling Federal Systems + NAS2-13210 + NASA, Ames Research Center + Mail Stop 233-18 + Moffett Field CA 94035 + + + Purpose: encapsulates ASN.1 g3-encoded scanlines in FCRP - + Fujitsu proprietary command/response protocol. + resulting file can be transmitted by Fujitsu fax modem. + FCRP begins each scanline with ESC + and replaces G3 EOL + with NUL NUL after padding with zeros to byte-align. + this module is used by the FaxMail package. + + Input: ASN.1 G3 encoded fax file received as faxmail enclosure. + + Output: FCRP encapsulated G3 image file for transmittal. + + Errors: + + External references: + name description source + ---- ----------- ------ + + Files: + name description + ---- ----------- + + + Environment: 4.3 BSD UNIX + + Development History: + date initials description + Apr 91 jdk code developer. +*/ + + +#include +#include +#ifdef sun +#include +#else +#ifdef vax +#include +#else +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif +#endif +#include +#include +#include +#include + +#define MASK 0x80 /* initial mask for bit manipulation */ +#define BUF_SIZE 4096 /* buffer size */ + +#define TRUE 1 /* booleans */ +#define FALSE 0 +#define BOOL int +#define NUL '\000' /* nul char */ +#define ESC '\033' /* esc char */ +#define PLUS '\053' /* + char */ +#define FF '\014' /* form feed */ + + +/* forward declarations */ +static void output(); +static void set_bit(); +static void clr_bit(); + +/* global variables */ +static int fu_fd; /* file descriptor for FCRP file */ +static int write_cnt; /* characters written to write_buf */ +static unsigned char g3_ch; /* character in production */ +static unsigned char write_mask; /* masked bit in char written */ +static unsigned char save_ch; /* last character written */ +static unsigned char *buf_ptr; /* pointer into write_buf */ + +/* + * Convert each scanline to have escape + as prefix and NUL NUL as suffix + * Return number of bytes placed into sink + */ +fujicnvrt(source, sink, length) +unsigned char *source, *sink; +int length; /* of source; sink assumed to be big enough */ +{ + register unsigned char bit_mask;/* masks bit in currently read byte */ + register unsigned char *ptr; /* pointer into read buffer */ + register unsigned char *eptr; /* pointer to end of read buffer */ + register int zero_bits = 0; /* number of consecutive zero bits */ + BOOL past_init = FALSE; /* past the first eol sequence */ + BOOL new_page = FALSE; /* start on new page */ + int scanlines = 0; + + write_cnt = 0; /* initialize for output */ + write_mask = MASK; + buf_ptr = sink; /* set start of write buffer */ + zero_bits = 8; /* initial NUL (part of eol) */ + if (new_page) { + g3_ch = FF; + output(g3_ch); + } + output(ESC); + output(PLUS); + eptr = source + length; + for (ptr = source; ptr < eptr; ptr++) { + for (bit_mask = MASK; bit_mask > 0;) { + if (*ptr & bit_mask) { + if (zero_bits >= 11) { + zero_bits = 0; + write_mask = MASK; + if (past_init) { + g3_ch ^= g3_ch; + if (save_ch != g3_ch) + output(g3_ch); + output(g3_ch); + output(ESC); + output(PLUS); + scanlines++; + } else { + past_init = TRUE; + g3_ch ^= g3_ch; + } + if (bit_mask == 0) { + bit_mask = MASK; + if (++ptr == eptr) + break; + } + } else { + set_bit(); + zero_bits = 0; + } + } else { + if (past_init) + clr_bit(); + zero_bits++; + } + bit_mask >>= 1; + } + } + while (write_mask != MASK) /* write character in production */ + clr_bit(); + if (g3_ch) { + g3_ch ^= g3_ch; + output(g3_ch); + } + output(g3_ch); +/* fprintf(stderr, "%d scanlines\n", scanlines); */ + return(write_cnt); +} + + + +/*++ output() + * function: output one character into write buffer + * parameters: o_ch - unsigned character to write into buffer. + * return: none. + * global: buf_ptr - pointer into write buffer. + * save_ch - most recent character written. + * write_cnt - number of characters written into write buffer. + * write_buf - output buffer. + * called by: main(), set_bit(), clear_bit(). + * calls: none. + --*/ + +static void +output(o_ch) +register unsigned char o_ch; +{ + *buf_ptr++ = save_ch = o_ch; + write_cnt++; +} + + +/*++ set_bit() + * function: sets bit in current byte; + * outputs to write buffer when byte is full. + * parameters: none. + * return: none. + * global: write_mask - masks current bit in g3_ch. + * g3_ch - character currently in production. + * called by: main(). + * calls: output(). + --*/ + +static void +set_bit() +{ + g3_ch |= write_mask; + write_mask >>= 1; + if (write_mask == 0) { + output(g3_ch); + write_mask = MASK; + } +} + + +/*++ clr_bit() + * function: clears bit in current byte; + * outputs to write buffer when byte is full. + * parameters: none. + * return: none. + * global: write_mask - masks current bit in g3_ch. + * g3_ch - character currently in production. + * called by: main(). + * calls: output(). + --*/ + +static void +clr_bit() +{ + g3_ch &= ~write_mask; + write_mask >>= 1; + if (write_mask == 0) { + output(g3_ch); + write_mask = MASK; + } +} diff --git a/Chans/fax/dexNet200/dexnet_intf.c b/Chans/fax/dexNet200/dexnet_intf.c new file mode 100644 index 0000000..dfb9775 --- /dev/null +++ b/Chans/fax/dexNet200/dexnet_intf.c @@ -0,0 +1,479 @@ +/* dexnet_intf.c: interfcae routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_intf.c,v 6.0 1991/12/18 20:08:53 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_intf.c,v 6.0 1991/12/18 20:08:53 jpo Rel $ + * + * $Log: dexnet_intf.c,v $ + * Revision 6.0 1991/12/18 20:08:53 jpo + * Release 6.0 + * + */ + +/* Interface to the Dexnet 200 Fax Modem */ + +#include "util.h" +#include "retcode.h" +#include "adr.h" +#include "qmgr.h" +#include +#include "tb_bpt88.h" +#include "IOB-types.h" +#include "MTA-types.h" +#include "or.h" +#include +#include +#include +#include "../faxgeneric.h" +#include "dexnet.h" + +#define DEM(faxctl) ((DexModem *)((faxctl)->softc)) + +extern CHAN *mychan; +static int numPages; + +/* + * Open dexNet device and initialize + * Return OK or NOTOK + */ +dexOpen(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + int ret; + + ret = openDexModem(dem); + if (ret != OK) { + PP_LOG(LLOG_EXCEPTIONS, ("dexOpen: %s", dem->errBuf)); + strcpy(faxctl->errBuf, "Can't open fax device"); + return(ret); + } + return OK; +} + +/* close dexNet */ +dexClose(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + closeDexModem(dem); +} + +/* + * Copy the phone number from src to dst. Return the address of the next + * unused byte in dst. Filter src so as to only copy the following + * characters: + * 0-9, comma (indicates pause), W (indicates wait for dialtone) + * P is changed to comma + * All other characters are ignored. + */ +static char * +copyPhoneNumber(src, dst) +char *src, *dst; +{ + for (; *src; src++) { + if (isdigit(*src) || (*src == ',') || (*src == 'W')) + *dst++ = *src; + else if (*src == 'P') + *dst++ = ','; + } + return(dst); +} + + +#define FAX_TELNOSIZE 28 + +static int localCall = 7; +static int longDistance = 10; + +/* + * Normalize the phone number. In general, copy the phone number 'from' + * into 'to', skipping "phone" whitespace (see macro isPhoneWhite). + * + * Add prefix for local access, long distance and international calls. + * Disallow long distance and international calls if necessary. + * + * Return OK or NOTOK and set faxctl->errBuf + * + * NOTE: this is completely USA-centric + */ +static int convertPhoneNumber(faxctl, from, to) +FaxCtlr *faxctl; +char *from, *to; +{ + char *ifrom = from, *ito = to; + DexModem *dem = DEM(faxctl); + int digits = 0; + + /* count the actual number of digits */ + for (;*ifrom;ifrom++) + if (isdigit(*ifrom)) + digits++; + + if (digits < localCall) { + ; /* do nothing */ + } else if (digits == localCall) { + /* add local access if defined */ + if (dem->localPrefix) + ito = copyPhoneNumber(dem->localPrefix, ito); + } else if (digits == longDistance) { + if (dem->noLongDistance) { + sprintf(faxctl->errBuf, "Long distance calls not allowed"); + return(NOTOK); + } else if (dem->longdPrefix) + ito = copyPhoneNumber(dem->longdPrefix, ito); + } else if (digits > longDistance) { + char *plus = index(from, '+'); + if (!plus) { + sprintf(faxctl->errBuf, "International call not flagged with +"); + return(NOTOK); + } + if (dem->noInternational) { + sprintf(faxctl->errBuf, "International calls not allowed"); + return(NOTOK); + } + if (dem->intlPrefix) + ito = copyPhoneNumber(dem->intlPrefix, ito); + } else { + sprintf(faxctl->errBuf, "Invalid telephone number with %d digits", digits); + return(NOTOK); + } + + ito = copyPhoneNumber(from, ito); + *ito = '\0'; + + return OK; +} + +/* + * Initialize for transmission + * Returns: PP return code + */ +dexInitXmit(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + char now[30], telno[FAX_TELNOSIZE]; + char *date, *tim; + time_t clock; + int ret = RP_BOK; + + faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure; + numPages = 0; + + if (convertPhoneNumber(faxctl, faxctl->telno, telno) != OK) { + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return(RP_MECH); + } + + PP_TRACE(("Dialing %s", telno)); + + /* currently setup at 19.2K */ + if (setupDexModem(dem, 1) != OK) { + PP_LOG(LLOG_EXCEPTIONS, ("dexInitXmit: setup %s", dem->errBuf)); + strcpy(faxctl->errBuf, "Can't setup fax device"); + return(RP_MECH); + } + + time(&clock); + strcpy(now, ctime(&clock)); + date = now; + date[10] = (char)0; + tim = &now[11]; + tim[8] = (char)0; + + if (dialDexModem(dem, telno, date, tim, dem->tti) != OK) { + PP_LOG(LLOG_EXCEPTIONS, ("dexOpen: dial %s", dem->errBuf)); + strcpy(faxctl->errBuf, "Can't dial remote fax device"); + ret = RP_MECH; + } + return(ret); +} + +/* + * Abort the call. It would be nice to just send a RESET to the modem, + * but it may be in la-la land with CTS off, so the only sure-fire way + * to reset is to use the hardware reset (drop DTR for a bit). Arrgh! + */ +dexAbort(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + hardResetDexModem(dem); +} + +/* + * Terminate transmission to remote fax + * Returns: OK or NOTOK + */ +dexTermXmit(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + int ret = OK; + + if ((ret = eomDexModem(dem)) != OK) { + /* based on actual error, either retry or abort */ + if (dem->msgCode == dexNotAFax) { + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + } else { + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + } + PP_LOG(LLOG_EXCEPTIONS, ("dexTermXmit: dial %s", dem->msgBuf)); + strcpy(faxctl->errBuf, dem->msgBuf); + ret = NOTOK; + } + return(ret); +} + +/* + * Set/Test the G3 Parameters + */ + +dexSetParams(faxctl, params) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileParameters *params; +{ + DexModem *dem = DEM(faxctl); + + if (params -> non__basic__parameters) { + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_two__dimensional) == 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to deal with two dimensional fax")); + sprintf(faxctl->errBuf, + "Unable to deal with two dimensional fax"); + return NOTOK; + } + + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_uncompressed) == 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to deal with uncompressed fax")); + sprintf(faxctl->errBuf, + "Unable to deal with uncompressed fax"); + return NOTOK; + } + + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_fine__resolution) == 1) + IssueData(dem, FINE_RES, "FINE_RES"); + + } + return OK; +} + +/* set correct error code based upon dexnet errors */ +dexGenQmgrError(faxctl) +FaxCtlr *faxctl; +{ + DexModem *dem = DEM(faxctl); + if (dem->msgBuf[0]) { + strcpy(faxctl->errBuf, dem->msgBuf); + switch (dem->msgCode) { + case dexNotAFax: + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + break; + case dexNoResponse: /* no answer, retry message */ + case dexBusy: + case dexDisconnect: /* dropped line */ + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + break; + /* all else gets MTA failure */ + default: + faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure; + break; + } + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Error sending page: %s", dem->errBuf)); + strcpy(faxctl->errBuf, "Error communicating with fax modem"); + } +} + +/* + * Send one page of G3 fax + * Returns: OK or NOTOK + */ +dexSendPage(faxctl, str, len, last) +FaxCtlr *faxctl; +char *str; /* g3 fax data to send */ +int len; /* len of str in bytes */ +int last; /* true if last page */ +{ + DexModem *dem = DEM(faxctl); + unsigned char *fuji; + int fujiLen; + int ret = OK; + + faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure; + + if ((dem->maxPages > 0) && (numPages++ > dem->maxPages)) { + /* have exceeded page count; stop transmission */ + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + sprintf(faxctl->errBuf, "Transmission truncated: pagecount %d exceeded", + dem->maxPages); + return(NOTOK); + } + + /* + * Convert G3 fax to (stupidly encoded) dexNet coding. + * conversion will add 4 bytes for every scanline. Thus + * about 1800 scanlines * 4 < 8000 + */ + fuji = (unsigned char *)malloc(len + 8000); + fujiLen = fujicnvrt(str, fuji, len); + ret = sendDexModem(dem, fuji, fujiLen, /* G3 mode */0); + free(fuji); + + if (ret != OK) { + dexGenQmgrError(faxctl); + } + return(ret); +} + +/* + * Open file and send as text to fax modem. + * Reads entire file into memory, converts each linefeed to carriage + * return, linefeed. Return OK or NOTOK + */ +dexSendIA5File(faxctl, fileName, last) +FaxCtlr *faxctl; +char *fileName; /* file to send */ +int last; /* true if last bodypart */ +{ + struct stat sbuf; + unsigned char *buf; + int len = 0, bufLen; + int lines = 0; + unsigned char *p; + int cc; + FILE *fp; + int ret; + DexModem *dem = DEM(faxctl); + + faxctl->qmgrErrCode = int_Qmgr_status_mtaFailure; + + if ((fp = fopen(fileName, "r")) == NULL) { + PP_SLOG(LLOG_EXCEPTIONS, fileName, + ("Can't open file")); + strcpy(faxctl->errBuf, "Error communicating with fax modem"); + return(NOTOK); + } + + fstat(fileno(fp), &sbuf); + bufLen = sbuf.st_size*2; /* worst case estimate */ + p = buf = (unsigned char *)malloc(bufLen); + bzero(buf, bufLen); + + while (fgets(p, bufLen - len, fp) != NULL) { + cc = strlen(p); + p[cc++] = '\r'; /* add carriage return */ + len += cc; + p += cc; + lines++; + } + + /* assume 66 lines per page */ + if ((dem->maxPages > 0) && ((lines/66) > dem->maxPages)) { + /* exceeded page count */ + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + sprintf(faxctl->errBuf, "Attempt to send more than %d pages", + dem->maxPages); + free (buf); + return(NOTOK); + } + + ret = sendDexModem(dem, buf, len, /* textmode true */ 1); + free(buf); + + if (ret != OK) { + dexGenQmgrError(faxctl); + } + return(ret); +} + +/* + * parse info line arguments + * + * out: name of device + * tti: ng tti field + * noLong: disallow long distance calls + * noIntl: disallow international calls + * localPrefix: local access prefix (i.e., outside line) + * longPrefix: long distance access prefix + * intlPrefix: international prefix + * max_pages: limit number of pages sent to this value + */ +int dexArgParse (faxctl, key, value) +FaxCtlr *faxctl; +char *key; +char *value; +{ + DexModem *dem = DEM(faxctl); + + if (lexequ(key, "out") == 0) + strcpy(dem->devName, value); + else if (lexequ(key, "tti") == 0) + strcpy(dem->tti, value); + else if (lexequ(key, "localPrefix") == 0) + dem->localPrefix = strdup(value); + else if (lexequ(key, "longPrefix") == 0) + dem->longdPrefix = strdup(value); + else if (lexequ(key, "intlPrefix") == 0) + dem->intlPrefix = strdup(value); + else if (lexequ(key, "long") == 0) + if (lexequ(value, "ok") == 0) + dem->noLongDistance = 0; + else + dem->noLongDistance = 1; + else if (lexequ(key, "intl") == 0) + if (lexequ(value, "ok") == 0) + dem->noInternational = 0; + else + dem->noInternational = 1; + else if (lexequ(key, "maxPages") == 0) + dem->maxPages = atoi(value); + else { + sprintf(faxctl->errBuf, + "Unknown info arg '%s=%s", + key, value); + return NOTOK; + } + return OK; +} + +/* + * Return a fax control block + */ + +FaxCtlr *init_faxctrlr() +{ + FaxCtlr *faxctl; + DexModem *dem; + + faxctl = (FaxCtlr *)malloc(sizeof(FaxCtlr)); + bzero(faxctl, sizeof(FaxCtlr)); + + dem = (DexModem *)malloc(sizeof(DexModem)); + bzero(dem, sizeof(DexModem)); + sprintf(dem->devName, "/dev/tty01"); /* default for now */ + faxctl->softc = (char *) dem; + + faxctl->open = dexOpen; + faxctl->close = dexClose; + faxctl->initXmit = dexInitXmit; + faxctl->abort = dexAbort; + faxctl->termXmit = dexTermXmit; + faxctl->setG3Params = dexSetParams; + faxctl->sendPage = dexSendPage; + faxctl->setIA5Params = NULLIFP; + faxctl->sendIA5File = dexSendIA5File; + faxctl->arg_parse = dexArgParse; + return faxctl; +} diff --git a/Chans/fax/dexNet200/dexnet_util.c b/Chans/fax/dexNet200/dexnet_util.c new file mode 100644 index 0000000..fceca14 --- /dev/null +++ b/Chans/fax/dexNet200/dexnet_util.c @@ -0,0 +1,789 @@ +/* dexnet_util.c: various utility routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_util.c,v 6.0 1991/12/18 20:08:53 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/dexNet200/RCS/dexnet_util.c,v 6.0 1991/12/18 20:08:53 jpo Rel $ + * + * $Log: dexnet_util.c,v $ + * Revision 6.0 1991/12/18 20:08:53 jpo + * Release 6.0 + * + */ + +/* Modified by Pekka Nikander for sunos 4 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dexnet.h" + +/* pp includes */ +#include "util.h" +#include "retcode.h" +#include "adr.h" +#include "qmgr.h" +#include +#include "tb_bpt88.h" +#include "IOB-types.h" +#include "MTA-types.h" +#include "or.h" +#include +#ifndef sun +#include +#endif +#include "../faxgeneric.h" + +/* + * Driver for Fujitsu dexNET 200 fax modem, adopted for DECstation + * 5000. + * + * This driver is based on a driver written by Jim Knowles (NASA). Many + * thanks go Jim for his help. + * + * This driver assumes that hardware (CTS) flow control is in use. + * At one point, I attempted to make it work with XON/XOFF. However, + * I never could make this work well. The problem was that there + * was a non-zero delay between the time that the dexnet buffer was + * full and the time that the XOFF was received by this program. + * Invariably, the program would write a few hundred bytes more after + * the buffer was full before getting the XOFF. This would corrupt + * the buffer resulting in either a loss of a few scan lines or + * a complete garbage page. + * + * Note that when the dexnet does a reset, DSR fluctuates, so this pin + * must be tied high for the kernel to be happy. Also, DCD fluctates + * in response to the fax telephone handshake; it must also be tied + * high for the device driver to be happy. + * + * Note that the error processing is complicated because of the + * fact that the entire g3 image may be written to the modem + * before any response is received (if the image is short + * enough). In this case, the errors (like busy) must be + * processed by the end of message procedure. + * + * This driver was developed for a DECstation 5000. The cable used to + * connect the dexnet to the 5000 was rs232: + * + * Modem (Male) Dec (Female) + * TD 2-------------2 + * RD 3-------------3 + * CTS 5-------------5 + * GND 7-------------7 + * +12 9-----+-------6 DSR + * |-------8 DCD + * DTR 20-------------20 + * + * Information about the dexNet 200 can be obtained from + * + * Fujitsu + * Imaging Systems of America, Inc + * Danbury Connecticut, 06810 + * (800) 537-1262 + * + * Robert Hagens + * November, 1991 + */ +int total_cc = 0; +static int readDebug = 0; +extern int fax_debug; + +#define doIoctl(dem, ioctlName, arg, msg)\ + if (ioctl((dem)->fd, (ioctlName), (arg)) == -1) {\ + sprintf((dem)->errBuf, "ioctl error: %s: %s", msg, sys_errname(errno));\ + return(NOTOK);\ + } + +/* + * dexNET 200 error response + */ +struct { + int code; + char *text; +} responseCodes[] = { + dexUnknown, "Unknown response", + dexNotReady, "Not Ready", + dexReady, "Ready", + dexConnected, "Connected", + dexWaiting, "Waiting for call", + dexDialing, "Dialing", + dexSID, "Station Identification", + dexTID, "Terminal Identification", + dexStandardRes, "Standard Resolution", + dexFineRes, "Fine Resolution", + dexCallTerm, "Call terminated normally", + dexAck, "Ack", + dexNak, "Nak", + dexRing, "Ring", + dexBufferLow,"Buffer low", + dex9600Baud, "Line speed 9600", + dex7200Baud, "Line speed 7200", + dex4800Baud, "Line speed 4800", + dex2400Baud, "Line speed 2400", + dexScanError, "Scan line error", + dexVersion, "Version", + dexBusy, "Busy", + dexNoResponse, "No response", + dexNotAFax, "Not a Fax", + dexDisconnect, "Line Disconnect", + dexResError, "Reserved Error", + dexUnderrun, "Buffer Underrun", + dexBufFull, "Buffer Full", + dexBufEmpty, "Buffer Empty", + -1, "" +}; + +/* map an response code to a textual string */ +static char * +codeToString(code) +int code; +{ + int i; + for (i=0; responseCodes[i].code != -1; i++) { + if (responseCodes[i].code == code) + return(responseCodes[i].text); + } + return("Code Unknown"); +} + +/* + * Open device. Configure line to device. Return ptr to + * modem control block + */ +openDexModem(dem) +DexModem *dem; +{ + struct sgttyb ttyb; /* structure for tty parameters */ + int disc = NTTYDISC; /* line discipline */ + int lflags = LLITOUT; /* local flags */ + int temp = 0; + + if ((dem->fd = open(dem->devName, O_RDWR)) == -1) { + sprintf(dem->errBuf, "%s: open: %s", dem->devName, + sys_errname(errno)); + return(NOTOK); + } + + /* Set the line discipline */ + doIoctl(dem, TIOCSETD, (char *)&disc, "TIOCSETD"); + +#ifdef TIOCMODEM + /* Set this tty to be a modem */ + doIoctl(dem, TIOCMODEM, (char *)&temp, "TIOCMODEM"); +#endif + + /* Hang up the fax - When a close is done on pDevName */ + doIoctl(dem, TIOCHPCL, (char *)NULL, "TIOCHPCL"); + + /* Fetch the basic parameters */ + doIoctl(dem, TIOCGETP, (char *)&ttyb, "TIOCGETP"); + + /* Set the speed to 9600 */ + ttyb.sg_ispeed = ttyb.sg_ospeed = B9600; + ttyb.sg_flags = ANYP| RAW | PASS8; + dem->highSpeed = 0; + + /* Set these parameters */ + doIoctl(dem, TIOCSETP, (char *)&ttyb, "TIOCSETP"); + + /* Suppress output translations */ + doIoctl(dem, TIOCLSET, (char *)&lflags, "TIOCLSET"); + + return(OK); +} + +/* make fd non blocking I/O */ +static +nonBlockIO(fd) +int fd; +{ + int flags; + fcntl(fd, F_GETFL, &flags); + flags |= O_NDELAY; + fcntl(fd, F_SETFL, &flags); +} + +static +blockIO(fd) +int fd; +{ + int flags; + fcntl(fd, F_GETFL, &flags); + flags &= ~O_NDELAY; + fcntl(fd, F_SETFL, &flags); +} + +/* + * Send command to modem. Make sure 'len' bytes were written. + * Msg is used only for diagnostics. Return success or failure of op + */ +writeDexModem(dexp, buf, len, msg) +DexModem *dexp; +unsigned char *buf; +int len; +char *msg; +{ + int cc; +#ifdef DUMPWRITE + if (len < 100) { + int i; + printf("writeDexModem: "); + for (i=0; ifd, buf, len)) == -1 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { + fd_set writefds; + + FD_ZERO(&writefds); + FD_SET(dexp->fd, &writefds); + + if (select(dexp->fd+1, NULL, &writefds, NULL, NULL) < 0) { + sprintf(dexp->errBuf, "select: %s", sys_errname(errno)); + return(NOTOK); + } + } + if (cc != len) { + sprintf(dexp->errBuf, "write: %s", sys_errname(errno)); + return(NOTOK); + } + return(OK); +} + +/* block/read one char from the modem. fd may be in non-blocking mode, so + use select to block here if we get EWOULDBLOCK */ +static unsigned char +readModem(dexp) +DexModem *dexp; +{ + int l; + unsigned char c = NULL; + + if ((l = read(dexp->fd, &c, 1)) < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(dexp->fd, &readfds); + + if (select(dexp->fd+1, &readfds, NULL, NULL, NULL) < 0) { + perror("select"); + } + /* could assert (FD_ISSET(dexp->fd, &readfds)) at this point */ + if ((l = read(dexp->fd, &c, 1)) < 0) + perror("readModem"); + } else + perror("readModem"); + } + + if (readDebug) + PP_TRACE(("readModem: x%02x\n", c)); + return(c); +} + +/* Return true if there is data ready to be read on modem */ +static char +dataPresent(dexp) +DexModem *dexp; +{ + long cc; + if (ioctl(dexp->fd, FIONREAD, &cc) == -1) { + perror("ioctl: FIONREAD"); + return(0); + } + return(cc > 0); +} + +/* + * Parse the response contained in buf and return an integer code + * corresponding to the response. Some responses contain an ascii + * string as part of the response. This is returned in misc + */ +static +readResponse(dexp, misc) +DexModem *dexp; +char **misc; /* ascii part of response (assume misc is big enough) */ +{ + static unsigned char buf[100], *bp; + int code = dexUnknown; + unsigned char c; + + /* TODO: set timeout to catch hanging read */ + + bzero(buf, sizeof(buf)); + bp = buf; + + c = readModem(dexp); + if (c == ESC) { + switch(readModem(dexp)) { + case DLE: + switch(readModem(dexp)) { + case '0': code = dexNotReady; break; + case '1': code = dexReady; break; + case '2': code = dexConnected; break; + case '3': code = dexDisconnect; break; + case '4': code = dexWaiting; break; + case '5': code = dexNotAFax; break; + case '6': code = dexDialing; break; + case '7': code = dexBusy; break; + case '8': code = dexNoResponse; break; + case '9': + code = dexSID; + while ((c = readModem(dexp)) != CR) + *bp++ = c; + break; + case ':': + code = dexTID; + while ((c = readModem(dexp)) != CR) + *bp++ = c; + break; + case '=': code = dexCallTerm; break; + case 'R': code = dexRing; break; + case 'W': code = dexBufferLow; break; + case ';': code = dexResError; break; + case '<': code = dexUnderrun; break; + default: + break; + } + break; + + case BEL: + switch(readModem(dexp)) { + case '0': code = dexStandardRes; break; + case '1': code = dexFineRes; break; + case 'R': + *bp++ = 'R'; + while ((c = readModem(dexp)) != CR) + *bp++ = c; + code = dexVersion; + break; + default: + break; + } + break; + case FS: + switch(readModem(dexp)) { + case '\'': code = dex9600Baud; break; + case 'H': code = dex7200Baud; break; + case '0': code = dex4800Baud; break; + case CAN: code = dex2400Baud; break; + case '1': code = dexFineRes; break; + case 'R': + *bp++ = 'R'; + while ((c = readModem(dexp)) != CR) + *bp++ = c; + code = dexVersion; + break; + default: + break; + } + case HT: + readModem(dexp); /* returns # of scan lines in err */ + code = dexScanError; + break; + case ACK: + code = dexAck; + *bp++ = readModem(dexp); + break; + + case NAK: + code = dexNak; + *bp++ = readModem(dexp); + break; + } + } else if (c == XXON) { + code = dexBufEmpty; + } else if (c == XXOFF) { + code = dexBufFull; + } + + if ((misc != NULL) && (bp != buf)) + *misc = (char *)buf; + + PP_LOG(LLOG_DEBUG, + ("readResponse: %d: %s (%s)", code, codeToString(code), buf)); + + return(code); +} + +/* + * physically reset dexnet by dropping DTR for 4 seconds. + * note: this is a *real time* constraint. DTR must be dropped + * for at least 3.1 seconds but not more than 5.9 seconds. Thank + * you very much, fujitsu. + */ +hardResetDexModem(dem) +DexModem *dem; +{ + ioctl(dem->fd, TIOCSDTR, 0); + ioctl(dem->fd, TIOCCDTR, 0); + sleep(4); + ioctl(dem->fd, TIOCSDTR, 0); + + /* we don't yet know if this worked, but if it did, the speed is now + * 9600. If it didn't, we're screwed anyway. + */ + dem->highSpeed = 0; +} + +char nulls[] = {'\000', '\000'}; +/* + * Set up the modem. Return OK or NOTOK + * This can be called no matter what state the modem + * is in. + */ +setupDexModem(dem, fast) +DexModem *dem; +int fast; /* true if 19.2K baud */ +{ +#ifdef sun + struct termios tty_struct; +#endif + struct sgttyb ttyb; + char *p; + + fax_debug = 1; + + /* + * This should bring the modem back to 9600 baud, text mode + */ + hardResetDexModem(dem); + + /* + * Make sure tty is at 9600 baud + */ + doIoctl(dem, TIOCGETP, (char *)&ttyb, "TIOCGETP"); + ttyb.sg_ispeed = ttyb.sg_ospeed = B9600; + doIoctl(dem, TIOCSETP, (char *)&ttyb, "TIOCSETP"); + +#ifdef sun + /* + * Set up hardware flow control + */ + doIoctl(dem, TCGETS, (char *)&tty_struct, "TCGETS"); + tty_struct.c_cflag |= CRTSCTS; + tty_struct.c_cflag |= CLOCAL; + doIoctl(dem, TCSETS, (char *)&tty_struct, "TCSETS"); +#endif + + /* + * Return to factory defaults + */ + if (writeDexModem(dem, FACTDEF, sizeof(FACTDEF)-1, "FACTDEF:") == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, (dem->errBuf)); + return(NOTOK); + } + if (readResponse(dem, NULL) != dexReady) { + strcat(dem->errBuf, "Modem not ready (FACTDEF)"); + return(NOTOK); + } + + /* soft reset as well */ + IssueCommand(dem, RESET, "RESET"); + if (readResponse(dem, NULL) != dexReady) { + strcat(dem->errBuf, "Modem not ready (RESET)"); + return(NOTOK); + } + + IssueCommand(dem, ASK_VERSION, "Check Version"); + readResponse(dem, &p); + if ((p == NULL) || ((strcmp(p, "REV1.9") != 0) && + (strcmp(p, "REV2.0") != 0))) { + strcat(dem->errBuf, "Modem software version mismatch: expect rev1.9 or rev2.0"); + return(NOTOK); + } + + IssueCommand(dem, SPEAKER_ON, "Set Speaker On"); + + if (fast) { + /* Send at 19200 */ + dem->highSpeed = 1; + IssueCommand(dem, BAUD_19200, "Set baud 19200"); + + /* Set the speed to 19200 */ + doIoctl(dem, TIOCGETP, (char *)&ttyb, "TIOCGETP"); + ttyb.sg_ispeed = ttyb.sg_ospeed = B19200; + doIoctl(dem, TIOCSETP, (char *)&ttyb, "TIOCSETP"); + } else { + dem->highSpeed = 0; + IssueCommand(dem, BAUD_9600, "Set baud 9600"); + } + + /* + * WARNING: response code parse routines now assume zero retry + * will be set. This parameter changes the order and kind of + * responses that the dexnet will generate + */ + IssueCommand(dem, ZERO_RETRY, "Set ZERO_RETRY"); + + /* make sure modem is ready */ + IssueCommand(dem, ASK_STAT, "Check Status"); + if (readResponse(dem, NULL) == dexReady) + return(OK); + else { + /* try reset again (needed when running at 19200 */ + IssueCommand(dem, RESET, "RESET"); + if (readResponse(dem, NULL) == dexReady) { + IssueCommand(dem, ZERO_RETRY, "Set ZERO_RETRY"); + return(OK); + } else { + strcat(dem->errBuf, "Modem not ready"); + return(NOTOK); + } + } + +} + + +/* This function will dial a number, set the date, time and + TTI strings on the page header. A OK return signifies + a successful completion. A null number will cause this + routine to return a NOTOK. The date, time and TTI are + optional. To not send these, just pass in NULLs. +*/ +dialDexModem(dem, snumber, sdate, stime, stti) +DexModem *dem; +char *snumber, *sdate, *stime, *stti; +{ + /* dial number */ + if (snumber == NULL) { + strcat(dem->errBuf, "can't dial NULL number"); + return(NOTOK); + } + + IssueCommand(dem, DIAL_NMBR, "Dial number"); + IssueData(dem, snumber, strlen(snumber)); + IssueData(dem, "\r", 1); + + /* Send date if not NULL */ + if (sdate) { + IssueCommand(dem, SEND_DATE, "Send date"); + IssueData(dem, sdate, strlen(sdate)); + IssueData(dem, "\r", 1); + } + + /* Send the time if not NULL */ + if (stime) { + IssueCommand(dem, SEND_TIME, "Send time"); + IssueData(dem, stime, strlen(stime)); + IssueData(dem, "\r", 1); + } + + /* Send the TTI if not NULL */ + if (stti) { + IssueCommand(dem, SEND_TTI, "Send TTI"); + IssueData(dem, stti, strlen(stti)); + IssueData(dem, "\r", 1); + } + return(OK); +} + +/* + * Interpret response code; possible set error message in msgBuf. + * return OK or NOTOK depending on code received. It is assumed that + * if NOTOK is returned, a message will be in msgBuf. + */ +static +processResponse(dem, code, buf) +DexModem *dem; +int code; +char *buf; +{ + int retcode = OK; + if (buf == NULL) + buf = ""; + + dem->msgCode = dexReady; /* no error */ + + switch (code) { + case dexAck: + PP_TRACE(("Page %s sent ok", buf)); + break; + case dexNak: + PP_TRACE(("Page %s sent with errors", buf)); + dem->xmitErrs++; + break; + case dexConnected: + PP_TRACE(("Connected")); + if (dem->stationId[0]) + PP_TRACE(("\tto station %s", dem->stationId)); + if (dem->terminalId[0]) + PP_TRACE(("\tto terminal %s", dem->terminalId)); + break; + + case dexNoResponse: + sprintf(dem->msgBuf, "No response from remote fax"); + PP_TRACE(("%s", dem->msgBuf)); + dem->msgCode = dexNoResponse; + retcode = NOTOK; + break; + + case dexBusy: + sprintf(dem->msgBuf, "Remote fax line is busy"); + PP_TRACE(("%s", dem->msgBuf)); + dem->msgCode = dexBusy; + retcode = NOTOK; + break; + + case dexSID: + strcpy(dem->stationId, buf); + break; + + case dexTID: + strcpy(dem->terminalId, buf); + break; + + case dexNotAFax: + /* fatal message */ + sprintf(dem->msgBuf, "Remote device is not a fax"); + PP_TRACE(("%s", dem->msgBuf)); + retcode = NOTOK; + dem->msgCode = dexNotAFax; + break; + + case dexDisconnect: + /* fatal message */ + sprintf(dem->msgBuf, "Lost connection to fax machine"); + PP_TRACE(("%s", dem->msgBuf)); + dem->msgCode = dexDisconnect; + retcode = NOTOK; + break; + + case dexNotReady: + /* msgBuf already set by previous response */ + PP_TRACE(("%s", dem->msgBuf)); + retcode = NOTOK; + break; + + case dexReady: + PP_TRACE(("Call terminated normally")); + break; + + default: + PP_TRACE(("%s", codeToString(code))); + } + return(retcode); +} + +/* + * Send file in mode specified (g3 or ascii). Return OK if sent, + * NOTOK if not sent. + */ +sendDexModem(dem, data, dataLen, textMode) +DexModem *dem; +unsigned char *data; /* data to send */ +int dataLen; /* of buf */ +int textMode; /* true if text, false if image */ +{ + char *mesg; + int retcode = OK; + int blockSize = 512; + + PP_TRACE(("Enter sendDexModem")); + + dem->msgBuf[0] = (char)0; + dem->errBuf[0] = (char)0; + + /* turn on image if g3 and not running at 19.2 */ + if ((!textMode) && (!dem->highSpeed)) { + IssueCommand(dem, IMAGE_MODE, "Set Image Mode"); + } + +/* TODO: what if this blocks */ + nonBlockIO(dem->fd); + + while (dataLen > 0) { + int bytesToWrite; + unsigned char *buf; + + buf = data; + bytesToWrite = dataLen > blockSize ? blockSize : dataLen; + data += bytesToWrite; + dataLen -= bytesToWrite; + + while (1) { + int cc; + cc = write(dem->fd, buf, bytesToWrite); + if (cc == bytesToWrite) + break; + else if ((cc == -1) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) { + fd_set readfds, writefds; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_SET(dem->fd, &readfds); + FD_SET(dem->fd, &writefds); + + if (select(dem->fd+1, &readfds, &writefds, NULL, NULL) < 0) { + sprintf(dem->errBuf, "select: %s", sys_errname(errno)); + retcode = NOTOK; + goto quit; + } + if (FD_ISSET(dem->fd, &readfds)) { + int code; + + code = readResponse(dem, &mesg); + retcode = processResponse(dem, code, mesg); + if (retcode == NOTOK) goto quit; + } + } else if (cc > 0) { + bytesToWrite -= cc; + buf += cc; + } else { + sprintf(dem->errBuf, "write: %s", + sys_errname(errno)); + retcode = NOTOK; + goto quit; + } + } + } + +quit: + PP_TRACE(("Leave sendDexModem, ret %d", retcode)); + return(retcode); +} + +eomDexModem(dem) +DexModem *dem; +{ + int retcode = OK; + int code; + + blockIO(dem->fd); + + if (writeDexModem(dem, END_OF_TRANS, sizeof(END_OF_TRANS)-1, + "send EOT") == NOTOK) { + sprintf(dem->msgBuf, "Error communicating with local modem"); + return(NOTOK); + } + + do { + char *mesg = NULL; + code = readResponse(dem, &mesg); + retcode = processResponse(dem, code, mesg); + } while (!((retcode == NOTOK) || (code == dexReady))); + + return(retcode); +} + +closeDexModem(dem) +DexModem *dem; +{ + if (dem->highSpeed) + IssueCommand(dem, BAUD_9600, "Set baud 9600"); + close(dem->fd); + return(OK); +} diff --git a/Chans/fax/dexNet200/make b/Chans/fax/dexNet200/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Chans/fax/dexNet200/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/fax/fax_in.c b/Chans/fax/fax_in.c new file mode 100644 index 0000000..54cc5e9 --- /dev/null +++ b/Chans/fax/fax_in.c @@ -0,0 +1,567 @@ +/* faxd.c: PP skelton for inbound fax deamon */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/RCS/fax_in.c,v 6.0 1991/12/18 20:07:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/RCS/fax_in.c,v 6.0 1991/12/18 20:07:09 jpo Rel $ + * + * $Log: fax_in.c,v $ + * Revision 6.0 1991/12/18 20:07:09 jpo + * Release 6.0 + * + */ +#include "util.h" +#include "IOB-types.h" +#include "prm.h" +#include "q.h" +#include "retcode.h" +#include "sys.file.h" +#include "ap.h" +#include "or.h" +#include +#include "faxgeneric.h" + +void advise (); +void adios (); +#define ps_advise(ps, f) \ + advise (LLOG_EXCEPTIONS, NULLCP, "%s: %s",\ + (f), ps_error ((ps) -> ps_errno)) + +extern FaxCtlr *init_faxctrlr(); +extern struct type_IOB_ORName *orn2orname(); +extern char *quedfldir; + +static void dirinit(); + +CHAN *mychan; +struct type_IOB_InformationObject *infoobj = NULL; +struct prm_vars params; +Q_struct Qstruct; +FaxCtlr *faxctl = NULL; +char msgid [LINESIZE]; + +/* not actually used */ +int table_verified = FALSE; + +main (argc, argv) +int argc; +char **argv; +{ + struct type_IOB_G3FacsimileBodyPart *g3fax; + sys_init (argv[0]); + dirinit(); + + if ((faxctl = init_faxctrlr(FAX_INBOUND, + argc, + argv)) == (FaxCtlr *) NULL) { + err_abrt(RP_MECH, + "Unable to initialise fax driver specific elements"); + } + + if (init_PP_stuff(faxctl) != OK) + err_abrt(RP_MECH, + "Unable to initialise PP specfics"); + fillin_infoobj(&infoobj, faxctl); + + /* daemon so continually loop */ + while (1) { + if (faxctl->receiveG3Fax == NULLIFP) { + err_abrt(RP_MECH, + "No receiveG3Fax procedure given for fax driver"); + } + + if ((*faxctl->receiveG3Fax) (faxctl, &g3fax) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("fax receiveG3Fax failed ['%s']", + faxctl->errBuf)); + } else if (deal_with_fax (faxctl, g3fax) != OK) { + /* have accepted fax from remote */ + /* ought to dump somewhere */ + /* so as not to lose it */ + PP_LOG(LLOG_EXCEPTIONS, + ("failed to deal with incoming fax")); + } + + if (g3fax) + free_IOB_G3FacsimileBodyPart (g3fax); + } +} + +/* --- routine to move to correct place in file system --- */ +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", quedfldir); +} + +/* */ + +/* wrap up fax and submit */ +deal_with_fax(faxctl, fax) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileBodyPart *fax; +{ + PE pe = NULLPE; + + if (infoobj -> un.ipm -> heading -> this__IPM != + (struct type_IOB_IPMIdentifier *) NULL) + free_IOB_IPMIdentifier (infoobj -> un.ipm -> heading -> this__IPM); + gen_mid (&(infoobj -> un.ipm -> heading -> this__IPM)); + infoobj -> un.ipm -> body ->BodyPart->un.g3__facsimile = fax; + if (encode_IOB_InformationObject (&pe, 1, 0, NULLCP, infoobj) != OK) { + PP_OPER(NULLCP, + ("deal_with_fax failed to encode info object [%s]", PY_pepy)); +/* send_to_printer(fax)*/ + return NOTOK; + } + + submitPE (pe); + + if (pe != NULLPE) pe_free(pe); + + return OK; +} + +/* */ + +int io_running = FALSE; + +stop_io() +{ + if (io_running == TRUE) + io_end(NOTOK); + io_running = FALSE; +} + +submitPE (pe) +PE pe; +{ + PS ps; + RP_Buf rps, *rp = &rps; + + if (io_running == FALSE) { + if (rp_isbad (io_init(rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("io_init err %s", rp -> rp_line)); + exit (1); + } + io_running = TRUE; + } + + if ((ps = ps_alloc(str_open)) == NULLPS) { + ps_advise (ps, "ps_alloc"); + exit(1); + } + + if (str_setup (ps, NULLPE, 0, 0) == NOTOK) { + advise (NULLCP, "str_setup loses"); + exit (1); + } + + if (pe2ps(ps, pe) == NOTOK) { + ps_advise(ps, "pe2ps loses"); + exit(1); + } + + if (rp_isbad (io_wprm (¶ms, rp))) { + PP_LOG(LLOG_EXCEPTIONS, + ("io_wprm err %s", + rp -> rp_line)); + stop_io(); + exit (1); + } + if (rp_isbad (io_wrq (&Qstruct, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_wrq err %s", + rp -> rp_line)); + stop_io(); + exit(1); + } + + if (rp_isbad (io_wadr (Qstruct.Oaddress, AD_ORIGINATOR, rp))) { + PP_OPER (NULLCP, ("io_wadr originator/postmaster err %s", + rp -> rp_line)); + stop_io(); + exit (1); + } + + if (rp_isbad (io_wadr (Qstruct.Raddress, AD_RECIPIENT, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_wadr recipient err %s", + rp -> rp_line)); + stop_io(); + exit (1); + } + + if (rp_isbad (io_adend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_adend err %s", + rp -> rp_line)); + stop_io(); + exit (1); + } + + if (rp_isbad (io_tinit (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("tinit blows %s", rp -> rp_line)); + stop_io(); + } + if (rp_isbad (io_tpart (Qstruct.cont_type, FALSE, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("io_tpart blows %s", rp -> rp_line)); + stop_io(); + exit (1); + } + if (rp_isbad (io_tdata(ps->ps_base, + ps -> ps_ptr - ps -> ps_base))) { + PP_LOG(LLOG_EXCEPTIONS, ("io_tdata error")); + stop_io(); + exit (1); + } + + if (rp_isbad (io_tdend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdend fails")); + stop_io(); + exit(1); + } + + if (rp_isbad (io_tend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tend fails")); + stop_io(); + exit(1); + } + + ps_free(ps); +} + +/* */ +/* copied from dr2rfc code */ + +/* build up structures need to submit fax into PP */ +extern char *loc_dom_mta, *cont_p22, *hdr_p22_bp, *hdr_p2_bp; +extern char *getpostmaster(); + +static init_PP_stuff(faxctl) +FaxCtlr *faxctl; +{ + EncodedIT *ep = &Qstruct.encodedinfo; + + if ((mychan = ch_nm2struct (faxctl->channel)) == NULLCHAN) { + PP_OPER (NULLCP, + ("Channel '%s' not known", faxctl->channel)); + exit(1); + } + + if (decode_ch_in_info(mychan -> ch_in_info, faxctl) != OK) + return NOTOK; + + prm_init(¶ms); + params.prm_opts = PRM_ACCEPTALL | PRM_NOTRACE; + q_init (&Qstruct); + Qstruct.msgtype = MT_UMPDU; + Qstruct.inbound = list_rchan_new (loc_dom_mta, + faxctl->channel); + Qstruct.cont_type = strdup(mychan -> ch_content_in); + + /* eits completely run by tailoring */ + ep->eit_types = NULL; + if (mychan->ch_hdr_in != NULLIST_BPT) + list_bpt_add(&ep->eit_types, + list_bpt_dup(mychan -> ch_hdr_in)); + else + list_bpt_add(&ep->eit_types, + list_bpt_new((lexequ(mychan -> ch_content_in, + cont_p22) == 0) ? + hdr_p22_bp : hdr_p2_bp)); + if (mychan->ch_bpt_in != NULLIST_BPT) + list_bpt_add(&ep->eit_types, + list_bpt_dup(mychan -> ch_bpt_in)); + else + list_bpt_add(&ep->eit_types, + list_bpt_new("g3fax")); + + /* -- create the ADDR struct for orig and recipient -- */ + Qstruct.Oaddress = adr_new (getpostmaster(mychan->ch_in_ad_type), + mychan->ch_in_ad_type, 0); + Qstruct.Raddress = adr_new (faxctl->fax_recip, + mychan->ch_in_ad_type, 1); + return OK; +} + +static int decode_ch_in_info (info, faxctl) +char *info; +FaxCtlr *faxctl; +{ + char *info_copy; + int margc,i; + char *margv[100]; + + if (info == NULLCP) + return OK; + + info_copy = strdup(info); + margc = sstr2arg(info_copy, 100, margv, ",="); + + for (i = 0; i < margc; i++) { + /* PP specific args */ + if (faxctl->arg_parse != NULLIFP) { + /* pass to driver specific parser */ + if ((*faxctl->arg_parse) (faxctl, + margv[i], + margv[i+1]) == OK) + i++; + else { + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + free(info_copy); + return NOTOK; + } + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("No arg_parse routine registered, unrecognised ch_info element '%s'", + margv[i])); + free(info_copy); + return NOTOK; + } + } + free(info_copy); + return OK; +} + + +/* */ +/* copied from p2flatten code */ + +fillin_infoobj(pinfoobj, faxctl) +struct type_IOB_InformationObject **pinfoobj; +FaxCtlr *faxctl; +{ + *pinfoobj = (struct type_IOB_InformationObject *) calloc(1, + sizeof(struct type_IOB_InformationObject)); + (*pinfoobj)->offset = type_IOB_InformationObject_ipm; + fillin_ipm(&((*pinfoobj)->un.ipm), faxctl); +} + +int fillin_ipm(pipm, faxctl) +struct type_IOB_IPM **pipm; +FaxCtlr *faxctl; +{ + *pipm = (struct type_IOB_IPM *) + calloc(1, sizeof(struct type_IOB_IPM)); + fillin_heading(&((*pipm)->heading), faxctl); + fillin_body(&((*pipm)->body), faxctl); +} + +int fillin_heading(pheading, faxctl) +struct type_IOB_Heading **pheading; +FaxCtlr *faxctl; +{ + /* stright from rfc1148 code */ + struct type_IOB_Heading *head; + + head = (struct type_IOB_Heading *) + calloc (1, sizeof (struct type_IOB_Heading)); + + fillin_sender (&(head->originator), faxctl); + fillin_recip_seq(&(head->primary__recipients), faxctl); + fillin_subject(&(head->subject), faxctl); + + *pheading = head; +} + +int fillin_sender (poriginator, faxctl) +struct type_IOB_OriginatorField *poriginator; +FaxCtlr *faxctl; +{ + fillin_ORdesc(poriginator, faxctl, + getpostmaster(mychan->ch_in_ad_type), + mychan->ch_in_ad_type); +} + +int fillin_recip_seq(or_recip_ptr, faxctl) +struct type_IOB_RecipientSequence **or_recip_ptr; +FaxCtlr *faxctl; +{ + *or_recip_ptr = (struct type_IOB_RecipientSequence *) + calloc (1, sizeof(struct type_IOB_RecipientSequence)); + fillin_recip(&(*or_recip_ptr)->RecipientSpecifier, faxctl); +} + +int fillin_recip(precip, faxctl) +struct type_IOB_RecipientSpecifier **precip; +FaxCtlr *faxctl; +{ + *precip = (struct type_IOB_RecipientSpecifier *) + calloc(1, sizeof(struct type_IOB_RecipientSpecifier)); + fillin_ORdesc(&(*precip)->recipient, faxctl, + faxctl->fax_recip, mychan->ch_in_ad_type); +} + +int fillin_ORdesc(pdesc, faxctl, addr, type) +struct type_IOB_ORDescriptor **pdesc; +FaxCtlr *faxctl; +char *addr; +int type; +{ + char buf[BUFSIZ]; + PE pe; + ORName orn; + int retval; + OR_ptr or; + *pdesc = (struct type_IOB_ORDescriptor *) + calloc (1, sizeof(struct type_IOB_ORDescriptor)); + + switch (type) { + case AD_X400_TYPE: + or = or_std2or(addr); + break; + default: + sprintf(buf, "%s", addr); + retval = or_rfc2or(buf, &or); + break; + } + + or = or_default(or); + orn.on_or = or; + orn.on_dn = (DN) NULL; + (*pdesc)->formal__name = orn2orname(&orn); + or_free(or); +} + +int fillin_subject(subject_ptr, faxctl) +struct type_IOB_SubjectField **subject_ptr; +FaxCtlr *faxctl; +{ + *subject_ptr = (struct type_IOB_SubjectField *) + calloc (1, sizeof(struct type_IOB_SubjectField)); + + *subject_ptr = str2qb (faxctl->subject, + strlen(faxctl->subject), 1); +} + +int fillin_body(pbody, faxctl) +struct type_IOB_Body **pbody; +FaxCtlr *faxctl; +{ + struct type_IOB_Body *temp; + + temp = (struct type_IOB_Body *) + calloc(1, sizeof(struct type_IOB_Body)); + temp -> BodyPart = (struct type_IOB_BodyPart *) + calloc(1, sizeof(struct type_IOB_BodyPart)); + temp->BodyPart->offset = type_IOB_BodyPart_g3__facsimile; + *pbody = temp; +} + +gen_mid (mid_ptr) /* generate random mailid */ +struct type_IOB_IPMIdentifier **mid_ptr; +{ + OR_ptr or; + ORName orn; + long now; + + if (*mid_ptr) + free_IOB_IPMIdentifier(*mid_ptr); + *mid_ptr = (struct type_IOB_IPMIdentifier *) + calloc (1,sizeof (struct type_IOB_IPMIdentifier)); + + (void) time (&now); + sprintf (msgid, "%ld %s", getpid(), ctime (&now)); + msgid [strlen(msgid) - 1] = '\0'; + (*mid_ptr)->user__relative__identifier = str2qb(msgid, + strlen(msgid), + 1); + or = or_std2or(getpostmaster(AD_X400_TYPE)); + or = or_default(or); + orn.on_or = or; + orn.on_dn = (DN) NULL; + (*mid_ptr)->user = orn2orname(orn); + or_free(or); + +} + +/* + * various isode-like routines + */ + +/* pe_done: utility routine to do the right thing for pe errors */ +int pe_done (pe, msg) +PE pe; +char *msg; +{ + if (pe->pe_errno) + { + PP_OPER(NULLCP, + ("%s: [%s] %s",msg,PY_pepy,pe_error(pe->pe_errno))); + pe_free (pe); + return NOTOK; + } + else + { + pe_free (pe); + return OK; + } +} + +/* ps_done: like pe_done */ +int ps_done (ps, msg) +PS ps; +char *msg; +{ + ps_advise (ps, msg); + ps_free (ps); + return NOTOK; +} + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Chans/fax/fax_out.c b/Chans/fax/fax_out.c new file mode 100644 index 0000000..4d188e0 --- /dev/null +++ b/Chans/fax/fax_out.c @@ -0,0 +1,929 @@ +/* fax_out.c: PP skelton for outbound fax channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/RCS/fax_out.c,v 6.0 1991/12/18 20:07:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/RCS/fax_out.c,v 6.0 1991/12/18 20:07:09 jpo Rel $ + * + * $Log: fax_out.c,v $ + * Revision 6.0 1991/12/18 20:07:09 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "retcode.h" +#include "prm.h" +#include "q.h" +#include "qmgr.h" +#include "dr.h" +#include +#include "tb_bpt88.h" +#include "IOB-types.h" +#include "MTA-types.h" +#include +#include +#include +#include "faxgeneric.h" + +extern char *quedfldir; +extern FaxCtlr *init_faxctrlr(); + +static int initialise(), endfunc(), faxit(), decode_ch_out_info(); +static struct type_Qmgr_DeliveryStatus *process(); +static void dirinit(), douser(); +static char *get_fax_number(); +static char *this_msg; +static int firstSuccessDR, firstFailureDR; + +void advise (); +void adios (); +#define ps_advise(ps, f) \ + advise (LLOG_EXCEPTIONS, NULLCP, "%s: %s",\ + (f), ps_error ((ps) -> ps_errno)) + +int alwaysConfirm, table_verified, fax_debug; +CHAN *mychan; +Q_struct Qstruct; +FaxCtlr *faxctl = NULL; + +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); + dirinit (); + fax_debug = 0; + + if ((faxctl = init_faxctrlr(FAX_OUTBOUND, + argc, + argv)) == (FaxCtlr *) NULL) { + err_abrt(RP_MECH, + "Unable to initialise fax driver specific elements"); + } + +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1], "debug") == 0)) { + fax_debug = 1; + debug_channel_control (argc, argv, initialise, process, endfunc); + } else +#endif + channel_control (argc, argv, initialise, process, endfunc); +} + + +/* --- routine to move to correct place in file system --- */ +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", quedfldir); +} + +/* ARGSUSED */ +static int endfunc (arg) +struct type_Qmgr_Channel *arg; +{ + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); +} + +/* --- channel initialise routines --- */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str (arg); + + if ((mychan = ch_nm2struct (name)) == NULLCHAN) { + PP_OPER (NULLCP, + ("Channel '%s' not known", name)); + if (name != NULLCP) + free(name); + return NOTOK; + } + + if (name != NULLCP) + free(name); + + if (decode_ch_out_info(mychan -> ch_out_info, faxctl) != OK) + return NOTOK; + + if (faxctl->open != NULLIFP + && (*faxctl->open) (faxctl) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("fax open failed ['%s']", + faxctl->errBuf)); + return NOTOK; + } + + return OK; +} + +/* --- main processing routine --- */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + struct prm_vars prm; + Q_struct *qp = &Qstruct; + ADDR *ad_sendr = NULLADDR, + *ad_recip = NULLADDR; + int retval, ad_count; + + bzero ((char *) &prm, sizeof prm); + bzero ((char *) qp, sizeof *qp); + firstSuccessDR = firstFailureDR = TRUE; + + this_msg = qb2str (arg -> qid); + + PP_NOTICE (("Processing msg %s", this_msg)); + + delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, + &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, + ("rd_msg err: %s", this_msg)); + return delivery_setallstate (int_Qmgr_status_mtaFailure, + "Can't read message"); + } + + PP_NOTICE(("Fax sender: %s", ad_sendr->ad_value)); + + for (up = arg -> users; up; up = up -> next) + douser (up -> RecipientId -> parm, ad_recip, this_msg); + if (rp_isbad(wr_q2dr (&Qstruct, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure",mychan->ch_name)); + (void) delivery_resetDRs (int_Qmgr_status_mtaFailure); + } + rd_end(); + prm_free(&prm); + q_free(qp); + + return deliverystate; +} + +/* + * process one extension-id for this message + */ + +static void douser (rno, ad_recip, msgd) +int rno; +ADDR *ad_recip; +char *msgd; +{ + ADDR *ap; + + PP_TRACE (("douser (%d, ad_recip, %s)", rno, msgd)); + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + if (rno != ap -> ad_no) + continue; + + if (lchan_acheck (ap, mychan, 1, NULLVP) == NOTOK) { + return; + } else { + faxit (ap); + return; + } + } + + PP_LOG (LLOG_EXCEPTIONS, + ("user not recipient of %s", this_msg)); + + delivery_setstate (rno, int_Qmgr_status_mtaFailure, + "user is not recipient of message"); +} + +/* + * If status is not related to a failure DR, then just return status. + * If it is a negativeDR, then check if this is the first failure. If + * so, return negativeDR, otherwise return failure shared DR. + */ +static +filterQmgrStatus(status) +int status; +{ + int ret = status; + + if (status == int_Qmgr_status_negativeDR) { + if (!firstFailureDR) + ret = int_Qmgr_status_failureSharedDR; + firstFailureDR = FALSE; + } + + return(ret); +} + +/* + * + */ + +static int faxit (ap) +ADDR *ap; +{ + int retval = NOTOK; + char file[MAXPATHLENGTH], next[MAXPATHLENGTH]; + struct stat st; + int size; + struct timeval start, stop; + char *formatdir = NULLCP; + + + size = 0; + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message %s", this_msg)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_mtaFailure, + "Can't find message"); + return RP_MECH; + } + + if (rp_isbad (retval = msg_rinit (formatdir))) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit can't init %s", formatdir)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_mtaFailure, + "can't read the body"); + return RP_MECH; + } + +#ifdef DONE_IN_INITIALISE + if ((*faxctl->open)(faxctl) != OK) { + PP_LOG (LLOG_EXCEPTIONS, ("%s", faxctl->errBuf)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_mtaFailure, + faxctl->errBuf); + return RP_MECH; + } +#endif + + /* get phone number */ +{ + char *telno; + faxctl->errBuf[0] = '\0'; + if (ap && (telno = get_fax_number(ap, faxctl)) != NULLCP) { + PP_NOTICE(("faxing to %s for recipient %s", telno,ap->ad_value)); + strcpy(faxctl->telno, telno); + free(telno); + } else { + if (faxctl->errBuf[0] != '\0') + sprintf(faxctl->errBuf, + "Can't determine phone number for address '%s'", + ap -> ad_r400adr); + PP_LOG (LLOG_EXCEPTIONS, ("%s", faxctl->errBuf)); + if (faxctl->abort != NULLIFP) + (*faxctl->abort)(faxctl); + delivery_setstate(ap -> ad_no, + filterQmgrStatus(int_Qmgr_status_negativeDR), + faxctl->errBuf); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, -1, faxctl->errBuf); + return RP_MECH; + } +} + +#ifdef SVR4 + (void) gettimeofday(&start); +#else + (void) gettimeofday(&start, (struct timezone *)NULL); +#endif + faxctl->errBuf[0] = '\0'; + if (faxctl->initXmit != NULLIFP + && rp_isbad((*faxctl->initXmit)(faxctl))) { + if (faxctl->abort != NULLIFP) + (*faxctl->abort)(faxctl); + PP_LOG (LLOG_EXCEPTIONS, ("initXmit failed [%s]", + faxctl->errBuf)); + delivery_setstate (ap -> ad_no, + filterQmgrStatus(faxctl->qmgrErrCode), + faxctl->errBuf); + if (faxctl->qmgrErrCode == int_Qmgr_status_negativeDR) + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, -1, faxctl->errBuf); + return RP_MECH; + } + + if (msg_rfile (next) != RP_OK) { + if (faxctl->abort != NULLIFP) + (*faxctl->abort)(faxctl); + PP_LOG(LLOG_EXCEPTIONS, ("Empty directory %s", formatdir)); + delivery_setstate (ap -> ad_no, int_Qmgr_status_mtaFailure, + "empty directory"); + return RP_MECH; + } else { + retval = OK; + do { + strcpy(file,next); + if (msg_rfile(next) != RP_OK) + next[0] = '\0'; + if (stat (file, &st) != NOTOK) + size += st.st_size; + if (rp_isbad(fax_bodypart (faxctl, + file, + (next[0] == '\0')))) { + PP_LOG (LLOG_EXCEPTIONS, ("fax_bodypart failed [%s]", + faxctl->errBuf)); + delivery_setstate (ap -> ad_no, + filterQmgrStatus(faxctl->qmgrErrCode), + faxctl->errBuf); + if (faxctl->qmgrErrCode == int_Qmgr_status_negativeDR) + set_1dr (&Qstruct, ap -> ad_no, + this_msg, + DRR_UNABLE_TO_TRANSFER, -1, + faxctl->errBuf); + if (faxctl->abort != NULLIFP) + (*faxctl->abort)(faxctl); + retval = NOTOK; + } + } while (retval == OK && next[0] != '\0'); + + msg_rend(); + + if (retval == OK) { + if ((*faxctl->termXmit)(faxctl) != OK) { + PP_LOG(LLOG_EXCEPTIONS, ("termXmit failed [%s]", + faxctl->errBuf)); + delivery_setstate (ap -> ad_no, + filterQmgrStatus(faxctl->qmgrErrCode), + faxctl->errBuf); + if (faxctl->qmgrErrCode == int_Qmgr_status_negativeDR) + set_1dr (&Qstruct, ap -> ad_no, + this_msg, + DRR_UNABLE_TO_TRANSFER, -1, + faxctl->errBuf); + if (faxctl->abort != NULLIFP) + (*faxctl->abort)(faxctl); + retval = NOTOK; + } + } + } + +#ifdef SVR4 + (void) gettimeofday (&stop); +#else + (void) gettimeofday(&stop, (struct timezone *)NULL); +#endif + + if (retval == OK) { + PP_NOTICE((">>> Fax: msg sent to %s in %d seconds", + ap -> ad_value, + stop.tv_sec - start.tv_sec)); + + if (alwaysConfirm == TRUE || + ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + char buf[BUFSIZ]; + if (lexequ(faxctl->telno, "0") == 0) + sprintf(buf, "message locally printed"); + else + sprintf(buf, "message fax'd to '%s'", + faxctl->telno); + + set_1dr (&Qstruct, ap -> ad_no, + this_msg, DRR_NO_REASON, -1, buf); + + delivery_set (ap -> ad_no, + (firstSuccessDR == TRUE) ? + int_Qmgr_status_positiveDR : + int_Qmgr_status_successSharedDR); + firstSuccessDR = FALSE; + } + else { + (void) wr_ad_status (ap, AD_STAT_DONE); + (void) wr_stat (ap, &Qstruct, this_msg, size); + delivery_set (ap -> ad_no, int_Qmgr_status_success); + } + } + return retval; +} + +/* + * send a bodypart to fax machine + */ + +extern CMD_TABLE bptbl_body_parts88[/* x400 84 body_parts */]; + +static int type_of_file(file) +char *file; +{ + char *dot; + if ((dot = rindex(file, '.')) == NULLCP) + return NOTOK; + dot++; + if (lexequ(dot, rcmd_srch(BPT_G3FAX, bptbl_body_parts88)) == 0) + return BPT_G3FAX; + if (lexequ(dot, rcmd_srch(BPT_IA5, bptbl_body_parts88)) == 0) + return BPT_IA5; + return NOTOK; +} + +int num_sent; + +static int fax_bodypart (faxctl, file, last) +FaxCtlr *faxctl; +char *file; +int last; +{ + int type; + num_sent = 0; + switch ((type = type_of_file(file))) { + case BPT_G3FAX: + if (faxctl->sendPage != NULLIFP) + return fax_g3_bodypart (faxctl, file, last); + break; + case BPT_IA5: + if (faxctl->sendIA5File != NULLIFP) + return fax_ia5_bodypart (faxctl, file, last); + break; + default: + break; + } + + sprintf(faxctl->errBuf, "Unable to fax '%s' bodyparts", + (type == NOTOK) ? file : rcmd_srch(type, bptbl_body_parts88)); + PP_LOG(LLOG_EXCEPTIONS, ("%s", faxctl->errBuf)); + return RP_MECH; +} + +static int fax_ia5_bodypart (faxctl, file, last) +FaxCtlr *faxctl; +char *file; +int last; +{ + int retcode; + + PP_DBG(("hello fax_ia5_bodypart")); + if (faxctl->setIA5Params != NULLIFP + && (*faxctl->setIA5Params) (faxctl) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("setIA5Params failed [%s]", + faxctl->errBuf)); + return RP_MECH; + } + + retcode = (*faxctl->sendIA5File)(faxctl, file, last); + if (retcode == OK) + return(OK); + else + return(RP_MECH); +} + +static int fax_g3_bodypart (faxctl, file, last) +FaxCtlr *faxctl; +char *file; +int last; +{ + register PS psin; + FILE *fp; + struct type_IOB_G3FacsimileBodyPart *g3fax = NULL; + int retval = RP_MECH; + + PP_DBG (("hello fax_g3_bodypart")); + + /* read in and decode fax bodypart */ + + if ((fp = fopen (file, "r")) == (FILE *)0) { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + sprintf(faxctl->errBuf, + "Can't open file '%s'", file); + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + return RP_MECH; + } + + if ((psin = ps_alloc (std_open)) == NULLPS) + { + (void) fclose (fp); + ps_advise (psin, "ps_alloc"); + sprintf(faxctl->errBuf, + "ps_alloc failed"); + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + return RP_MECH; + } + + if (std_setup (psin, fp) == NOTOK) + { + ps_free (psin); + (void) fclose (fp); + advise (LLOG_EXCEPTIONS, NULLCP, "%s: std_setup loses", file); + sprintf(faxctl->errBuf, + "std_setup failed"); + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + return RP_MECH; + } + + if (do_decode_fax(psin, &g3fax) == NOTOK) { + (void) fclose (fp); + PP_LOG(LLOG_EXCEPTIONS, + ("failed to decode G3FacsimileBodyPart")); + ps_done(psin, "ps2pe"); + sprintf(faxctl->errBuf, + "unable to decode fax bodypart"); + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + return RP_MECH; + } + + (void) fclose (fp); + + + if (g3fax->parameters + && faxctl->setG3Params != NULLIFP + && (*faxctl->setG3Params)(faxctl, g3fax->parameters) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("setG3Params failed [%s]", faxctl->errBuf)); + return RP_MECH; + } + + if (fax_bitstrings (faxctl, g3fax, last) == OK) + retval = OK; +/* if (g3fax != NULL) + free_IOB_G3FacsimileBodyPart(g3fax);*/ + return retval; +} + +/* + * send each page of g3fax to fax machine + */ + +static int fax_bitstrings (faxctl, g3fax, last) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileBodyPart *g3fax; +int last; +{ + struct type_IOB_G3FacsimileData *ix; + int retval; + + for (ix = g3fax -> data; ix != NULL; ix = ix -> next) { + int len; + char *str; + + if ((str = bitstr2strb (ix -> element_IOB_0, &len)) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, ("empty page")); + return NOTOK; + } + len = (len + BITSPERBYTE -1)/BITSPERBYTE; + + retval = faxctl->sendPage(faxctl, str, len, + (last && ix -> next == NULL)); + free (str); + if (retval != OK) + return retval; + } + return OK; +} + +/* + * parse info field + */ + +static int decode_ch_out_info(info, faxctl) +char *info; +FaxCtlr *faxctl; +{ + char *info_copy; + int margc,i; + char *margv[100]; + + if (info == NULLCP) + return OK; + + info_copy = strdup(info); + margc = sstr2arg(info_copy, 100, margv, ",="); + + alwaysConfirm = FALSE; + + for (i = 0; i < margc; i++) { + /* PP specific args */ + if (lexequ(margv[i], "confirm") == 0) { + i++; + if (lexequ(margv[i], "always") == 0) + alwaysConfirm = TRUE; + else if (lexequ(margv[i], "never") == 0) + alwaysConfirm = FALSE; + } else if (faxctl->arg_parse != NULLIFP) { + /* pass to driver specific parser */ + if ((*faxctl->arg_parse) (faxctl, + margv[i], + margv[i+1]) == OK) + i++; + else { + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + free(info_copy); + return NOTOK; + } + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("No arg_parse routine registered, unrecognised ch_info element '%s'", + margv[i])); + free(info_copy); + return NOTOK; + } + } + free(info_copy); + return OK; +} + +/* + * + * address to telephone number mapping via table lookup + */ + +static void tblentry2num(buf, ptelno, porg) +char *buf; +char **ptelno; +char **porg; +{ + /* parse as number,rest */ + char *telno = NULLCP, *org = NULLCP, *ix; + + if ((ix = index(buf, ',')) == NULLCP) { + compress(buf,buf); + telno = strdup(buf); + } else { + *ix++ = '\0'; + compress(buf, buf); + telno = strdup(buf); + /* for now rest is company */ + if (*ix != '\0') + org = strdup(ix); + } + + if (ptelno != NULL) + *ptelno = telno; + else if (telno != NULLCP) + free(telno); + + if (porg != NULL) + *porg = org; + else if (org != NULLCP) + free(org); +} + +static char *get_fax_number(adr, faxctl) +ADDR *adr; +FaxCtlr *faxctl; +{ + OR_ptr or, or2; + char *telno = NULLCP, buffer[BUFSIZ]; + int using_outmta = FALSE; + table_verified = FALSE; + + if (adr->ad_r400adr == NULLCP + || adr->ad_r400adr[0] != '/') + return NULLCP; + + if ((or = or_std2or(adr->ad_r400adr)) == NULLOR) { + sprintf(faxctl->errBuf, + "Unable to parse X.400 address '%s'", + adr->ad_r400adr); + PP_LOG(LLOG_EXCEPTIONS, + ("%s",faxctl->errBuf)); + return NULLCP; + } + or2 = or; + while ((or2 = or_locate (or2, OR_DD)) != NULLOR) { + if (cmd_srch(or2->or_ddname, + ortbl_ddvalid) == OR_DDVALID_FAX) { + telno = strdup (or2->or_value); + break; + } else if (or2 -> or_next != NULLOR) + or2 = or2 -> or_next; + else + break; + + } + + /* use outmta */ + if (telno == NULLCP + && adr -> ad_outchan != NULLIST_RCHAN) { + using_outmta = TRUE; + telno = strdup(adr -> ad_outchan -> li_mta); + } + if (telno != NULLCP + && mychan != NULLCHAN + && mychan -> ch_table != NULLTBL + && tb_k2val (mychan -> ch_table, telno, buffer, TRUE) != NOTOK) { + table_verified = TRUE; + PP_NOTICE(("fax key '%s' verfied in table '%s'", + telno, mychan -> ch_table -> tb_name)); + free (telno); + tblentry2num(buffer, &telno, (char **) NULL); + } else if (using_outmta == TRUE) { + sprintf(faxctl->errBuf, + "Unable to obtain remote fax info for address '%s'", + adr->ad_r400adr); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + if (telno) + free(telno); + if (or) + or_free(or); + return NULLCP; + } + if (or) + or_free(or); + return telno; +} + +/* + * decode from PE to C struct + */ + +extern PE ps2pe_aux (); + +static int do_decode_fax (psin, pfax) +register PS psin; +struct type_IOB_G3FacsimileBodyPart **pfax; +{ + struct type_IOB_G3FacsimileData *new, *tail = NULL; + int pages; + register PE pe = NULLPE; + + /* get first chunk */ + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + ps_done (psin, "ps2pe_aux"); + return NOTOK; + } + + if ((PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_UNIV, PE_CONS_SEQ)) + && (PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_CONT, (PElementID) 0x03))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected sequence")); + return NOTOK; + } + + pe_free (pe); + + *pfax = (struct type_IOB_G3FacsimileBodyPart *) calloc (1, + sizeof (struct type_IOB_G3FacsimileBodyPart)); + + /* get and decode parameters */ + if ((pe = ps2pe (psin)) == NULLPE) { /* EOF or error? */ + ps_done (psin, "ps2pe"); + return NOTOK; + } + PY_pepy[0] = 0; + + if (decode_IOB_G3FacsimileParameters(pe, 1, + NULLIP, NULLVP, + &((*pfax) -> parameters)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_G3FacsimileParameters failure [%s]", + PY_pepy)); + pe_done(pe, "Parse failure IOB_G3FacsimileParameters"); + return NOTOK; + } + + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("parse_IOB_G3FacsimileParameters non fatal failure [%s]", + PY_pepy)); + + pe_free (pe); + + /* get next chunk */ + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + ps_done (psin, "ps2pe_aux"); + return NOTOK; + } + + if (PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_UNIV, PE_CONS_SEQ)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected sequence")); + return NOTOK; + } + + pe_free (pe); + + pages = 0; + while ((pe = ps2pe (psin)) != NULLPE) { + switch (PE_ID(pe -> pe_class, pe -> pe_id)) { + case PE_ID (PE_CLASS_UNIV, PE_PRIM_BITS): + break; + case PE_ID (PE_CLASS_UNIV, PE_UNIV_EOC) : + pe_free(pe); + continue; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected bitstring")); + return NOTOK; + } + new = (struct type_IOB_G3FacsimileData *) (calloc (1, + sizeof(struct type_IOB_G3FacsimileData))); + new -> element_IOB_0 = prim2bit(pe); + if ( (*pfax) -> data == NULL) + (*pfax) -> data = tail = new; + else { + tail -> next = new; + tail = tail -> next; + } + pages++; + } + + if ((*pfax) -> parameters -> optionals == opt_IOB_G3FacsimileParameters_number__of__pages + && (*pfax) -> parameters -> number__of__pages != pages) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect number of pages in G3FacsimileBodyPart: expected %d, got %d", + (*pfax) -> parameters -> number__of__pages, pages)); + return NOTOK; + } + return OK; +} + +/* + * various isode-like routines + */ + +/* pe_done: utility routine to do the right thing for pe errors */ +int pe_done (pe, msg) +PE pe; +char *msg; +{ + if (pe->pe_errno) + { + PP_OPER(NULLCP, + ("%s: [%s] %s",msg,PY_pepy,pe_error(pe->pe_errno))); + pe_free (pe); + return NOTOK; + } + else + { + pe_free (pe); + return OK; + } +} + +/* ps_done: like pe_done */ +int ps_done (ps, msg) +PS ps; +char *msg; +{ + ps_advise (ps, msg); + ps_free (ps); + return NOTOK; +} + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Chans/fax/faxgeneric.h b/Chans/fax/faxgeneric.h new file mode 100644 index 0000000..aa05dbb --- /dev/null +++ b/Chans/fax/faxgeneric.h @@ -0,0 +1,121 @@ +/* faxgeneric.h: generic fax structure */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/fax/RCS/faxgeneric.h,v 6.0 1991/12/18 20:07:09 jpo Rel $ + * + * $Log: faxgeneric.h,v $ + * Revision 6.0 1991/12/18 20:07:09 jpo + * Release 6.0 + * + * + */ + +#ifndef _H_FAXGEN +#define _H_FAXGEN + +/* + * The idea is that these routines only need to know about the specific + * fax modem. They do not need to know how to generate delivery reports, + * whether it is the first or second DR, etc. + * + * The softc ptr allows each fax modem to have a specific data structure + * + * open (FaxCtlr *) + * called once to open the fax device. + * should return OK or NOTOK. + * close (FaxCtlr *) + * called when channel is shutting down. + * return not checked. + * initXmit (FaxCtlr *) + * called once for each recipient, before any data is sent. + * called after phone number is determined and set in FaxCtlr *, + * normally will send dial string down to modem. + * returns PP return code + * abort (FaxCtlr *) + * called at any time to abort transmission. + * return not checked. + * termXmit (FaxCtlr *) + * called after all pages have been sent to recipient. + * returns OK or NOTOK + * setG3Params (FaxCtlr *, struct type_IOB_G3FacsimileParameters *params) + * called once per page to set/test G3 parameters including + * resolution of page. also initialises modem for g3fax + * transmission + * returns OK or NOTOK + * sendPage (FaxCtlr *, char *bits, int len, int last) + * called to send one page of G3 fax. + * forth parameter indicates whether last bit of fax message. + * note that G3 fax page encoded in X.400 order + * returns OK or NOTOK + * setIA5Params (FaxCtlr *) + * call obnce per file of ia5 to initialise modem for ia5 + * transmission + * return OK or NOTOK; + * sendIA5File (FaxCtlr *, char *file, int last) + * send one file of IA5 text. + * third parameter indicates whether last bit of fax message. + * returns OK or NOTOK + * arg_parse (FaxCtlr *, char *key, char *value) + * parse an info line argument + * return OK or NOTOK + * + * Whenever any routine returns an error status, it should place a + * error message into the field 'errBuf'. + * + * If initXmit(), sendPage(), sendIA5File(), or termXmit() return an + * error status, they + * must also set the field 'qmgrErrCode'. This code is used to pass + * error status information back to the qmgr. The only values that + * should be returned in this field are + * int_Qmgr_status_negativeDR - permanent failure; + * send DR + * int_Qmgr_status_messageFailure - transient failure, + * retry message + * int_Qmgr_status_mtaFailure - transient failure, + * retry channel + * In the case of the permanent failure, the generic fax driver code + * will worry about converting a negativeDR status into a shared DR + * status (if necessary). Also, the generic fax code will automatically + * build an error report (with 'errBuf' as the message). + */ + +/* + * Generic control data structure for each fax modem + */ +typedef struct _faxCtlr { + char *softc; /* controller specific state */ + int (*open)(); /* open routine */ + int (*close)(); /* close routine */ + int (*arg_parse)(); /* parse info line argument */ + char errBuf[BUFSIZ]; /* error messages go here */ + int qmgrErrCode; /* passed back to Qmgr */ + +/* outbound parameters and function pointers */ + char telno[255]; /* telephone number */ + int (*initXmit)(); /* initialize for transmission */ + int (*abort)(); /* abort transmission */ + int (*termXmit)(); /* terminate transmission */ + int (*setG3Params)(); /* set G3 fax parameters */ + int (*sendPage)(); /* send one page of G3 fax */ + int (*setIA5Params)(); /* set of ia5 transmission */ + int (*sendIA5File)(); /* send one file of IA5 text */ + +/* inbound parameters and function pointers */ + char channel[BUFSIZ]; /* inbound channel name */ + char fax_recip[BUFSIZ]; /* recip address for incoming faxes */ + char subject[BUFSIZ]; /* standard string for subject */ + /* strings on submitted messages */ + int (*receiveG3Fax)(); /* wait and get incoming fax */ +} FaxCtlr; + +#define NULLFAXCTRLR ((FaxCtlr *)0) + +extern FaxCtlr *int_faxctrlr(); + +#define BITSPERBYTE 8 + + +#define FAX_OUTBOUND 0 +#define FAX_INBOUND 1 +#define FAX_BOTH 2 +#endif diff --git a/Chans/fax/make b/Chans/fax/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/fax/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/fax/ps250/Makefile b/Chans/fax/ps250/Makefile new file mode 100644 index 0000000..9586ba6 --- /dev/null +++ b/Chans/fax/ps250/Makefile @@ -0,0 +1,133 @@ +# dexNet200 fax driver Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/Makefile,v 6.0 1991/12/18 20:07:26 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:07:26 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +PPOUTSRCS = ../fax_out.c +PPOUTOBJS = ../fax_out.o + +PPINSRCS = ../fax_in.c +PPINOBJS = ../fax_in.o + +SRCS = ps250_intf.c ps250_util.c \ + ps250_stat.c ps250_manage.c ps250_trans.c \ + ps250_basic.c error_codes.c +OBJS = ps250_intf.o ps250_util.o \ + ps250_stat.o ps250_manage.o ps250_trans.o \ + ps250_basic.o error_codes.o + +HEADERS = ../../../h +LIBPP = ../../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xfax xfaxd + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +install: inst-dir inst-out + +inst-dir: $(CHANDIR) + +lint: l-out l-in + +############################################################ +# +# Fax channel +# +############################################################ + +xfax: $(OBJS) $(PPOUTOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(PPOUTOBJS) $(LIBPP) $(LIBSYS) + +saber_out_src: $(PPOUTSRCS) $(SRCS) + #load -C $(CFLAGS) $(PPOUTSRCS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_out_obj: $(OBJS) $(PPOUTOBJS) + #load -C $(CFLAGS) $(OBJS) $(PPOUTOBJS) $(LIBPP) $(LIBSYS) + +inst-out: $(CHANDIR)/ps250 +$(CHANDIR)/ps250: xfax + -$(BACKUP) $@ zxfax + rm -f $@ + $(INSTALL) xfax $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Panasonic 250 outbound fax channel installed normally"; echo "" + +l-out: $(SRCS) $(PPOUTSRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(PPOUTSRCS) $(LINTLIBS) + +############################################################ +# +# Fax daemon +# +############################################################ + +xfaxd: $(OBJS) $(PPINOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(PPINOBJS) $(LIBPP) $(LIBSYS) + +saber_in_src: $(SRCS) $(PPINSRCS) + #load -C $(CFLAGS) $(SRCS) $(PPINSRCS) $(LIBPP) $(LIBSYS) + +saber_in_obj: $(OBJS) $(PPINOBJS) + #load -C $(CFLAGS) $(OBJS) $(PPINOBJS) $(LIBPP) $(LIBSYS) + +inst-out: $(CHANDIR)/ps250d +$(CHANDIR)/ps250d: xfaxd + -$(BACKUP) $@ zxfaxd + rm -f $@ + $(INSTALL) xfaxd $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Panasonic 250 inbound fax daemon installed normally"; echo "" + +l-in: $(SRCS) $(PPINSRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(PPINSRCS) $(LINTLIBS) + +############################################################ +# +# Misc +# +############################################################ + +clean: tidy + (echo "cd tools; $(MAKE) $@"; cd tools; $(MAKE) $@) + rm -f $(PROGS) + +tidy: + (echo "cd tools; $(MAKE) $@"; cd tools; $(MAKE) $@) + rm -f $(OBJS) core a.out Makefile.old + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Chans/fax/ps250/error_codes.c b/Chans/fax/ps250/error_codes.c new file mode 100644 index 0000000..120d2b8 --- /dev/null +++ b/Chans/fax/ps250/error_codes.c @@ -0,0 +1,113 @@ +/* error_codes.c: error codes for the SystemFax 250 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/error_codes.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/error_codes.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: error_codes.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ +#include "util.h" +#include + +CMD_TABLE fax_errors [] = { /* fax error codes */ + "rcv paper jam (check paper path)", 2, + "rcv paper path (reset cutter blue wheel)", 4, + "no recording paper (load paper)", 10, + "thermal head temp high (reset machine)", 20, + "tx jam (document edge faulty or ADF requires adjustment see manual", 30, + "tx jam (document exceeds 1m long check length of original or paper path)", 31, + "tx guide pulled forward, paper loading door open, or bottom door open", 60, + "call failed (single go) busy line or wrong no.", 400, + "line faulty or incompatible fax machine", 402, + "polling not set up at other end", 403, + "probable jam at other end", 404, + "bad line unable to transmit", 405, + "other end fault (jam, too many errors)", 407, + "far end has too many errors on rcv'd doc", 408, + "far end has too many errors on rcv'd doc and voice request required", 409, + "faulty line", 410, + "polling password wrong", 411, + "paper jam/document too long at far end", 412, + "polling not on at other fax or code wrong", 414, + "polling password not correct", 415, + "faulty line or doc too long at other end", 416, + "rcv too many errors on document", 417, + "rcv too many errors on document, other end requests voice request", 418, + "rcv too many errors on document, your end requests voice request", 419, + "rcv'd call is not a fax call or line faulty", 420, + "bad line or non compatible G3 machine", 422, + "bad line or non compatible G3 machine", 427, + "bad line retry", 430, + "bad line retry", 432, + "paper jam at other end", 436, + "faulty line", 451, + "faulty line or paper jam at other end", 458, + "faulty line", 459, + "faulty line or non standard G2 machine", 464, + "faulty line or non standard G2 machine", 465, + "faulty line or non standard G2 machine and paper jam at other end", 466, + "faulty line or non standard G2 machine", 467, + "faulty line or non standard G2 machine", 468, + "paper jam other end or line faulty", 469, + "faulty line or non standard G2 machine", 473, + "faulty line or non standard G2 machine", 474, + "faulty line or non standard G2 machine", 476, + "faulty line or non standard G2 machine", 478, + "paper jam other end or line fault", 479, + "paper jam other end or line fault", 480, + "line fault", 481, + "line fault or machine fault", 483, + "64 errored lines over error count", 490, + "line fault or machine fault", 492, + "paper jam other end or line fault", 493, + "line fault or paper jam other end", 494, + "paper jam other end or line fault", 495, + "line fault", 540, + "line fault or other end dropped out", 541, + "fault other end or line fault", 542, + "other end fault or line fault", 543, + "line fault tx not possible", 544, + "other end fault", 550, + "other end fault", 552, + "other fax abnormal end inc. stop button", 553, + "line fault", 554, + "line fault, voice request from other fax", 555, + "document not on ADF or an auto retry", 623, + "three dial attempts to one number failed", 630, +#ifdef WHAT_DOCS_SAY + "info code returned to i/f when dial command fails at each attempt", 693, +#endif + "dialing attempt failed", 693, + 0, -1 + }; + +char fax_err_buf[BUFSIZ]; + +char *faxerr2str(err) +int err; +{ + char *ret; + + if ((ret = rcmd_srch(err, fax_errors)) != NULLCP) + (void) sprintf(fax_err_buf, "%s", ret); + else if (err >= 0 && err < 100) + (void) sprintf(fax_err_buf, "mechanical problems"); + else if (err >= 400 && err < 500) + (void) sprintf(fax_err_buf, "communication problems"); + else if (err >= 500 && err < 600) + (void) sprintf(fax_err_buf, "CCITT error correction mode problems"); + else if (err >= 600 && err < 700) + (void) sprintf(fax_err_buf, "autodialling problems"); + else + (void) sprintf(fax_err_buf, "unknown error number '%d'", err); + + return fax_err_buf; +} + + diff --git a/Chans/fax/ps250/make b/Chans/fax/ps250/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Chans/fax/ps250/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/fax/ps250/ps250.h b/Chans/fax/ps250/ps250.h new file mode 100644 index 0000000..91239b9 --- /dev/null +++ b/Chans/fax/ps250/ps250.h @@ -0,0 +1,230 @@ +/* ps250.h: header file for the Panasonic 250 fax machine */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250.h,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250.h,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + * + */ + +#include + +/* + General format of command/response packet + + Header 2 bytes + Control 1 byte + Address 1 byte + Length 1 byte + Information variable + check sum 1 byte +*/ + + +#define FAX_HEADER 0x10 +#define FAX_ADDRESS 0x00 +#define FAX_CONTROL 0x1C +#define FAX_RETRANS 0x38 + +/* COMMAND codes */ +#define COM_STOP 0x11 +#define COM_ENQ1 0x12 +#define COM_ENQ2 0x13 +#define COM_TRANS 0x21 +#define COM_REVPL 0x22 +#define COM_READ 0x30 +#define COM_WRITE 0x31 +#define COM_MOVE 0x32 +#define COM_IDSET 0x40 + +/* response codes */ +#define RESP_ACK 0x50 +#define RESP_REJ 0x51 +#define RESP_STAT1 0x52 +#define RESP_STAT2 0x53 +#define RESP_DATA 0x54 + +/* Command Error codes */ + +#define COMERR_OK 0 +#define COMERR_UNDEF_COMMAND 0x40 +#define COMERR_UNAC_COMMAND 0x41 +#define COMERR_PARAM 0x42 +#define COMERR_FRAME 0x43 + +#define MODE_MASK 0xf0 +#define MODE_WAIT_JOB 0x00 +#define MODE_WAIT_BLOCK 0x20 +#define MODE_FAX_WORKING 0x30 + +#define STATE_MASK 0x0f +#define STATE_COMPUTER 0x03 +#define STATE_FAX 0x04 + +#define RING_IN 0x01 + +#define SCAN_DOC_SCAN 0x01 +#define SCAN_NODOC 0x02 +#define SCAN_FEEDERR 0x04 +#define SCAN_TOOLONG 0x08 +#define SCAN_B4 0x10 + +#define PRINT_PJAM 0x04 +#define PRINT_NOPAPER 0x10 + +#define JOB_IN 0x01 +#define JOB_READY 0x13 +#define JOB_DATA_AVAIL 0x23 +#define JOB_RETRANS 0x33 +#define JOB_NORM_END_MASK 0x03 +#define JOB_NORM_END 0x00 +#define JOB_FAULT_JOB_END 0x02 +#define JOB_LINE_DISC_MASK 0x1f +#define JOB_LINE_DISC 0x12 + +#define RES_MASK 0x07 +#define RES_7_7 0x01 +#define RES_3_85 0x02 +#define RES_15_4 0x03 + +#define COMM_GMASK 0x03 +#define COMM_G2 0x01 +#define COMM_G3 0x03 + +#define COMM_XR_MASK 0x05 +#define COMM_XMT 0x05 +#define COMM_RCV 0x01 + +#define COMM_SPEED_MASK 0x1B +#define COMM_SPEED_2400 0x03 +#define COMM_SPEED_4800 0x0B +#define COMM_SPEED_7200 0x13 +#define COMM_SPEED_9600 0x1B + +#define COMM_MHR_MASK 0x23 +#define COMM_MH 0x03 +#define COMM_MR 0x23 + +#define COMM_POLLED 0x83 + +#define FAXMINSIZE 7 +#define FAXBUFSIZ 262 /* max fax trans/recv buffer */ +#define FAXHDRSIZE 5 + +typedef struct faxcomm { + int flags; + int len; + int command; + char data[FAXBUFSIZ]; +} Faxcomm; + +typedef struct stat1 { + int ce_code; + int mode_cmd; + int ring_in; + int scan_stat; + int print_stat; + int job_info; + char fecode[4]; + int res; + int comm; + char remid[21]; + int errlines; + int page_no; +} Stat1; + +#define FAX_CLOCKLEN 11 +#define FAX_LOCALIDLEN 21 +typedef struct stat2 { + char clock[FAX_CLOCKLEN]; + char local[FAX_LOCALIDLEN]; +} Stat2, Idset; + +#define FAX_TELNOSIZE 28 +#define FAX_REMIDSIZE 21 + +#define FAX_TYPE_MH 0x00 +#define FAX_TYPE_RASTER 0x20 +#define FAX_TYPE_ASCII 0x30 + +#define FAX_MODE_PC 0x01 +#define FAX_MODE_SCANNER 0x02 +#define FAX_MODE_PRINTER 0x03 +#define FAX_MODE_REMOTE 0x04 + +#define FAX_PARAM1_RES385 0x02 +#define FAX_PARAM1_RES77 0x01 +#define FAX_PARAM1_RES154 0x03 +#define FAX_PARAM1_RES77G 0x09 + +#define FAX_PARAM2_G2 0x03 +#define FAX_PARAM2_G3 0x02 +#define FAX_PARAM2_POLLING 0x10 +#define FAX_PARAM2_POLLED 0x20 +#define FAX_PARAM2_OTI_TOP 0x08 +#define FAX_PARAM2_OTI_BOT 0x04 +#define FAX_PARAM2_ECMON 0x40 + +typedef struct trans { + char src_type; + char src_addr; + char dst_type; + char dst_addr; + int param1; + int param2; + char telno[FAX_TELNOSIZE]; + char remid[FAX_REMIDSIZE]; +} Trans; + +#define MAXDATASIZ 254 + +#define DATA_PAGE_END 0x08 +#define DATA_DOC_END 0x04 + +typedef struct data { + char data[MAXDATASIZ]; + int datalen; + int pageEnd; + int docEnd; +} Data; + +#define FAX_WRITE_EOF 0x04 +#define FAX_WRITE_EOP 0x08 +#define FAX_WRITE_MOVE 0x10 + +#define FAX_DEVICE "/dev/fax" + +void timet2fax (); +int fax_readpacket (), fax_writepacket (); +int fax_getstat1 (), fax_getstat2 (); +int fax_idset (), fax_simplecom (); +void fax_pstat1 (); + +#define fax_sendstop(fd) fax_simplecom((fd), COM_STOP) +#define fax_sendenq1(fd) fax_simplecom((fd), COM_ENQ1) +#define fax_sendenq2(fd) fax_simplecom((fd), COM_ENQ2) + +#define BITSPERBYTE 8 + + +typedef struct _psModem { + int fd; /* fd open to modem */ + char devName[BUFSIZ]; /* name of device */ + int resolution; /* resolution to use */ + int polled; /* whether using polling */ + char *phone_prefix; /* prefix to add to all phone numbers */ + int softcar; /* whether softcar is in use or not */ + int nattempts; /* number of times to try to connect to remote site */ + int sleepFor; /* seconds to sleep for between attempts */ + int connected; /* whether managed to connect or not */ + int scanner; /* whether data is waiting on scanner */ + /* or is actual inbound fax */ + char errBuf[BUFSIZ]; +} PsModem; + +#define PSM(faxctl) ((PsModem *) ((faxctl)->softc)) + +extern char *faxerr2str(); diff --git a/Chans/fax/ps250/ps250_basic.c b/Chans/fax/ps250/ps250_basic.c new file mode 100644 index 0000000..1a337f1 --- /dev/null +++ b/Chans/fax/ps250/ps250_basic.c @@ -0,0 +1,207 @@ +/* ps250_basic.c: basic encode decode fax control sequences */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_basic.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_basic.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_basic.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "ps250.h" +#ifdef SYS5 /* Can't use isode/sys.file.h due to termios.h */ +#include +#else +#include +#endif +#include +#include +#include +#include + +extern void advise (), adios (); +int fax_debug = 0; + +static void hexdump(); + +/* #define CHECKSUM */ + +/* + * basic io (chunk level) + */ + +#define INC 32 + +int writex (fd, buffer, size) +int fd; +char *buffer; +int size; +{ + char *cp = buffer; + int done = cp - buffer; + int num, n; + while (done < size) { + if (size - done < INC) + num = size - done; + else + num = INC; + + if ((n = write (fd, cp, num)) <= 0) + return NOTOK; +/* if (fax_debug) + hexdump ("<=", cp, n);*/ + cp += num; + done = cp - buffer; + } + return done; +} + +static int readx (fd, buffer, size) +int fd; +char *buffer; +int size; +{ + char *cp = buffer; + int count = 0, n; + + while (size > 0) { + if ((n = read (fd, cp, size)) <= 0) + return NOTOK; +/* if (fax_debug) + hexdump ("=>", cp, n);*/ + count += n; + size -= n; + cp += n; + } + return count; +} + +/* + * basic io (packet level) + */ + +int fax_writepacket (fd, fp) +Faxcomm *fp; +{ + char *cp; + int len; + char buffer[FAXBUFSIZ]; + + cp = buffer; + *cp ++ = FAX_HEADER; + *cp ++ = FAX_HEADER; + *cp ++ = FAX_CONTROL; + *cp ++ = FAX_ADDRESS; + len = 1 + fp -> len; + *cp ++ = len == 256 ? 0 : len; + *cp ++ = fp -> command; + if (fp -> len) { + bcopy (fp -> data, cp, fp -> len); + cp += fp -> len; + } + *cp = fax_checksum (buffer, cp - buffer); + cp ++; + + if (writex (fd, buffer, cp - buffer) != cp - buffer) + return NOTOK; + return OK; +} + +int fax_readpacket (fd, fp) +int fd; +Faxcomm *fp; +{ + char buffer[FAXBUFSIZ]; + unsigned int len; + + if ((len = readx (fd, buffer, FAXHDRSIZE)) != FAXHDRSIZE) { + advise ("read", "Read fax header size failed"); + return NOTOK; + } + if (buffer[0] != FAX_HEADER || + buffer[1] != FAX_HEADER || + buffer[2] != FAX_CONTROL || + buffer[3] != FAX_ADDRESS) { + advise (NULLCP, "Incorrect Fax header"); + return NOTOK; + } + len = (unsigned char) buffer[FAXHDRSIZE - 1]; + if (len == 0) + len = 256; + +#ifdef CHECKSUM + len ++; +#endif + if (readx (fd, &buffer[FAXHDRSIZE], len) != len) { + advise ("read", "failed to read %d more bytes", len); + return NOTOK; + } +#ifdef CHECKSUM + if ((tmp = fax_checksum (buffer, FAXHDRSIZE + len)) != + buffer[FAXHDRSIZE + len - 1]) { + advise (NULLCP, "Checksum failed %d != %d", + buffer[FAXHDRSIZE + len - 1], tmp); + return NOTOK; + } +#endif + fp -> flags = 0; + fp -> command = buffer[FAXHDRSIZE]; + fp -> len = len - 1; + if (fp -> len) + bcopy (&buffer[FAXHDRSIZE+1], fp -> data, fp -> len); + return OK; +} + +/* + * checksum routine + */ + +int fax_checksum (bp, len) +int len; +char *bp; +{ + char *cp, *ep = bp + len; + int sum = 0; + + for (cp = bp + 2; cp < ep; cp ++) + sum += *cp; + return 0x100 - (sum % 0x100); +} + +/* misc */ + +static void hexdump (str, bp, n) +char *str; +char *bp; +int n; +{ + static char hex[] = "0123456789ABCDEF"; + + fputs (str, stdout); + while (n -- > 0) { + putchar (hex[(*bp >> 4) & 0xf]); + putchar (hex[*bp & 0xf]); + bp ++; + } + putchar ('\n'); +} + +int fax_simplecom (fd, type) +int fd; +int type; +{ + Faxcomm pack; + + pack.flags = 0; + pack.command = type; + pack.len = 0; + + return fax_writepacket (fd, &pack); +} diff --git a/Chans/fax/ps250/ps250_intf.c b/Chans/fax/ps250/ps250_intf.c new file mode 100644 index 0000000..152f2e2 --- /dev/null +++ b/Chans/fax/ps250/ps250_intf.c @@ -0,0 +1,629 @@ +/* ps250_intf.c: interface routines for Panasonic 250 driver */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_intf.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_intf.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_intf.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ +#include "util.h" +#include "retcode.h" +#include "qmgr.h" +#include "chan.h" +#include "IOB-types.h" +#include "../faxgeneric.h" +#include "ps250.h" + +/* + * Heuristics for whether to bounce or not on failure + */ + +extern int table_verified; + +static void isPermanentFail(faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + /* set qmgrErrCode to negativeDR in certain situations */ + + if (psm->connected == FALSE) + /* no connection so not permanent */ + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + else { + /* connected */ + if (table_verified == TRUE) + /* in table so not permanent */ + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + else + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + } +} + +/* + * Open ps250 device and initialize + * Return OK or NOTOK + */ + +psOpen (faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + + if (openPsModem(psm) != OK) { + sprintf(faxctl->errBuf, + "openPsModem failed [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + return OK; +} + +/* + * Close fax device + */ + +psClose (faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + + return closePsModem(psm); +} + +/* + * Initialise for transmission + */ + +extern CHAN *mychan; + +static int isValidPhoneChar (ch) +char ch; +{ + if (isdigit(ch) + || isspace(ch)) + return OK; + switch (ch) { + case '-': +/* case '+': tested for explicitly */ + return OK; + default: + break; + } + return NOTOK; +} + +static int convertPhoneNumber(psm, from, to, pfatal) +PsModem *psm; +char *from; +char *to; +int *pfatal; +{ + char *ifrom = from, *ito = to; + char intprefix[FAX_TELNOSIZE]; +#define INT_PREFIX "int_prefix" +#define PAUSE 0x3F + while (*ifrom != '\0' && isspace(*ifrom)) *ifrom++; + + *pfatal = FALSE; + + if (psm->phone_prefix) { + /* insert phone prefix */ + char *ix = psm->phone_prefix; + while (*ix != '\0' && (ito - to) < FAX_TELNOSIZE) { + if (isValidPhoneChar(*ix) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal phone character '%c' in prefix '%s'", + *ix, psm->phone_prefix)); + to[0] = '\0'; + sprintf(psm->errBuf, + "Illegal character '%c'", + *ix); + return NOTOK; + } + if (isspace(*ix) || + *ix == '-') + ito++; + else + *ito++ = *ix++; + } + } + + if (*ifrom == '+') { + /* insert national prefix */ + ifrom++; + if (mychan && + mychan -> ch_table && + tb_k2val (mychan -> ch_table, + INT_PREFIX, intprefix, TRUE) != NOTOK) { + char *ix = &(intprefix[0]); + while (*ix != '\0' && + (ito - to) < FAX_TELNOSIZE) { + if (isValidPhoneChar(*ix) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal phone character '%c' in international prefix '%s'", + *ix, intprefix)); + to[0] = '\0'; + sprintf(psm->errBuf, + "Illegal character '%c'", + *ix); + return NOTOK; + } + if (isspace(*ix) || + *ix == '-') + ito++; + else + *ito++ = *ix++; + + } + } + } + + /* any errors from here in are bad errors */ + *pfatal = TRUE; + while (*ifrom != '\0' && + (ito - to) < FAX_TELNOSIZE) { + if (isValidPhoneChar(*ifrom) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal phone character '%c' in '%s'", + *ifrom, from)); + sprintf(psm->errBuf, + "Illegal character '%c'", + *ifrom); + to[0] ='\0'; + return NOTOK; + } + if (isspace(*ifrom) || + *ifrom == '-') + ifrom++; + else if (*ifrom == 'P' + || *ifrom == 'p') { + *ito = PAUSE; + *ifrom++; + } else + *ito++ = *ifrom++; + } + if ((ito - to) >= FAX_TELNOSIZE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Phone number '%s' is too long. Maximum is %d", + from, FAX_TELNOSIZE)); + sprintf(psm->errBuf, + "Number too long (max=%d)", + FAX_TELNOSIZE); + to[0] = '\0'; + return NOTOK; + } + *ito = '\0'; + return OK; +} + +psInitXmit (faxctl) +FaxCtlr *faxctl; +{ + char telno[FAX_TELNOSIZE]; + int drit = FALSE; + PsModem *psm = PSM(faxctl); + + faxctl->qmgrErrCode = int_Qmgr_status_messageFailure; + + if (convertPhoneNumber (psm, faxctl->telno, telno, &drit) != OK) { + sprintf(faxctl->errBuf, + "Unable to convert telephone number '%s' [%s]", + faxctl->telno, psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + if (drit == TRUE + && table_verified != TRUE) + /* bad user given phone number */ + faxctl->qmgrErrCode = int_Qmgr_status_negativeDR; + return RP_MECH; + } + + if (dialPsModem(psm, telno) != OK) { + sprintf(faxctl->errBuf, + "Unable to initial Xmit [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + isPermanentFail(faxctl); + return NOTOK; + } + return OK; +} + +/* + * Abort the current call to the fax machine + */ + +psAbort (faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + abortPsModem(psm); +} + +/* + * Terminate transmission + */ + +psTermXmit (faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + if (eomPsModem(psm) != OK) { + sprintf(faxctl->errBuf, + "Bad termination of transmission [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + isPermanentFail(faxctl); + return NOTOK; + } + return OK; +} + +/* + * Test/Set G3 Fax Parameters + */ + +psSetG3Params (faxctl, params) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileParameters *params; +{ + PsModem *psm = PSM(faxctl); + + if (params -> non__basic__parameters) { + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_two__dimensional) == 1) { + sprintf(faxctl->errBuf, + "Unable to deal with two dimensional fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_uncompressed) == 1) { + sprintf(faxctl->errBuf, + "Unable to deal with uncompressed fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + + if (bit_test(params -> non__basic__parameters, + bit_MTA_G3FacsimileNonBasicParameters_fine__resolution) == 1) { + sprintf(faxctl->errBuf, + "Unable to deal with fine resolution"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + } + if (psModemG3init(psm) != OK) { + sprintf(faxctl->errBuf, + "Failed to initialise modem for fax transmission [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + return OK; +} + +/* + * Send page of G3 fax to fax modem + */ + + +/* + * reverse bit orderings + */ + +void reverse_strb(str, len) +char str[]; +int len; +{ + int i; + for (i = 0; i < len; i++) + str[i] = flip_bits((unsigned char) str[i]); +} + +psSendPage (faxctl, str, len, last) +FaxCtlr *faxctl; +char *str; +int len; +int last; +{ + PsModem *psm = PSM(faxctl); + + /* G3Fax encoding is reverse bit ordering of X400 encoding */ + reverse_strb(str, len); + + return sendPsModem(psm, str, len, last); +} + +/* + * Set IA5 transmission parameters + */ + +psSetIA5Params (faxctl) +FaxCtlr *faxctl; +{ + PsModem *psm = PSM(faxctl); + + if (psModemIA5init(psm) != OK) { + sprintf(faxctl->errBuf, + "Failed to initialise modem for ia5 transmission [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + return OK; +} + +/* + * Send page of ia5 to fax modem + */ + +psSendIA5File (faxctl, fileName, last) +FaxCtlr *faxctl; +char *fileName; +int last; +{ + PsModem *psm = PSM(faxctl); + FILE *fp; + + if ((fp = fopen (fileName, "r")) == (FILE *) 0) { + PP_SLOG (LLOG_EXCEPTIONS, fileName, + ("Can't open file")); + sprintf(faxctl->errBuf, + "Unable to open IA5 file '%s'", + fileName); + return NOTOK; + } + + if (sendPsModemIA5 (psm, fp, last) != OK) { + sprintf(faxctl->errBuf, + "failed to send ia5 file [%s]", + psm->errBuf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + fclose(fp); + return NOTOK; + } + fclose(fp); + return OK; +} + +/* + * Wait for and store inbound faxes + */ + +psReceiveG3Fax (faxctl, pg3fax) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileBodyPart **pg3fax; +{ + PsModem *psm = PSM(faxctl); + /* open */ + if (faxctl->open != NULLIFP + && (*faxctl->open) (faxctl) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("fax open failed ['%s']", + faxctl->errBuf)); + return NOTOK; + } + /* wait */ + if (ps_wait_for_fax (psm) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("ps_wait_for_fax failed ['%s']", + faxctl->errBuf)); + return NOTOK; + } + /* scan */ + if (ps_init_listen (psm) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("ps_init_fax_listen failed ['%s']", + faxctl->errBuf)); + return NOTOK; + } + ps_wait_for_data(psm); + + if (rcvPsModem (psm, pg3fax) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("ps_fax_read_bitstrings failed ['%s']", + faxctl->errBuf)); + return NOTOK; + } + /* close */ + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + + return OK; +} + +/* + * Parse out-info line arguments + */ + +psArgParseOut (faxctl, key, value) +FaxCtlr *faxctl; +char *key; +char *value; +{ + PsModem *psm = PSM(faxctl); + + if (!isstr(value)) { + sprintf(faxctl->errBuf, + "No value given with key '%s'", + key); + PP_LOG (LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + + if (lexequ(key, "out") == 0) + strcpy(psm->devName, value); + else if (lexequ(key, "prefix") == 0) + psm->phone_prefix = strdup(value); + else if (lexequ(key, "nattempts") == 0) { + if ((psm->nattempts = atoi(value)) <= 0) { + sprintf(faxctl->errBuf, + "Cannot set number of attempts to '%s'", + value); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + } else if (lexequ(key, "sleep") == 0) { + if ((psm->sleepFor = atoi(value)) <= 0) { + sprintf(faxctl->errBuf, + "Cannot set sleep time to '%s'", + value); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + } else if (lexequ(key, "softcar") == 0) { + if (lexequ(value, "used") == 0) + psm->softcar = TRUE; + } + else { + sprintf(faxctl->errBuf, + "Unknown info arg '%s=%s", + key, (isstr(value)) ? value : "(null)"); + return NOTOK; + } + return OK; +} + +/* + * Parse out-info line arguments + */ + +psArgParseIn (faxctl, key, value) +FaxCtlr *faxctl; +char *key; +char *value; +{ + PsModem *psm = PSM(faxctl); + + if (!isstr(value)) { + sprintf(faxctl->errBuf, + "No value given with key '%s'", + key); + PP_LOG (LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + return NOTOK; + } + + if (lexequ(key, "in") == 0) + strcpy(psm->devName, value); + else if (lexequ(key, "master") == 0) + strcpy(faxctl->fax_recip,value); + else if (lexequ(key, "subject") == 0) + strcpy(faxctl->subject, value); + else if (lexequ(key, "softcar") == 0) { + if (lexequ(value, "used") == 0) + psm->softcar = TRUE; + } + else { + sprintf(faxctl->errBuf, + "Unknown info arg '%s=%s", + key, (isstr(value)) ? value : "(null)"); + return NOTOK; + } + return OK; +} + +/* + * Return a fax control block + */ + +extern int optind; +extern char *optarg; + +FaxCtlr *init_faxctrlr(type, argc, argv) +int type; +int argc; +char **argv; +{ + FaxCtlr *faxctl; + PsModem *psm; + int opt; + + faxctl = (FaxCtlr *)malloc(sizeof(FaxCtlr)); + bzero(faxctl, sizeof(FaxCtlr)); + + psm = (PsModem *)malloc(sizeof(PsModem)); + bzero(psm, sizeof(PsModem)); + switch (type) { + case FAX_OUTBOUND: + psm->nattempts = 3; + psm->sleepFor = 30; /* 1/2 min */ + psm->polled = FALSE; + sprintf(psm->devName, "/dev/faxout"); /* default for now */ + faxctl->setG3Params = psSetG3Params; + faxctl->sendPage = psSendPage; + faxctl->setIA5Params = psSetIA5Params; + faxctl->sendIA5File = psSendIA5File; + faxctl->arg_parse = psArgParseOut; + break; + case FAX_INBOUND: + sprintf(psm->devName, "/dev/faxin"); + sprintf(faxctl->channel, "fax"); + sprintf(faxctl->fax_recip, "faxmaster"); + sprintf(faxctl->subject, "Inbound fax message"); + faxctl->receiveG3Fax = psReceiveG3Fax; + psm->nattempts = 1; + faxctl->arg_parse = psArgParseIn; + + /* now deal with command line args */ + + while ((opt = getopt(argc, argv, "c:")) != EOF) + switch(opt) { + case 'c': + /* override channel name */ + strcpy(faxctl->channel, optarg); + break; + default: + (void) sprintf(faxctl->errBuf, + "Unknown command line argument '-%c'", + (char) opt); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", faxctl->errBuf)); + free(psm); + free(faxctl); + return (FaxCtlr *) NULL; + + break; + } + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unsupported fax type '%d'", type)); + free(psm); + free(faxctl); + return (FaxCtlr *) NULL; + } + + psm->softcar = FALSE; + psm->resolution = FAX_PARAM1_RES385; + faxctl->softc = (char *) psm; + + faxctl->open = psOpen; + faxctl->close = psClose; + faxctl->initXmit = psInitXmit; + faxctl->abort = psAbort; + faxctl->termXmit = psTermXmit; + + return faxctl; +} diff --git a/Chans/fax/ps250/ps250_manage.c b/Chans/fax/ps250/ps250_manage.c new file mode 100644 index 0000000..be15372 --- /dev/null +++ b/Chans/fax/ps250/ps250_manage.c @@ -0,0 +1,241 @@ +/* ps250_manage.c: general management of fax connections */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_manage.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_manage.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_manage.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "ps250.h" +#include "retcode.h" +#include + +/* +*/ + +int fax_move_and_check (psm, trans) +PsModem *psm; +Trans *trans; +{ + Stat1 st1; + + if (fax_move(psm->fd, trans) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("fax_move failed")); + return NOTOK; + } + if (fax_getresp (psm->fd, &st1) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + return OK; +} + +int fax_trans_and_check (psm, trans, listen) +PsModem *psm; +Trans *trans; +int listen; +{ + Stat1 st1; + int resp, job; + int attempts = 0; + int cont = TRUE; + int enqSleep = 1; + psm->connected = FALSE; + + for (attempts = 0; attempts < psm->nattempts; attempts++) { + if (attempts != 0) { + sleep (psm->sleepFor); + fax_sendstop(psm->fd); + fax_getstat1(psm->fd, &st1); + } + + if (fax_trans (psm->fd, trans) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to initialise fax parameters")); + return NOTOK; + } + + if (listen) + /* do enq1 elsewhere */ + return OK; + + if ((resp = fax_getresp (psm->fd, &st1)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + + if (trans->telno[0] == 0) + /* local print so don't wait */ + return OK; + cont = TRUE; + while (cont == TRUE && resp == RESP_STAT1) { + + switch (job = get_job_info(st1.job_info)) { + case JOB_READY: + if ((st1.comm & COMM_GMASK) == COMM_G2 + || (st1.comm & COMM_GMASK) == COMM_G3) { + psm->connected = TRUE; + return OK; + } + break; + case JOB_IN: + break; + default: + sprintf(psm->errBuf, + "Unexpected job info '%d'", job); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + if (st1.fecode[0]) { + sprintf(psm->errBuf, + "Fax error code: %s", + faxerr2str(atoi(st1.fecode))); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + } + switch (atoi(st1.fecode)) { + case 692: + /* busy */ + cont = FALSE; + break; + case 690: + /* no dial */ + return NOTOK; + default: + /* failed */ + psm->connected = TRUE; + return NOTOK; + } + } + if (cont == TRUE) { + sleep (enqSleep); + if (fax_sendenq1(psm->fd) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("sendenq1 failed")); + return NOTOK; + } + if ((resp = fax_getresp (psm->fd, &st1)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + } + } + } + return NOTOK; +} + +int fax_revpl_and_check (psm, trans) +PsModem *psm; +Trans *trans; +{ + Stat1 st1; + + if (fax_revpl (psm->fd, trans) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to initialise fax parameters")); + return NOTOK; + } + + if ((fax_getresp (psm->fd, &st1)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + fax_pstat1(&st1); + return OK; +} + +int num_sent; + +extern char *get_job_str(); + +int fax_write_and_check (psm, buf, num, flags) +PsModem *psm; +char *buf; +int num, flags; +{ + Stat1 st1; + int resp; + + if (fax_write (psm->fd, buf, num, flags)) { + PP_LOG(LLOG_EXCEPTIONS, + ("fax_write failed")); + return NOTOK; + } + if ((resp = fax_getresp (psm->fd, &st1)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + if (resp == RESP_ACK) { + num_sent += num; + return OK; + } + while (resp == RESP_STAT1) { + switch (get_job_info(st1.job_info)) { + case JOB_RETRANS: + return fax_write_and_check (psm, buf, num, flags); + case JOB_READY: + num_sent += num; + return OK; + case JOB_IN: + /* wait and send enq1 */ + if (flags & FAX_WRITE_EOF) + /* do waiting in term fax */ + return OK; + sleep (1); + if (fax_sendenq1(psm->fd) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("sendenq1 failed")); + return NOTOK; + } + if ((resp = fax_getresp (psm->fd, &st1)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad response from fax")); + return NOTOK; + } + break; + default: + /* WORK rest of cases */ + PP_LOG(LLOG_EXCEPTIONS, + ("fax_write_and_check: Unexpected job info '%s'", + get_job_str(st1.job_info))); + if (st1.fecode[0]) + PP_LOG(LLOG_EXCEPTIONS, + ("Fax error code: %s", + faxerr2str(atoi(st1.fecode)))); + + return NOTOK; + } + } + return OK; +} + +int fax_read_and_check (psm, data) +PsModem *psm; +Data *data; +{ + if (fax_read (psm->fd, TRUE) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("fax_read failed")); + return NOTOK; + } + if (fax_data(psm->fd, data) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("fax_data failed")); + return NOTOK; + } + return OK; +} + diff --git a/Chans/fax/ps250/ps250_stat.c b/Chans/fax/ps250/ps250_stat.c new file mode 100644 index 0000000..9ee00c7 --- /dev/null +++ b/Chans/fax/ps250/ps250_stat.c @@ -0,0 +1,401 @@ +/* ps250_stat.c: routines to enquiry of PS 250s status */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_stat.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_stat.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_stat.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "ps250.h" + +extern void advise (), adios (); + +char *get_job_str(), *get_com_str(); + +int fax_getstat1 (fd, sp) +int fd; +Stat1 *sp; +{ + Faxcomm fc; + + if (fax_readpacket (fd, &fc) == NOTOK) + return NOTOK; + if (fc.command != RESP_STAT1) + return NOTOK; + return fax_fc2stat1 (&fc, sp); +} + +fax_fc2data (fp, dp) +Faxcomm *fp; +Data *dp; +{ + char *cp; + + bzero ((char *)dp, sizeof *dp); + cp = fp -> data; + + dp->pageEnd = (*cp) & DATA_PAGE_END; + dp->docEnd = (*cp) & DATA_DOC_END; + + cp++; + dp->datalen = fp -> len - 1; + bcopy(cp, dp->data, dp->datalen); +} + +fax_fc2stat1 (fp, sp) +Faxcomm *fp; +Stat1 *sp; +{ + char *cp; + + cp = fp -> data; + bzero ((char *)sp, sizeof *sp); + sp -> ce_code = *cp++; + sp -> mode_cmd = *cp++; + sp -> ring_in = *cp++; + sp -> scan_stat = *cp++; + sp -> print_stat = *cp ++; + sp -> job_info = *cp ++; + if (*cp) { + bcopy (cp, sp -> fecode, 4); + cp += 4; + } + else cp ++; + + sp -> res = *cp ++; + sp -> comm = *cp ++; + if (*cp == 0) { + sp -> remid[0] = 0; + cp ++; + } + else { + bcopy (cp, sp -> remid, 21); + cp += 21; + } + + sp -> errlines = *cp << 8 | cp[1]; + cp += 2; + sp -> page_no = atoi (cp); + cp += 3; + if (cp - fp -> data != fp -> len) + advise (NULLCP, "Packet length mismatch %d != %d", + cp - fp -> data, fp -> len); + return OK; +} + +void fax_pstat1(sp) +Stat1 *sp; +{ + if (sp -> ce_code != COMERR_OK) + PP_LOG(LLOG_DEBUG, + ("=>Command Code: %s\n", + get_com_str(sp->ce_code))) + switch (sp -> mode_cmd & MODE_MASK) { + case MODE_WAIT_JOB: + PP_LOG(LLOG_DEBUG, + ("Mode : Wait Job")); + break; + case MODE_WAIT_BLOCK: + PP_LOG(LLOG_DEBUG, + ("Mode : Wait Block")); + break; + case MODE_FAX_WORKING: + PP_LOG(LLOG_DEBUG, + ("Mode : Fax working")); + break; + default: + PP_LOG(LLOG_DEBUG, + ("Unknown Mode : 0x%x", sp -> mode_cmd & MODE_MASK)); + break; + } + putchar ('\n'); + + if (sp -> ring_in == RING_IN) + PP_LOG(LLOG_DEBUG, + ("Ring in set")); + + if (sp -> scan_stat & SCAN_DOC_SCAN) + PP_LOG(LLOG_DEBUG, + ("Scanner Status: Document scanner")); + if (sp -> scan_stat & SCAN_NODOC) + PP_LOG(LLOG_DEBUG, + ("Scanner Status: No document on ADF")); + if (sp -> scan_stat & SCAN_FEEDERR) + PP_LOG(LLOG_DEBUG, + ("Scanner Status: Feeder Error")); + if (sp -> scan_stat & SCAN_TOOLONG) + PP_LOG(LLOG_DEBUG, + ("Scanner Status: Document too long")); + if (sp -> scan_stat & SCAN_B4) + PP_LOG(LLOG_DEBUG, + ("Scanner Status: Document B4 size")); + + if (sp -> print_stat & PRINT_PJAM) + PP_LOG(LLOG_DEBUG, + ("Printer Status: Printer Jam")); + if (sp -> print_stat & PRINT_NOPAPER) + PP_LOG(LLOG_DEBUG, + ("Printer Status: No paper")); + + PP_LOG(LLOG_DEBUG, + ("Job Info: %s", get_job_str(sp->job_info))); + + if (sp -> fecode[0]) + PP_LOG(LLOG_EXCEPTIONS, + ("Fax error code: %s", + faxerr2str(atoi(sp -> fecode)))); + + if (sp -> res !=0) { + switch (sp -> res & RES_MASK) { + case RES_7_7: + PP_LOG(LLOG_DEBUG, + ("Resolution: 7.7 lines/mm")); + break; + case RES_3_85: + PP_LOG(LLOG_DEBUG, + ("Resolution: 3.85 lines/mm")); + break; + case RES_15_4: + PP_LOG(LLOG_DEBUG, + ("Resolution: 15.4 lines/mm")); + break; + default: + PP_LOG(LLOG_DEBUG, + ("Resolution: Unknown (0x%x)", sp -> res)); + break; + } + } else + PP_LOG(LLOG_DEBUG, + ("Resolution: unset")); + + if (sp -> comm != 0) { + char buf[BUFSIZ]; + switch (sp -> comm & COMM_GMASK) { + case COMM_G2: + strcpy(buf," G2"); + break; + case COMM_G3: + strcpy(buf, " G3"); + break; + default: + sprintf (buf, " %d", sp -> comm); + break; + } + switch (sp -> comm & COMM_XR_MASK) { + case COMM_XMT: + strcat (buf, " XMT"); + break; + case COMM_RCV: + strcat (buf, " RCV"); + break; + default: + break; + } + + switch (sp -> comm & COMM_SPEED_MASK) { + case COMM_SPEED_2400: + strcat (buf, " 2400baud"); + break; + case COMM_SPEED_4800: + strcat (buf, " 4800 baud"); + break; + case COMM_SPEED_7200: + strcat (buf, " 7200baud"); + break; + case COMM_SPEED_9600: + strcat (buf, " 9600baud"); + break; + default: + break; + } + + switch (sp -> comm & COMM_MHR_MASK) { + case COMM_MH: + strcat (buf, " MH"); + break; + case COMM_MR: + strcat (buf, " MR"); + break; + } + if ((sp -> comm & COMM_POLLED) == COMM_POLLED) + strcat (buf, " Polled"); + PP_LOG(LLOG_DEBUG, + ("Comms: %s",buf)); + } else + PP_LOG(LLOG_DEBUG, + ("Comms: unset")); + + if (sp -> remid[0]) + PP_LOG(LLOG_DEBUG, + ("Remote Id: %s", sp -> remid)); + + if (sp -> errlines) + PP_LOG(LLOG_EXCEPTIONS, + (" Error Lines: %d", sp -> errlines)); + + if (sp -> page_no) + PP_LOG(LLOG_DEBUG, + ("Page No: %d", sp->page_no)); +} + +static char ret[128]; + +char *get_com_str(com) +int com; +{ + switch (com) { + case COMERR_UNDEF_COMMAND: + sprintf (ret, "Undefined Command"); + break; + case COMERR_UNAC_COMMAND: + sprintf (ret, "Unacceptable Command"); + break; + case COMERR_PARAM: + sprintf (ret, "Command Parameter Error"); + break; + case COMERR_FRAME: + sprintf (ret, "Frame Error"); + default: + sprintf (ret, "Unknown response code 0x%x", com); + break; + } + return ret; +} + +char *get_job_str(job) +int job; +{ + switch (get_job_info (job)) { + case JOB_IN: + sprintf (ret, "Job In"); + break; + case JOB_READY: + sprintf (ret, "Job ready"); + break; + case JOB_DATA_AVAIL: + sprintf (ret, "Job data avilable"); + break; + case JOB_RETRANS: + sprintf (ret, "Job retransmit last block"); + break; + case JOB_NORM_END: + sprintf (ret, "Normal end"); + break; + case JOB_FAULT_JOB_END: + sprintf (ret, "Fault job end"); + break; + case JOB_LINE_DISC: + sprintf (ret, "Line disconnected"); + break; + default: + sprintf (ret, "Unknown value %o", job); + break; + } + return ret; +} + +int get_job_info(job) +int job; +{ + if ((job & JOB_READY) == JOB_READY) + return JOB_READY; + if ((job & JOB_DATA_AVAIL) == JOB_DATA_AVAIL) + return JOB_DATA_AVAIL; + if ((job & JOB_RETRANS) == JOB_RETRANS) + return JOB_RETRANS; + if ((job & JOB_NORM_END_MASK) == JOB_NORM_END) + return JOB_NORM_END; + if ((job & JOB_NORM_END_MASK) == JOB_FAULT_JOB_END) + return JOB_FAULT_JOB_END; + if ((job & JOB_LINE_DISC_MASK) == JOB_LINE_DISC) + return JOB_LINE_DISC; + if ((job & JOB_IN)) + return JOB_IN; + return NOTOK; +} + +void timet2fax (t, buf) +time_t t; +char buf[]; +{ + struct tm *tm; + + tm = localtime (&t); + (void) sprintf (buf, "%02d%02d%02d%02d%02d", + tm -> tm_min, tm -> tm_hour, tm -> tm_mday, + tm -> tm_mon + 1, tm -> tm_year); +} + +int fax_idset (fd, ip) +int fd; +Idset *ip; +{ + Faxcomm fc; + char *cp; + + fc.flags = 0; + fc.command = COM_IDSET; + + if (ip -> clock[0]) { + bcopy (ip -> clock, fc.data, FAX_CLOCKLEN); + fc.len = FAX_CLOCKLEN; + cp = fc.data + FAX_CLOCKLEN; + } + else { + fc.data[0] = 0; + cp = fc.data + 1; + fc.len = 1; + } + + if (ip -> local[0]) { + bcopy (ip -> local, cp, FAX_LOCALIDLEN); + fc.len += FAX_LOCALIDLEN; + } + else { + *cp = 0; + fc.len ++; + } + + return fax_writepacket (fd, &fc); +} + +fax_getstat2 (fd, sp) +int fd; +Stat2 *sp; +{ + Faxcomm fc; + char *cp; + + if (fax_readpacket (fd, &fc) == NOTOK) + return NOTOK; + if (fc.command != RESP_STAT2) { + advise (NULLCP, "Not a stat2 response"); + return NOTOK; + } + + if (fc.data[0] == 0) { + sp -> clock[0] = 0; + cp = fc.data + 1; + } + else { + bcopy (fc.data, sp -> clock, FAX_CLOCKLEN); + cp = fc.data + FAX_CLOCKLEN; + } + + if (*cp) + bcopy (cp, sp -> local, FAX_LOCALIDLEN); + else + sp -> local[0] = 0; + return OK; +} + + + diff --git a/Chans/fax/ps250/ps250_trans.c b/Chans/fax/ps250/ps250_trans.c new file mode 100644 index 0000000..dc29756 --- /dev/null +++ b/Chans/fax/ps250/ps250_trans.c @@ -0,0 +1,238 @@ +/* fax_trans.c: wrappers around basic ps 250 functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_trans.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_trans.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_trans.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "ps250.h" + +/* + * wrap up and initialise the tranmission parameters + */ +extern char *get_com_str(); +extern int fax_debug; + +int fax_trans (fd, tp) +int fd; +Trans *tp; +{ + Faxcomm fc; + char *cp; + int len; + + fc.flags = 0; + fc.command = COM_TRANS; + cp = fc.data; + fc.len = 0; + *cp ++ = tp -> src_type | tp -> src_addr; + fc.len ++; + *cp ++ = tp -> dst_type | tp -> dst_addr; + fc.len ++; + *cp ++ = tp -> param1; + fc.len ++; + *cp ++ = tp -> param2; + fc.len ++; + len = strlen (tp -> telno); + if (len >= FAX_TELNOSIZE) + return NOTOK; + strcpy (cp, tp -> telno); + len ++; + cp += len; + fc.len += len; + if (tp -> remid[0]) { + bcopy (tp -> remid, cp, FAX_REMIDSIZE); + fc.len += FAX_REMIDSIZE; + } + else { + *cp++ = 0; + fc.len ++; + } + + return fax_writepacket (fd, &fc); +} + +int fax_revpl (fd, tp) +int fd; +Trans *tp; +{ + Faxcomm fc; + char *cp; + int len; + + fc.flags = 0; + fc.command = COM_REVPL; + cp = fc.data; + fc.len = 0; + *cp ++ = tp -> src_type | tp -> src_addr; + fc.len ++; + *cp ++ = tp -> dst_type | tp -> dst_addr; + fc.len ++; + *cp ++ = tp -> param1; + fc.len ++; + *cp ++ = tp -> param2; + fc.len ++; + len = strlen (tp -> telno); + if (len >= FAX_TELNOSIZE) + return NOTOK; + strcpy (cp, tp -> telno); + len ++; + cp += len; + fc.len += len; + if (tp -> remid[0]) { + bcopy (tp -> remid, cp, FAX_REMIDSIZE); + fc.len += FAX_REMIDSIZE; + } + else { + *cp++ = 0; + fc.len ++; + } + + return fax_writepacket (fd, &fc); +} + +int fax_move (fd, tp) +int fd; +Trans *tp; +{ + Faxcomm fc; + char *cp; + + fc.flags = 0; + fc.command = COM_MOVE; + fc.len = 4; + cp = fc.data; + *cp++ = tp -> src_type | tp -> src_addr; + *cp++ = tp -> dst_type | tp -> dst_addr; + *cp++ = tp -> param1; + *cp++ = 0; + return fax_writepacket (fd, &fc); +} + +/* + * send data to fax + */ + +fax_write (fd, data, len, flags) +int fd; +char *data; +int len, flags; +{ + Faxcomm fc; + + fc.flags = 0; + fc.len = len + 1; + fc.command = COM_WRITE; + fc.data[0] = flags; + bcopy (data, &fc.data[1], len); + return fax_writepacket (fd, &fc); +} + +/* + * request data from fax + */ + +fax_read(fd, ok) +int fd, ok; +{ + char *cp, buffer[FAXBUFSIZ]; + + cp = buffer; + *cp ++ = FAX_HEADER; + *cp ++ = FAX_HEADER; + if (ok) + *cp ++ = FAX_CONTROL; + else + *cp ++ = FAX_RETRANS; + *cp ++ = FAX_ADDRESS; + *cp ++ = 1; + *cp ++ = COM_READ; + *cp = fax_checksum (buffer, cp - buffer); + *cp++; + if (writex (fd, buffer, cp - buffer) != cp - buffer) + return NOTOK; + return OK; +} + +fax_data (fd, data) +int fd; +Data *data; +{ + Faxcomm fc; + + if (fax_readpacket(fd, &fc) == NOTOK) + return NOTOK; + if (fc.command != RESP_DATA) + return NOTOK; + fax_fc2data(&fc, data); + return OK; +} + +/* + * read response from fax + */ + +int fax_getresp(fd, st1) +int fd; +Stat1 *st1; +{ + Faxcomm fc; + int retval = NOTOK; + + if (fax_readpacket (fd, &fc) == NOTOK) + return NOTOK; + switch (fc.command) { + case RESP_ACK: +/* if (fax_debug) + printf("=> ACK ");*/ + retval = OK; + break; + case RESP_STAT1: + if (fax_debug) + PP_LOG(LLOG_DEBUG, + ("fax_getresp: STAT1")); + retval = OK; + fax_fc2stat1 (&fc, st1); + if (fax_debug) + fax_pstat1 (st1); + break; + case RESP_REJ: + if (fax_debug) + PP_LOG(LLOG_NOTICE, + ("fax_getresp: REJ")); + fax_fc2stat1 (&fc, st1); + if (fax_debug) + fax_pstat1 (st1); + if (st1->ce_code != COMERR_OK) + PP_LOG(LLOG_EXCEPTIONS, + ("Command code: %s", get_com_str(st1->ce_code))); + if (st1->fecode[0]) + PP_LOG(LLOG_EXCEPTIONS, + ("Fax error code: %s", + faxerr2str(atoi(st1->fecode)))); + break; + case RESP_STAT2: + if (fax_debug) + PP_LOG(LLOG_DEBUG, + ("fax_getresp: STAT2")); + break; + case RESP_DATA: + if (fax_debug) + PP_LOG(LLOG_DEBUG, + ("fax_getresp: DATA")); + break; + } + if (retval == NOTOK) + return retval; + return fc.command; +} + diff --git a/Chans/fax/ps250/ps250_util.c b/Chans/fax/ps250/ps250_util.c new file mode 100644 index 0000000..a14e69d --- /dev/null +++ b/Chans/fax/ps250/ps250_util.c @@ -0,0 +1,629 @@ +/* ps250_util.c: utility routines for Panasonic 250 fax machine */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_util.c,v 6.0 1991/12/18 20:07:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/RCS/ps250_util.c,v 6.0 1991/12/18 20:07:26 jpo Rel $ + * + * $Log: ps250_util.c,v $ + * Revision 6.0 1991/12/18 20:07:26 jpo + * Release 6.0 + * + */ +#include "util.h" +#include "retcode.h" +#include "qmgr.h" +#include "IOB-types.h" +#include +#include +#ifdef SYS5 /* Can't use isode/sys.file.h due to termios.h */ +#include +#else +#include +#endif +#include "../faxgeneric.h" +#include "ps250.h" + +static int set_softcar(); +static void set_hardcar(); + +Trans trans; + +/* + * Open and initialise fax device + */ + +openPsModem(psm) +PsModem *psm; +{ + static struct termios tios; + + if ((psm->fd = open (psm->devName, O_RDWR, 0)) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, + psm->devName, + ("unable to open fax device")); + sprintf(psm->errBuf, + "Unable to open fax device '%s'", + psm->devName); + return NOTOK; + } + + /* initialise line parameters */ +/* (void) ioctl (psm->fd, TIOCEXCL, 0); */ + tios.c_iflag = 0; + tios.c_oflag = 0; + tios.c_cflag = B19200 | CS8 | CREAD | CSTOPB | PARENB | + PARODD | CRTSCTS | HUPCL; + tios.c_lflag = 0; + tios.c_cc[VMIN] = 1; + if (ioctl (psm->fd, TCSETS, &tios) == NOTOK) { + PP_SLOG(LLOG_EXCEPTIONS, psm->devName, + ("ioctl failed")); + (void) close (psm->fd); + sprintf(psm->errBuf, + "Unable to initialise line parameters"); + return NOTOK; + } + sleep(1); + if (psm->softcar == TRUE) + return set_softcar(psm); + return OK; +} + +/* + * Close fax device + */ + +closePsModem (psm) +PsModem *psm; +{ + int val = TIOCM_DSR|TIOCM_DTR; + + if (psm->softcar == TRUE) + set_hardcar(psm); + (void) ioctl (psm->fd, TIOCMBIC, &val); + return close (psm->fd); +} + +/* + * Initial fax device for Xmit + */ + +dialPsModem(psm, telno) +PsModem *psm; +char *telno; +{ + + trans.src_type = FAX_TYPE_MH; + trans.src_addr = FAX_MODE_PC; + trans.dst_type = FAX_TYPE_MH; + trans.param1 = psm->resolution; + trans.param2 = FAX_PARAM2_G3 | FAX_PARAM2_OTI_TOP | + FAX_PARAM2_OTI_BOT | FAX_PARAM2_ECMON; + + if (psm->polled == TRUE) + trans.param2 |= FAX_PARAM2_POLLED; + + if (atoi(telno) == 0 && telno[0] != '+') { + PP_NOTICE(("printing fax locally")); + trans.telno[0] = 0; + trans.dst_addr = FAX_MODE_PRINTER; + } else { + PP_NOTICE(("faxing to %s", + telno)); + strcpy(trans.telno, telno); + trans.dst_addr = FAX_MODE_REMOTE; + } + + trans.remid[0] = 0; + + if (fax_trans_and_check (psm, &trans, FALSE) != OK) + return RP_MECH; + return OK; +} + +/* + * Initial fax device for Listen + */ + +ps_init_listen(psm) +PsModem *psm; +{ + + trans.src_type = FAX_TYPE_MH; + trans.src_addr = (psm->scanner) ? FAX_MODE_SCANNER : FAX_MODE_REMOTE; + trans.dst_type = FAX_TYPE_MH; + trans.dst_addr = FAX_MODE_PC; + trans.param1 = psm->resolution; + trans.param2 = FAX_PARAM2_G3 | FAX_PARAM2_OTI_TOP | + FAX_PARAM2_OTI_BOT | FAX_PARAM2_ECMON; + + if (psm->polled == TRUE) + trans.param2 |= FAX_PARAM2_POLLED; + + trans.telno[0] = 0; + trans.remid[0] = 0; + + if (fax_trans_and_check (psm, &trans, TRUE) != OK) + return RP_MECH; + return OK; +} + +/* + * software carrier detect switching routines + */ + +static int set_softcar (psm) +PsModem *psm; +{ + int softcar; + + if (psm->softcar != TRUE) + return OK; + + if (ioctl (psm->fd, TIOCGSOFTCAR, &softcar) == -1) { + PP_SLOG (LLOG_EXCEPTIONS, psm->devName, + ("ioctl(TIOCGSOFTCAR) failed")); + sprintf(psm->errBuf, + "ioctl(TIOCGSOFTCAR) failed"); + return NOTOK; + } + + if (softcar == 0) { + /* need to switch on softcar */ + softcar = 1; + if (ioctl (psm->fd, TIOCSSOFTCAR, &softcar) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, psm->devName, + ("ioctl(TIOCSSOFTCAR) failed")); + sprintf(psm->errBuf, + "ioctl(TIOCSSOFTCAR) failed"); + return NOTOK; + } + } + return OK; +} + +static void set_hardcar(psm) +PsModem *psm; +{ + int softcar; + + if (psm->softcar != TRUE) + return; + + if (ioctl (psm->fd, TIOCGSOFTCAR, &softcar) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, psm->devName, + ("ioctl(TIOCGSOFTCAR) failed")); + return; + } + + if (softcar == 1) { + /* need to switch off softcar */ + softcar = 0; + if (ioctl (psm->fd, TIOCSSOFTCAR, &softcar) == -1) + PP_SLOG(LLOG_EXCEPTIONS, psm->devName, + ("ioctl(TIOCSSOFTCAR) failed")); + } +} + +/* + * Abort a fax + */ + +abortPsModem (psm) +PsModem *psm; +{ + Stat1 st1; + fax_sendstop(psm->fd); + fax_getstat1(psm->fd, &st1); +} + +/* + * wait for end of transmission + */ + +eomPsModem(psm) +PsModem *psm; +{ + Stat1 st1; + int cont = TRUE; + while (cont == TRUE) { + if (fax_sendenq1(psm->fd) == NOTOK) { + sprintf(psm->errBuf, + "sendenq1 failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + cont = FALSE; + switch (fax_getresp(psm->fd, &st1)) { + case RESP_STAT1: + switch (get_job_info(st1.job_info)) { + case JOB_NORM_END: + break; + case JOB_FAULT_JOB_END: + case JOB_LINE_DISC: + sprintf(psm->errBuf, + "bad termination from fax"); + abortPsModem(psm); + return NOTOK; + case JOB_IN: + cont = TRUE; + break; + default: + sprintf(psm->errBuf, + "unknown termination from fax %o", + st1.job_info); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + default: + break; + } + if (cont == TRUE) + sleep(1); + } + return OK; +} + +/* + * Initialise modem for fax transmission + */ + +static int reinit_fax (fd, trans, src_type, dst_type, param1) +int fd; +Trans *trans; +char src_type; +char dst_type; +int param1; +{ + if (src_type != trans->src_type + || dst_type != trans -> dst_type + || param1 != trans -> param1) { + /* have to change type */ + trans->src_type = src_type; + trans->dst_type = dst_type; + trans -> param1 = param1; + + if (fax_move_and_check(fd, trans) == NOTOK) + return NOTOK; + } + return OK; +} + +psModemG3init (psm) +PsModem *psm; +{ + if (reinit_fax(psm->fd, &trans, + FAX_TYPE_MH, FAX_TYPE_MH, psm->resolution) != OK) { + sprintf(psm->errBuf, + "initialise failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + return OK; +} + +/* + * Initialise modem for ia5 transmission + */ + +psModemIA5init (psm) +PsModem *psm; +{ + if (reinit_fax(psm->fd, &trans, + FAX_TYPE_ASCII, FAX_TYPE_RASTER, + psm->resolution) != OK) { + sprintf(psm->errBuf, + "initialise failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + return OK; +} + +/* + * Send page of bits to fax modem + */ + +extern int num_sent; + +sendPsModem (psm, str, len, last) +PsModem *psm; +char *str; +int len; +int last; +{ + char *ix; + int sendflag, sendlen; + + sendflag = sendlen = num_sent = 0; + ix = str; + while (ix - str < len && sendflag == 0) { + sendlen = ((ix + MAXDATASIZ) > (str + len)) ? + len - (ix - str) : MAXDATASIZ; + if (ix - str + sendlen >= len) { + /* last bit of page */ + if (last) + sendflag = FAX_WRITE_EOF | FAX_WRITE_EOP; + else + sendflag = FAX_WRITE_EOP; + } else + sendflag = 0; + if (fax_write_and_check (psm, ix, + sendlen, sendflag) != OK) { + sprintf(psm->errBuf, + "fax_write_and_check failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + if (sendflag) { + if (last) + PP_LOG(LLOG_NOTICE, + ("EOF (%d sent)", num_sent)); + else + PP_LOG(LLOG_NOTICE, + ("EOP (%d sent)", num_sent)); + } + ix += sendlen; + } + return OK; +} + +/* + * Send file of IA5 to fax modem + */ + +sendPsModemIA5 (psm, fp, last) +PsModem *psm; +FILE *fp; +int last; +{ + int n, numLines, LinesPerA4 = 24*3; + char buf[250]; + + numLines = 0; + + while (fgets (buf, sizeof(buf), fp) != NULLCP) { + if (feof(fp)) + break; + n = strlen(buf); + if (n < sizeof(buf)) { + buf[n++] = '\r'; + if (n < sizeof(buf)) + buf[n++] = '\0'; + n = strlen(buf); + } + if (fax_write_and_check (psm, buf, n, + (++numLines == LinesPerA4) ? FAX_WRITE_EOP : 0) != OK) { + sprintf(psm->errBuf, + "fax_write_and_check failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + if (numLines == LinesPerA4) numLines = 0; + } + /* fillout last page */ + n = 0; + while (numLines++ < LinesPerA4) { + buf[n++] = '\n'; + buf[n++] = '\r'; + } + if (n == 0) + buf[n++] = ' '; + buf[n] = '\0'; + if (fax_write_and_check (psm, buf, n, + (last) ? (FAX_WRITE_EOP | FAX_WRITE_EOF) : FAX_WRITE_EOP) != OK) { + sprintf(psm->errBuf, + "fax_write_and_check failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + return OK; +} + +/* */ + +/* loop waiting for inbound fax */ +ps_wait_for_fax (psm) +PsModem *psm; +{ + Stat1 st1; + int cont = TRUE; + + do { + if (fax_sendenq1(psm->fd) == NOTOK) { + sprintf(psm->errBuf, + "sendenq1 failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + + if (fax_getresp (psm->fd, &st1) == NOTOK) { + sprintf(psm->errBuf, + "bad response from fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + + if (st1.ring_in == RING_IN) { + psm->scanner = FALSE; + cont = FALSE; + } else if ((st1.scan_stat & SCAN_DOC_SCAN) == SCAN_DOC_SCAN) { + psm->scanner = TRUE; + cont = FALSE; + } + + if (cont == TRUE) + sleep(1); + } while (cont == TRUE); + return OK; +} + +/* */ + +/* loop waiting for inbound data */ +ps_wait_for_data (psm) +PsModem *psm; +{ + Stat1 st1; + + if (fax_getresp (psm->fd, &st1) == NOTOK) { + sprintf(psm->errBuf, + "bad response from fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + + while (get_job_info(st1.job_info) != JOB_DATA_AVAIL) { + sleep (1); + + if (fax_sendenq1(psm->fd) == NOTOK) { + sprintf(psm->errBuf, + "sendenq1 failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + + + if (fax_getresp (psm->fd, &st1) == NOTOK) { + sprintf(psm->errBuf, + "bad response from fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + return NOTOK; + } + } + + return OK; +} + +/* */ +/* receive data from fax */ + +rcvPsModem(psm, pg3fax) +PsModem *psm; +struct type_IOB_G3FacsimileBodyPart **pg3fax; +{ + struct type_IOB_G3FacsimileBodyPart *ret = (struct type_IOB_G3FacsimileBodyPart *) + calloc (1, sizeof (struct type_IOB_G3FacsimileBodyPart)); + struct type_IOB_G3FacsimileData *ix, *t = NULL; + int retval, last; + + ret -> parameters = (struct type_IOB_G3FacsimileParameters *) + calloc(1, sizeof(struct type_IOB_G3FacsimileParameters)); + ret -> parameters -> optionals = + opt_IOB_G3FacsimileParameters_number__of__pages; + + do { + if ((retval = rcvPsPage(psm, &ix, &last)) != OK) + return retval; + if (ret->data == NULL) + ret -> data = t = ix; + else { + t -> next = ix; + t = ix; + } + ret -> parameters -> number__of__pages++; + } while (last != TRUE); + *pg3fax = ret; + return retval; +} + +/* */ +/* receive page from fax */ + +static void add_to_strb(pstr, ptotal, plus, len) +char **pstr; +int *ptotal; +char *plus; +int len; +{ + char *ret; + + if (*pstr == NULLCP) + ret = malloc(len * sizeof(char)); + else + ret = realloc(*pstr, (len+(*ptotal)) * sizeof(char)); + + bcopy (plus, (ret + (*ptotal)), len); + *ptotal += len; + *pstr = ret; +} + +rcvPsPage(psm, pdata, plast) +PsModem *psm; +struct type_IOB_G3FacsimileData **pdata; +int *plast; +{ + Stat1 st1; + Data data; + int cont, total; + char *str = NULLCP; + + *pdata = (struct type_IOB_G3FacsimileData *) NULL; + *plast = FALSE; + cont = TRUE; + total = 0; + + do { + if (fax_read_and_check(psm, &data) == NOTOK) + return NOTOK; + reverse_strb(data.data, data.datalen); + add_to_strb(&str, &total, data.data, data.datalen); + if (data.docEnd) + *plast = TRUE; + if (data.pageEnd) + cont = FALSE; + if (cont == TRUE) { + if (fax_sendenq1(psm->fd) == NOTOK) { + sprintf(psm->errBuf, + "sendenq1 failed"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + if (str != NULLCP) free(str); + return NOTOK; + } + if (fax_getresp (psm->fd, &st1) == NOTOK) { + sprintf(psm->errBuf, + "Bad response from fax"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + if (str != NULLCP) free(str); + return NOTOK; + } + if (get_job_info(st1.job_info) != JOB_DATA_AVAIL) { + sprintf(psm->errBuf, + "No data waiting to be read"); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", psm->errBuf)); + if (str != NULLCP) free(str); + return NOTOK; + } + } + } while (cont == TRUE); + + if (str != NULLCP) { + *pdata = (struct type_IOB_G3FacsimileData *) + malloc(sizeof(struct type_IOB_G3FacsimileData)); + (*pdata) -> element_IOB_0 = + strb2bitstr (str, (total * BITSPERBYTE), + PE_CLASS_UNIV, + PE_PRIM_BITS); + (*pdata) -> next = NULL; + free (str); + } + return OK; +} diff --git a/Chans/fax/ps250/tools/Makefile b/Chans/fax/ps250/tools/Makefile new file mode 100644 index 0000000..ddf7a39 --- /dev/null +++ b/Chans/fax/ps250/tools/Makefile @@ -0,0 +1,95 @@ +# Fax Tools Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/Makefile,v 6.0 1991/12/18 20:08:25 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:08:25 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +PPBETA = ../../../.. + +PS250OBJS = ../error_codes.o ../ps250_basic.o ../ps250_intf.o \ + ../ps250_manage.o ../ps250_stat.o ../ps250_trans.o ../ps250_util.o + +HEADERS = $(PPBETA)/h +LIBPP = $(PPBETA)/Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) $(PEPSYHEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = $(PPBETA)/Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xfax_print xfaxid xfaxenq1 xfaxsetid + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# Fax Print +# +############################################################ + +xfax_print: fax_print.o $(PS250OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ \ + fax_print.o $(PS250OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Fax ID +# +############################################################ + +xfaxid: faxid.o $(LIBPP) $(PS250OBJS) + $(CC) $(LDFLAGS) -o $@ faxid.o $(PS250OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Fax enq1 +# +############################################################ + +xfaxenq1: faxenq1.o $(LIBPP) $(PS250OBJS) + $(CC) $(LDFLAGS) -o $@ faxenq1.o $(PS250OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Fax set id +# +############################################################ + +xfaxsetid: setid.o $(LIBPP) $(PS250OBJS) + $(CC) $(LDFLAGS) -o $@ setid.o $(PS250OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc +# +############################################################ + +clean: tidy + rm -f $(PROGS) + +tidy: + rm -f *.o core a.out Makefile.old + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Chans/fax/ps250/tools/fax_print.c b/Chans/fax/ps250/tools/fax_print.c new file mode 100644 index 0000000..b7e8371 --- /dev/null +++ b/Chans/fax/ps250/tools/fax_print.c @@ -0,0 +1,480 @@ +/* fax_print.c: print given file of p2 or ia5 on fax printer */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/fax_print.c,v 6.0 1991/12/18 20:08:25 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/fax_print.c,v 6.0 1991/12/18 20:08:25 jpo Rel $ + * + * $Log: fax_print.c,v $ + * Revision 6.0 1991/12/18 20:08:25 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "chan.h" +#include +#include "../../faxgeneric.h" +#include "../ps250.h" +#include +#include +#include "retcode.h" +#include "IOB-types.h" + +#define OPT_P2 1 +#define OPT_IA5 2 +#define OPT_FAX 3 +#define OPT_FILE 4 +#define OPT_SOFTCAR 5 +#define OPT_RES_7_7 6 +#define OPT_RES_3_85 7 +#define OPT_RES_15_4 8 + +CMD_TABLE tbl_options [] = { /* rfc822norm commandline options */ + "-p2", OPT_P2, + "-ia5", OPT_IA5, + "-fax", OPT_FAX, + "-file",OPT_FILE, + "-softcar", OPT_SOFTCAR, + "-3.85", OPT_RES_3_85, + "-7.7", OPT_RES_7_7, + "-15.4", OPT_RES_15_4, + 0, -1 + }; + +int isP2 = TRUE; +char *file = NULLCP; +int res; + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + +#define ps_advise(ps, f) \ + advise (LLOG_EXCEPTIONS, NULLCP, "%s: %s",\ + (f), ps_error ((ps) -> ps_errno)) + +extern FaxCtlr *init_faxctrlr(); +extern int fax_debug; +CHAN *mychan = NULLCHAN; +int table_verified = FALSE; + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp; + FaxCtlr *faxctl = init_faxctrlr(); + PsModem *psm = PSM(faxctl); + + sys_init (argv[0]); + *argv++; + while (*argv != NULL) { + switch (cmd_srch(*argv, tbl_options)) { + case OPT_P2: + isP2 = TRUE; + break; + case OPT_IA5: + isP2 = FALSE; + break; + case OPT_FAX: + if (*(argv+1) == NULLCP) { + fprintf(stderr, + "no fax device given with flag '%s'\n",*argv); + exit(1); + } + argv++; + sprintf(psm->devName, "%s", *argv); + break; + + case OPT_FILE: + if (*(argv+1) == NULLCP) { + fprintf(stderr, + "no file given with flag '%s'\n",*argv); + exit(1); + } + argv++; + file = *argv; + break; + + case OPT_SOFTCAR: + psm->softcar = TRUE; + break; + + case OPT_RES_3_85: + res = RES_3_85; + break; + + case OPT_RES_7_7: + res = RES_7_7; + break; + + case OPT_RES_15_4: + res = RES_15_4; + break; + + default: + fprintf(stderr, + "unknown option '%s'\n", *argv); + exit(1); + } + argv++; + } + + if (file != NULLCP) { + if (isP2 + && (fp = fopen (file, "r")) == (FILE *)0) { + fprintf(stderr, + "Can't open file '%s'\n", file); + exit(1); + } + } else + fp = stdin; + + + if (faxctl->open != NULLIFP + && (*faxctl->open) (faxctl) != OK) { + fprintf(stderr, + "fax open failed [%s]\n", + faxctl->errBuf); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + + sprintf (faxctl -> telno, "0"); + + if (faxctl->initXmit != NULLIFP + && rp_isbad((*faxctl->initXmit)(faxctl))) { + if (faxctl -> abort != NULLIFP) + (*faxctl->abort) (faxctl); + fprintf(stderr, + "unable to initialise fax device for printing [%s]\n", + faxctl->errBuf); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + + if (isP2) + print_P2(faxctl, fp); + else + print_ia5(faxctl, file); + + if (faxctl->close != NULLIFP) + (*faxctl->close) (faxctl); + + if (file != NULLCP) fclose(fp); + +} + +/* */ + +print_P2 (faxctl, fp) +FaxCtlr *faxctl; +FILE *fp; +{ + register PE pe = NULLPE; + register PS psin; + struct type_IOB_G3FacsimileBodyPart *g3fax = NULL; + + if ((psin = ps_alloc (std_open)) == NULLPS) + { + ps_advise (psin, "ps_alloc"); + if (faxctl -> abort != NULLIFP) + (*faxctl->abort) (faxctl); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + + if (std_setup (psin, fp) == NOTOK) + { + ps_free (psin); + advise (LLOG_EXCEPTIONS, NULLCP, "%s: std_setup loses", file); + if (faxctl -> abort != NULLIFP) + (*faxctl->abort) (faxctl); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + + if (do_decode_fax(psin, &g3fax) == NOTOK) { + fprintf(stderr, + "failed to decode G3FacsimileBodyPart\n"); + ps_done(psin, "ps2pe"); + if (faxctl -> abort != NULLIFP) + (*faxctl->abort) (faxctl); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + + if (g3fax->parameters + && faxctl->setG3Params != NULLIFP + && (*faxctl->setG3Params)(faxctl, g3fax->parameters) != OK) { + fprintf(stderr, + "setG3Params failed [%s]", faxctl->errBuf); + return RP_MECH; + } + + + if (fax_bitstrings (faxctl, g3fax, TRUE) != OK) { + fprintf(stderr, + "Failed to fax bitstrings\n"); + + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } + if (pe != NULLPE) + pe_free (pe); +} + +/* + * send each page of g3fax to fax machine + */ + +static int fax_bitstrings (faxctl, g3fax, last) +FaxCtlr *faxctl; +struct type_IOB_G3FacsimileBodyPart *g3fax; +int last; +{ + struct type_IOB_G3FacsimileData *ix; + int retval; + + for (ix = g3fax -> data; ix != NULL; ix = ix -> next) { + int len; + char *str; + + if ((str = bitstr2strb (ix -> element_IOB_0, &len)) == NULLCP) { + fprintf(stderr,"empty page"); + return NOTOK; + } + len = (len + BITSPERBYTE -1)/BITSPERBYTE; + + retval = faxctl->sendPage(faxctl, str, len, + (last && ix -> next == NULL)); + free (str); + if (retval != OK) + return retval; + } + return OK; +} + +print_ia5 (faxctl, file) +FaxCtlr *faxctl; +char *file; +{ + if (faxctl->setIA5Params != NULLIFP + && (*faxctl->setIA5Params) (faxctl) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("setIA5Params failed [%s]", + faxctl->errBuf)); + return RP_MECH; + } + + if ((*faxctl->sendIA5File)(faxctl, file, TRUE) != OK) { + if (faxctl -> abort != NULLIFP) + (*faxctl->abort) (faxctl); + fprintf(stderr, + "sendIA5File failed [%s]", + faxctl->errBuf); + if (faxctl->close != NULLIFP) + (*faxctl->close)(faxctl); + exit(1); + } +} + + +/* + * decode from PE to C struct + */ +extern PE ps2pe_aux (); + +static int do_decode_fax (psin, pfax) +register PS psin; +struct type_IOB_G3FacsimileBodyPart **pfax; +{ + struct type_IOB_G3FacsimileData *new, *tail = NULL; + int pages; + register PE pe = NULLPE; + + /* get first chunk */ + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + ps_done (psin, "ps2pe_aux"); + return NOTOK; + } + + if ((PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_UNIV, PE_CONS_SEQ)) + && (PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_CONT, (PElementID) 0x03))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected sequence")); + return NOTOK; + } + + pe_free (pe); + + *pfax = (struct type_IOB_G3FacsimileBodyPart *) calloc (1, + sizeof (struct type_IOB_G3FacsimileBodyPart)); + + /* get and decode parameters */ + if ((pe = ps2pe (psin)) == NULLPE) { /* EOF or error? */ + ps_done (psin, "ps2pe"); + return NOTOK; + } + PY_pepy[0] = 0; + + if (decode_IOB_G3FacsimileParameters(pe, 1, + NULLIP, NULLVP, + &((*pfax) -> parameters)) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_G3FacsimileParameters failure [%s]", + PY_pepy)); + pe_done(pe, "Parse failure IOB_G3FacsimileParameters"); + return NOTOK; + } + + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("parse_IOB_G3FacsimileParameters non fatal failure [%s]", + PY_pepy)); + + pe_free (pe); + + /* get next chunk */ + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + ps_done (psin, "ps2pe_aux"); + return NOTOK; + } + + if (PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_UNIV, PE_CONS_SEQ)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected sequence")); + return NOTOK; + } + + pe_free (pe); + + pages = 0; + while ((pe = ps2pe (psin)) != NULLPE) { + switch (PE_ID(pe -> pe_class, pe -> pe_id)) { + case PE_ID (PE_CLASS_UNIV, PE_PRIM_BITS): + break; + case PE_ID (PE_CLASS_UNIV, PE_UNIV_EOC) : + pe_free(pe); + continue; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected pe in G3FacsimileBodyPart: expected bitstring")); + return NOTOK; + } + new = (struct type_IOB_G3FacsimileData *) (calloc (1, + sizeof(struct type_IOB_G3FacsimileData))); + new -> element_IOB_0 = prim2bit(pe); + if ( (*pfax) -> data == NULL) + (*pfax) -> data = tail = new; + else { + tail -> next = new; + tail = tail -> next; + } + pages++; + } + + if ((*pfax) -> parameters -> optionals == opt_IOB_G3FacsimileParameters_number__of__pages + && (*pfax) -> parameters -> number__of__pages != pages) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect number of pages in G3FacsimileBodyPart: expected %d, got %d", + (*pfax) -> parameters -> number__of__pages, pages)); + return NOTOK; + } + return OK; +} + +/* + * various isode-like routines + */ + +/* pe_done: utility routine to do the right thing for pe errors */ +int pe_done (pe, msg) +PE pe; +char *msg; +{ + if (pe->pe_errno) + { + PP_OPER(NULLCP, + ("%s: [%s] %s",msg,PY_pepy,pe_error(pe->pe_errno))); + pe_free (pe); + return NOTOK; + } + else + { + pe_free (pe); + return OK; + } +} + +/* ps_done: like pe_done */ +int ps_done (ps, msg) +PS ps; +char *msg; +{ + ps_advise (ps, msg); + ps_free (ps); + return NOTOK; +} + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + diff --git a/Chans/fax/ps250/tools/faxenq1.c b/Chans/fax/ps250/tools/faxenq1.c new file mode 100644 index 0000000..51280a5 --- /dev/null +++ b/Chans/fax/ps250/tools/faxenq1.c @@ -0,0 +1,171 @@ +/* faxenq1.c: send an enquire 1 to Panasonic */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/faxenq1.c,v 6.0 1991/12/18 20:08:25 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/faxenq1.c,v 6.0 1991/12/18 20:08:25 jpo Rel $ + * + * $Log: faxenq1.c,v $ + * Revision 6.0 1991/12/18 20:08:25 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "chan.h" +#include +#include "../../faxgeneric.h" +#include "../ps250.h" +#include + +void adios (), advise (); + +char *myname; +static char *localid = 0; + +extern FaxCtlr *init_faxctrlr(); +extern int fax_debug; +CHAN *mychan = NULLCHAN; +int table_verified = FALSE; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + FaxCtlr *faxctl = init_faxctrlr(); + PsModem *psm = PSM(faxctl); + + myname = argv[0]; + while((opt = getopt(argc, argv, "sdf:l:")) != EOF) + switch (opt) { + case 'd': + fax_debug = 1; + break; + case 's': + psm->softcar = TRUE; + break; + case 'f': + sprintf(psm->devName, "%s", optarg); + break; + default: + adios (NULLCP, "Usage: %s [-s] [-d] [-f device]", myname); + break; + } + argc -= optind; + argv += optind; + + enq1 (faxctl); + exit (0); +} + +enq1 (faxctl) +FaxCtlr *faxctl; +{ + Stat1 stat1; + Stat2 s2; + int fd; + time_t now; + PsModem *psm = PSM(faxctl); + + if (faxctl->open != NULLIFP + && (*faxctl->open) (faxctl) != OK) { + fprintf(stderr, + "fax open failed [%s]\n", + faxctl->errBuf); + exit(1); + } + + if (fax_sendenq1 (psm->fd) == NOTOK) + adios (NULLCP, "enq1 failed"); + + if (fax_getstat1 (psm->fd, &stat1) == NOTOK) + adios ("fax_getstat1", "failed"); + fax_pstat1 (&stat1); + + if (fax_sendenq2 (psm->fd) == NOTOK) + adios ("send enq2", "failed"); + + if (fax_getstat2 (psm->fd, &s2) == NOTOK) + adios ("read packet", "failed"); + + if (faxctl->close != NULLIFP) + (*faxctl->close) (faxctl); + + printf ("Fax clock: %s\n", s2.clock); + printf ("Fax local ID: %s\n", s2.local); +} + + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Chans/fax/ps250/tools/faxid.c b/Chans/fax/ps250/tools/faxid.c new file mode 100644 index 0000000..12cf726 --- /dev/null +++ b/Chans/fax/ps250/tools/faxid.c @@ -0,0 +1,162 @@ +/* faxid.c: get id from Panasonic */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/faxid.c,v 6.0 1991/12/18 20:08:25 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/faxid.c,v 6.0 1991/12/18 20:08:25 jpo Rel $ + * + * $Log: faxid.c,v $ + * Revision 6.0 1991/12/18 20:08:25 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "chan.h" +#include +#include "../../faxgeneric.h" +#include "../ps250.h" +#include + +void adios (), advise (); + +char *myname; + +extern FaxCtlr *init_faxctrlr(); +extern int fax_debug; +CHAN *mychan = NULLCHAN; +int table_verified = FALSE; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + FaxCtlr *faxctl = init_faxctrlr(); + PsModem *psm = PSM(faxctl); + + myname = argv[0]; + while((opt = getopt(argc, argv, "sdf:")) != EOF) + switch (opt) { + case 'd': + fax_debug = 1; + break; + case 'f': + sprintf(psm->devName, "%s", optarg); + break; + case 's': + psm->softcar = TRUE; + break; + default: + adios (NULLCP, "Usage: %s [-s] [-d] [-f device]", myname); + break; + } + argc -= optind; + argv += optind; + + test1(faxctl); + exit (0); +} + +test1(faxctrl) +FaxCtlr *faxctrl; +{ + PsModem *psm = PSM(faxctrl); + Faxcomm pack; + Stat2 s2; + int fd; + + if (faxctrl->open != NULLIFP + && (*faxctrl->open) (faxctrl) != OK) { + fprintf(stderr, + "fax open failed [%s]\n", + faxctrl->errBuf); + exit(1); + } + + if (fax_sendenq2 (psm->fd) == NOTOK) + adios ("send enq2", "failed"); + + if (fax_getstat2 (psm->fd, &s2) == NOTOK) + adios ("read packet", "failed"); + + if (faxctrl->close != NULLIFP) + (*faxctrl->close) (faxctrl); + + printf ("Fax clock: %s\n", s2.clock); + printf ("Fax local ID: %s\n", s2.local); +} + + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Chans/fax/ps250/tools/make b/Chans/fax/ps250/tools/make new file mode 100755 index 0000000..b6ce556 --- /dev/null +++ b/Chans/fax/ps250/tools/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/fax/ps250/tools/setid.c b/Chans/fax/ps250/tools/setid.c new file mode 100644 index 0000000..52bf012 --- /dev/null +++ b/Chans/fax/ps250/tools/setid.c @@ -0,0 +1,185 @@ +/* setid.c: set user id on Panasonic */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/setid.c,v 6.0 1991/12/18 20:08:25 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/fax/ps250/tools/RCS/setid.c,v 6.0 1991/12/18 20:08:25 jpo Rel $ + * + * $Log: setid.c,v $ + * Revision 6.0 1991/12/18 20:08:25 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "chan.h" +#include +#include "../../faxgeneric.h" +#include "../ps250.h" +#include +#include + +void adios (), advise (); + +char *myname; +static char *localid = 0; + +extern FaxCtlr *init_faxctrlr(); +extern int fax_debug; +CHAN *mychan = NULLCHAN; +int table_verified = FALSE; + + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + FaxCtlr *faxctl = init_faxctrlr(); + PsModem *psm = PSM(faxctl); + + myname = argv[0]; + while((opt = getopt(argc, argv, "sdf:l:")) != EOF) + switch (opt) { + case 'd': + fax_debug = 1; + break; + case 's': + psm->softcar = TRUE; + break; + case 'f': + sprintf(psm->devName, "%s", optarg); + break; + case 'l': + localid = optarg; + break; + default: + adios (NULLCP, "Usage: %s [-s] [-d] [-f device] [-l localid]", myname); + break; + } + argc -= optind; + argv += optind; + + setid (faxctl); + exit (0); +} + +setid (faxctl) +FaxCtlr *faxctl; +{ + Idset id; + Stat1 stat1; + Stat2 s2; + int fd; + time_t now; + PsModem *psm = PSM(faxctl); + + if (faxctl->open != NULLIFP + && (*faxctl->open) (faxctl) != OK) { + fprintf(stderr, + "fax open failed ['%s']", + faxctl->errBuf); + exit(1); + } + + (void) time (&now); + timet2fax (now, id.clock); + if (localid) + (void) sprintf (id.local, "%20s", localid); + else + id.local[0] = 0; + + if (fax_idset (psm->fd, &id) == NOTOK) + adios ("fax_idset", "failed"); + + if (fax_getstat1 (psm->fd, &stat1) == NOTOK) + adios ("fax_getstat1", "failed"); +/* fax_pstat1 (&stat1);*/ + + if (fax_sendenq2 (psm->fd) == NOTOK) + adios ("send enq2", "failed"); + + if (fax_getstat2 (psm->fd, &s2) == NOTOK) + adios ("read packet", "failed"); + + printf ("Fax clock: %s\n", s2.clock); + printf ("Fax local ID: %s\n", s2.local); + + if (faxctl->close != NULLIFP) + (*faxctl->close) (faxctl); + +} + + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Chans/filtercontrol/Makefile b/Chans/filtercontrol/Makefile new file mode 100644 index 0000000..1723a01 --- /dev/null +++ b/Chans/filtercontrol/Makefile @@ -0,0 +1,150 @@ +# Makefile for filter control channel - ros version +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/filtercontrol/RCS/Makefile,v 6.0 1991/12/18 20:10:08 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:10:08 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = filtercont.c +OBJS = filtercont.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) #-DDBG_CHAN +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -u $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xfilter + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# Filter control +# +############################################################ + +xfilter: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj:$(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + +install: inst-dir inst-fcontrol inst-removebp + +inst-fcontrol: $(CHANDIR)/fcontrol +$(CHANDIR)/fcontrol: xfilter + -$(BACKUP) $@ zxfilter + rm -f $@ + $(INSTALL) xfilter $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "fcontrol channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +inst-removebp: $(FORMDIR)/removebp +$(FORMDIR)/removebp: removebp.sh + -$(BACKUP) $@ zxremovebp + rm -f $@ + $(INSTALL) removebp.sh $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "removebp script installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old zxfilter $(PROGS) *.BAK + + +lint: l-filter + +l-filter: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +filtercont.o: filtercont.c +filtercont.o: ../../h/util.h +filtercont.o: ../../h/config.h +filtercont.o: ../../h/ll_log.h +filtercont.o: ../../h/retcode.h +filtercont.o: ../../h/expand.h +filtercont.o: ../../h/qmgr.h +filtercont.o: ../../h/Qmgr-types.h +filtercont.o: ../../h/Qmgr-ops.h +filtercont.o: ../../h/q.h +filtercont.o: ../../h/adr.h +filtercont.o: ../../h/list_rchan.h +filtercont.o: ../../h/chan.h +filtercont.o: ../../h/table.h +filtercont.o: ../../h/list_bpt.h +filtercont.o: ../../h/auth.h +filtercont.o: ../../h/list_bpt.h +filtercont.o: ../../h/extension.h +filtercont.o: ../../h/mta.h +filtercont.o: ../../h/adr.h +filtercont.o: ../../h/list_bpt.h +filtercont.o: ../../h/aparse.h +filtercont.o: ../../h/ap.h +filtercont.o: ../../h/util.h +filtercont.o: ../../h/or.h +filtercont.o: ../../h/chan.h +filtercont.o: ../../h/auth.h +filtercont.o: ../../h/list_rchan.h +filtercont.o: ../../h/mta.h +filtercont.o: ../../h/prm.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/filtercontrol/filtercont.c b/Chans/filtercontrol/filtercont.c new file mode 100644 index 0000000..1d6764c --- /dev/null +++ b/Chans/filtercontrol/filtercont.c @@ -0,0 +1,703 @@ +/* filtercont.c: filter control channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/filtercontrol/RCS/filtercont.c,v 6.0 1991/12/18 20:10:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/filtercontrol/RCS/filtercont.c,v 6.0 1991/12/18 20:10:08 jpo Rel $ + * + * $Log: filtercont.c,v $ + * Revision 6.0 1991/12/18 20:10:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include "expand.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include +#include +#include +#include +#include + +extern char *quedfldir; +extern char *formdfldir; +extern char *logdfldir; +extern CHAN *ch_nm2struct(); +extern char *expand_dyn (); +extern void err_abrt(), rd_end(), sys_init(), arg2vstr(); +extern int errno; +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; +char *none_str = "none", *yes_str = "yes", *no_str = "no"; + +static struct type_Qmgr_DeliveryStatus *process (); +static int processMsg (); +static int doFormat (); +static int is_mychan_file (); +static int in_BPT (); +static int file_create (); +static int do_child_logging (); +static int file_link (); +static int initialise (); +static int security_check (); +static void dirinit (); +static ADDR *getnthrecip (); +int first_failureDR; +int value; +char *error, buf[BUFSIZ]; + +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process, NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, ("Chan/filtercont : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + (void) signal (SIGCHLD, SIG_DFL); + /* check if a filter channel */ + if (name != NULL) free(name); + return OK; +} + +/* */ +/* routine to check if allowed to filter this message through this channel */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/fcontrol channel err: '%s'",msg_chan)); + result = FALSE; + } + + /* free all storage used */ + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to do filter */ + +Expand expand_macros[] = { + "sender", NULLCP, + "822sender", NULLCP, + "400sender", NULLCP, + "qid", NULLCP, + "ua-id", NULLCP, + "p1-id", NULLCP, + "recip", NULLCP, + "822recip", NULLCP, + "400recip", NULLCP, + "outtable", NULLCP, + "outmta", NULLCP, + "confirm", NULLCP, + "intable", NULLCP, + NULLCP, NULLCP}; + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + struct type_Qmgr_UserList *ix; + ADDR *adr; + + bzero((char *) &que,sizeof(que)); + bzero((char *) &prm,sizeof(prm)); + + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + first_failureDR = TRUE; + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_NOTICE, + ("%s formatting msg '%s'",mychan->ch_name,this_msg)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s rd_msg err: '%s'",mychan->ch_name,this_msg)); + rd_end(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "Can't read message"); + } + + expand_macros[0].expansion = que.Oaddress->ad_value; + expand_macros[1].expansion = que.Oaddress->ad_r822adr; + expand_macros[2].expansion = que.Oaddress->ad_r400adr; + expand_macros[3].expansion = this_msg; + expand_macros[4].expansion = que.ua_id; + expand_macros[5].expansion = que.msgid.mpduid_string; + if (mychan->ch_table != NULLTBL) + expand_macros[9].expansion = mychan->ch_table->tb_name; + else + expand_macros[9].expansion = none_str; + + expand_macros[11].expansion = no_str; + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip(&que, ix->RecipientId->parm)) != NULL + && adr -> ad_usrreq == AD_USR_CONFIRM) { + expand_macros[11].expansion = yes_str; + break; + } + } + if (mychan->ch_in_table != NULLTBL) + expand_macros[12].expansion = mychan->ch_in_table->tb_name; + else + expand_macros[12].expansion = none_str; + + + if (arg->users == NULL) + PP_LOG(LLOG_NOTICE, + ("%s : passed a NULL user list for message '%s'", + mychan->ch_name, + this_msg)); + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + error = NULLCP; + if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s : failed to find recipient %d of msg '%s'",mychan->ch_name,ix->RecipientId->parm, this_msg)); + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch(chan_acheck (adr, mychan, 1, (char **)NULL)) { + case OK: + expand_macros[6].expansion = adr -> ad_value; + expand_macros[7].expansion = adr -> ad_r822adr; + expand_macros[8].expansion = adr -> ad_r400adr; + if (adr -> ad_outchan + && adr -> ad_outchan -> li_mta) + expand_macros[10].expansion = adr -> ad_outchan -> li_mta; + else + expand_macros[10].expansion = none_str; + + value = int_Qmgr_status_messageFailure; + if (processMsg(this_msg,adr) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s : failed to process msg '%s' for recip '%d' on channel '%s'",mychan->ch_name,this_msg, adr->ad_no, this_chan)); + delivery_setstate(adr->ad_no, + value, + (error == NULLCP) ? "Problems with filtering" : error); + } else { + /* CHANGE update adr->ad_rcnt in struct and in file */ + PP_LOG(LLOG_NOTICE, + ("%s : processed '%s' for recipient %d",mychan->ch_name,this_msg,adr->ad_no)); + adr->ad_rcnt++; + wr_ad_rcntno(adr,adr->ad_rcnt); + delivery_set(adr->ad_no,int_Qmgr_status_success); + } + break; + default: + break; + } + if (error != NULLCP) + free(error); + } + rd_end(); + q_free(&que); + prm_free(&prm); + return deliverystate; +} + +/* */ +static int processMsg (msg,recip) +/* returns OK if managed to process msg for recip on mychan */ +char *msg; +ADDR *recip; +{ + char *origdir = NULL, + *newdir = NULL; + int result = OK; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s original directory not found for recipient %d of message '%s'",mychan->ch_name,recip->ad_no, msg)); + error = strdup("Unable to find original directory"); + result = NOTOK; + } + + /* temp change so as to get new directory name */ + recip->ad_rcnt++; + if (result == OK) { + LIST_RCHAN *lix; + int count; + for (lix = recip->ad_fmtchan, count = 0; + lix != NULLIST_RCHAN; + lix = lix->li_next,count++) + continue; + if (count < recip->ad_rcnt) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s ran out of reformatter channels !")); + error = strdup("Ran out of reformatter channels !"); + result = NOTOK; + } + } + if ((result == OK) + && (qid2dir(msg, recip, FALSE, &newdir) != OK)) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s couldn't construct new directory for recipient '%d' of message '%s'",mychan->ch_name,recip->ad_no, msg)); + error = strdup ("Unable to construct new directory"); + result = NOTOK; + } + recip->ad_rcnt--; + + if ((result == OK) + && (stat(newdir, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory already exists and so reformatting already done */ + PP_LOG(LLOG_NOTICE, + ("%s : work already done for recipient %d of message '%s'",mychan->ch_name,recip->ad_no, msg)); + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + + if ((result == OK) && (doFormat(origdir,newdir,msg) != OK)) + result = NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return result; +} + +/* */ +static int doFormat (orig, new, msg) +/* reformats orig directory contents to new directory through mychan */ +char *orig, /* original directory */ + *new, /* new directory */ + *msg; /* message */ +{ + char tmpdir[MAXPATHLENGTH], + newfile[MAXPATHLENGTH], + *stripped_file, + *origfile, + *subdir, + file[MAXPATHLENGTH]; + int result = OK; + struct stat statbuf; + (void) sprintf(tmpdir, "%s/tmp.%s", + msg, mychan->ch_name); + + if (stat(tmpdir, &statbuf) == OK) { + (void) recrm (tmpdir); + if (rmdir (tmpdir) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, tmpdir, + (error = strdup("can't remove directory"))); + result = NOTOK; + } + } + + if (result == OK && mkdir(tmpdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, tmpdir, + ("Can't make directory")); + if (errno == ENOSPC) + value = int_Qmgr_status_mtaFailure; + (void) sprintf (buf, + "Unable to make temporary directory '%s'", + tmpdir); + error = strdup(buf); + result = NOTOK; + } + + if (result == OK) { + msg_rinit(orig); + if (msg_rfile(file) != RP_OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s empty or non exsistant dir %s",mychan->ch_name,orig)); + (void) sprintf (buf, + "Original directory '%s' is empty", + orig); + error = strdup (buf); + result = NOTOK; + } else { + do { + stripped_file = file + strlen(orig) + 1; + (void) sprintf(newfile,"%s/%s",tmpdir, stripped_file); + stripped_file = newfile + strlen(tmpdir) +1; + /* stripped file now local to tmpdir */ + origfile = rindex(file,'/'); + *origfile = '\0'; + while ((result == OK) + && ((subdir = index(stripped_file,'/')) != NULL)){ + /* check intervening directories */ + *subdir = '\0'; + if (!((stat(newfile, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR))) { + /* sub dir not there so mkdir */ + if (mkdir(newfile, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, + newfile, + ("Can't make directory")); + (void) sprintf (buf, + "Failed to make directory '%s'", + newfile); + error = strdup(buf); + result = NOTOK; + } else + PP_TRACE(("%s : made directory %s",mychan->ch_name,newfile)); + + } + *subdir = '/'; + stripped_file = subdir+1; + } + if ( result == OK) { + + subdir = rindex(newfile,'/'); + *subdir = '\0'; + if (is_mychan_file(stripped_file) == TRUE) + result = file_create(file,newfile,stripped_file); + else + result = file_link(file,newfile,stripped_file); + *subdir = '/'; + } + *origfile = '/'; + } while ((result == OK) && (msg_rfile(file) == RP_OK)) ; + + } + msg_rend(); + + if ((result == OK) && (rename(tmpdir, new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Can't rename directory '%s' to '%s'", + tmpdir, new)); + (void) sprintf (buf, + "Failed to rename %s to %s", + tmpdir, new); + error = strdup (buf); + result = NOTOK; + } + } + + return result; +} + +static int is_mychan_file(name) +char *name; +{ + char *suffix; + if (in_BPT(name, mychan->ch_hdr_in) == TRUE) + return TRUE; + if ((suffix = index(name,'.')) == NULL) + return FALSE; + return in_BPT(++suffix,mychan->ch_bpt_in); +} + +static int in_BPT(suffix, list) +char *suffix; +LIST_BPT *list; +{ + LIST_BPT *ix = list; + + while ((ix != NULL) + && (strcmp(suffix,ix->li_name) != 0)) + ix = ix->li_next; + return (ix == NULL) ? FALSE : TRUE; +} + +/* */ +static int file_create (orig, tmp, file) +char *orig, /* original message directory */ + *tmp, /* where to put new file */ + *file; /* file to format */ +{ + char filein[MAXPATHLENGTH], /* input file */ + fileout[MAXPATHLENGTH], /* output file */ + *name = NULL, /* base name of file */ + *program = NULL, /* full name of exec'd program */ + *ix, + *info_copy, + *expanded = NULL, + *margv[100]; + int fd_in, /* input file id */ + fd_out, /* output file id */ + fd_sterr[2], /* stderr pipe */ + pid, /* child process id */ + pgmresult, + margc, + i, total_len, + result = OK; + struct stat statbuf; + + (void) sprintf(filein, "%s/%s",orig,file); + + if (mychan->ch_hdr_out && mychan->ch_hdr_out->li_name) + (void) sprintf(fileout, "%s/%s",tmp, + mychan->ch_hdr_out->li_name); + else { + name = strdup(file); + ix = index(name,'.'); + *ix = '\0'; + + (void) sprintf(fileout, "%s/%s.%s", + tmp,name,mychan->ch_bpt_out->li_name); + } + + if ((fd_in = open(filein, O_RDONLY, 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, filein, + ("Can't open input file")); + (void) sprintf(buf, + "Unable to open input file '%s'", + filein); + error = strdup(buf); + return NOTOK; + } + if ((fd_out = open(fileout, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, fileout, + ("Can't open output file")); + (void) sprintf(buf, + "Unable to open output file '%s'", + fileout); + error = strdup(buf); + return NOTOK; + } + if (pipe(fd_sterr) != 0) { + PP_SLOG(LLOG_EXCEPTIONS, "pipe", + ("Can't pipe standard err")); + error = strdup("Failed to pipe standard error"); + return NOTOK; + } + + /* get program name */ + if (mychan->ch_out_info == NULL) { + PP_OPER(NULLCP, + ("%s cannot find channel info",mychan->ch_name)); + value = int_Qmgr_status_mtaFailure; + error = strdup("No channel info associated with channel"); + return NOTOK; + } + info_copy = strdup (mychan -> ch_out_info); + if ((margc = sstr2arg(info_copy, 100, margv, " \t")) < 1) { + PP_OPER(NULLCP, + ("%s : no arguments in info string", + mychan->ch_name)); + value = int_Qmgr_status_mtaFailure; + (void) sprintf(buf, + "No arguments in info string '%s'", + mychan -> ch_out_info); + error = strdup(buf); + return NOTOK; + } + if (margv[0][0] == '/') + /* given full path name */ + program = strdup(margv[0]); + else { + program = (char *) malloc((unsigned int) + (strlen(formdfldir) + 1 + + strlen(margv[0]) + 1)); + (void) sprintf(program,"%s/%s",formdfldir,margv[0]); + } + + if (stat(program, &statbuf) != OK) { + PP_OPER(NULLCP, + ("%s : missing filter '%s'",mychan -> ch_name, program)); + value = int_Qmgr_status_mtaFailure; + (void) sprintf (buf, + "Missing filter '%s'", + program); + error = strdup(buf); + return NOTOK; + } + + total_len = 0; + for (i = 0; i < margc; i++) { + if (index (margv[i], '$')) + margv[i] = expand_dyn (margv[i], + expand_macros); + else + margv[i] = strdup (margv[i]); + total_len += strlen(margv[i]) + 3; + /* +3 for intervening space and possible quotes */ + } + total_len += 10; + /* just in case */ + + expanded = malloc((unsigned)(total_len * sizeof(char))); + arg2vstr (0, total_len, expanded, margv); + if ((ix = index (expanded, ' ')) == NULLCP) + ix = expanded; + PP_NOTICE (("%s %s < %s > %s", program, ix, + filein, fileout)); + +#ifdef BSD42 + if ((pid = vfork ()) == 0) { +#else + if ((pid = tryfork()) == 0) { +#endif + /* in child so redirect in- and out-put */ + (void) dup2 (fd_in, 0); + (void) dup2 (fd_out, 1); + (void) dup2 (fd_sterr[1], 2); + (void) close(fd_in); + (void) close(fd_out); + (void) close(fd_sterr[0]); + (void) close(fd_sterr[1]); + + (void) execv(program,margv); + _exit (1); + } else if (pid == -1) { + PP_SLOG(LLOG_EXCEPTIONS, this_msg, + ("tryfork failed")); + error = strdup("Tryfork tailed"); + result = NOTOK; + } else { +#ifdef SVR4 + int wst; +#else + union wait wst; +#endif + + while ((pgmresult = wait(&wst)) != pid && pgmresult != -1) + PP_TRACE(("process %d returned", pgmresult)); + + if ((pgmresult == pid) && !WIFSIGNALED(wst) && + (WEXITSTATUS(wst) == 0)) + result = OK; + else + result = NOTOK; + } + (void) close(fd_sterr[1]); + do_child_logging(fd_sterr[0]); + (void) close(fd_in); + (void) close(fd_out); + if (program != NULL) free(program); + + for (i = 0; i < margc; i++) + free(margv[i]); + if (expanded) free(expanded); + free (info_copy); + + return result; +} + +static int do_child_logging(ifd) +int ifd; +{ + /* log stuff child puts out on stderr */ + char line[LINESIZE]; + int len; + FILE *fd = fdopen(ifd, "r"); + + while (fgets(line, LINESIZE, fd) != NULL) { + len = strlen(line); + if (line[len-1] == '\n') + line[len-1] = '\0'; + PP_LOG(LLOG_NOTICE, + ("%s : %s",mychan->ch_name,line)); + } + (void) fclose(fd); +} + +static int file_link(orig,tmp,file) +char *orig, /* original message directory */ + *tmp, /* new temporary directory */ + *file; /* file to link across */ +{ + char old[MAXPATHLENGTH], /* old file */ + new[MAXPATHLENGTH]; /* new link */ + struct stat statbuf; + int result = OK; + + (void) sprintf(old, "%s/%s",orig,file); + + (void) sprintf(new, "%s/%s",tmp,file); + + if ((stat(old, &statbuf) == OK) + && (stat(new, &statbuf) != OK) + && (link(old, new) != -1)) { + result = OK; + } else { + (void) sprintf(buf, + "Failed to link '%s' to '%s'", + new, old); + error = strdup(buf); + result = NOTOK; + } + + return result; +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + diff --git a/Chans/filtercontrol/make b/Chans/filtercontrol/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/filtercontrol/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/filtercontrol/removebp.sh b/Chans/filtercontrol/removebp.sh new file mode 100755 index 0000000..052a731 --- /dev/null +++ b/Chans/filtercontrol/removebp.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +# +# Trivial shell script to remove indicated body parts. + +echo "************************************************************" +echo "*" +echo "* There was a $* body part present here" +echo "* It was removed as the destination cannot support this format" +echo "*" +echo "************************************************************" + diff --git a/Chans/grey/Makefile b/Chans/grey/Makefile new file mode 100644 index 0000000..f9d796b --- /dev/null +++ b/Chans/grey/Makefile @@ -0,0 +1,242 @@ +# GreyBook channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/grey/RCS/Makefile,v 6.0 1991/12/18 20:10:19 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:10:19 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = io_grey.c ppp.c tppp.c +OBJS = io_grey.o ppp.o tppp.o +UNQO = $(NIFTPSRC)/lib/pqproc/ppQunspool.o +UNPO = $(NIFTPSRC)/lib/pqproc/ppPunspool.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = greyout greyin +CHECKS = checkQbin +default: $(CHECKS) $(PROGS) + +install: inst-dir inst-greyout inst-greyin +inst-dir: $(CHANDIR) + +# If unix-niftp has been re-installed, make io_grey.o newer to force copy +checkQbin: io_grey.o ALWAYS + @sh -c "cmp -s io_grey.o $(UNQO) || \ + { echo touch io_grey.o; touch io_grey.o; } || \ + kill $$$$" + +# If the unix-niftp copy is out of date, Zap it. +$(UNQO): io_grey.o + cp io_grey.o $@ + +greyin: xgreyin +xgreyin: $(NIFTPSRC)/bin/q$(NIFTPINTERFACE) $(LIBPP) + cp $(NIFTPSRC)/bin/q$(NIFTPINTERFACE) xgreyin +$(NIFTPSRC)/bin/q$(NIFTPINTERFACE): $(UNQO) + rm -f $(NIFTPSRC)/bin/q$(NIFTPINTERFACE) + cd $(NIFTPSRC); make lib/pqproc q$(NIFTPINTERFACE) \ + NIFTPINTERFACE=$(NIFTPINTERFACE) + +saber_greyin_src:io_grey.c + #load -C $(CFLAGS) io_grey.c $(LIBPP) $(LIBSYS) + #setopt path $(NIFTPSRC) $(NIFTPSRC)/lib/pqproc + #load -C -I$(NIFTPSRC)/h \ + $(NIFTPSRC)/lib/gen/*.c \ + $(NIFTPSRC)/lib/mmdf/*.c \ + $(NIFTPSRC)/lib/sun/netlisten.c \ + $(NIFTPSRC)/lib/sun/netsubs.c + #load -C -I$(NIFTPSRC)/h \ + tcccomm.c rectrans.c timer.c dec.c data.c record.c \ + adr_trans.c \ + attr_log.c stat.c ts_buff_dec.c find_user.c \ + perms.c qdocket.c rsft.c nrs_rev.c \ + ppQdummy.c + #load -C -I$(NIFTPSRC)/h $(NIFTPSRC)/bin/ftq.c + +inst-greyin: $(CHANDIR)/greyin +$(CHANDIR)/greyin: xgreyin + -$(BACKUP) $@ zxgreyin + rm -f $@ + $(INSTALL) xgreyin $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "greyin channel installed normally"; echo "" + + +greyout: xgreyout +xgreyout: $(UNPO) $(LIBPP) + rm -f $(NIFTPSRC)/bin/$@ + cd $(NIFTPSRC); make lib/pqproc/libppp.a $@ NIFTPINTERFACE=$(NIFTPINTERFACE) + cp $(NIFTPSRC)/bin/$@ $@ + +saber_greyout_src:ppp.c + #load -C $(CFLAGS) ppp.c $(LIBPP) $(LIBSYS) + #setopt path $(NIFTPSRC) $(NIFTPSRC)/lib/pqproc + #load -C -I$(NIFTPSRC)/h \ + $(NIFTPSRC)/lib/gen/*.c \ + $(NIFTPSRC)/lib/mmdf/*.c \ + $(NIFTPSRC)/lib/sun/netopen.c \ + $(NIFTPSRC)/lib/sun/netsubs.c + #load -C -I$(NIFTPSRC)/h \ + ppPunspool.c \ + pdocket.c sft.c tcccomm.c rectrans.c timer.c \ + dec.c data.c record.c adr_trans.c \ + attr_log.c stat.c ts_buff_dec.c find_user.c + #load -C -I$(NIFTPSRC)/h -DFULLPP $(NIFTPSRC)/bin/ftp.c + +$(UNPO): ppp.o + cp ppp.o $@ + +inst-greyout: $(CHANDIR)/greyout +$(CHANDIR)/greyout: xgreyout + -$(BACKUP) $@ zxgreyout + rm -f $@ + $(INSTALL) xgreyout $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "greyout channel installed normally"; echo "" + + +tgreyin: xtgreyin + +xtgreyin: tgreyin.o io_grey.o + $(CC) $(LDFLAGS) -o $@ tgreyin.o io_grey.o $(LIBPP) $(LIBSYS) + +saber_greyin: tgreyin.c io_grey.c + #load -C $(CFLAGS) tgreyin.c io_grey.c $(LIBPP) $(LIBSYS) + +clean: tidy + rm -f $(OBJS) *.o +tidy: + rm -f core* a.out *.old *.BAK xgreyout zx* xgreyin xtgreyin tgreyin + +lint: l-greyout l-greyin + +l-greyout: ppp.c + $(LINT) $(LLFLAGS) ppp.c $(LINTLIBS) + +l-greyin: io_grey.c + $(LINT) $(LLFLAGS) io_grey.c $(LINTLIBS) + + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +ALWAYS: + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +io_grey.o: io_grey.c +io_grey.o: ../../h/util.h +io_grey.o: ../../h/config.h +io_grey.o: ../../h/ll_log.h +io_grey.o: ../../h/prm.h +io_grey.o: ../../h/q.h +io_grey.o: ../../h/adr.h +io_grey.o: ../../h/list_rchan.h +io_grey.o: ../../h/chan.h +io_grey.o: ../../h/table.h +io_grey.o: ../../h/list_bpt.h +io_grey.o: ../../h/auth.h +io_grey.o: ../../h/list_bpt.h +io_grey.o: ../../h/extension.h +io_grey.o: ../../h/mta.h +io_grey.o: ../../h/adr.h +io_grey.o: ../../h/list_bpt.h +io_grey.o: ../../h/aparse.h +io_grey.o: ../../h/ap.h +io_grey.o: ../../h/util.h +io_grey.o: ../../h/or.h +io_grey.o: ../../h/chan.h +io_grey.o: ../../h/auth.h +io_grey.o: ../../h/list_rchan.h +io_grey.o: ../../h/mta.h +io_grey.o: ../../h/adr.h +io_grey.o: ../../h/ap.h +io_grey.o: ../../h/retcode.h +io_grey.o: ../../h/tb_q.h +io_grey.o: ../../h/tb_a.h +io_grey.o: ../../h/tb_prm.h +ppp.o: ppp.c +ppp.o: ../../h/util.h +ppp.o: ../../h/config.h +ppp.o: ../../h/ll_log.h +ppp.o: ../../h/ppp.h +ppp.o: ../../h/qmgr.h +ppp.o: ../../h/Qmgr-types.h +ppp.o: ../../h/Qmgr-ops.h +ppp.o: ../../h/prm.h +ppp.o: ../../h/q.h +ppp.o: ../../h/adr.h +ppp.o: ../../h/list_rchan.h +ppp.o: ../../h/chan.h +ppp.o: ../../h/table.h +ppp.o: ../../h/list_bpt.h +ppp.o: ../../h/auth.h +ppp.o: ../../h/list_bpt.h +ppp.o: ../../h/extension.h +ppp.o: ../../h/mta.h +ppp.o: ../../h/adr.h +ppp.o: ../../h/list_bpt.h +ppp.o: ../../h/aparse.h +ppp.o: ../../h/ap.h +ppp.o: ../../h/util.h +ppp.o: ../../h/or.h +ppp.o: ../../h/chan.h +ppp.o: ../../h/auth.h +ppp.o: ../../h/list_rchan.h +ppp.o: ../../h/mta.h +ppp.o: ../../h/adr.h +ppp.o: ../../h/chan.h +ppp.o: ../../h/retcode.h +ppp.o: ../../h/dr.h +ppp.o: ../../h/extension.h +ppp.o: ../../h/mta.h +ppp.o: ../../h/ap.h +tppp.o: tppp.c +tppp.o: ../../h/util.h +tppp.o: ../../h/config.h +tppp.o: ../../h/ll_log.h +tppp.o: ../../h/ppp.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/grey/README b/Chans/grey/README new file mode 100644 index 0000000..81e78c6 --- /dev/null +++ b/Chans/grey/README @@ -0,0 +1,20 @@ +Grey book interface. + +This interface is for the grey book protocol running over Blue book +file transfer protocol. This is a JANET specific protocol. + +The files in this directory represent only the PP specific parts of +the interface. PP is designed to make use of the unix-niftp public +domain package to complete this channel. If you do not currently have +this package you will not make much headway! + +The particular unix-niftp you need should have the appropriate hooks +in for PP. This requires the latest version of unix-niftp. + +This is obtainable from Piete Brooks at cambridge university (pb@uk.ac.cam.cl). +You can get information on the current unix-niftp version from him or +from the info-server at cambridge. + +If you have problems with this - or are confused, drop a note to the +pp-support address and we will see if something can be sorted out. + diff --git a/Chans/grey/io_grey.c b/Chans/grey/io_grey.c new file mode 100644 index 0000000..880fc25 --- /dev/null +++ b/Chans/grey/io_grey.c @@ -0,0 +1,858 @@ +/* io_grey.c: These are IO routines for the greybook channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/grey/RCS/io_grey.c,v 6.0 1991/12/18 20:10:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/grey/RCS/io_grey.c,v 6.0 1991/12/18 20:10:19 jpo Rel $ + * + * $Log: io_grey.c,v $ + * Revision 6.0 1991/12/18 20:10:19 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "prm.h" +#include "q.h" +#include "adr.h" +#include "ap.h" +#include "retcode.h" +#include "tb_q.h" +#include "tb_a.h" +#include "tb_prm.h" +#include +#include + + +/*--- statics ---*/ +static struct prm_vars prm = { NULLCP, 0, PRM_ACCEPTALL }; +static Q_struct Qstruct; + + +static int submit_started = 0; +#define ST_OPENED 3 +#define ST_DATAINIT 4 +#define ST_JNTHDR 0 +#define ST_MSGHDR 1 +#define ST_BODY 2 +static int state = ST_OPENED; + + +static AP_ptr newdomain(); +static char *compress(); +static void berror (); +static int add_via(); +static int aprd_done(); +static int aprd_init(); +static int aprdchr(); +static int fixup_sender(); +static int hdr_done(); +static int hdr_init(); +static int hdr_read(); +static int process_addrs(); +static int pp_error (); + +static CHAN *mychan = NULLCHAN; +static char **errstr = (char **) 0; +static char *theheader = NULLCP; +static char *hdrptr; +static char *apchptr; +static char *apcharacters = NULLCP; +static char *fromhost = NULLCP; + +static int data_bytes; +static struct timeval data_timer; + +/*--- externals */ +extern ADDR *adr_new(); +extern char *postmaster; +extern char *ia5_bp, *hdr_822_bp; + +#define GB_NOTOK NOTOK +#define GB_OK OK +#define GB_RECIPFAILED -2 +#define GB_SENDERFAILED -3 + + +/* ------------------- Begin Routines ---------------------------------- */ + + +char errbuffer[BUFSIZ]; + +/*--- tell PP that a call is arriving ---*/ +int pp_open (channame, hostname, perrstr) +char *channame; +char *hostname; +char **perrstr; +{ + RP_Buf reply; + Q_struct *qp = &Qstruct; + LIST_BPT *new; + extern char *quedfldir; + static int onceonly = 1; + + errstr = perrstr; + if (onceonly) { + chan_init (channame); + (void) chdir (quedfldir); + ap_use_percent (); + (void) signal(SIGPIPE, SIG_IGN); + onceonly = 0; + } + + if (state != ST_OPENED) + return pp_error (errstr, GB_RECIPFAILED, + "Illegal call to ppp_open - internal botch"); + PP_TRACE (("pp_open (%s, %s)", channame, hostname)); + + if ((mychan = ch_mta2struct (channame, hostname)) == NULLCHAN) { + (void) sprintf (errbuffer, + "Local error: Channel '%s' is not known", + channame); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + rename_log (mychan -> ch_name); + + PP_NOTICE (("Incoming Call from %s to %s", hostname, mychan->ch_name)); + if (fromhost) + free (fromhost); + fromhost = strdup (hostname); + + if (submit_started == 0 && rp_isbad (io_init (&reply))) { + berror (errbuffer, "Can't initialise mail system", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + submit_started = 1; + + if (rp_isbad (io_wprm (&prm, &reply))) { + berror (errbuffer, "Can't set parameters", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + + /*--- initialize queue structure ---*/ + + q_init (qp); + qp -> msgtype = MT_UMPDU; + qp -> inbound = list_rchan_new (hostname, NULL); + qp -> inbound -> li_chan = mychan; + + qp -> encodedinfo.eit_types = NULLIST_BPT; + new = list_bpt_new (hdr_822_bp); + list_bpt_add (&qp -> encodedinfo.eit_types, new); + new = list_bpt_new (ia5_bp); + list_bpt_add (&qp -> encodedinfo.eit_types, new); + + if (rp_isbad (io_wrq (qp, &reply))) { + berror (errbuffer, "Can't write Q struct", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + data_bytes = 0; + timer_start (&data_timer); + state = ST_DATAINIT; + return GB_OK; +} + +/* ARGSUSED */ +int pp_write (fd, buff, size) /*--- write some data to PP ---*/ +int fd; +char buff[]; +int size; +{ + static int linefeed = 0; + static struct qbuf *qb[2] = {NULL, NULL}, *qp = NULL; + char *cp = NULLCP, + *ep = NULLCP, + *bp = NULLCP, + *q; + int retval; + + PP_TRACE (("pp_write (%d bytes)", size)); + + data_bytes += size; + + switch (state) { + case ST_DATAINIT: + linefeed = 0; + if (qb[0]) + qb_free (qb[0]), qb[0] = NULL; + if (qb[1]) + qb_free (qb[1]), qb[1] = NULL; + state = ST_JNTHDR; + /* fall */ + case ST_JNTHDR: + case ST_MSGHDR: + for (bp = cp = buff, ep = buff + size; cp < ep; cp++) { + switch (*cp) { + case '\r': + case ' ': + case '\t': + continue; + case '\n': + linefeed ++; + if (linefeed < 2) + continue; + for (q = cp - 1; q > bp && *q == '\r'; q--) + continue; + + if (qb[state] == NULL) + qb[state] = str2qb (bp, q - bp + 1, 1); + else { + qp = str2qb (bp, q - bp + 1, 0); + insque (qp, qb[state]->qb_back); + } + bp = cp + 1; + state ++; + if (state < ST_BODY) + continue; + break; + default: + linefeed = 0; + continue; + } + break; + } + if (state != ST_BODY && bp + 1 < ep) { + if (qb[state] == NULL) + qb[state] = str2qb (bp, ep - bp, 1); + else { + qp = str2qb (bp, ep - bp, 0); + insque (qp, qb[state]->qb_back); + } + } + + if (qb[0]) { + cp = NULLCP; + PP_DBG (("pp_write/qb[0]='%.900s'", + cp = qb2str(qb[0]))); + if (cp) + free (cp); + } + if (qb[1]) { + cp = NULLCP; + PP_DBG (("pp_write/qb[1]='%.900s'", + cp = qb2str (qb[1]))); + if (cp) + free (cp); + } + + if (state == ST_BODY) { /* GOT IT - lets go!! */ + if ((retval = process_addrs (qb[0], qb[1], errstr)) + != GB_OK) + return retval; + qb_free (qb[0]); qb[0] = NULL; + qb_free (qb[1]); qb[1] = NULL; + if (bp + 1 < ep) + if (rp_isbad (io_tdata(bp, size - (bp-buff)))) + return pp_error (errstr, + GB_RECIPFAILED, + "Data Copy failed"); + } + break; + + + case ST_BODY: + if (size <= 0) { + PP_LOG (LLOG_EXCEPTIONS, ("Funny size to pp_write: %d", + size)); + return size; + } + if (rp_isbad (io_tdata (buff, size))) + return pp_error (errstr, GB_RECIPFAILED, + "Data Copy Faield"); + return size; + default: + return pp_error (errstr, GB_RECIPFAILED, + "Illegal call to pp_write - internal error"); + } + return size; +} + +/* ARGSUSED */ +int pp_close(fd) /*--- tell PP that all the data has arrived ---*/ +int fd; +{ + RP_Buf reply; + + PP_TRACE (("pp_close()")); + + if (state == ST_MSGHDR) + if (pp_write (0, "\n", 1) != 1) + return pp_error (errstr, GB_RECIPFAILED, + "pp_write (internal call) failed"); + + if (state != ST_BODY) + return pp_error (errstr, GB_RECIPFAILED, + "Illegal call to pp_close - internal error"); + + timer_end (&data_timer, data_bytes, "Data Received"); + if (rp_isbad (io_tdend (&reply))) { + berror (errbuffer, "data termination failed", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + if (rp_isbad (io_tend (&reply))) { + berror (errbuffer, "data termination (2) failed", &reply); + if (rp_gbval (reply.rp_val) == RP_BNO) + return pp_error (errstr, GB_NOTOK, errbuffer); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + PP_NOTICE (("Message successfully transfered")); + state = ST_OPENED; + return GB_OK; +} + + + + +/* ------------------- Static Routines ---------------------------------- */ + +static AP_ptr newdomain (domn) +char *domn; +{ + PP_TRACE (("newdomain (%s)", domn)); + return ap_new ((*domn == '[') ? AP_DOMAIN_LITERAL : AP_DOMAIN, domn); +} + + + + +static process_addrs (qbjnt, qbhdr, errstr) +struct qbuf *qbjnt; +struct qbuf *qbhdr; +char **errstr; +{ + RP_Buf reply; + char *name, + *contents, + buffer[BUFSIZ], + sbuf[BUFSIZ], + reasonmsg[BUFSIZ], + *p = NULLCP; + AP_ptr ap_sender = NULLAP, + jntroute = NULLAP, + local = NULLAP, + domain = NULLAP, + route = NULLAP, + jntaddr = NULLAP, + ackaddr = NULLAP, + aptr; + ADDR *ap = NULLADDR; + int got_sender = 0, + ack_flag = AD_USR_BASIC, + retval; + struct qbuf *qp = NULL; + int n; + + + PP_TRACE (("process_addrs()")); + + hdr_init (qbhdr); + + + reasonmsg[0] = 0; + while (hdr_read (&name, &contents) != NOTOK) { + + PP_DBG (("process_addrs (%s %s)", name, contents)); + + if (lexequ ("sender", name) == 0) { + if ((aptr = ap_s2t (contents)) == BADAP || + aptr == NULLAP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad sender field %s", + contents)); + (void) sprintf (reasonmsg, + "sender %s not parseable", contents); + } + else { + (void) strcpy (sbuf, contents); + ap_sender = aptr; + got_sender = 1; + } + } + + if (lexequ ("from", name) == 0 && !got_sender) { + if ((aptr = ap_s2t (contents)) == BADAP || + aptr == NULLAP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad from field %s", + contents)); + (void) sprintf (reasonmsg, + "From %s not parseable", contents); + } + else { + ap_sender = aptr; + (void) strcpy (sbuf, contents); + } + } + + if (lexequ ("via", name) == 0) { + if (add_via (contents, &jntroute, buffer) == NOTOK) { + return pp_error (errstr, GB_NOTOK, + buffer); + } + } + + if (lexequ ("acknowledge-to", name) == 0) + if ((ackaddr = ap_s2t(contents)) == BADAP || + aptr == NULLAP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad acknowledge-to field %s", + contents)); + aptr = NULLAP; + } + } + + hdr_done(); + + if (!ap_sender) { + if (reasonmsg[0]) + return pp_error (errstr, GB_NOTOK, + reasonmsg); + return pp_error (errstr, GB_NOTOK, + "No sender field present in Header"); + } + + if (fixup_sender (ap_sender, jntroute, buffer, ackaddr)) + ack_flag = AD_USR_CONFIRM; + + ap = adr_new (buffer, AD_822_TYPE, 0); + + PP_NOTICE (("Sender '%s', original sender '%s'", ap->ad_value, sbuf)); + + if (rp_isbad (io_wadr (ap, AD_ORIGINATOR, &reply))) { + (void) sprintf (buffer, "Bad sender '%s'", ap -> ad_value); + adr_tfree (ap); + berror (errbuffer, buffer, &reply); + if (reply.rp_val == RP_BHST || + rp_gbval(reply.rp_val) == RP_BNO) + return pp_error (errstr, GB_NOTOK, errbuffer); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + adr_tfree (ap); + + aprd_init (qbjnt); + + n = 0; + while ((jntaddr = ap_pinit (aprdchr)) != BADAP) { + switch (retval = ap_1adr()) { + case NOTOK: + ap_free (jntaddr); + aprd_done (); + return pp_error (errstr, GB_NOTOK, + "unparseable JNT address - BAD JNT HEADER"); + + case DONE: + ap_free (jntaddr); + break; + } + + if (retval == DONE) + break; + + ap_t2p (jntaddr, (AP_ptr *)0, (AP_ptr *)0, &local, + &domain, &route); + + if (route == NULLAP) { + if (domain && domain -> ap_obtype == AP_DOMAIN_LITERAL) { + ap_free (domain); + domain = NULLAP; + } + } + else { + if (route -> ap_obtype == AP_DOMAIN_LITERAL) { + aptr = route; + route = aptr -> ap_next; + if (route -> ap_obtype != AP_DOMAIN_LITERAL || + route -> ap_obtype != AP_DOMAIN) + route = NULLAP; + ap_free (aptr); + } + } + ap_dmnormalize (domain, mychan -> ch_ad_order); + p = ap_p2s_nc (NULLAP, NULLAP, local, domain, route); + ap = adr_new (p, AD_822_TYPE, 1); + ap -> ad_usrreq = ack_flag; + + PP_NOTICE (("Recipient Address '%s'", ap->ad_value)); + + if (rp_isbad (io_wadr (ap, AD_RECIPIENT, &reply))) { + berror (errbuffer, "Recipient failed", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + adr_tfree (ap); + n ++; + } + if (n == 0) + return pp_error (errstr, GB_NOTOK, + "No recipients in JNT Header"); + + if (rp_isbad (io_adend (&reply))) { + berror (errbuffer, "Address termination failed", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + aprd_done(); + + if (rp_isbad (io_tinit (&reply)) || + rp_isbad (io_tpart (hdr_822_bp, FALSE, &reply))) { + berror (errbuffer, "Text initialisation", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + for (qp = qbhdr -> qb_forw; qp != qbhdr; qp = qp -> qb_forw) { + if (qp -> qb_len <= 0) + continue; + if (rp_isbad (io_tdata (qp->qb_data, qp->qb_len))) { + (void) sprintf (errbuffer, "Data copy Failed"); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + } + + if (rp_isbad (io_tdend (&reply))) { + berror (errbuffer, "Text termination problem", &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + if (rp_isbad (io_tpart ("1.ia5", FALSE, &reply))) { + berror (errbuffer, "Text body initialiastion probelms", + &reply); + return pp_error (errstr, GB_RECIPFAILED, errbuffer); + } + + return GB_OK; +} + +static int fixup_sender (sender, jntroute, dest, ack_to) +AP_ptr sender; +AP_ptr jntroute; +char *dest; +AP_ptr ack_to; +{ + extern char *loc_dom_site; + AP_ptr ap, + route = NULLAP, + domain = NULLAP, + mbox = NULLAP; + int donevia = 0; + int ack = 0; + char *p; + + + PP_TRACE (("fixup_sender()")); + + + ap_t2p (sender, (AP_ptr *)0, (AP_ptr *)0, &mbox, &domain, &route); + +#define pp_is_burning_up_cpu_time 1 + + while (pp_is_burning_up_cpu_time) { + + if (jntroute != NULLAP) { + ap = jntroute; + jntroute = jntroute -> ap_next; + } + else if (donevia) + break; + else { + donevia = TRUE; + if (fromhost == NULLCP || *fromhost == '\0') + ap = newdomain (loc_dom_site); + else + ap = newdomain (fromhost); + } + + + if (domain ==NULLAP) + domain = ap; + else { + ap -> ap_next = route; + route = ap; + } + } + + + /*--- normalise the domains ---*/ + ap_dmnormalize (domain, mychan -> ch_ad_order); + + for (ap = route; ap != NULLAP; ap = ap -> ap_next) + switch (ap -> ap_obtype) { + case AP_DOMAIN: + ap_dmnormalize (ap, mychan -> ch_ad_order); + break; + + default: + break; + } + + /*--- eliminating redundant entries ---*/ + while (route != NULLAP) { + AP_ptr last = domain; + + for (ap = route; ap -> ap_next != NULLAP;) { + if (ap -> ap_next ->ap_obtype == AP_NIL) + break; + last = ap; + ap = ap -> ap_next; + } + PP_TRACE(("comparing %s & %s", + last -> ap_obvalue, ap -> ap_obvalue)); + if (lexequ (last -> ap_obvalue, ap -> ap_obvalue) == 0) { + PP_TRACE (("Removing duplicate route %s (dom %s)", + ap -> ap_obvalue, domain -> ap_obvalue)); + ap -> ap_obtype = AP_NIL; + free (ap -> ap_obvalue); + ap -> ap_obvalue = NULLCP; + if (ap == route) { + ap_free (route); + route = NULLAP; + break; + } + } + else + break; + } + if (ack_to) { + AP_ptr mb, dmn; + + ap_t2p (ack_to, NULLAPP, NULLAPP, &mb, &dmn, NULLAPP); + if (dmn) ap_dmnormalize (dmn, mychan -> ch_ad_order); + if (mb && dmn && + lexequ (mb -> ap_obvalue, mbox -> ap_obvalue) == 0 && + lexequ (dmn -> ap_obvalue, domain -> ap_obvalue) == 0) + ack = 1; + } + p = ap_p2s_nc (NULLAP, NULLAP, mbox, domain, route); + (void) strcpy (dest, p); + free (p); + return ack; +} + +#define retsloppy() (mychan -> ch_strict_mode == CH_STRICT_CHECK ? NOTOK : OK) + +static add_via (str, route, ebuf) +char *str; +AP_ptr *route; +char *ebuf; +{ + char *p, *q; + AP_ptr ap; + + + PP_TRACE (("add_via (%s)", str)); + + if ((p = rindex (str, ';')) != NULLCP) + *p = '\0'; + else { + (void) sprintf (ebuf, "Illegal Via: field, No ';' \"%s\"", + str); + PP_LOG (LLOG_EXCEPTIONS, ("%s", ebuf)); + return retsloppy(); + } + + compress (str, str); + + while ((p = index (str, '(')) != NULLCP) { + if ((q = index (p, ')')) != NULLCP) { + q++; + while (*q) + *p++ = *q++; + *p = '\0'; + } + else + break; + } + + compress (str, str); + if (str == NULLCP || *str == NULL) { + (void) sprintf (ebuf, "empty host component in via field"); + PP_LOG (LLOG_EXCEPTIONS, ("%s", ebuf)); + return retsloppy(); + } + ap = newdomain (str); + ap -> ap_next = *route; + *route = ap; + return OK; +} + + + + + +static hdr_init (qb) +struct qbuf *qb; +{ + hdrptr = theheader = qb2str (qb); + PP_TRACE (("hdr_init (%.999s)", hdrptr)); +} + + + + +static hdr_read (name, contents) +char **name, **contents; +{ + PP_DBG (("hdr_read (%.80s)", hdrptr)); + + if (*hdrptr == '\0') + return NOTOK; + + *name = hdrptr; + for (*name = hdrptr; *hdrptr; hdrptr++) { + if (*hdrptr == ':') { + *hdrptr ++ = '\0'; + break; + } + if (*hdrptr == '\n') { + *hdrptr = '\0'; + *contents = hdrptr; + hdrptr ++; + return OK; + } + } + compress (*name, *name); + + if (*hdrptr == '\0') + return OK; + + while (*hdrptr == ' ' || *hdrptr == '\t') + hdrptr ++; + + for (*contents = hdrptr; *hdrptr; hdrptr++) { + if (*hdrptr == '\n') { + if (isspace (hdrptr[1])) { + *hdrptr = ' '; + continue; + } + *hdrptr ++ = '\0'; + break; + } + } + return OK; +} + + + + +static hdr_done() +{ + PP_TRACE (("hdr_done()")); + if (theheader) { + free (theheader); + theheader = NULLCP; + } +} + + + +static aprd_init (qb) +struct qbuf *qb; +{ + apchptr= apcharacters = qb2str (qb); + PP_TRACE (("aprd_init (%.999s)", apchptr)); +} + + + +static aprdchr() +{ + return *apchptr == '\0' ? EOF : *apchptr++; +} + + + +static aprd_done() +{ + PP_TRACE (("aprd_done()")); + if (apcharacters) { + free (apcharacters); + apcharacters = NULLCP; + } +} + + + +static char *compress (fromptr, toptr) +register char *fromptr; +register char *toptr; +{ + register char chr; + char *in_toptr = toptr; + + + PP_DBG (("compress (%s)", fromptr)); + + + /*--- init to skip leading spaces tabs and newlines --- */ + + chr = ' '; + + + while ((*toptr = *fromptr++) != '\0') { + + /*--- only save the spaces found in between words ---*/ + if (isspace (*toptr)) { + if (chr != ' ') + *toptr++ = chr = ' '; + } + else + chr = *toptr++; + } + + + /*--- remove trailing spaces, tabs and newlines if any ---*/ + if ((chr == ' ') + && (toptr != in_toptr)) + *--toptr = '\0'; + + return (toptr); +} + +static void berror (buffer, str, rp) +char *buffer, *str; +RP_Buf *rp; +{ + (void) sprintf (buffer, "%s ([%s] %s)", + str, rp_valstr (rp->rp_val), + rp -> rp_line[0] ? rp -> rp_line : + "No further information"); +} + +static int pp_error (err, code, str) +char **err; +int code; +char *str; +{ + char *kind; + + switch (code) { + case GB_OK: + kind = "ok"; + break; + case GB_RECIPFAILED: + kind = "failed - recipient temp"; + break; + case GB_NOTOK: + kind = "failed - permanent"; + break; + + case GB_SENDERFAILED: + kind = "failed - sender temporary"; + break; + default: + kind = "UNKNOWN"; + break; + } + if (err) *err = strdup (str); + PP_LOG (LLOG_EXCEPTIONS, ("%s %s", str, kind)); + submit_started = 0; + io_end (NOTOK); + state = ST_OPENED; + return code; +} diff --git a/Chans/grey/make b/Chans/grey/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/grey/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/grey/ppp.c b/Chans/grey/ppp.c new file mode 100644 index 0000000..e52c9fa --- /dev/null +++ b/Chans/grey/ppp.c @@ -0,0 +1,947 @@ +/* ppp.c: ppp interface routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/grey/RCS/ppp.c,v 6.0 1991/12/18 20:10:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/grey/RCS/ppp.c,v 6.0 1991/12/18 20:10:19 jpo Rel $ + * + * $Log: ppp.c,v $ + * Revision 6.0 1991/12/18 20:10:19 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ppp.h" +#include "qmgr.h" +#include "prm.h" +#include "q.h" +#include "adr.h" +#include "chan.h" +#include +#include "retcode.h" +#include "dr.h" +#include "ap.h" + +static int ppp_sd = NOTOK; +static CHAN *mychan; +static struct prm_vars prm; +static Q_struct Qs; +static ADDR *ad_sender, *ad_recip, *ad_list; +static enum { jnthdr, initialise, go } state; +static char *this_msg; +static int naddrs = 0; +static char *cur_host; +static char *cur_net; +static char *jnt_host; +static int rox_id; +static int ppp_error_status; +static int data_bytes; +static struct timeval data_timer; +#if PP_DEBUG > PP_DEBUG_NONE +static int ppp_debug = 0; +static int debug_init (), debug_nextmsg (); +static void pdeliverystatus (), pindividualdeliverystatus (); +#endif + +static int ppp_initfnx (), ppp_procfnx (); +static void ppp_lose (); +static int ros_indication (), ros_work (), ros_result (), + error (), ureject (); +static void ros_advise (), acs_advise (); +static void cleanup_everything (); +static char *bigendian (); +static char *mk_jnt (); +static int assemble_jntheader (); +static int fetch_data (); +static int ppp_procfnx_aux (); + +static int lastop = NOTOK; +#define INITOP 1 +#define PROCOP 2 +extern struct RyOperation table_Qmgr_Operations[]; +extern char *quedfldir; + +int ppp_init (argc, argv) +int argc; +char **argv; +{ + struct AcSAPstart acss; + register struct AcSAPstart *acs = &acss; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + register struct PSAPstart *ps = &acs -> acs_start; + int result; + + chan_init (argv[0]); + (void) chdir (quedfldir); +#if PP_DEBUG > PP_DEBUG_NONE + for (result = 0; result < argc; result ++) + if (strcmp (argv[result], "debug") == 0) + return debug_init (); +#endif + if (RyDispatch (NOTOK, table_Qmgr_Operations, + operation_Qmgr_channelInitialise, ppp_initfnx, + roi) == NOTOK) { + ros_advise (rop, "RyDispatch: channelInitialise"); + return NOTOK; + } + if (RyDispatch (NOTOK, table_Qmgr_Operations, + operation_Qmgr_processmessage, ppp_procfnx, + roi) == NOTOK) { + ros_advise (rop, "RyDispatch: processmessage"); + return NOTOK; + } + + if (AcInit (argc, argv, acs, aci) == NOTOK) { + acs_advise (aca, "AcInit"); + return NOTOK; + } + + PP_DBG (("A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>", + acs -> acs_sd, sprintoid (acs -> acs_context), + sprintaei (&acs -> acs_callingtitle), + sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo)); + ppp_sd = acs -> acs_sd; + + result = AcAssocResponse (ppp_sd, ACS_ACCEPT, ACS_USER_NULL, + NULLOID, NULLAEI, NULLPA, NULLPC, + ps -> ps_defctxresult, + ps -> ps_prequirements, + ps -> ps_srequirements, SERIAL_NONE, + ps -> ps_settings, &ps -> ps_connect, + NULLPEP, 0, aci); + ACSFREE (acs); + if (result == NOTOK) { + acs_advise (aca, "A-ASSOCIATE.RESPONSE"); + return ppp_sd = NOTOK; + } + if (RoSetService (ppp_sd, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + ppp_lose (); + return NOTOK; + } + + /* try and get the init channel op */ + if (ros_work (ppp_sd, INITOP) != OK) { + ppp_lose (); + return NOTOK; + } + return OK; +} + + +int ppp_getnextmessage (host, net) +char **host; +char **net; +{ + int result; + + state = jnthdr; +#if PP_DEBUG > PP_DEBUG_NONE + if (ppp_debug) + result = debug_nextmsg (); + else +#endif + result = ros_work (ppp_sd, PROCOP); + switch (result) { + default: + case NOTOK: + ros_result (ppp_sd, deliverystate, rox_id); + ppp_lose (); + return NOTOK; + + case OK: + if (ppp_error_status == NOTOK) { + ros_result (ppp_sd, deliverystate, rox_id); + return ppp_getnextmessage (host, net); + } + if (jnt_host) + free (jnt_host); + *host = jnt_host = mk_jnt(cur_host); + if (jnt_host == NULLCP) + return NOTOK; + if (cur_net) + free (cur_net); + if (mychan -> ch_out_info == NULLCP) { + PP_OPER (NULLCP, ("Channel %s has no info string", + mychan -> ch_name)); + return NOTOK; + } + *net = cur_net = strdup (mychan -> ch_out_info); + return OK; + + case DONE: + return DONE; + } +} + +static char *hdrbuf; + +int ppp_getdata (buf, len) +char **buf; +int *len; +{ + if (hdrbuf) { + free (hdrbuf); + hdrbuf = NULLCP; + } + + switch (state) { + case jnthdr: + data_bytes = 0; + timer_start (&data_timer); + state = initialise; + return assemble_jntheader (buf, len); + + case initialise: + case go: + return fetch_data (buf, len); + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Bad state in getdata")); + return NOTOK; + } +} + +static int assemble_jntheader (buf, lengthp) +char **buf; +int *lengthp; +{ + ADDR *ap; + char *str; + int len = 0; + + PP_NOTICE (("Originator %s", ad_sender -> ad_r822adr)); + for (ap = ad_list; ap; ap = ap -> ad_next) { + if ((str = bigendian (ap -> ad_r822adr)) == NULLCP) + return NOTOK; + if (hdrbuf == NULL) { + hdrbuf = smalloc (len = strlen (str) + 2 + 1); + (void) strcpy (hdrbuf, str); + (void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n"); + } + else { + hdrbuf = realloc (hdrbuf, len += strlen (str) + 2); + (void) strcat (hdrbuf, str); + (void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n"); + } + } + *buf = hdrbuf; + *lengthp = len - 1; + data_bytes += len - 1; + return OK; +} + +static char transbuf[BUFSIZ]; +static char *formatdir; + +static int fetch_data (buf, lengthp) +char **buf; +int *lengthp; +{ + char filename[BUFSIZ]; + static FILE *fp; + static int first; + int n; + + *buf = ""; + *lengthp = 0; + + if (state == initialise) { + state = go; + first = 1; + + if (qid2dir (this_msg, ad_list, TRUE, &formatdir) == NOTOK) + return NOTOK; + if (msg_rinit (formatdir) != RP_OK) + return NOTOK; + if (msg_rfile (filename) != RP_OK) { + msg_rend (); + return NOTOK; + } + if ((fp = fopen (filename, "r")) == NULL) { + msg_rend (); + return NOTOK; + } + } + + if (!feof(fp) && (n = fread (transbuf, 1, sizeof transbuf, fp)) > 0) { + *buf = transbuf; + *lengthp = n; + data_bytes += n; + return OK; + } + if (first) { + first = 0; + (void) strcpy (transbuf, "\n"); + *buf = transbuf; + *lengthp = 1; + data_bytes += 1; + return OK; + } + + if (ferror (fp)) { + msg_rend (); + (void) fclose (fp); + return NOTOK; + } + (void) fclose (fp); + + + if ((n = msg_rfile (filename)) == RP_DONE){ + msg_rend (); + *lengthp = 0; + return DONE; + } + + if (rp_isbad (n)) { + msg_rend (); + return NOTOK; + } + + if ((fp = fopen (filename, "r")) == NULL) { + msg_rend (); + return NOTOK; + } + + return fetch_data (buf, lengthp); +} + +int ppp_status (status, reason) +int status; +char *reason; +{ + ADDR *ap; + char buf[BUFSIZ]; + int confrep = int_Qmgr_status_positiveDR; + int drrep = int_Qmgr_status_negativeDR; + + if (status == PPP_STATUS_DONE) + timer_end (&data_timer, data_bytes, "Data Transfered"); + + for (ap = ad_list; ap; ap = ap -> ad_next) { + if (ap -> ad_resp == 0) + continue; + switch (status) { + case PPP_STATUS_DONE: + if (ap ->ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + (void) sprintf (buf, "Successfully sent to %s for recipient %s", + cur_host, ap -> ad_r822adr); + set_1dr (&Qs, ap -> ad_no, this_msg, + DRR_NO_REASON, + -1, buf); + delivery_set (ap -> ad_no, confrep); + confrep = int_Qmgr_status_successSharedDR; + } + else { + (void) wr_ad_status (ap, AD_STAT_DONE); + (void) wr_stat (ap, &Qs, this_msg, data_bytes); + delivery_set (ap -> ad_no, + int_Qmgr_status_success); + } + PP_NOTICE ((">>> Message %s transfered to %s on %s", + this_msg, ap -> ad_r822adr, cur_host)); + break; + + case PPP_STATUS_CONNECT_FAILED: + delivery_setstate (ap -> ad_no, + int_Qmgr_status_mtaFailure, + reason); + PP_NOTICE (("Connection to %s failed [%s]", + cur_host, reason ? reason : "")); + break; + + case PPP_STATUS_PERMANENT_FAILURE: + (void) sprintf (buf, + "Blue book transfer to %s failed (permanent error code): \"%s\"", + cur_host, reason); + delivery_set (ap -> ad_no, + drrep); + drrep = int_Qmgr_status_failureSharedDR; + set_1dr (&Qs, ap -> ad_no, this_msg, + DRR_TRANSFER_FAILURE, + DRD_UNRECOGNISED_OR, buf); + PP_NOTICE (("Transfer to %s for %s perm failed [%s]", + cur_host, this_msg, buf)); + break; + + case PPP_STATUS_TRANSIENT_FAILURE: + delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + reason); + PP_NOTICE (("Temporary failure for %s to %s [%s]", + this_msg, cur_host, reason ? reason : "")); + break; + } + } + if (rp_isbad(wr_q2dr (&Qs, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure",mychan->ch_name)); + (void) delivery_resetDRs (int_Qmgr_status_messageFailure); + } + + cleanup_everything (); + rd_end (); +#if PP_DEBUG > PP_DEBUG_NONE + if (ppp_debug){ + pdeliverystatus (deliverystate); + return OK; + } + else +#endif + return ros_result (ppp_sd, deliverystate, rox_id); +} + +void ppp_terminate () +{ + if (ppp_sd != NOTOK) + ppp_lose (); +} + +static void ppp_lose () +{ + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + + (void) AcUAbortRequest (ppp_sd, NULLPEP, 0, &acis); + (void) RyLose (ppp_sd, roi); + ppp_sd = NOTOK; +} + +static int ppp_initfnx (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + char *p; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + p = qb2str ((struct type_Qmgr_Channel *) in); + + if ((mychan = ch_nm2struct (p)) == NULLCHAN) { + PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p)); + free (p); + error (sd, error_Qmgr_protocol, (caddr_t) NULL, rox -> rox_id); + return NOTOK; + } + PP_NOTICE (("Starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); + rename_log (mychan -> ch_name); + + free (p); + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, + ROS_NOPRIO, roi) == NOTOK) { + ros_advise (&roi -> roi_preject, "RESULT"); + return NOTOK; + } + + lastop = INITOP; + return OK; +} + +static int ppp_procfnx (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_ProcMsg *arg = (struct type_Qmgr_ProcMsg *)in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + rox_id = rox -> rox_id; + lastop = PROCOP; + return ppp_procfnx_aux (arg); +} + +static int ppp_procfnx_aux (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + int retval; + int ad_count = 0; + ADDR *ap, *alp = NULL; + + delivery_init (arg -> users); + + if (this_msg) + free (this_msg); + this_msg = qb2str (arg -> qid); + + ad_sender = NULLADDR; + + if (ad_recip) { + q_free (&Qs); + prm_free (&prm); + } + ad_recip = NULLADDR; + + retval = rd_msg (this_msg, &prm, &Qs, &ad_sender, &ad_recip, &ad_count); + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("local/rd_msg err: %s", this_msg)); + return NOTOK; + } + + naddrs = 0; + ad_list = NULLADDR; + ppp_error_status = OK; + for (ap = ad_recip; ap; ap = ap -> ad_next) { + for (up = arg ->users; up; up = up -> next) { + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + switch (chan_acheck (ap, mychan, ad_list == NULLADDR, + &cur_host)) { + case OK: + break; + + default: + continue; + } + break; + } + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = alp = (ADDR *) calloc (1, sizeof *alp); + else { + alp -> ad_next = (ADDR *) calloc (1, sizeof *alp); + alp = alp -> ad_next; + } + *alp = *ap; + alp -> ad_next = NULLADDR; + naddrs ++; + } + + if (ad_list == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list")); + rd_end (); + ppp_error_status = NOTOK; + return OK; + } + PP_NOTICE (("Processing msg %s to %s", this_msg, cur_host)); + return OK; +} + + +static int ros_work (fd, what) +int fd; +int what; +{ + int result; + caddr_t out; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + fd_set rfds; + + for (;;) { + PP_TRACE (("ros_work loop (%d, %d)", fd, what)); + FD_ZERO (&rfds); + FD_SET (fd, &rfds); + xselect (fd + 1, &rfds, NULLFD, NULLFD, NOTOK); + switch (result = RyWait (fd, NULLIP, &out, OK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + case OK: + case DONE: + if ((result = ros_indication (fd, roi)) != OK) + return result; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("unknown return from RoWaitRequest=%d", + result)); + return NOTOK; + } + break; + } + if (lastop == what) + return OK; + return NOTOK; +} + +/* */ + +static int ros_indication (sd, roi) +int sd; +register struct RoSAPindication *roi; +{ + int reply, + result; + + switch (roi -> roi_type) { + case ROI_INVOKE: + case ROI_RESULT: + case ROI_ERROR: + PP_LOG (LLOG_EXCEPTIONS, + ("unexpected indication type=%d", roi -> roi_type)); + return NOTOK; + + case ROI_UREJECT: + { + register struct RoSAPureject *rou = + &roi -> roi_ureject; + + if (rou -> rou_noid) + PP_LOG (LLOG_EXCEPTIONS, + ("RO-REJECT-U.INDICATION/%d: %s", + sd, RoErrString (rou -> rou_reason))); + else + PP_LOG (LLOG_EXCEPTIONS, + ("RO-REJECT-U.INDICATION/%d: %s (id=%d)", + sd, RoErrString (rou -> rou_reason), + rou -> rou_id)); + return NOTOK; + } + + case ROI_PREJECT: + { + register struct RoSAPpreject *rop = + &roi -> roi_preject; + + ros_advise (rop, "RO-REJECT-P.INDICATION"); + return NOTOK; + } + + case ROI_FINISH: + { + register struct AcSAPfinish *acf = &roi -> roi_finish; + struct AcSAPindication acis; + register struct AcSAPabort *aca = &acis.aci_abort; + + PP_TRACE (("A-RELEASE.INDICATION/%d: %d", + sd, acf -> acf_reason)); + + result = AcRelResponse (sd, reply = ACS_ACCEPT, + ACR_NORMAL, NULLPEP, 0, &acis); + + ACFFREE (acf); + + if (result == NOTOK) + acs_advise (aca, "A-RELEASE.RESPONSE"); + else + if (reply != ACS_ACCEPT) + break; + + return DONE; + } + /* NOTREACHED */ + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("unknown indication type=%d", roi -> roi_type)); + return NOTOK; + } + return OK; +} + +static int ros_result (sd, val, id) +int sd; +struct type_Qmgr_DeliveryStatus *val; +int id; +{ + struct RoSAPindication rois; + struct RoSAPindication *roi = &rois; + + if (val == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + id); + + if (RyDsResult (sd, id, (caddr_t) val, ROS_NOPRIO, roi) + == NOTOK) { + ros_advise (&roi -> roi_preject, "RESULT"); + return NOTOK; + } + return OK; +} + +/* ERRORS */ + +static void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s", event, buffer)); + if (ROS_FATAL (rop -> rop_reason)) + exit (1); +} + +/* */ + +static void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s (source %d)", event, buffer, + aca -> aca_source)); +} + +/* ERROR */ + +static int error (sd, err, param, id) +int sd, + err; +caddr_t param; +int id; +{ + struct RoSAPindication rois; + struct RoSAPindication *roi = &rois; + + if (RyDsError (sd, id, err, param, ROS_NOPRIO, roi) == NOTOK) { + ros_advise (&roi -> roi_preject, "ERROR"); + return NOTOK; + } + + return OK; +} + +static int ureject (sd, reason, rox, roi) +int sd, + reason; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) { + ros_advise (&roi -> roi_preject, "U-REJECT"); + return NOTOK; + } + + return OK; +} + +static char *bigendian (addr) +char *addr; +{ + extern int ap_outtype; + static char *newaddr = NULLCP; + AP_ptr tree = NULLAP, + group = NULLAP, + name = NULLAP, + local = NULLAP, + domain = NULLAP, + route = NULLAP; + + if (newaddr) { + free (newaddr); + newaddr = NULLCP; + } + + + ap_outtype = AP_PARSE_733 | AP_PARSE_BIG; + + + if (ap_s2p (addr, &tree, &group, &name, &local, &domain, &route) + == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to parse (s2p) Recipient addr %s", addr)); + return NULLCP; + } + + + if ((newaddr = ap_p2s (group, name, local, domain, route)) + == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to parse (p2s) Recipient addr %s", addr)); + newaddr = NULLCP; + } + + ap_free (tree); + + PP_NOTICE (("Recipient Address '%s'", newaddr)); + return newaddr; +} + +#if PP_DEBUG > PP_DEBUG_NONE +static int debug_init () +{ + char buf[BUFSIZ], *p; + + fprintf (stderr, "Running in debug mode\nInput channel name: "); + ppp_debug = 1; + (void) fflush (stderr); + + if (fgets (buf, sizeof buf, stdin) == NULL) + return NOTOK; + if ((p = index (buf, '\n')) != NULLCP) + *p = '\0'; + if ((mychan = ch_nm2struct (buf)) == NULLCHAN) { + PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p)); + return NOTOK; + } + return OK; +} + +static int debug_nextmsg () +{ + char buf[BUFSIZ], *p; + int num; + struct type_Qmgr_ProcMsg *arg; + struct type_Qmgr_UserList *temp, *tail = NULL; + + fprintf (stderr, "Input message name: "); + (void) fflush (stderr); + + if (fgets (buf, sizeof buf, stdin) == NULL) + return NOTOK; + if ((p = index (buf, '\n')) != NULLCP) + *p = '\0'; + arg = (struct type_Qmgr_ProcMsg *) calloc (1, sizeof *arg); + arg -> qid = str2qb (buf, strlen (buf), 1); + arg -> channel = str2qb (mychan -> ch_name, + strlen (mychan -> ch_name), 1); + fprintf (stderr, "Input recipients terminated by -1: "); + fflush (stderr); + + do { + scanf ("%d", &num); + if (num != -1) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof *temp); + temp -> RecipientId = (struct type_Qmgr_RecipientId *) + calloc (1, sizeof *temp->RecipientId); + temp -> RecipientId -> parm = num; + if (arg -> users) { + tail -> next = temp; + tail = temp; + } + else + arg -> users = tail = temp; + } + } while (num != -1); + while ((num = getchar()) != EOF && num != '\n') + continue; + return ppp_procfnx_aux (arg); +} + +static void pdeliverystatus (status) +struct type_Qmgr_DeliveryStatus *status; +{ + fprintf (stderr, "Delivery status\n"); + if (status == NULL) + fprintf (stderr, "Complete failure\n"); + else { + struct type_Qmgr_DeliveryStatus *ix = status; + while (ix != NULL) + { + pindividualdeliverystatus(ix->IndividualDeliveryStatus); + ix = ix->next; + } + } +} + +static void pindividualdeliverystatus(status) +struct type_Qmgr_IndividualDeliveryStatus *status; +{ + fprintf (stderr, "Recipient %d: ", status->recipient->parm); + + switch (status->status) { + case int_Qmgr_status_success: + fprintf (stderr, "success"); + break; + case int_Qmgr_status_successSharedDR: + fprintf (stderr, "successSharedDR"); + break; + case int_Qmgr_status_failureSharedDR: + fprintf (stderr, "failureSharedDR"); + break; + case int_Qmgr_status_negativeDR: + fprintf (stderr, "negativeDR"); + break; + case int_Qmgr_status_positiveDR: + fprintf (stderr, "positiveDR"); + break; + case int_Qmgr_status_messageFailure: + fprintf (stderr, "message failure"); + break; + case int_Qmgr_status_mtaFailure: + fprintf (stderr, "mta failure"); + break; + case int_Qmgr_status_mtaAndMessageFailure: + fprintf (stderr, "mta and message failure"); + break; + default: + fprintf (stderr, "unknown"); + break; + } + putc ('\n', stderr); +} + +#endif + +static void cleanup_everything () +{ + if (hdrbuf != NULL) { + free (hdrbuf); + hdrbuf = NULL; + } + lastop = NOTOK; +} + +static char *mk_jnt (str) +char *str; +{ + char buf1[BUFSIZ], buf2[BUFSIZ]; + char *argv[30]; + int argc; + + strcpy (buf1, str); + argc = sstr2arg (buf1, 30, argv, "."); + + if (argc < 1) + return NULLCP; + strcpy (buf2, argv[--argc]); + while (--argc >= 0) { + strcat (buf2, "."); + strcat (buf2, argv[argc]); + } + return strdup (buf2); +} diff --git a/Chans/grey/tgreyin.c b/Chans/grey/tgreyin.c new file mode 100644 index 0000000..995a71b --- /dev/null +++ b/Chans/grey/tgreyin.c @@ -0,0 +1,86 @@ +/* tgreyin.c: test */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/grey/RCS/tgreyin.c,v 6.0 1991/12/18 20:10:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/grey/RCS/tgreyin.c,v 6.0 1991/12/18 20:10:19 jpo Rel $ + * + * $Log: tgreyin.c,v $ + * Revision 6.0 1991/12/18 20:10:19 jpo + * Release 6.0 + * + */ + +#include "util.h" + +static char *myname; +static char *host = "uk.co.xtel", *chan = "gb-janet"; + + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + while((opt = getopt(argc, argv, "c:h:")) != EOF) + switch (opt) { + case 'c': + chan = optarg; + break; + case 'h': + host = optarg; + break; + default: + fprintf (stderr, "Usage: %s\n", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc > 0) + while (argc --) { + FILE *fp; + char *ap = *argv++; + + if ((fp = fopen (ap, "r")) == NULL) { + fprintf (stderr, "Can't read %s\n", ap); + exit (1); + } + doit (fp); + fclose (fp); + } + else + doit (stdin); + exit (0); +} + +doit (fp) +FILE *fp; +{ + char *errstr; + char buf[BUFSIZ]; + int n; + + printf ("pp_open(%s,%s)\n", chan, host); + if (pp_open (chan, host, &errstr) != OK) { + printf ("FAILED in pp_open: %s\n", errstr); + return; + } + while ((n = fread (buf, 1, sizeof buf, fp)) > 0) { + printf ("pp_write (0, %*.*s, %d)\n", n, n, buf, n); + if (pp_write (0, buf, n) != n) { + printf ("FAILED in pp_write: %s\n", errstr); + return; + } + } + + printf ("pp_close (0)\n"); + if (pp_close (0) != OK) + printf ("FAILED in pp_close: %s\n", errstr); +} diff --git a/Chans/lists/Makefile b/Chans/lists/Makefile new file mode 100644 index 0000000..86a567e --- /dev/null +++ b/Chans/lists/Makefile @@ -0,0 +1,564 @@ +# dirlist Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/lists/RCS/Makefile,v 6.0 1991/12/18 20:10:43 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:10:43 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + +SRCS = DL_tables.c MD_tables.c \ + list.c dish.c dl.c dl_permit.c dl_util.c dl_x500.c \ + init.c lmnpq_dish.c or2addr.c \ + syn_oraddr.c syn_orname.c syn_permit.c syn_policy.c +OBJS = DL_tables.o MD_tables.o \ + list.o dirlist.o dish.o dl.o dl_permit.o dl_util.o dl_x500.o \ + init.o lmnpq_dish.o or2addr.o \ + syn_oraddr.o syn_orname.o syn_permit.o syn_policy.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +TBSRCS = list.c +TBOBJS = list.o + +OLIB = MD_tables.o DL_tables.o \ + syn_oraddr.o syn_orname.o syn_policy.o syn_permit.o \ + or2addr.o dl_util.o dl_x500.o dl_permit.o init.o hack.o \ + lmnpq_dish.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) -I$(PEPSYHDRS) + +#ILIBS = -ldsap -lisode +LIBS = $(LIBPP) $(LIBSYS) +LIBDISH = -ldish + +# GNU Readline (if needed by dish) +LIBRL = +#LIBRL = -lreadline -ltermcap +#LIBRL = -L /xtel/users/cjr/src/readline -lreadline -ltermcap + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LINTDSAP = /usr/local/lib/lint/llib-ldsap.ln +LINTISODE = /usr/local/lib/lint/llib-lisode.ln +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = $(LINTISODE) $(LINTDSAP) ../../Lib/llib-lpp.ln + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xdl xdirlist xlist + +default: $(PROGS) + +dirlist: xdirlist +lsd: xlsd +dl: xdl + +install: inst-channel inst-uip +inst-channel: inst-dir inst-dirlist inst-list +inst-uip: inst-dl + +# List channel using directory... +xdirlist: libdl.a dirlist.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ dirlist.o libdl.a $(LIBS) + +# dl - User interface +xdl: libdl.a dl.o hack.o $(LIBPP) + $(CC) $(LDOPTIONS) -o $@ dl.o libdl.a $(LIBS) + + +# if dish uses GNU Readline uncomment the following macro +LGNUREADLINE= # -lreadline -ltermcap + +# if you have ISODE > 6.8 then it is easiest to make xlsd in +# the ISODE tree as dish. See ISODE/config/OPTIONS for details. +# You then get MHS attributes in ALL DUAs. +xlsd: libdl.a dish.o $(QLIB) $(LIBPP) + -$(CC) $(OPTIONS) -o $@ dish.o \ + libdl.a $(LIBDISH) $(LIBS) $(LIBRL) $(LGNUREADLINE) + +dish.o: dish.c + $(CC) $(CFLAGS) -DUSE_PP -c $*.c + +dirlist.c: list.c + rm -f dirlist.c + ln list.c dirlist.c + +dirlist.o: dirlist.c + $(CC) $(CFLAGS) -DDIRLIST -c dirlist.c + +libdl: + rm -f libdl.a + $(AR) $(ARFLAGS)r $@.a $(OLIB) + $(RANLIB) $@.a + +libdl.a: $(OLIB) + $(AR) $(ARFLAGS)r $@ $? + $(RANLIB) $@ + +lint: l-dirlist l-list + +l-dirlist: $(SRCS) + $(LINT) $(LLFLAGS) -DDIRLIST $(SRCS) $(LINTLIBS) + + +inst-dirlist: $(CHANDIR)/dirlist + +$(CHANDIR)/dirlist: xdirlist + -$(BACKUP) $@ zxdirlist + rm -f $@ + $(INSTALL) xdirlist $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dirlist channel installed normally"; echo "" + +inst-dl: $(USRBINDIR)/dl + +$(USRBINDIR)/dl: xdl + -$(BACKUP) $@ zxdl + rm -f $@ + $(INSTALL) xdl $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + +# could install this as dish. +# and link 'lmnpq' to 'list' +inst-lsd: $(USRBINDIR)/lsd + +$(USRBINDIR)/lsd: xlsd + @echo You might want to install this a dish \! + -$(BACKUP) $@ zxlsd + rm -f $@ + $(INSTALL) xlsd $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) $(OLIB) DL* MD* libdl.a dirlist.c \ + $(HEADERS)/MD-types.h $(HEADERS)/MD_defs.h \ + $(HEADERS)/MD_pre_defs.h \ + $(HEADERS)/DL-types.h $(HEADERS)/DL_defs.h \ + $(HEADERS)/DL_pre_defs.h + +tidy: + rm -f core a.out *.cld $(PROGS) *.BAK zx* *.ph \ + xufn xtest xlsd + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + +.py.c:; $(PEPY) $*.py + +.py.o:; $(PEPY) $*.py + $(CC) $(CFLAGS) -c $*.c + +IOB.ph: ../../Lib/x400/IOB.ph + cp ../../Lib/x400/IOB.ph . + +MD-types.h MD_tables.c: md.py IOB.ph dlist.h + $(PEPSY) -i dlist.h -A md.py + cp MD-types.h $(HEADERS) + -if [ -f MD_defs.h ]; then \ + cp MD_defs.h MD_pre_defs.h $(HEADERS); \ + fi + +DL-types.h DL_tables.c: dl.py dlist.h + $(PEPSY) -i dlist.h -A dl.py + cp DL-types.h $(HEADERS) + -if [ -f DL_defs.h ]; then\ + cp DL_defs.h DL_pre_defs.h $(HEADERS); \ + fi + +MD_tables.c: DL_tables.c + +#dish.c: $(ISODESRC)/quipu/dish/dish.c +# @echo WARNING $? has changed \! + +############################################################ +# +# table based list channel +# +############################################################ + +list: xlist + +xlist: $(TBOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(TBOBJS) $(LIBPP) $(LIBSYS) + +l-list: $(TBSRCS) + $(LINT) $(LLFLAGS) $(TBSRCS) $(LINTLIBS) + +inst-list: $(CHANDIR)/list +$(CHANDIR)/list: xlist + -$(BACKUP) $@ zxlist + rm -f $@ + $(INSTALL) xlist $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "list channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +DL_tables.o: DL_tables.c +DL_tables.o: DL-types.h +DL_tables.o: dlist.h +DL_tables.o: ../../h/util.h +DL_tables.o: ../../h/config.h +DL_tables.o: ../../h/ll_log.h +DL_tables.o: ../../h/or.h +DL_tables.o: DL-types.h +DL_tables.o: MD-types.h +DL_tables.o: dlist.h +DL_tables.o: ../../h/IOB-types.h +DL_tables.o: ../../h/MTA-types.h +DL_tables.o: ../../h/Toks-types.h +DL_tables.o: ../../h/Auth-types.h +MD_tables.o: MD_tables.c +MD_tables.o: MD-types.h +MD_tables.o: dlist.h +MD_tables.o: ../../h/util.h +MD_tables.o: ../../h/config.h +MD_tables.o: ../../h/ll_log.h +MD_tables.o: ../../h/or.h +MD_tables.o: DL-types.h +MD_tables.o: dlist.h +MD_tables.o: MD-types.h +MD_tables.o: ../../h/IOB-types.h +MD_tables.o: ../../h/MTA-types.h +MD_tables.o: ../../h/Toks-types.h +MD_tables.o: ../../h/Auth-types.h +list.o: list.c +list.o: ../../h/util.h +list.o: ../../h/config.h +list.o: ../../h/ll_log.h +list.o: ../../h/head.h +list.o: ../../h/util.h +list.o: ../../h/retcode.h +list.o: ../../h/qmgr.h +list.o: ../../h/Qmgr-types.h +list.o: ../../h/Qmgr-ops.h +list.o: ../../h/chan.h +list.o: ../../h/table.h +list.o: ../../h/list_bpt.h +list.o: ../../h/q.h +list.o: ../../h/adr.h +list.o: ../../h/list_rchan.h +list.o: ../../h/chan.h +list.o: ../../h/auth.h +list.o: ../../h/list_bpt.h +list.o: ../../h/extension.h +list.o: ../../h/mta.h +list.o: ../../h/adr.h +list.o: ../../h/list_bpt.h +list.o: ../../h/aparse.h +list.o: ../../h/ap.h +list.o: ../../h/util.h +list.o: ../../h/or.h +list.o: ../../h/chan.h +list.o: ../../h/auth.h +list.o: ../../h/list_rchan.h +list.o: ../../h/mta.h +list.o: ../../h/dr.h +list.o: ../../h/extension.h +list.o: ../../h/mta.h +list.o: ../../h/or.h +list.o: ../../h/prm.h +list.o: ../../h/dl.h +list.o: ../../h/retcode.h +list.o: ../../h/sys.file.h +dish.o: dish.c +dl.o: dl.c +dl.o: dlist.h +dl.o: ../../h/util.h +dl.o: ../../h/config.h +dl.o: ../../h/ll_log.h +dl.o: ../../h/or.h +dl.o: DL-types.h +dl.o: dlist.h +dl.o: MD-types.h +dl.o: dlist.h +dl.o: ../../h/IOB-types.h +dl.o: ../../h/MTA-types.h +dl.o: ../../h/Toks-types.h +dl.o: ../../h/Auth-types.h +dl.o: ../../h/retcode.h +dl.o: ../../h/dl.h +dl_permit.o: dl_permit.c +dl_permit.o: dlist.h +dl_permit.o: ../../h/util.h +dl_permit.o: ../../h/config.h +dl_permit.o: ../../h/ll_log.h +dl_permit.o: ../../h/or.h +dl_permit.o: DL-types.h +dl_permit.o: dlist.h +dl_permit.o: MD-types.h +dl_permit.o: dlist.h +dl_permit.o: ../../h/IOB-types.h +dl_permit.o: ../../h/MTA-types.h +dl_permit.o: ../../h/Toks-types.h +dl_permit.o: ../../h/Auth-types.h +dl_permit.o: ../../h/adr.h +dl_permit.o: ../../h/list_rchan.h +dl_permit.o: ../../h/chan.h +dl_permit.o: ../../h/table.h +dl_permit.o: ../../h/list_bpt.h +dl_permit.o: ../../h/auth.h +dl_permit.o: ../../h/list_bpt.h +dl_permit.o: ../../h/extension.h +dl_permit.o: ../../h/mta.h +dl_permit.o: ../../h/adr.h +dl_permit.o: ../../h/list_bpt.h +dl_permit.o: ../../h/aparse.h +dl_permit.o: ../../h/ap.h +dl_permit.o: ../../h/util.h +dl_permit.o: ../../h/or.h +dl_permit.o: ../../h/chan.h +dl_permit.o: ../../h/auth.h +dl_permit.o: ../../h/list_rchan.h +dl_permit.o: ../../h/or.h +dl_util.o: dl_util.c +dl_util.o: dlist.h +dl_util.o: ../../h/util.h +dl_util.o: ../../h/config.h +dl_util.o: ../../h/ll_log.h +dl_util.o: ../../h/or.h +dl_util.o: DL-types.h +dl_util.o: dlist.h +dl_util.o: MD-types.h +dl_util.o: dlist.h +dl_util.o: ../../h/IOB-types.h +dl_util.o: ../../h/MTA-types.h +dl_util.o: ../../h/Toks-types.h +dl_util.o: ../../h/Auth-types.h +dl_util.o: ../../h/retcode.h +dl_util.o: ../../h/adr.h +dl_util.o: ../../h/list_rchan.h +dl_util.o: ../../h/chan.h +dl_util.o: ../../h/table.h +dl_util.o: ../../h/list_bpt.h +dl_util.o: ../../h/auth.h +dl_util.o: ../../h/list_bpt.h +dl_util.o: ../../h/extension.h +dl_util.o: ../../h/mta.h +dl_util.o: ../../h/adr.h +dl_util.o: ../../h/list_bpt.h +dl_util.o: ../../h/aparse.h +dl_util.o: ../../h/ap.h +dl_util.o: ../../h/util.h +dl_util.o: ../../h/or.h +dl_util.o: ../../h/chan.h +dl_util.o: ../../h/auth.h +dl_util.o: ../../h/list_rchan.h +dl_util.o: ../../h/or.h +dl_x500.o: dl_x500.c +dl_x500.o: dlist.h +dl_x500.o: ../../h/util.h +dl_x500.o: ../../h/config.h +dl_x500.o: ../../h/ll_log.h +dl_x500.o: ../../h/or.h +dl_x500.o: DL-types.h +dl_x500.o: dlist.h +dl_x500.o: MD-types.h +dl_x500.o: dlist.h +dl_x500.o: ../../h/IOB-types.h +dl_x500.o: ../../h/MTA-types.h +dl_x500.o: ../../h/Toks-types.h +dl_x500.o: ../../h/Auth-types.h +init.o: init.c +init.o: dlist.h +init.o: ../../h/util.h +init.o: ../../h/config.h +init.o: ../../h/ll_log.h +init.o: ../../h/or.h +init.o: DL-types.h +init.o: dlist.h +init.o: MD-types.h +init.o: dlist.h +init.o: ../../h/IOB-types.h +init.o: ../../h/MTA-types.h +init.o: ../../h/Toks-types.h +init.o: ../../h/Auth-types.h +lmnpq_dish.o: lmnpq_dish.c +lmnpq_dish.o: dlist.h +lmnpq_dish.o: ../../h/util.h +lmnpq_dish.o: ../../h/config.h +lmnpq_dish.o: ../../h/ll_log.h +lmnpq_dish.o: ../../h/or.h +lmnpq_dish.o: DL-types.h +lmnpq_dish.o: dlist.h +lmnpq_dish.o: MD-types.h +lmnpq_dish.o: dlist.h +lmnpq_dish.o: ../../h/IOB-types.h +lmnpq_dish.o: ../../h/MTA-types.h +lmnpq_dish.o: ../../h/Toks-types.h +lmnpq_dish.o: ../../h/Auth-types.h +or2addr.o: or2addr.c +or2addr.o: dlist.h +or2addr.o: ../../h/util.h +or2addr.o: ../../h/config.h +or2addr.o: ../../h/ll_log.h +or2addr.o: ../../h/or.h +or2addr.o: DL-types.h +or2addr.o: dlist.h +or2addr.o: MD-types.h +or2addr.o: dlist.h +or2addr.o: ../../h/IOB-types.h +or2addr.o: ../../h/MTA-types.h +or2addr.o: ../../h/Toks-types.h +or2addr.o: ../../h/Auth-types.h +or2addr.o: ../../h/retcode.h +or2addr.o: ../../h/or.h +or2addr.o: ../../h/adr.h +or2addr.o: ../../h/list_rchan.h +or2addr.o: ../../h/chan.h +or2addr.o: ../../h/table.h +or2addr.o: ../../h/list_bpt.h +or2addr.o: ../../h/auth.h +or2addr.o: ../../h/list_bpt.h +or2addr.o: ../../h/extension.h +or2addr.o: ../../h/mta.h +or2addr.o: ../../h/adr.h +or2addr.o: ../../h/list_bpt.h +or2addr.o: ../../h/aparse.h +or2addr.o: ../../h/ap.h +or2addr.o: ../../h/util.h +or2addr.o: ../../h/or.h +or2addr.o: ../../h/chan.h +or2addr.o: ../../h/auth.h +or2addr.o: ../../h/list_rchan.h +syn_oraddr.o: syn_oraddr.c +syn_oraddr.o: ../../h/util.h +syn_oraddr.o: ../../h/config.h +syn_oraddr.o: ../../h/ll_log.h +syn_oraddr.o: ../../h/retcode.h +syn_oraddr.o: ../../h/adr.h +syn_oraddr.o: ../../h/list_rchan.h +syn_oraddr.o: ../../h/chan.h +syn_oraddr.o: ../../h/table.h +syn_oraddr.o: ../../h/list_bpt.h +syn_oraddr.o: ../../h/auth.h +syn_oraddr.o: ../../h/list_bpt.h +syn_oraddr.o: ../../h/extension.h +syn_oraddr.o: ../../h/mta.h +syn_oraddr.o: ../../h/adr.h +syn_oraddr.o: ../../h/list_bpt.h +syn_oraddr.o: ../../h/aparse.h +syn_oraddr.o: ../../h/ap.h +syn_oraddr.o: ../../h/util.h +syn_oraddr.o: ../../h/or.h +syn_oraddr.o: ../../h/chan.h +syn_oraddr.o: ../../h/auth.h +syn_oraddr.o: ../../h/list_rchan.h +syn_oraddr.o: ../../h/ap.h +syn_oraddr.o: dlist.h +syn_oraddr.o: ../../h/util.h +syn_oraddr.o: ../../h/or.h +syn_oraddr.o: DL-types.h +syn_oraddr.o: dlist.h +syn_oraddr.o: MD-types.h +syn_oraddr.o: dlist.h +syn_oraddr.o: ../../h/IOB-types.h +syn_oraddr.o: ../../h/MTA-types.h +syn_oraddr.o: ../../h/Toks-types.h +syn_oraddr.o: ../../h/Auth-types.h +syn_orname.o: syn_orname.c +syn_orname.o: ../../h/util.h +syn_orname.o: ../../h/config.h +syn_orname.o: ../../h/ll_log.h +syn_orname.o: ../../h/retcode.h +syn_orname.o: ../../h/adr.h +syn_orname.o: ../../h/list_rchan.h +syn_orname.o: ../../h/chan.h +syn_orname.o: ../../h/table.h +syn_orname.o: ../../h/list_bpt.h +syn_orname.o: ../../h/auth.h +syn_orname.o: ../../h/list_bpt.h +syn_orname.o: ../../h/extension.h +syn_orname.o: ../../h/mta.h +syn_orname.o: ../../h/adr.h +syn_orname.o: ../../h/list_bpt.h +syn_orname.o: ../../h/aparse.h +syn_orname.o: ../../h/ap.h +syn_orname.o: ../../h/util.h +syn_orname.o: ../../h/or.h +syn_orname.o: ../../h/chan.h +syn_orname.o: ../../h/auth.h +syn_orname.o: ../../h/list_rchan.h +syn_orname.o: ../../h/ap.h +syn_orname.o: dlist.h +syn_orname.o: ../../h/util.h +syn_orname.o: ../../h/or.h +syn_orname.o: DL-types.h +syn_orname.o: dlist.h +syn_orname.o: MD-types.h +syn_orname.o: dlist.h +syn_orname.o: ../../h/IOB-types.h +syn_orname.o: ../../h/MTA-types.h +syn_orname.o: ../../h/Toks-types.h +syn_orname.o: ../../h/Auth-types.h +syn_permit.o: syn_permit.c +syn_permit.o: dlist.h +syn_permit.o: ../../h/util.h +syn_permit.o: ../../h/config.h +syn_permit.o: ../../h/ll_log.h +syn_permit.o: ../../h/or.h +syn_permit.o: DL-types.h +syn_permit.o: dlist.h +syn_permit.o: MD-types.h +syn_permit.o: dlist.h +syn_permit.o: ../../h/IOB-types.h +syn_permit.o: ../../h/MTA-types.h +syn_permit.o: ../../h/Toks-types.h +syn_permit.o: ../../h/Auth-types.h +syn_policy.o: syn_policy.c +syn_policy.o: dlist.h +syn_policy.o: ../../h/util.h +syn_policy.o: ../../h/config.h +syn_policy.o: ../../h/ll_log.h +syn_policy.o: ../../h/or.h +syn_policy.o: DL-types.h +syn_policy.o: dlist.h +syn_policy.o: MD-types.h +syn_policy.o: dlist.h +syn_policy.o: ../../h/IOB-types.h +syn_policy.o: ../../h/MTA-types.h +syn_policy.o: ../../h/Toks-types.h +syn_policy.o: ../../h/Auth-types.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/lists/READ-ME b/Chans/lists/READ-ME new file mode 100644 index 0000000..73e2904 --- /dev/null +++ b/Chans/lists/READ-ME @@ -0,0 +1,123 @@ +This directory contains code for an X.500 Directory based list channel. + +The binaries made by default are: + +dirlist - the list channel itself. +dl - a Directory based replacement to mlist. +lsd - a version of Dish that knows about mail lists, and + the various X.400 attribute syntaxes. + +The user interfaces uses the concept of User Friendly Naming (ufn). +That is instead of using DN's you can enter strings such as + Robbins, UCL + Onions, Nottingham + Rose, Nyser, USA +and the 'ufn' code will interactively try to establish the correct DN. +UFN is described in full by an Steve Kille paper. +(You will need a ufnrc file, in your ETCDIR, this is installed from +the others/quipu/uips/fred directory of the ISODE source tree). + +The structure of the DIT: + +A directorty mail list needs 2 entries in the DIT. There are many +'working' examples of such lists under the X-Tel branch of the DIT. + +Fisrt off, there is the entry for the list itself. If the list is +called 'foobar'. Then the entry will have a commonName attribute of +'foobar'. This must be unique at this level in the DIT but does not +necassarily have to be the RDN. +This entry has the objectclass 'ppDistributionList'. +Attributes: + + mhsDLMembers - The members to send the mail to ! + Syntax is: ORName ::= $ + If you use the 'dl' interface, you don't need to specify the + ORaddress component as it is looked up in the DIT ! + Typically you would enter a UFN, and the directory + will do the rest. + + dl-policy - The list delivery policy + It is generaly best to leave this to the default + value, but if you want to change it the syntax is: + ::= $ $ + ::= 'TRUE' | 'FALSE' + -- If TRUE sub lists are allowed. + ::= 'ORIGINAL' | 'TRUE' | 'FALSE' + -- Is message content conversion allowed. + -- ORIGINAL implies use parameter fro original message + ::= 'ORIGINAL' | 'HIGH' | 'LOW' | 'NORMAL' + -- The priority to use when delivering the message + + mhsDLSubmitPermissions - Defines who can send to the list. + The default is a special token 'ALL' which permits + anybody to send mail to the list. However it is + possible to restrict the use of the list. The syntax is: + ::= | | | + ::= 'GROUP #' + -- Memeber of the X.500 group can send to the list + ::= 'INDIVIDUAL #' + -- The individual defined by ORName may send. + ::= 'MEMBER #' + -- A Member of the named list may send. + -- Only works if the named list is also directory based. + ::= 'PATTERN #' + -- Anybody who's ORName Matches the pattern can send. + -- E.g if was 'c=GB', then only people in 'GB" could send + + owner - This is the DN of the manager of the list. + The manager should be represented by a pp-role entry. + In the foobar example it would have a commonName of + foobar-request. + + +Pretty complex eh? +Don't worry - there is a tool to do it all for you! + +First of all, in the pp-tailor file you will need someting like the +following to configure the dirlist channel... + +chan dirlist prog=dirlist, + show="via Directory List Channel",type=both + chanout=dr2rfc,adr=x400, + +You can also specify a name to bind with using the info field. e.g., + info="dn= c=GB@o=X-Tel Serives Ltd@cn=foobar" +optionally with a password: + info="dn= c=GB@o=X-Tel Serives Ltd@cn=foobar,password=Secret" + + +Now to create a list itself. +Say you want to create a list called 'foobar'. The first step is to +set up a local user 'foobar', to be expanded by the dirlist channel: + + foobar: dirlist + +And an alias for foobar-request + + foobar-request: alias somebody-else + + +The rest is done by the 'dl' tools. +Run + dl -m -u MANAGER-DN +Where MANAGER-DN is the DN of a user who as write access to the local +part of the directory tree. +At the prompt type 'c' for create. +Having answered a questions, such as the name of the list manager +the list will be created. +The list manager can then add names using the dl tool. + +Instead of typing 'c', you can use the 'u' option to convert a PP +tables list to a directory list. + +It is advisable to monitor the lists to see if any DNs or mail +addresses change. The dl tools can be used to check the list out, and +make any changes. +I run 'dl -f -m -q' from cron twice a week. +This checks all local mail lists, mailing the list manager if there is +a problem with the list. Without the -m flag the errors are reported +to stdout. + +The list manager can then update the list with the dl tool. + +Colin Robbins, xtel, GB diff --git a/Chans/lists/dish.c b/Chans/lists/dish.c new file mode 100644 index 0000000..dbfed37 --- /dev/null +++ b/Chans/lists/dish.c @@ -0,0 +1,93 @@ +/* dish.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/dish.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dish.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dish.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + +/* Taken from ISODE quipu/dish/dish.c */ + +#ifdef USE_PP +#include +#include +#else +#include "manifest.h" +#include "quipu/util.h" +#endif + +/* + OPTIONS... + + USE_PP: Build a version of dish with the PP enhancements. + Needs libpp.a and libdl.a from PP (PP 4.2 and above). + Made automatically in PP/Tools/dlist. + + MANAGE: Build a management version of Dish. + Needs libmanage.a from ISODE/others/quipu/uips/manage + Made automatically in ISODE/others/quipu/uips/manage. + + + */ + +#ifdef MANAGE +IFP call_add_alias (); +IFP call_del_alias (); +IFP call_alias_chk (); +#endif + +#ifdef USE_PP +IFP call_dlist (); +#endif + +main (argc, argv) +int argc; +char **argv; +{ + + quipu_syntaxes (); + +#ifdef REVOKE_SYNTAX + revoke_syntax(); +#endif + +#ifdef USE_PP + pp_quipu_init (argv[0]); +#endif + + dish_init (argc,argv); + +#ifdef USE_PP + pp_quipu_run (); + + add_dish_command ("lmnpq", call_dlist, 2); + add_dish_help ("lmnpq", "[-dncheck] [-orcheck] [-orupdate] [-check] [-update]", + FALSE, FALSE, + "List Manager Now using PP and Quipu,"); +#endif + +#ifdef MANAGE + add_dish_command ("add_alias", call_add_alias, 5); + add_dish_help ("add_alias", " ", FALSE, FALSE, + "add an alias entry,"); + add_dish_command ("del_alias", call_del_alias, 5); + add_dish_help ("del_alias", "", FALSE, FALSE, + "delete an alias entry,"); + add_dish_command ("alias_chk", call_alias_chk, 5); + add_dish_help ("alias_chk", "", FALSE, FALSE, + "Check alias or all aliases below ,"); +#endif + + add_dish_help ("quit","", FALSE, FALSE, "Quit the program."); + add_dish_help (NULLCP,NULLCP,0,0,NULLCP); + + do_dish (); +} diff --git a/Chans/lists/dl.c b/Chans/lists/dl.c new file mode 100644 index 0000000..0d3653d --- /dev/null +++ b/Chans/lists/dl.c @@ -0,0 +1,1919 @@ +/* dl.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dl.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include "retcode.h" +#include +#include /* ds_search uses di_block - include this for lint !!! */ +#include +#include +#include +#include "dl.h" + +extern LLog *log_dsap; +extern char * tailfile; +extern char * dsa_address; +extern char * myname; +extern char * local_dit; +extern char *postmaster; +extern Attr_Sequence current_print; +extern AttributeType at_Member; +extern AttributeType at_ObjectClass; +extern AttributeType at_Permit; +extern AttributeType at_Policy; +extern char * dn2str(); +extern char * dn2ufn(); + +extern Filter strfilter(), ocfilter(), joinfilter(); + +DN localdn = NULLDN; +DN user = NULLDN; +extern int str2dl(); +DN get_manager_dn(); +DN mail2dn(); +DN dl_str2ufn (); +char * userstr; +char * strdl = NULLCP; +char manager_mode = FALSE; +char verify = FALSE; +char quiet = FALSE; +char printdl = FALSE; +Attr_Sequence ufn_dl; + +ORName * ufn_orName_parse(); +extern OR_ptr orAddr_parse_user(); + +char * pager; +FILE * out; + +ORName * user_in_list (); +ORName * addr_in_list (); + +main (argc, argv) +int argc; +char **argv; +{ +DN dn_dl = NULLDN; +int n = 1; + sys_init(argv[0]); + + quipu_syntaxes (); + + pp_syntaxes (); + or_myinit(); + + dsap_init (&n, &argv); + log_dsap -> ll_file = strdup ("dsap.log"); + + (void) pp_quipu_run (); + + if ((pager = getenv("PAGER")) == NULL) + pager = "more"; + + if (local_dit) + localdn = str2dn (local_dit); + + do_args (argc,argv, &dn_dl); + + if (dn_dl) + do_list (dn_dl,strdl); + else + do_select (); + + dl_unbind (); +} + +do_args (argc,argv,dn_dl) +int argc; +char **argv; +DN *dn_dl; +{ +int x, res; +char * dsa = NULLCP; +char * passwd = NULLCP; +char buf [LINESIZE]; + + for (x=1; x] [-c ] [listname] -m -q -v -p\n",argv[0]); + exit (-1); + } else + strdl = argv[x]; + } + + if (printdl && !strdl) { + (void) fprintf (stderr,"print which list ?\n"); + exit (-1); + } + + if (dsa != NULLCP) { + FILE *fp; + char save_bdsa[LINESIZE]; + + (void) strcpy (myname = save_bdsa, dsa); + dsa_address = NULLCP; + + /* read tailor file to get address */ + + if( (fp = fopen(isodefile(tailfile, 0), "r")) == (FILE *)NULL) { + (void) fprintf (stderr,"can't open %s",tailfile); + exit (-1); + } + + while(fgets(buf, sizeof(buf), fp) != NULLCP) + if ( (*buf != '#') && (*buf != '\n') ) + /* not a comment or blank */ + (void) tai_string (buf); + + (void) fclose(fp); + + if (dsa_address == NULLCP) + dsa_address = myname; + } + + if (user == NULLDN) { + /* try ~/.quipurc */ + + FILE * file; + char * home, *p, *part1, *part2, *TidyString(); + char Dish_Home[LINESIZE]; + char Read_in_Stuff[LINESIZE]; + + if (home = getenv ("QUIPURC")) + (void) strcpy (Dish_Home, home); + else + if (home = getenv ("HOME")) + (void) sprintf (Dish_Home, "%s/.quipurc", home); + else + (void) strcpy (Dish_Home, "./.quipurc"); + + if ((file = fopen (Dish_Home, "r")) != 0) { + while (fgets (Read_in_Stuff, LINESIZE, file) != 0) { + p = SkipSpace (Read_in_Stuff); + if (( *p == '#') || (*p == '\0')) + continue; /* ignore comments and blanks */ + + part1 = p; + if ((part2 = index (p,':')) == NULLCP) + continue; + + *part2++ = '\0'; + part2 = TidyString (part2); + + if (lexequ (part1, "username") == 0) { + userstr = strdup (part2); + user = str2dn (userstr); + } else if (lexequ (part1, "password") == 0) + passwd = strdup (part2); + } + (void) fclose (file); + } + } + + if ((user != NULLDN) && (passwd == NULLCP)) { + (void) sprintf (buf,"Enter password for \"%s\": ",userstr); + (void) strcpy (buf,getpassword (buf)); + passwd = buf; + + } + + if (dl_bind (user,passwd) == NOTOK) { + (void) fprintf (stderr,"Attempt to connect to DSA failed\n"); + exit (-1); + } + + if (strdl) + if ((res = str2dl (strdl,localdn, dn_dl)) != OK) { + if (res == NOTOK) + (void) fprintf (stderr,"Unknown list '%s'\n",strdl); + else + (void) fprintf (stderr,"Temporary failure for '%s'\n",strdl); + exit (-1); + } +} + +static void openpager(ps) +PS ps; +{ + (void) ps_flush (ps); + + if (isatty(fileno((FILE *)ps->ps_addr)) == 0) { + out = stdout; + } else if ((out = popen(pager,"w")) == NULL) { + (void) fprintf(stderr,"unable to start pager '%s'",pager); + out = stdout; + } + + ps->ps_addr = (caddr_t) out; +} + +static void closepager(ps) +PS ps; +{ + (void) ps_flush(ps); + + if (out != stdout) { + (void) pclose(out); + out = stdout; + } + + ps->ps_addr = (caddr_t) out; +} + +do_select () +{ +int quit = FALSE; +char buf[BUFSIZ], + tmpbuf[BUFSIZ], + ch; +PS ps; +DN dn_dl; +DN newloc; +int res; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + (void) fprintf (stderr,"Can't set up output (3)\n"); + return; + } + if (std_setup (ps, stdout) == NOTOK) { + (void) fprintf (stderr,"Can't set up output (4)\n"); + return; + } + + if (verify) { + select_all (ps); + return; + } + + while (quit == FALSE) { + (void) printf("\n> "); + (void) fflush (stdout); + if (gets (buf) == NULL) { + (void) printf ("\n"); + exit(OK); + } + compress (buf, buf); + if (buf[0] == NULL || strlen(buf) == 0) { + (void) printf("\nType 'h' or '?' for help\n"); + continue; + } + if ((int)strlen(buf) > 1) + ch = 'A'; + else if (*buf == '?') + ch = '?'; + else + ch = uptolow(*buf); + switch (ch) + { + case 'h': + case '?': + (void) printf ("\nOptions are:\n"); + (void) printf (" 'l'ist the list,\n"); + (void) printf (" 'c'reate a list,\n"); + (void) printf (" 'u'pgrade a list to a directory list,\n"); + (void) printf (" 'w'hich lists am I on,\n"); + (void) printf (" 'm'ove to somewhere else in the DIT,\n"); + (void) printf (" 'q'uit,\n"); + (void) printf (" OR, the name of a list to visit.\n"); + break; + case 'q': + quit = TRUE; + break; + case 'l': + openpager(ps); + dl_search (ps); + closepager(ps); + break; + case 'c': + if (!user) + (void) fprintf (stderr,"Don't know your distinguished name !\n"); + else if (dl_create (ps) == 0) + (void) printf ("Done\n"); + else + (void) fprintf (stderr,"\nList creation failed\n"); + break; + case 'u': + if (!user) + (void) fprintf (stderr,"Don't know your distinguished name !\n"); + else if (dl_upgrade (ps) == 0) + (void) printf ("Done\n"); + else + (void) fprintf (stderr,"\nList upgrade failed\n"); + break; + case 'w': + openpager(ps); + which_list (ps); + closepager(ps); + continue; + case 'm': + ps_print (ps,"Currently at '"); + ufn_dn_print (ps,localdn,FALSE); + ps_print (ps,"'\nEnter new location: "); + (void) ps_flush (ps); + if ((gets(tmpbuf) == NULL) || (tmpbuf == NULLCP) || (*tmpbuf == 0)) { + ps_print (ps,"\n(exit)\n"); + clearerr(stdin); + break; + } + compress (tmpbuf, tmpbuf); + if ((newloc = dl_str2ufn (tmpbuf)) != NULLDN) { + (void) printf ("Moved!\n"); + localdn = newloc; + } + break; + case 'A': + if ((res = str2dl (buf,localdn,&dn_dl)) == OK) { + (void) fprintf (stderr,"Reading '%s'...\n",buf); + do_list (dn_dl,buf); + } else { + if (res == NOTOK) + (void) fprintf (stderr,"Unknown list '%s'\n",buf); + else + (void) fprintf (stderr,"Temporary failure '%s'\n",buf); + } + break; + default: + (void) printf("\nType 'h' or '?' for help\n"); + break; + } + } + ps_free (ps); +} + +static ORName * num2or (num) +int num; +{ +Attr_Sequence as; +AV_Sequence avs; +int i = 1; + + if (current_print == NULLATTR) { + (void) fprintf (stderr,"List has changed - check number!!!\n"); + return NULLORName; + } + + if ((as = as_find_type (current_print,at_Member)) == NULLATTR) { + (void) fprintf (stderr,"List has changed - check number!!!\n"); + return NULLORName; + } + + for(avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next, i++) + if (i == num) { + current_print = NULLATTR; + return (ORName *) avs->avseq_av.av_struct; + } + + (void) fprintf (stderr,"Number too high\n"); + return NULLORName; + +} + +do_list (dn_dl,prompt) +DN dn_dl; +char * prompt; +{ +Attr_Sequence as; +int quit = FALSE; +char buf[BUFSIZ], + tmpbuf[BUFSIZ], + ch; +PS ps; +ORName * orname; +char can_write; +ORName * on_list; +char re_read = FALSE; + + switch (dir_getdl_aux (dn_dl, &as)) { + case OK: + break; + case DONE: + (void) fprintf (stderr, "Temporary failure to read the list '%s'\n",dn2ufn(dn_dl,FALSE)); + return; + default: + (void) fprintf (stderr,"Can't read the list '%s'\n",dn2ufn(dn_dl,FALSE)); + return; + } + + if ((ps = ps_alloc (std_open)) == NULLPS) { + (void) fprintf (stderr,"Can't set up output\n"); + return; + } + if (std_setup (ps, stdout) == NOTOK) { + (void)fprintf (stderr,"Can't set up output (2)\n"); + return; + } + + if (printdl) { + dl_print (ps,dn_dl); + return; + } + + if (verify) { + if (manager_mode) + check_dl_members (ps,dn_dl,as,TRUE,TRUE,TRUE,quiet); + else + check_dl_members (ps,dn_dl,as,TRUE,TRUE,FALSE,quiet); + return; + } + + if (!(can_write = can_user_write (as,user))) { + if (!quiet) + (void) printf("Only the manager can modify this list.\n"); + on_list = user_in_list (as,user); + } + + + while (quit == FALSE) { + + if (re_read) { + switch (dir_getdl_aux (dn_dl, &as)){ + case OK: + break; + case DONE: + (void) fprintf (stderr, "Temporary failure to re-read the list\n"); + return; + default: + (void) fprintf (stderr,"Can't re-read the list!\n"); + return; + } + if (!(can_write = can_user_write (as,user))) + on_list = user_in_list (as,user); + + re_read = FALSE; + } + + (void) printf("\n%s> ",prompt); + (void) fflush (stdout); + if (gets (buf) == NULL) { + clearerr (stdin); + (void) printf("\n"); + return; + } + compress (buf, buf); + if (buf[0] == NULL || strlen(buf) == 0) { + (void) printf("\nType 'h' or '?' for help\n"); + continue; + } + if ((int)strlen(buf) > 1) + ch = 'Z'; + else if (*buf == '?') + ch = '?'; + else + ch = uptolow(*buf); + switch (ch) + { + case 'h': + case '?': + (void) printf ("\nOptions are:\n"); + (void) printf (" 'p'rint to view the list,\n"); + (void) printf (" 'f'ind entry in the list\n"); + (void) printf (" 'c'heck the list, reporting errors,\n"); + if (can_write) { + (void) printf (" 'v'alidate the list, updating errors,\n"); + (void) printf (" 'r'emove an entry from the list,\n"); + (void) printf (" 'm'odify attributes (owner, policy and permission),\n"); + (void) printf (" 'q'uit,\n"); + (void) printf (" OR, enter an ORName to add to the list.\n"); + } else { + if (on_list) + (void) printf (" 'r'emove yourself from the list,\n"); + else if (user) + (void) printf (" 'a'dd yourself to the list,\n"); + (void) printf (" 'q'uit.\n"); + } + break; + case 'q': + quit = TRUE; + break; + case 'p': + openpager(ps); + dl_print (ps,dn_dl); + closepager(ps); + break; + case 'f': + (void) printf ("give name to check: "); + if ((gets(tmpbuf) == NULL) || (tmpbuf == NULLCP) || (*tmpbuf == 0)) { + ps_print (ps,"\n(exit)\n"); + clearerr(stdin); + break; + } + compress (tmpbuf, tmpbuf); + orname = ufn_orName_parse (tmpbuf,as); + + if (orname != NULLORName) { + ps_print (ps,"Found: "); + orName_print (ps,orname,UFNOUT); + } + break; + + case 'r': + if (! can_write) { + if (on_list) { + if (! user) + goto wally; + (void) mail_manager (ps,user,TRUE,as,dn_dl); + break; + } + goto wally; + } + (void) printf ("give username to be removed: "); + if ((gets(tmpbuf) == NULL) || (tmpbuf == NULLCP) || (*tmpbuf == 0)) { + ps_print (ps,"\n(exit)\n"); + clearerr(stdin); + break; + } + compress (tmpbuf, tmpbuf); + if (isdigit (*tmpbuf)) + orname = num2or (atoi(tmpbuf)); + else + orname = ufn_orName_parse (tmpbuf,as); + + if (orname != NULLORName) { + if (check_list (ps,orname,as,dn_dl,TRUE)) { + if (! orname_confirm(ps,orname,TRUE)) { + clearerr(stdin); + break; + } + ps_print (ps,"Removing...\n"); + (void) dl_modify (ps,orname,dn_dl,TRUE); + re_read = TRUE; + } + } + break; + case 'c': + switch (dir_getdl_aux (dn_dl, &as)) { + case OK: + break; + case DONE: + fprintf (stderr, "Temporary failure to read the list\n"); + break; + default: + (void) fprintf (stderr,"Can't read the list\n"); + break; + } + openpager(ps); + check_dl_members (ps,dn_dl,as,TRUE,TRUE,FALSE,quiet); + closepager(ps); + break; + case 'v': + if (! can_write) + goto wally; + switch (dir_getdl_aux (dn_dl, &as)) { + case OK: + break; + case DONE: + (void) fprintf (stderr, "Temporary failure to read the list\n"); + break; + default: + (void) fprintf (stderr,"Can't read the list\n"); + break; + } + check_dl_members (ps,dn_dl,as,TRUE,TRUE,TRUE,quiet); + re_read = TRUE; + break; + case 'a': + if (! can_write) { + if (on_list) { + ps_print (ps,"You are already on the list!\n"); + } else { + if (!user) + goto wally; + (void) mail_manager (ps,user,FALSE,as,dn_dl); + } + } else + (void) printf("\nType 'h' or '?' for help\n"); + break; + case 'm': + if (! can_write) + goto wally; + else + modify_dl_attrs (ps,dn_dl,as); + break; + case 'Z': + if (! can_write) { +wally:; + if (user) { + ps_print (ps,"\nYou do not have sufficient access rights to modify the list,\n"); + ps_print (ps,"You should contact the list manager ("); + ufn_dn_print (ps,get_manager_dn(as,TRUE),FALSE); + ps_print (ps,").\n"); + } else { + ps_print (ps,"\nI don't know who you are.\n"); + } + break; + + } else if ((orname = ufn_orName_parse (buf,NULLATTR)) != NULLORName) + if (check_list (ps,orname,as,dn_dl,FALSE)) { + if (orname_confirm(ps,orname,FALSE)) { + (void) dl_modify(ps,orname,dn_dl,FALSE); + re_read = TRUE; + } + } + break; + default: + (void) printf("\nType 'h' or '?' for help\n"); + break; + } + } + ps_free (ps); +} + +check_list (ps,orname,as,dn_dl,remove) +PS ps; +ORName * orname; +Attr_Sequence as; +DN dn_dl; +char remove; +{ +ORName * or; + + if (orname->on_dn) + if (or = user_in_list (as,orname->on_dn)) /* Assign */ + goto out; + + if (orname->on_or) { + if (or = addr_in_list (as,orname->on_or)) { /* Assign */ +out:; + if (remove) + return TRUE; + else { + ps_print (ps,"'"); + orName_print (ps,or,UFNOUT); + ps_print (ps,"' is already on the list!\n"); + (void) check_ORName (ps,or,TRUE,TRUE,FALSE,dn_dl,FALSE); + return FALSE; + } + } + } + + if (remove) { + ps_print (ps,"'"); + orName_print (ps,or,UFNOUT); + ps_print (ps,"' is not on the list!\n"); + return FALSE; + } + + return check_ORName (ps,orname,TRUE,TRUE,FALSE,dn_dl,FALSE); + +} + +dl_search (ps) +PS ps; +{ +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filt; +EntryInfo * ptr; + + if ((filt = ocfilter ("ppDistributionList")) == NULLFILTER) + return; + + search_arg.sra_baseobject = localdn; + search_arg.sra_filter = filt; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = FALSE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = NULLATTR; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + filter_free (filt); + log_ds_error (&err); + ds_error_free (&err); + (void) fprintf (stderr,"Search returned an error !\n"); + return; + } + + ps_print (ps,"Found the following lists:"); + + for (ptr = result.CSR_entries; ptr != NULLENTRYINFO; ptr=ptr->ent_next) { + ps_print (ps,"\n "); + ufn_dn_print (ps,ptr->ent_dn,FALSE); + } + ps_print (ps,"\n"); +} + + +select_all (ps) +PS ps; +{ +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filt; +EntryInfo * ptr; +int res; +Attr_Sequence as; +static PS nps = NULLPS; + + if (nps == NULL + && ((nps = ps_alloc (str_open)) == NULLPS) + || str_setup (nps, NULLCP, BUFSIZ, 0) == NOTOK) { + if (nps) + ps_free (nps), nps = NULLPS; + + return; + } + + + if ((filt = ocfilter ("ppDistributionList")) == NULLFILTER) + return; + + search_arg.sra_baseobject = localdn; + search_arg.sra_filter = filt; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = FALSE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = NULLATTR; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + filter_free (filt); + log_ds_error (&err); + ds_error_free (&err); + ps_printf (ps,"Can't find any lists\n"); + return; + } + + for (ptr = result.CSR_entries; ptr != NULLENTRYINFO; ptr=ptr->ent_next) { + nps -> ps_base = NULL, nps -> ps_cnt = 0; + nps -> ps_ptr = NULL, nps -> ps_bufsiz = 0; + + switch (dir_getdl_aux (ptr->ent_dn, &as)) { + case OK: + res = check_dl_members (nps,ptr->ent_dn,as,TRUE,TRUE,FALSE,quiet); + if (res == NOTOK) { + if (manager_mode) { + ps_print (ps,"\nErrors found in list '"); + ufn_dn_print (ps,ptr->ent_dn,FALSE); + ps_print (ps,"' (manager informed).\n\n"); + *--nps -> ps_ptr = NULL, nps -> ps_cnt++; + message2manager (ptr->ent_dn,nps->ps_base); + } else { + ps_print (ps,"\nErrors found in list '"); + ufn_dn_print (ps,ptr->ent_dn,FALSE); + *--nps -> ps_ptr = NULL, nps -> ps_cnt++; + ps_printf (ps,"'\n%s\n\n",nps->ps_base); + } + } + break; + case DONE: + break; + default: + ps_printf (ps,"Can't read the list '%s'\n",dn2ufn(ptr->ent_dn,FALSE)); + } + } +} + +which_list (ps) +PS ps; +{ +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filt_dl, filt_dn, filt_oraddr, filt_or, filt_and, filt_dn2; +EntryInfo * ptr; +AttributeValue av; +ORName * or, * orName_parse(); +OR_ptr newor, as2or(), saveor; +Attr_Sequence as; + + if (user == NULLDN) { + (void) fprintf (stderr,"You did not supply a name at the start, so I don't know who you are!\n"); + return; + } + + or = ufn_orName_parse (userstr,NULLATTR); + if (dn2addr (or->on_dn, &as) == OK) + newor = as2or (as); + + if (newor == NULLOR) { + (void) fprintf (stderr,"Can't work out your mail adddress\n"); + return; + } + or->on_or = newor; + + av = AttrV_alloc (); + av->av_struct = (caddr_t) or; + + av->av_syntax = at_Member->oa_syntax; + + filt_dn = filter_alloc (); + filt_dn->flt_next = NULLFILTER; + filt_dn->flt_type = FILTER_ITEM; + filt_dn->FUITEM.fi_type = FILTERITEM_EQUALITY; + filt_dn->FUITEM.UNAVA.ava_type = AttrT_cpy(at_Member); + filt_dn->FUITEM.UNAVA.ava_value = AttrV_cpy (av); + + filt_dn2 = filter_alloc (); + filt_dn2->flt_next = filt_dn; + filt_dn2->flt_type = FILTER_ITEM; + filt_dn2->FUITEM.fi_type = FILTERITEM_EQUALITY; + filt_dn2->FUITEM.UNAVA.ava_type = AttrT_cpy(at_Member); + saveor = or->on_or; + or->on_or = NULLOR; + filt_dn2->FUITEM.UNAVA.ava_value = AttrV_cpy (av); + or->on_or = saveor; + + dn_free (or->on_dn); + or->on_dn = NULLDN; + + filt_oraddr = filter_alloc (); + filt_oraddr->flt_next = filt_dn2; + filt_oraddr->flt_type = FILTER_ITEM; + filt_oraddr->FUITEM.fi_type = FILTERITEM_EQUALITY; + filt_oraddr->FUITEM.UNAVA.ava_type = AttrT_cpy(at_Member); + filt_oraddr->FUITEM.UNAVA.ava_value = av; + + filt_or = joinfilter (filt_oraddr,FILTER_OR); + + if ((filt_dl = ocfilter ("ppDistributionList")) == NULLFILTER) + return; + + filt_dl->flt_next = filt_or; + + filt_and = joinfilter (filt_dl,FILTER_AND); + + search_arg.sra_baseobject = localdn; + search_arg.sra_filter = filt_and; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = FALSE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = NULLATTR; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + filter_free (filt_and); + log_ds_error (&err); + ds_error_free (&err); + (void) fprintf (stderr,"Search failed\n"); + return; + } + filter_free (filt_and); + + ps_print (ps,"You are on the following:"); + + for (ptr = result.CSR_entries; ptr != NULLENTRYINFO; ptr=ptr->ent_next) { + ps_print (ps,"\n "); + ufn_dn_print (ps,ptr->ent_dn,FALSE); + } + ps_print (ps,"\n"); +} + +can_user_write (as,thisuser) +Attr_Sequence as; +DN thisuser; +{ +DN manager; + + if (manager_mode) + return TRUE; + + if (thisuser == NULLDN) + return FALSE; + + if ((manager = get_manager_dn (as,TRUE)) == NULLDN) + return FALSE; + + if (dn_cmp (manager, thisuser) == 0) + return TRUE; + else + return FALSE; + +} + +ORName * user_in_list (as,thisuser) +Attr_Sequence as; +DN thisuser; +{ +ORName * or; +Attr_Sequence tmp; +AV_Sequence eptr; + + if (thisuser == NULLDN) + return NULLORName; + + if ((tmp = as_find_type (as,at_Member)) == NULLATTR) + return NULLORName; + + for (eptr = tmp->attr_value; eptr != NULLAV; eptr = eptr->avseq_next) { + or = (ORName *)eptr->avseq_av.av_struct; + if (dn_cmp (or->on_dn,thisuser) == 0) + return or; + } + + return NULLORName; +} + + +ORName * addr_in_list (as,addr) +Attr_Sequence as; +OR_ptr addr; +{ +ORName * or; +Attr_Sequence tmp; +AV_Sequence eptr; + + if (addr == NULLOR) + return NULLORName; + + if ((tmp = as_find_type (as,at_Member)) == NULLATTR) + return NULLORName; + + for (eptr = tmp->attr_value; eptr != NULLAV; eptr = eptr->avseq_next) { + or = (ORName *)eptr->avseq_av.av_struct; + if (orAddr_cmp (or->on_or,addr) == 0) + return or; + } + + return NULLORName; +} + + +DNS dl_interact (dns,dn,s) +DNS dns; +DN dn; +char * s; +{ +char buf[LINESIZE]; +DNS result = NULLDNS; +DNS newdns; +PS ps; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + (void) fprintf (stderr,"Can't set up output (5)\n"); + return NULLDNS; + } + if (std_setup (ps, stdout) == NOTOK) { + (void) fprintf (stderr,"Can't set up output (6)\n"); + return NULLDNS; + } + + if (dns == NULLDNS) + return NULLDNS; + + ps_printf (ps,"Please select from the following (matching '%s'):\n",s); + while (dns != NULLDNS) { + ps_print (ps," "); + (void) ufn_dn_print_aux (ps,dns->dns_dn,dn,TRUE); + if (ufn_dl) { + if (user_in_list (ufn_dl,dns->dns_dn)) { + DNS tmp; + ps_print (ps,"(Discarded - not in list)\n"); + tmp = dns; + dns = dns->dns_next; + tmp->dns_next = NULLDNS; + dn_seq_free (tmp); + continue; + } + } + ps_print (ps," [y/n] ? "); + (void) ps_flush (ps); + +again:; + if (gets (buf) == NULL) { + clearerr (stdin); + ps_print (ps,"(exit)\n"); + return result; + } + + if ((buf[0] == NULL) + || (strlen(buf) != 1) + || ((buf[0] != 'y') && (buf[0] != 'n'))) { + ps_print (ps,"Please type 'y' or 'n': "); + (void) ps_flush (ps); + goto again; + } + + if (buf[0] == 'y') { + newdns = dn_seq_alloc(); + newdns->dns_next = result; + newdns->dns_dn = dn_cpy (dns->dns_dn); + result = newdns; + dns = dns->dns_next; + } else { + DNS tmp; + tmp = dns; + dns = dns->dns_next; + tmp->dns_next = NULLDNS; + dn_seq_free (tmp); + } + } + ps_free (ps); + return result; +} + +DN dl_str2ufn (ufn) +char * ufn; +{ +DNS dns = NULLDNS; +int n; +char * v[20]; +PS ps; +extern char ufn_notify; +extern int print_parse_errors, parse_status; +static envlist el = NULLEL; +DN dn; +char * ptr; +int old; + + ptr = strdup (ufn); + + if ((ps = ps_alloc (std_open)) == NULLPS) { + (void) fprintf (stderr,"Can't set up output (7)\n"); + return NULLDN; + } + if (std_setup (ps, stdout) == NOTOK) { + (void) fprintf (stderr,"Can't set up output (8)\n"); + return NULLDN; + } + + if (index (ptr,'@') != NULLCP) { + /* DN or 822 address */ + + old = print_parse_errors; + print_parse_errors = FALSE; + + if ((dn = str2dn (ptr)) != NULLDN) { + free (ptr); + print_parse_errors = old; + return dn; + } + + parse_status--; /* ignore error */ + print_parse_errors = old; + + if ((dn = mail2dn (ps, ufn)) != NULLDN) { + free (ptr); + return dn; + } + } + free (ptr); + + if (el == NULLEL) { + ufn_notify = TRUE; + if ((el = read_envlist ()) == NULLEL) { + (void) fprintf (stderr,"Can't read environment\n"); + return NULLDN; + } + } + + + if ((n = sstr2arg (ufn,20,v,",\n")) == NOTOK) { + (void) fprintf (stderr, "Can't parse input !!!\n"); + return NULLDN; + } + + ps_print (ps,"Searching...\n"); + + if ( ! ufn_match (n,v,dl_interact,&dns,el)) { + (void) fprintf (stderr, "Try again later !!!\n"); + return NULLDN; + } else { + if (dns == NULLDNS) { + (void) fprintf (stderr, "Nothing matched\n"); + return NULLDN; + } else if (dns->dns_next == NULLDNS) { + return dns->dns_dn; + } else { + dns = dl_interact (dns,localdn,ufn); + if (dns == NULLDNS) { + (void) fprintf (stderr, "Nothing matched\n"); + return NULLDN; + } else if (dns->dns_next == NULLDNS) { + return dns->dns_dn; + } + ps_print (ps, "\nYou need to select one name!\n "); + return NULLDN; + } + } + /* NOTREACHED */ +} + +ORName * ufn_orName_parse (str,thisdl) +char * str; +Attr_Sequence thisdl; +{ +ORName * or, *newor; +char * ptr; +int old; +Attr_Sequence as; +OR_ptr as2or(); + + or = (ORName *) smalloc (sizeof (ORName)); + + if ( (ptr=index (str,'$')) == NULLCP) { + if ((or->on_dn = dl_str2ufn (str)) == NULLDN) + return (NULLORName); + + ufn_dl = thisdl; + + if (dn2addr (or->on_dn, &as) == OK) + or->on_or = as2or (as); + else + or->on_or = NULLOR; + + if (thisdl) { + if (user_in_list(thisdl,or->on_dn)) + return or; + + ORName_free (or); + (void) fprintf (stderr,"User not in list !\n"); + return NULLORName; + } + return or; + } + + *ptr--= 0; + if (isspace (*ptr)) { + *ptr = 0; + } + ptr++; + ptr++; + + if (*str == 0) + or->on_dn = NULLDN; + else { + if ((or->on_dn = dl_str2ufn (str)) == NULLDN) + return (NULLORName); + ufn_dl = thisdl; + } + + ptr = SkipSpace(ptr); + if (*ptr == 0) { + or->on_or = NULLOR; + if (or->on_dn != NULLDN) + if (dn2addr (or->on_dn, &as) == OK) + or->on_or = as2or (as); + } else if ((or->on_or = orAddr_parse_user (ptr)) == NULLOR) + return (NULLORName); + + if (thisdl) { + if (or->on_dn && user_in_list(thisdl,or->on_dn)) + return or; + if (or->on_or && (newor = addr_in_list(thisdl,or->on_or))) + return newor; + + ORName_free (or); + (void) fprintf (stderr,"User not in list !\n"); + return NULLORName; + } + return (or); +} + +char input[BUFSIZ]; + +static int getinput() +{ + RP_Buf rp; + + (void) fflush(stdout); + if (gets (input) == NULL) { + clearerr(stdin); + pps_end(NOTOK,&rp); + return NOTOK; + } + compress (input, input); + if (*input == '\0') { + pps_end(NOTOK,&rp); + return NOTOK; + } + return OK; +} + +static int readinput() +{ + (void) fflush(stdout); + if (gets (input) == NULL) { + clearerr(stdin); + return NOTOK; + } + compress (input, input); + if (*input == '\0') + return NOTOK; + + return OK; +} + +static int error_user() +{ + RP_Buf rp; + pps_end(NOTOK, &rp); + return NOTOK; +} + +static int error_pps(rp) +RP_Buf *rp; +{ + (void) printf("pps_error: %s\n",rp->rp_line); + (void) fflush(stdout); + return NOTOK; +} + +/* */ + +orname_confirm (ps,orname,remove) +PS ps; +ORName * orname; +char remove; +{ + register char c; + + if (remove) + ps_printf (ps,"Remove "); + else + ps_printf (ps,"Add "); + orName_print (ps,orname,UFNOUT); + + ps_printf (ps," [y/n/d] ? "); + ps_flush (ps); + +again:; + c = ttychar (); + + switch (c) + { + case 'Y': + case 'y': + (void) printf ("yes\r\n"); + (void) fflush (stdout); + return (TRUE); + + case 'N': + case 'n': + (void) printf ("no\r\n"); + (void) fflush(stdout); + return (FALSE); + + case 'D': + case 'd': + (void) printf ("display...\r\n"); + if (orname->on_dn) + dl_showentry (ps,orname->on_dn); + else + orName_print (ps,orname,UFNOUT); + if (remove) + ps_printf (ps,"Remove [y/n] ? "); + else + ps_printf (ps,"Add [y/n] ? "); + ps_flush (ps); + goto again; + + default: + (void) printf ("Type y(es), n(o) or (d)isplay "); + (void) fflush(stdout); + goto again; + } +} + +confirm (str) +char *str; +{ + register char c; + + if (str != NULL) { + (void) printf(str); + (void) fflush(stdout); + } + +again:; + + (void) printf (" [y/n] "); + (void) fflush (stdout); + + c = ttychar (); + + switch (c) + { + case 'Y': + case 'y': + (void) printf ("yes\r\n"); + (void) fflush (stdout); + return (TRUE); + + case 'N': + case 'n': + (void) printf ("no\r\n"); + (void) fflush(stdout); + return (FALSE); + default: + (void) printf ("Type y or n\n"); + (void) fflush(stdout); + goto again; + } +} + +ttychar () +{ + register int c; + char buf[LINESIZE]; + + (void) fflush (stdout); + if (fgets (buf, LINESIZE, stdin) == 0) + clearerr(stdin); + + c = buf[0]; + + c = toascii (c); /* get rid of high bit */ + + if (c == '\r') + c = '\n'; + + return (c); +} + +dl_create_dsa (ps) +PS ps; +{ +DN dn; +int res; +char *listname; +char *description; +DN owner; + + (void) printf("\nName of new list -> "); + if (readinput() == NOTOK) + return NOTOK; + + if ((res = str2dl (input,localdn,&dn)) != NOTOK) { + if (res == OK) { + (void) printf("'%s' list already exists...\n",input); + do_list (dn,input); + } else + (void) printf("Temporary directory failure\n",input); + dn_free (dn); + return NOTOK; + } + + listname = strdup(input); + + (void) printf ("Do local users '%s-request' and '%s' exist ",listname,listname); + + if (confirm (NULLCP) == FALSE) { + (void) printf("You need to create some local PP mail addresses\n"); + (void) printf("(contact the postmaster if you don't know how)\n\n"); + (void) printf("You need to create an alias of the form\n"); + (void) printf(" %s-request: alias \n",listname); + (void) printf("and a user of the form\n"); + (void) printf(" %s:dirlist []\n",listname); + (void) printf("\nThen try again!\n\n"); + return NOTOK; + } + + (void) printf("\nOwner of new list -> "); + if (readinput() == NOTOK) + return NOTOK; + + if ((owner = dl_str2ufn(input)) == NULLDN) { + (void) printf("\nInvalid Owner"); + return NOTOK; + } + + (void) printf("Description of list (one line only) -> "); + if (readinput() == NOTOK) + return NOTOK; + description = strdup(input); + + (void) printf("Creating entry for '%s-request'...\n",listname); + (void) fflush (stdout); + if (! add_list_request (ps, localdn, listname, owner)) { + return NOTOK; + } + + (void) printf("Creating entry for '%s'...\n",listname); + (void) fflush (stdout); + if (! add_new_list (ps,localdn, listname, owner, description,NULLATTR)) { + return NOTOK; + } + + (void) str2dl (listname,localdn,&dn); + do_list (dn,listname); + + return OK; +} + +dl_create (ps) +PS ps; +{ +RP_Buf rp; +DN dn; +int res; +char *get_spostmaster(); + + postmaster = get_spostmaster(); + + if (manager_mode) + return dl_create_dsa(ps); + + (void) printf("Please wait..."); + (void) fflush(stdout); + + if (pps_1adr("Directory based distribution list creation request", + postmaster, + &rp) != OK) + return error_pps(&rp); + + (void) printf("\nName of new list -> "); + if (getinput() == NOTOK) + return error_user(); + + if ((res = str2dl (input,localdn,&dn)) != NOTOK) { + dn_free (dn); + if (res == OK) + (void) printf("'%s' list already exists\n",input); + else + (void) printf("Temporary directory failure\n",input); + return error_user(); + } + + if (pps_txt("\nPlease create a directory based mail list:\n",&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n cn= ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + + if (pps_txt("\n Owner= ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(dn2str(user),&rp) != OK) + return error_pps(&rp); + + (void) printf("Description of list (one line only) -> "); + if (getinput() == NOTOK) + return error_user(); + if (pps_txt("\n Description= ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + + + if (pps_txt("\n\n(You can use the \"dl -m\" command to do this!)\n",&rp) != OK) + return error_pps(&rp); + + if (confirm ("Do you want to pass this request on to the postmaster ?") == FALSE) { + pps_end(NOTOK,&rp); + return 0; + } + + (void) printf("Sending..."); + (void) fflush(stdout); + if (pps_txt("\n(auto-mailing from the 'dl' tool)\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + + (void) printf ("\nYour request has been passed to an administrator\n"); + (void) printf ("You will be notified in a short time when the list has been created\n"); + (void) printf ("You can then use this program to enter names into the list\n\n"); + (void) fflush (stdout); + return 0; +} + +dl_upgrade_dsa (ps,list,listname) +PS ps; +dl *list; +char * listname; +{ +RP_Buf rp; +DN dn; +int res; +char *description; +DN owner; +Attr_Sequence nas, members = NULLATTR; +Attr_Sequence mail2member (); +Name * dlm; + + if ((res = str2dl (listname,localdn,&dn)) != NOTOK) { + if (res == OK) { + (void) printf("'%s' list already exists...\n",input); + do_list (dn,listname); + } else + (void) printf("Temporary directory failure\n",input); + dn_free (dn); + return NOTOK; + } + + if ((owner = mail2dn (ps, list->dl_moderator)) == NULLDN) { + (void) printf("\nInvalid Owner"); + return NOTOK; + } + + description = list->dl_desc; + + for (dlm = list -> dl_list; dlm != NULL; dlm = dlm -> next) { + if ((nas = mail2member (ps, dlm->name)) == NULLATTR) { + (void) printf("\naddress failed '%s'",dlm->name); + return NOTOK; + } + members = as_merge (members, nas); + } + + (void) printf("Creating entry for '%s-request'...\n",listname); + (void) fflush (stdout); + if (! add_list_request (ps, localdn, listname, owner)) { + return NOTOK; + } + + (void) printf("Creating entry for '%s'...\n",listname); + (void) fflush (stdout); + if (! add_new_list (ps,localdn, listname, owner, description,members)) { + return NOTOK; + } + + (void) printf("Directory entries created.\n\n"); + + (void) printf("WARNING: the address to DN mapping is experimental,\n"); + (void) printf("you should check the members of the list carefully\n\n"); + + (void) printf("You need to modify the PP tables form\n"); + (void) printf(" %s:list []\nto\n",listname); + (void) printf(" %s:dirlist []\n",listname); + + if (confirm ("Do you want to pass a request on to the postmaster ?") == FALSE) { + (void) str2dl (listname,localdn,&dn); + do_list (dn,listname); + return OK; + } + + (void) printf("Sending..."); + (void) fflush(stdout); + + if (pps_1adr("Directory based distribution list upgrade request", + postmaster, + &rp) != OK) + return error_pps(&rp); + + if (pps_txt("\nPlease change the PP table entry for the list\n'",&rp) != OK) + return error_pps(&rp); + if (pps_txt(listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt("' from 'list' to 'dirlist'\n",&rp) != OK) + return error_pps(&rp); + + if (pps_txt("\n(auto-mailing from the 'dl' tool)\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + + (void) str2dl (listname,localdn,&dn); + do_list (dn,listname); + return OK; +} + +dl_upgrade (ps) +PS ps; +{ +dl *list; +RP_Buf rp; +DN dn; +int res; +char *get_spostmaster(); + + postmaster = get_spostmaster(); + + (void) printf("\nName of list to upgrade -> "); + if (readinput() == NOTOK) + return NOTOK; + + switch (tb_getdl (input, &list, OK)) { + case OK: + break; + case DONE: + if (list != NULL) + dl_free(list); + (void) printf ("Temporary failure to expand list"); + return NOTOK; + default: + if (list != NULL) + dl_free(list); + (void) printf ("Failed to expand list"); + return NOTOK; + } + + if (manager_mode) + return dl_upgrade_dsa(ps,list,input); + + (void) printf("Please wait ..."); + (void) fflush(stdout); + + if (pps_1adr("Directory based distribution list upgrade request", + postmaster, + &rp) != OK) + return error_pps(&rp); + + if ((res = str2dl (input,localdn,&dn)) != NOTOK) { + dn_free (dn); + if (res == OK) + (void) printf("'%s' list already exists\n",input); + else + (void) printf("Temporary directory failure\n",input); + return error_user(); + } + + if (pps_txt("\nPlease convert the file based mail list\n ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\ninto a directory based mail list\n",&rp) != OK) + return error_pps(&rp); + if (pps_txt("(You can do this using the 'dl' program)\n",&rp) != OK) + return error_pps(&rp); + + (void) printf("\nDo you want to pass this request on to the postmaster ?"); + if (confirm (NULLCP) == FALSE) { + pps_end(NOTOK,&rp); + return 0; + } + + (void) printf("Sending..."); + (void) fflush(stdout); + + if (pps_txt("\n(auto-mailing from the 'dl' tool)\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + + (void) printf ("\nYour request has been passed to an administrator\n"); + (void) printf ("You will be notified in a short time when the list has been converted\n"); + (void) printf ("You can then use this program to enter names into the list\n\n"); + (void) fflush (stdout); + return 0; +} + + +mail_manager (ps,dn,remove,as,dn_dl) +PS ps; +DN dn; +char remove; +Attr_Sequence as; +DN dn_dl; +{ +DN manager, get_manager_dn(); +DN nice_manager; +RP_Buf rp; +Attr_Sequence das; +OR_ptr or,as2or (); +char man_buf [LINESIZE]; + + if (remove) + ps_print (ps,"\nSorry, you can't remove youself from the list.\n"); + else + ps_print (ps,"\nSorry, you can't add youself to the list.\n"); + + if ((manager = get_manager_dn(as,FALSE)) == NULLDN) + return NOTOK; + if ((nice_manager = get_manager_dn(as,TRUE)) == NULLDN) + return NOTOK; + + if (dn2addr (manager, &das) != OK) + return NOTOK; + + if ((or = as2or (das)) == NULLOR) + return NOTOK; + + or_or2rfc (or,man_buf); + + /* Could be neat - and check the submit permissions to make sure + * the user is allowed on the list ! + */ + + ps_print (ps, "Do you want to mail a request to the Manager,\n"); + ufn_dn_print (ps,nice_manager,TRUE); + ps_print (ps, " ?"); + (void) ps_flush (ps); + + if (! confirm (NULLCP)) + return NOTOK; + + (void) printf("Please wait...\n"); + (void) fflush(stdout); + + if (pps_1adr("Directory based distribution list modification request", + man_buf, + &rp) != OK) + return error_pps(&rp); + + if (remove) { + if (pps_txt("\nPlease remove\n ",&rp) != OK) + return error_pps(&rp); + } else { + if (pps_txt("\nPlease add\n ",&rp) != OK) + return error_pps(&rp); + } + + if (pps_txt(dn2ufn(dn,FALSE),&rp) != OK) + return error_pps(&rp); + + if (remove) { + if (pps_txt("\nfrom the list\n ",&rp) != OK) + return error_pps(&rp); + } else { + if (pps_txt("\nto the list\n ",&rp) != OK) + return error_pps(&rp); + } + + if (pps_txt(dn2ufn(dn_dl,FALSE),&rp) != OK) + return error_pps(&rp); + + if (pps_txt(".\n(auto-mailing from the 'dl' tool)\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + + (void) printf ("Your request has been passed to the manager.\n"); + (void) fflush (stdout); + + return 0; + +} + +message2manager (dn_dl,message) +DN dn_dl; +char * message; +{ +DN manager, get_manager_dn(); +RP_Buf rp; +Attr_Sequence as; +Attr_Sequence das; +OR_ptr or,as2or (); +char subject [LINESIZE]; +char man_buf [LINESIZE]; + + switch (dir_getdl_aux (dn_dl, &as)) { + case OK: + break; + default: + return NOTOK; + } + + if ((manager = get_manager_dn(as,FALSE)) == NULLDN) + return NOTOK; + + if (dn2addr (manager, &das) != OK) + return NOTOK; + + if ((or = as2or (das)) == NULLOR) + return NOTOK; + + or_or2rfc (or,man_buf); + + sprintf (subject,"Error in mailing list '%s'",dn2ufn(dn_dl,FALSE)); + if (pps_1adr(subject, man_buf, &rp) != OK) + return error_pps(&rp); + + if (pps_txt(message,&rp) != OK) + return error_pps(&rp); + + if (pps_txt("\n(auto-mailing from the 'dl' tool)\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + + return 0; + +} + +modify_dl_attrs (ps,dn_dl,as) +PS ps; +DN dn_dl; +Attr_Sequence as; +{ +Attr_Sequence tmp,ntmp; +DN dnm, ndnm, get_manager_dn(); +char buffer [LINESIZE]; + + if (( dnm = get_manager_dn(as,TRUE)) == NULLDN) + ps_print (ps,"Entry has no Owner !!!\n"); + else { + ps_print (ps,"Owner: "); + ufn_dn_print (ps,dnm,TRUE); + +retry_manager:; + ps_print (ps,"\nEnter new name ('return' for no change): "); + ps_flush (ps); + if (readinput() == OK) { + if ( (ndnm = dl_str2ufn (input)) == NULLDN) + goto retry_manager; + + if (! dl_modify_owner (ps,dnm,ndnm,dn_dl,quiet)) + return; + } + + if (((tmp = as_find_type (as,at_Permit)) == NULLATTR) + || (tmp->attr_value == NULLAV)) + ps_print (ps,"\nEntry has no mhsDLSubmitPermissions !!!\n"); + else { + ps_print (ps,"\nSubmit Permissions,"); + avs_seq_print (ps,tmp->attr_value, UFNOUT); + } + } + +retry_permit:; + ps_print (ps,"\nEnter new permission ('return' for no change): "); + ps_flush (ps); + if (readinput() == OK) { + sprintf (buffer,"mhsDLSubmitPermissions=%s",input); + if ( (ntmp = str2as (buffer)) == NULLATTR) + goto retry_permit; + + if (! dl_modify_attr (ps,tmp,ntmp,dn_dl,quiet)) + return; + } + + if (((tmp = as_find_type (as,at_Policy)) == NULLATTR) + || (tmp->attr_value == NULLAV)) + ps_print (ps,"\nEntry has no dl-policy\n"); + else { + ps_print (ps,"\nList Policy, "); + avs_seq_print (ps,tmp->attr_value, UFNOUT); + } + +retry_policy:; + ps_print (ps,"\nEnter new policy ('return' for no change): "); + ps_flush (ps); + if (readinput() == OK) { + sprintf (buffer,"dl-policy=%s",input); + if ( (ntmp = str2as (buffer)) == NULLATTR) + goto retry_policy; + + if (! dl_modify_attr (ps,tmp,ntmp,dn_dl,quiet)) + return; + } + + ps_print (ps,"\nDone!"); + +} + +#ifndef lint + +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + (void) _ll_log (log_dsap, code, ap); + + va_end (ap); +} + +#else +/* VARARGS */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Chans/lists/dl.py b/Chans/lists/dl.py new file mode 100644 index 0000000..283a1b6 --- /dev/null +++ b/Chans/lists/dl.py @@ -0,0 +1,44 @@ +-- dl.py + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl.py,v 6.0 1991/12/18 20:10:43 jpo Rel $ +-- +-- $Log: dl.py,v $ +-- Revision 6.0 1991/12/18 20:10:43 jpo +-- Release 6.0 +-- +-- + +DL + +DEFINITIONS ::= + +PREFIXES encode decode print + +BEGIN + +DlPolicy [[P struct dl_policy *]] + ::= + SET + { + furtherExpansionPermitted [0] + BOOLEAN [[b dp_expand]] + DEFAULT TRUE, + conversionProhibited [1] + ENUMERATED [[i dp_convert]] + { + original (1), + false (2), + true (3) + } + DEFAULT original, + priority [2] + ENUMERATED [[i dp_priority]] + { + original (1), + low (2), + normal (3), + high (4) + } + DEFAULT low + } +END diff --git a/Chans/lists/dl_permit.c b/Chans/lists/dl_permit.c new file mode 100644 index 0000000..bd97ef9 --- /dev/null +++ b/Chans/lists/dl_permit.c @@ -0,0 +1,182 @@ +/* dl_permit.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_permit.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_permit.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dl_permit.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include "adr.h" +#include "or.h" +#include + +extern AttributeType at_Permit; +extern AttributeType at_GroupMember; +extern AttributeType at_Member; +extern ORName *addr2orname(); + +static check_group (addr,dn) +ADDR * addr; +DN dn; +{ +Attr_Sequence as; +Attr_Sequence tmp; +AV_Sequence avs; +DN ad_dn; + + if (! addr->ad_dn) + return NOTOK; + + if (read_group_entry (dn, &as) != OK) + return NOTOK; + + if ((tmp = as_find_type(as,at_GroupMember)) == NULLATTR) + return NOTOK; + + if ((ad_dn = str2dn (addr->ad_dn)) == NULLDN) + return NOTOK; + + for (avs=tmp->attr_value; avs!= NULLAV; avs=avs->avseq_next) + if (dn_cmp (ad_dn,(DN)avs->avseq_av.av_struct) == 0) { + dn_free (ad_dn); + return OK; + } + + dn_free (ad_dn); + return NOTOK; +} + +static check_individual (addr,or) +ADDR * addr; +ORName * or; +{ +ORName * newor; +int res; + + newor = addr2orname (addr); + + res = orName_cmp_user (or,newor); + + ORName_free (newor); + + return res; +} + +static check_member (addr,or) +ADDR * addr; +ORName * or; +{ +Attr_Sequence tmp; +AV_Sequence avs; +Attr_Sequence as; + + if (or->on_dn == NULLDN) + return NOTOK; + + if (dir_getdl_aux (or->on_dn, &as) != OK) + return NOTOK; + + if ((tmp = as_find_type(as,at_Member)) == NULLATTR) + return NOTOK; + + for (avs=tmp->attr_value; avs!= NULLAV; avs=avs->avseq_next) + if (check_individual (addr,(ORName *)avs->avseq_av.av_struct) == OK) + return OK; + + return NOTOK; +} + +static or_cmp_prefix (a,b) +OR_ptr a,b; +{ + for (; (a != NULLOR) && (b != NULLOR); b = b->or_next) { + if (or_cmp (a,b) == TRUE) + a = a->or_next; + } + + if (a == NULLOR) + return OK; + else + return NOTOK; +} + +static check_pattern (addr,or) +ADDR * addr; +ORName * or; +{ +ORName * newor; + + newor = addr2orname (addr); + + if (or->on_dn) { + if (!newor->on_dn) + goto out; + if (dn_cmp_prefix (or->on_dn,newor->on_dn) == NOTOK) + goto out; + } + + if (or->on_or) { + if (!newor->on_or) + goto out; + + if (or_cmp_prefix (or->on_or,newor->on_or) == NOTOK) + goto out; + } + + ORName_free (newor); + return OK; + +out:; + ORName_free (newor); + return NOTOK; + + +} + +check_dl_permission (addr, as) +ADDR * addr; +Attr_Sequence as; +{ +Attr_Sequence tmp; +AV_Sequence loop; +struct dl_permit * ptr; +int res; + + if ((tmp = as_find_type (as,at_Permit)) == NULLATTR) + return NOTOK; /* Attribute is mandatory */ + + for (loop= tmp->attr_value;loop != NULLAV;loop = loop->avseq_next) { + + ptr = (struct dl_permit *)loop->avseq_av.av_struct; + + switch (ptr->dp_type) { + case DP_GROUP: + res = check_group (addr,ptr->dp_dn); + break; + case DP_INDIVIDUAL: + res = check_individual (addr,ptr->dp_or); + break; + case DP_MEMBER: + res = check_member (addr,ptr->dp_or); + break; + case DP_PATTERN: + res = check_pattern (addr,ptr->dp_or); + break; + } + + if (res == OK) + return OK; + } + + return NOTOK; +} diff --git a/Chans/lists/dl_util.c b/Chans/lists/dl_util.c new file mode 100644 index 0000000..4348270 --- /dev/null +++ b/Chans/lists/dl_util.c @@ -0,0 +1,581 @@ +/* dl_util.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_util.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_util.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dl_util.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include "retcode.h" +#include "adr.h" +#include "or.h" +#include + +extern AttributeType at_Member; +extern AttributeType at_Owner; +extern AttributeType at_Permit; +extern AttributeType at_Policy; +extern AttributeType at_ORAddress; +extern AttributeType at_RFC822; +extern AttributeType at_RoleOccupant; +extern OID dl_oc; + +extern OR_ptr orAddr_parse (); + +Attr_Sequence current_print = NULLATTR; + +extern LLog * log_dsap; + +ORName * addr2orname (addr) +ADDR * addr; +{ +ORName * or; +OR_ptr por = NULLOR; + + or = (ORName *) smalloc (sizeof (ORName)); + or->on_dn = NULLDN; + or->on_or = NULLOR; + + if (addr->ad_dn) + or->on_dn = str2dn (addr->ad_dn); + + if (addr->ad_value) { + + if (addr->ad_r822adr) + or_rfc2or(addr->ad_r822adr,&por); + else + por = or_std2or(addr->ad_value); + + if (por) + or->on_or = or_default(por); + } + + return (or); +} + + +OR_ptr as2or (as) +Attr_Sequence as; +{ +Attr_Sequence tmp; +OR_ptr or_cpy (); + + if ((tmp = as_find_type(as,at_ORAddress)) != NULLATTR) + if (tmp->attr_value) + return (or_cpy ((OR_ptr) tmp->attr_value->avseq_av.av_struct)); + if ((tmp = as_find_type(as,at_RFC822)) != NULLATTR) { + OR_ptr or; + if (tmp->attr_value) + if (or_rfc2or((char *)tmp->attr_value->avseq_av.av_struct,&or) == OK) + return (or); + } + + return NULLOR; +} + +avs_seq_print (ps,avs,format) +PS ps; +AV_Sequence avs; +int format; +{ +AV_Sequence eptr; + + for(eptr = avs; eptr != NULLAV; eptr = eptr->avseq_next) { + ps_print (ps," "); + AttrV_print (ps,&eptr->avseq_av,format); + ps_print (ps,"\n"); + } +} + +static int member_compar (a, b) +AV_Sequence *a, *b; +{ + ORName * aor = (ORName *)((*a)->avseq_av.av_struct); + ORName * bor = (ORName *)((*b)->avseq_av.av_struct); + + return orName_cmp (aor,bor); + +} + +static avs_seq_print_members (ps,avs) +PS ps; +AV_Sequence *avs; +{ +AV_Sequence eptr; +int i=0; +DN tdn, marker, next, trail = NULLDN; +extern char * local_dit; +ORName * or; + + marker = str2dn (local_dit); + + for(eptr = *avs; eptr != NULLAV; eptr = eptr->avseq_next) { + i++; + or = (ORName *)eptr->avseq_av.av_struct; + if ((tdn = or->on_dn) != NULLDN) { + for (next=marker; + (tdn!= NULLDN) && (next != NULLDN); + next=next->dn_parent, tdn=tdn->dn_parent) { + if (dn_comp_cmp(tdn,next) != 0) { + if (trail == NULLDN) + marker = NULLDN; + else + trail->dn_parent = NULLDN; + dn_free (next); + break; + } + trail = next; + } + if (tdn == NULLDN) { + if (trail == NULLDN) + marker = NULLDN; + else + trail->dn_parent = NULLDN; + dn_free (next); + } + } + } + + if (i>1) { + + AV_Sequence *base, *bp, *ep; + + base = (AV_Sequence *) smalloc ((int)i * sizeof *base); + ep = base; + for(eptr = *avs; eptr != NULLAV; eptr = eptr->avseq_next) + *ep++ = eptr; + + qsort ((char *) base, i, sizeof *base, (IFP) member_compar); + + bp = base; + eptr = *avs = *bp++; + while (bp < ep) { + eptr -> avseq_next = *bp; + eptr = *bp++; + } + eptr -> avseq_next = NULL; + free ((char *) base); + } + + i = 1; + + for(eptr = *avs; eptr != NULLAV; eptr = eptr->avseq_next) { + ps_printf (ps,"%2d: ",i++); + or = (ORName *)eptr->avseq_av.av_struct; + if (or->on_dn != NULLDN) +#ifdef MULTILINE_OUTPUT + (void) ufn_dn_print_aux (ps,or->on_dn,marker,TRUE); +#else + (void) ufn_dn_print_aux (ps,or->on_dn,marker,FALSE); +#endif + else { + ps_print (ps,"X.400 Address: "); + orAddr_print (ps,or->on_or,READOUT); + } + ps_print (ps,"\n"); + } +} + +check_ORName (ps,or,dncheck,orcheck,update,listname,quiet) +PS ps; +ORName * or; +char dncheck; +char orcheck; +char update; +DN listname; +char quiet; +{ +OR_ptr newor = NULLOR; +char buf [LINESIZE]; +Attr_Sequence as; +char ret = TRUE; +char res; + + if (update) + dncheck = TRUE; + + if (dncheck && (or->on_dn != NULLDN)) { + if (!quiet) { + ps_print (ps,"Checking '"); + ufn_dn_print (ps,or->on_dn,FALSE); + ps_print (ps,"'... "); + (void) ps_flush (ps); + } + + if ((res = dn2addr (or->on_dn, &as)) == OK) + newor = as2or (as); + + if (newor == NULLOR) { + if (quiet) { + if (res == NOTOK) { + ps_print (ps,"\n ORAddress lookup failed '"); + ufn_dn_print (ps,or->on_dn,FALSE); + ps_print (ps,"'"); + ret = FALSE; + } + } else if (res == DONE) + ps_print (ps,"\n *** Temporary ORAddress lookup failed ***\n"); + else { + ps_print (ps,"\n *** ORAddress lookup failed ***\n"); + ret = FALSE; + } + } else if (orAddr_cmp (newor, or->on_or) == 0) { + if (!quiet) + ps_print (ps,"OK\n"); + } else if (update) { + + if (orAddr_check (newor,&buf[0]) == OK) { + if (or->on_or == NULLOR) { + ps_print (ps,"\n Adding ORaddress "); + } else { + ps_print (ps,"\n Changing "); + orAddr_print (ps,or->on_or,READOUT); + ps_print (ps," to "); + } + orAddr_print (ps,newor,READOUT); + ps_print (ps,"... "); + (void) ps_flush (ps); + + if (or_modify (ps,or,newor,at_Member,listname)) { + ps_print (ps,"OK\n"); + or_free (or->on_or); + or->on_or = newor; + } + (void) ps_flush (ps); + return ret; + } else { + char buf2[BUFSIZ]; + or_or2std (newor,buf2,0); + ps_printf (ps,"\n *** BAD ORAddress in DIT (%s): %s *** \n",buf,buf2); + ret = FALSE; + } + } else if (orcheck && or->on_or != NULLOR) { + if (orAddr_check (newor,&buf[0]) == OK) { + if (quiet) { + ps_printf (ps,"\n Error: '%s'\n X.500: ",dn2ufn(or->on_dn,FALSE)); + } else + ps_print (ps,"\n *** Error ***\n X.500: "); + orAddr_print (ps,newor,EDBOUT); + ps_print (ps,"\n X.400: "); + orAddr_print (ps,or->on_or,EDBOUT); + ps_print (ps,"\n"); + ret = FALSE; + } else { + char buf2[BUFSIZ]; + or_or2std (newor,buf2,0); + ps_printf (ps,"\n *** BAD ORAddress in DIT (%s): %s ***\n",buf,buf2); + ret = FALSE; + } + } else { + if (!quiet) + ps_print (ps,"X.500 Name OK\n"); + if (or->on_or == NULLOR) + or->on_or = newor; + } + } + + if ((orcheck) && (or->on_or != NULLOR)) { + if (!quiet) { + ps_print (ps,"Checking "); + orAddr_print (ps,or->on_or,READOUT); + ps_print (ps,"... "); + } + + if (orAddr_check (or->on_or,&buf[0]) == OK) { + if (!quiet) + ps_printf (ps,"OK\n"); + } else { + if (quiet) { + ps_printf (ps,"\n Error: %s \n",buf); + orAddr_print (ps,or->on_or,READOUT); + ps_print (ps,"\n"); + } else + ps_printf (ps,"\n *** Error: %s *** \n",buf); + ret = FALSE; + } + } + (void) ps_flush (ps); + return ret; +} + +check_dl_members (ps,dn,as,dncheck,orcheck,update,quiet) +PS ps; +DN dn; +Attr_Sequence as; +char dncheck; +char orcheck; +char update; +char quiet; +{ +Attr_Sequence tmp; +AV_Sequence avs; +int res; +int result = OK; + + if ((tmp = as_find_type (as,at_Member)) == NULLATTR) { + ps_print (ps,"Can't find dl-members attribute!!!\n"); + return NOTOK; + } + + for (avs=tmp->attr_value; avs!= NULLAV; avs=avs->avseq_next) { + res = check_ORName (ps,(ORName *)avs->avseq_av.av_struct, + dncheck,orcheck,update,dn,quiet); + if (res == FALSE) + result = NOTOK; + } + + return result; +} + +dl_print (ps,dn) +PS ps; +DN dn; +{ +Attr_Sequence tmp; +Attr_Sequence as; +DN dnm, get_manager_dn(); + + switch (dir_getdl_aux (dn, &as)) { + case OK: + break; + case DONE: + ps_print (ps, "Temporary failure to read the entry"); + return; + default: + ps_print (ps,"Can't read the entry"); + return; + } + + current_print = as; + + if (( dnm = get_manager_dn(as,TRUE)) == NULLDN) + ps_print (ps,"\nEntry has no Owner !!!\n"); + else { + ps_print (ps,"\nOwner: "); + ufn_dn_print (ps,dnm,TRUE); + } + + if (((tmp = as_find_type (as,at_Permit)) == NULLATTR) + || (tmp->attr_value == NULLAV)) + ps_print (ps,"\n\nEntry has no mhsDLSubmitPermissions !!!\n"); + else { + ps_print (ps,"\n\nSubmit Permissions, "); + avs_seq_print (ps,tmp->attr_value, UFNOUT); + } + + if (((tmp = as_find_type (as,at_Policy)) == NULLATTR) + || (tmp->attr_value == NULLAV)) + ps_print (ps,"\nEntry has no dl-policy\n"); + else { + ps_print (ps,"\nList Policy, "); + avs_seq_print (ps,tmp->attr_value, UFNOUT); + } + + if ((tmp = as_find_type (as,at_Member)) == NULLATTR) { + ps_print (ps,"\nEntry has no dl-members !!!\n"); + return; + } + ps_print (ps,"\nMembers:\n"); + avs_seq_print_members (ps,&tmp->attr_value); + +} + + +ADDR * get_postmaster() +{ +static ADDR *res = NULLADDR; +ADDR *dn2ADDR(); +DN dn, search_postmaster(); +static DN localdn = NULLDN; +extern char * local_dit; +extern char * getpostmaster(); + + if (res != NULLADDR) + return res; + + if ((localdn == NULLDN) && local_dit) + localdn = str2dn (local_dit); + + if ((dn = search_postmaster(localdn)) == NULLDN) + return res = adr_new(getpostmaster(AD_822_TYPE), + AD_822_TYPE, 0); + + if ((res = dn2ADDR (dn,TRUE)) == NULLADDR) + return res = adr_new(getpostmaster(AD_822_TYPE), + AD_822_TYPE, 0); + + return res; +} + +char * get_spostmaster() +{ +ADDR *res; + + res = get_postmaster(); + return res->ad_value; +} + + +ADDR * get_manager(as) +Attr_Sequence as; +{ +Attr_Sequence tmp; +AV_Sequence avs; +ADDR * dn2ADDR(); +ADDR *ret = NULLADDR; +ADDR *next; +int num = 1; +int dn_print (); + + if ((tmp = as_find_type(as,at_Owner)) == NULLATTR) + return get_postmaster(); + + if ((avs = tmp->attr_value) == NULLAV) + return get_postmaster(); + + for (; avs!= NULLAV; avs=avs->avseq_next) { + if ((next = dn2ADDR ((DN)(avs->avseq_av.av_struct),TRUE)) == NULLADDR) { + pslog (log_dsap,LLOG_NOTICE,"Bad address in DN",dn_print,avs->avseq_av.av_struct); + continue; + } + next->ad_extension = num; + next->ad_no = num++; + adr_add(&ret, next); + } + return ret; +} + +DN get_manager_dn (as,unwrap) +Attr_Sequence as; +char unwrap; /* IF TRUE, and entry is a role, unwrap it */ +{ +Attr_Sequence tmp; +AV_Sequence avs; + + if ((tmp = as_find_type(as,at_Owner)) == NULLATTR) + return NULLDN; + + if ((avs = tmp->attr_value) == NULLAV) + return NULLDN; + + if (unwrap) { + if (dn2addr((DN)avs->avseq_av.av_struct, &tmp) != OK) + return (DN)avs->avseq_av.av_struct; + + if ((tmp = as_find_type (tmp,at_RoleOccupant)) == NULLATTR) + return (DN)avs->avseq_av.av_struct; + + if ((tmp->attr_value) == NULLAV) + return (DN)avs->avseq_av.av_struct; + avs = tmp->attr_value; + } + + return (DN)avs->avseq_av.av_struct; +} + + +DN mail2dn (ps,addr) +PS ps; +char * addr; +{ +DN dn, do_dm_match(); +ADDR * ad; +char *local, *ad_getlocal(); +RP_Buf rp; + + ps_printf (ps,"Looking for mail address '%s' in the directory...",addr); + + ad = adr_new (addr, (*addr == '/') ? AD_X400_TYPE : AD_822_TYPE, 1); + ad->ad_resp = YES; + +#ifdef UKORDER + (void) ad_parse(ad, &rp, CH_UK_PREF); +#else + (void) ad_parse(ad, &rp, CH_USA_PREF); +#endif + if (ad->ad_r400adr == NULLCP) { + adr_free (ad); + ps_printf (ps,"Failed\n",addr); + return NULLDN; + } + + if ((local = ad_getlocal (ad->ad_r400adr, AD_X400_TYPE)) == NULLCP) { + if (ad->ad_r822adr) + dn = do_dm_match (ad->ad_r822adr); + else + dn = do_dm_match (addr); + + if (dn) { + adr_free (ad); + ps_printf (ps,"%s\n", dn2ufn(dn,FALSE)); + return dn; + } else { + adr_free (ad); + ps_printf (ps,"Failed\n",addr); + return NULLDN; + } + } + + dn = do_dm_match (local); + + free (local); + adr_free (ad); + + ps_printf (ps,"%s\n", dn2ufn(dn,FALSE)); + + return dn; +} + +ORName * mail2orname (ps,addr) +PS ps; +char * addr; +{ +ORName * or; +char * ptr; +Attr_Sequence as; +OR_ptr as2or (), orAddr_parse_user(); + + or = (ORName *) smalloc (sizeof (ORName)); + + if ((or->on_dn = mail2dn(ps,addr)) == NULLDN) { + ptr = SkipSpace(addr); + if (*ptr == 0) + or->on_or = NULLOR; + else if ((or->on_or = orAddr_parse (ptr)) == NULLOR) + return (NULLORName); + } else { + if (dn2addr (or->on_dn, &as) != OK) + or->on_or = orAddr_parse (addr); + else + or->on_or = as2or (as); + } + + return (or); +} + +Attr_Sequence mail2member (ps, addr) +PS ps; +char * addr; +{ +AttributeValue av; +AV_Sequence avs; + + av = AttrV_alloc(); + av->av_syntax = str2syntax("ORName"); + if ((av->av_struct = (caddr_t) mail2orname(ps,addr)) == NULL) + return NULLATTR; + + avs = avs_comp_new(av); + return as_comp_new (AttrT_cpy(at_Member),avs,NULLACL_INFO); +} + diff --git a/Chans/lists/dl_x500.c b/Chans/lists/dl_x500.c new file mode 100644 index 0000000..5fc6963 --- /dev/null +++ b/Chans/lists/dl_x500.c @@ -0,0 +1,755 @@ +/* dl_x500.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_x500.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dl_x500.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dl_x500.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include +#include +#include +#include +#include +#include +#include /* ds_search uses di_block - include this for lint !!! */ +#include + +extern AttributeType at_Member; +extern AttributeType at_RoleOccupant; +extern AttributeType at_CommonName; +extern AttributeType at_Owner; +extern AttributeType at_Permit; +extern AttributeType at_Policy; +extern AttributeType at_ORAddress; +extern AttributeType at_RFC822; +extern AttributeType at_GroupMember; +extern AttributeType at_ObjectClass; +extern OID role_oc; +extern char * local_dit; + +extern LLog * log_dsap; + +extern Filter strfilter(), ocfilter(), joinfilter(); +extern Attr_Sequence as_combine(); +extern DN dn_append(); +extern char * dn2str(); + +static Attr_Sequence mailas = NULLATTR; + +extern int str2dl (); + +static int isPermanentError (error) +struct DSError *error; +{ +/* DONE == temporary, NOTOK == permanent */ + + switch (error -> dse_type) { + case DSE_REMOTEERROR: + case DSE_REFERRAL: + case DSE_ABANDONED: + return DONE; + case DSE_SERVICEERROR: + switch (error -> ERR_SERVICE.DSE_sv_problem) { + case DSE_SV_BUSY: + case DSE_SV_TIMELIMITEXCEEDED: + case DSE_SV_ADMINLIMITEXCEEDED: + return DONE; + default: + return NOTOK; + } + default: + return NOTOK; + } +} + +static int ds_cache_read (dn,as, pres) +DN dn; +Attr_Sequence as; +Attr_Sequence *pres; +{ +struct ds_read_arg read_arg; +struct ds_read_result result; +struct DSError error; +static CommonArgs ca = default_common_args; +Entry ptr; + + if ((ptr = local_find_entry (dn,TRUE)) != NULLENTRY) { + if (ptr->e_complete) { + *pres = ptr->e_attributes; + return OK; + } + if (as != NULLATTR) { + Attr_Sequence tmp; + for (tmp = as; tmp!= NULLATTR; tmp = tmp->attr_link) + if (as_find_type(ptr->e_attributes,tmp->attr_type) == NULLATTR) + goto do_read; + *pres = ptr->e_attributes; + return OK; + } + } + +do_read:; + + read_arg.rda_common = ca; /* struct copy */ + + read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + read_arg.rda_eis.eis_allattributes = FALSE; + read_arg.rda_eis.eis_select = as; + read_arg.rda_object = dn; + + if (ds_read (&read_arg, &error, &result) != DS_OK) { + int resultint = isPermanentError(&error); + log_ds_error (&error); + ds_error_free (&error); + *pres = NULLATTR; + return resultint; + } + + result.rdr_entry.ent_attr = as_merge (result.rdr_entry.ent_attr,as_cpy(as)); + + cache_entry (&result.rdr_entry,FALSE,TRUE); + *pres = result.rdr_entry.ent_attr; + return OK; +} + + +int dn2addr (dn, pres) +DN dn; +Attr_Sequence *pres; +{ +Attr_Sequence found; +int result; + + if (mailas == NULLATTR) { + Attr_Sequence as; + mailas = as_comp_new (at_ORAddress, NULLAV, NULLACL_INFO); + as = as_comp_new (at_RFC822, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + as = as_comp_new (at_ObjectClass, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + as = as_comp_new (at_RoleOccupant, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + } + + if ((result = ds_cache_read (dn,mailas, pres)) != OK) + return result; + + /* Have we got an address ? */ + if ((found = as_find_type (*pres,at_ORAddress)) != NULLATTR) + return OK; + + if ((found = as_find_type (*pres,at_RFC822)) != NULLATTR) + return OK; + + /* NO address, is it a role ? */ + if ((found = as_find_type (*pres,at_ObjectClass)) == NULLATTR) + return NOTOK; + + if (check_in_oc(role_oc,found->attr_value)) { + /* Its a role :- follow member... */ + if ((found = as_find_type (*pres,at_RoleOccupant)) == NULLATTR) + return NOTOK; + + return dn2addr ((DN)&found->attr_value->avseq_av, pres); + } + + return OK; + +} + + +int dir_getdl_aux (dn, pres) +DN dn; +Attr_Sequence *pres; +{ +static Attr_Sequence astop = NULLATTR; +int result; + + if (astop == NULLATTR) { + Attr_Sequence as; + astop = as_comp_new (at_Member, NULLAV, NULLACL_INFO); + as = as_comp_new (at_Owner, NULLAV, NULLACL_INFO); + astop = as_merge (astop,as); + as = as_comp_new (at_Permit, NULLAV, NULLACL_INFO); + astop = as_merge (astop,as); + as = as_comp_new (at_Policy, NULLAV, NULLACL_INFO); + astop = as_merge (astop,as); +/* + as = as_comp_new (acl_at, NULLAV, NULLACL_INFO); + astop = as_merge (astop,as); +*/ + } + result = ds_cache_read (dn,astop,pres); + return result; +} + +int dir_getdl (list, pas) +char * list; +Attr_Sequence *pas; +{ + DN dn; + int result; + static DN localdn = NULLDN; + + if ((localdn == NULLDN) && local_dit) + localdn = str2dn (local_dit); + + if ((result = str2dl(list,localdn,&dn)) != OK) + return result; + + result = dir_getdl_aux (dn, pas); + dn_free (dn); + + return result; +} + +int read_group_entry (dn, pres) +DN dn; +Attr_Sequence *pres; +{ +static Attr_Sequence astop = NULLATTR; + + if (astop == NULLATTR) + astop = as_comp_new (at_GroupMember, NULLAV, NULLACL_INFO); + + return (ds_cache_read (dn,astop, pres)); +} + + +or_modify (ps,old,newname,at,dn) +PS ps; +ORName * old; +OR_ptr newname; +AttributeType at; +DN dn; +{ +struct ds_modifyentry_arg mod_arg; +struct DSError error; +static CommonArgs ca = default_common_args; +struct entrymod *emnew; +AttributeValue av; +AV_Sequence avs; +ORName * newor; +ORName * orName_cpy(); +OR_ptr or_cpy(); + + mod_arg.mea_common = ca; + mod_arg.mea_object = dn; + + emnew = em_alloc (); + emnew->em_type = EM_ADDVALUES; + av = AttrV_alloc(); + av->av_syntax = str2syntax("ORName"); + newor = orName_cpy (old); + if (newor->on_or != NULLOR) + or_free (newor->on_or); + newor->on_or = or_cpy(newname); + av->av_struct = (caddr_t) newor; + avs = avs_comp_new(av); + emnew->em_what = as_comp_new (AttrT_cpy(at),avs,NULLACL_INFO); + + mod_arg.mea_changes = emnew; + + emnew = em_alloc (); + emnew->em_type = EM_REMOVEVALUES; + av = AttrV_alloc(); + av->av_syntax = str2syntax("ORName"); + av->av_struct = (caddr_t) orName_cpy(old); + avs = avs_comp_new(av); + emnew->em_what = as_comp_new (AttrT_cpy(at),avs,NULLACL_INFO); + emnew->em_next = NULLMOD; + + mod_arg.mea_changes->em_next = emnew; + + if (ds_modifyentry (&mod_arg, &error) != DS_OK) { + ds_error (ps, &error); + return FALSE; + } + delete_cache (old->on_dn); + + ems_free (mod_arg.mea_changes); + + return TRUE; +} + +dl_modify (ps,name,dn,delete) +PS ps; +ORName * name; +DN dn; +char delete; +{ +struct ds_modifyentry_arg mod_arg; +struct DSError error; +static CommonArgs ca = default_common_args; +struct entrymod *emnew; +AttributeValue av; +AV_Sequence avs; + + mod_arg.mea_common = ca; + mod_arg.mea_object = dn; + + emnew = em_alloc (); + if (delete) + emnew->em_type = EM_REMOVEVALUES; + else + emnew->em_type = EM_ADDVALUES; + av = AttrV_alloc(); + av->av_syntax = str2syntax("ORName"); + av->av_struct = (caddr_t) name; + avs = avs_comp_new(av); + emnew->em_what = as_comp_new (AttrT_cpy(at_Member),avs,NULLACL_INFO); + emnew->em_next = NULLMOD; + + mod_arg.mea_changes = emnew; + + if (ds_modifyentry (&mod_arg, &error) != DS_OK) { + ds_error (ps, &error); + return FALSE; + } + delete_cache (dn); + ems_free (mod_arg.mea_changes); + + return TRUE; +} + +dl_modify_attr (ps,oldas,newas,dl,quiet) +PS ps; +Attr_Sequence oldas,newas; +DN dl; +char quiet; +{ +struct ds_modifyentry_arg mod_arg; +struct DSError error; +static CommonArgs ca = default_common_args; +struct entrymod *emnew; + + mod_arg.mea_common = ca; + mod_arg.mea_object = dl; + + if ((! oldas) || (oldas->attr_value == NULLAV)) { + emnew = em_alloc (); + emnew->em_type = EM_ADDATTRIBUTE; + emnew->em_what = as_comp_cpy (newas); + } else { + emnew = em_alloc (); + emnew->em_type = EM_REMOVEATTRIBUTE; + emnew->em_what = as_comp_cpy (oldas); + emnew->em_next = em_alloc(); + emnew->em_next->em_type = EM_ADDATTRIBUTE; + emnew->em_next->em_what = as_comp_cpy (newas); + } + + emnew->em_next->em_next = NULLMOD; + + mod_arg.mea_changes = emnew; + + if (!quiet) { + ps_print (ps, "modifying..."); + ps_flush (ps); + } + + if (ds_modifyentry (&mod_arg, &error) != DS_OK) { + ds_error (ps, &error); + return FALSE; + } + + if (!quiet) { + ps_print (ps, "OK\n"); + ps_flush (ps); + } + + delete_cache (dl); + ems_free (mod_arg.mea_changes); + + return TRUE; +} + +dl_modify_owner (ps,olddn,newdn,dl,quiet) +PS ps; +DN olddn,newdn; +DN dl; +char quiet; +{ +struct ds_modifyentry_arg mod_arg; +struct DSError error; +static CommonArgs ca = default_common_args; +struct entrymod *emnew; +AttributeValue av; +AV_Sequence avs; + + mod_arg.mea_common = ca; + mod_arg.mea_object = dl; + + emnew = em_alloc (); + emnew->em_type = EM_REMOVEATTRIBUTE; + av = AttrV_alloc(); + av->av_syntax = str2syntax("DN"); + av->av_struct = (caddr_t) dn_cpy(olddn); + avs = avs_comp_new(av); + emnew->em_what = as_comp_new (AttrT_cpy(at_Owner),avs,NULLACL_INFO); + + emnew->em_next = em_alloc(); + emnew->em_next->em_type = EM_ADDATTRIBUTE; + av = AttrV_alloc(); + av->av_syntax = str2syntax("DN"); + av->av_struct = (caddr_t) dn_cpy(newdn); + avs = avs_comp_new(av); + emnew->em_next->em_what = as_comp_new (AttrT_cpy(at_Owner),avs,NULLACL_INFO); + emnew->em_next->em_next = NULLMOD; + + mod_arg.mea_changes = emnew; + + if (!quiet) { + ps_print (ps, "modifying..."); + ps_flush (ps); + } + + if (ds_modifyentry (&mod_arg, &error) != DS_OK) { + ds_error (ps, &error); + return FALSE; + } + + if (!quiet) { + ps_print (ps, "OK\n"); + ps_flush (ps); + } + + delete_cache (dl); + ems_free (mod_arg.mea_changes); + + return TRUE; +} + +dl_bind (name,passwd) +DN name; +char * passwd; +{ + struct ds_bind_arg bindarg; + struct ds_bind_arg bindresult; + struct ds_bind_error binderr; + + bindarg.dba_version = DBA_VERSION_V1988; + + bindarg.dba_passwd_len = 0; + bindarg.dba_passwd [0] = '\0'; + + if ((bindarg.dba_dn = name) != NULLDN) { + if (passwd) { + bindarg.dba_passwd_len = strlen (passwd); + (void) strcpy (bindarg.dba_passwd,passwd); + } + } + + if (ds_bind (&bindarg,&binderr,&bindresult) != DS_OK) + return NOTOK; + else + return OK; +} + + +dl_unbind () +{ + (void) ds_unbind (); +} + + +str2dl (str,localdn,res) +char * str; +DN localdn; +DN * res; +{ +extern int print_parse_errors; +int old; +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filtcn, filtoc, filtand; + + old = print_parse_errors; + print_parse_errors = FALSE; + *res = str2dn (str); + print_parse_errors = old; + + if (*res != NULLDN) + return OK; + + filtcn = strfilter (at_CommonName,str,FILTERITEM_EQUALITY); + if ((filtoc = ocfilter ("ppDistributionList")) == NULLFILTER) + return NOTOK; + + filtoc->flt_next = filtcn; + filtand = joinfilter (filtoc,FILTER_AND); + + search_arg.sra_baseobject = localdn; + search_arg.sra_filter = filtand; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = FALSE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = NULLATTR; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + int resultint = isPermanentError(&err); + filter_free (filtoc); + log_ds_error (&err); + ds_error_free (&err); + return resultint; + } + filter_free (filtoc); + + if (result.CSR_entries) { + if (*res = result.CSR_entries->ent_dn) /* assign */ + return OK; + } + + return NOTOK; + +} + + +DN search_postmaster (localdn) +DN localdn; +{ +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filtcn; + + if (mailas == NULLATTR) { + Attr_Sequence as; + mailas = as_comp_new (at_ORAddress, NULLAV, NULLACL_INFO); + as = as_comp_new (at_RFC822, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + as = as_comp_new (at_ObjectClass, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + as = as_comp_new (at_RoleOccupant, NULLAV, NULLACL_INFO); + mailas = as_merge (mailas,as); + } + + filtcn = strfilter (at_CommonName,"PostMaster",FILTERITEM_EQUALITY); + + search_arg.sra_baseobject = localdn; + search_arg.sra_filter = filtcn; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = TRUE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = mailas; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + filter_free (filtcn); + log_ds_error (&err); + ds_error_free (&err); + return NULLDN; + } + filter_free (filtcn); + + if (result.CSR_entries) { + cache_entry (result.CSR_entries,FALSE,TRUE); + return (result.CSR_entries->ent_dn); + } + + return NULLDN; +} + +dl_showentry(ps,dn) +PS ps; +DN dn; +{ +struct ds_read_arg read_arg; +struct ds_read_result result; +struct DSError error; +static CommonArgs ca = default_common_args; +Entry ptr; + + if ((ptr = local_find_entry (dn,TRUE)) != NULLENTRY) + if (ptr->e_complete) { + as_print (ps,ptr->e_attributes,READOUT); + return; + } + + read_arg.rda_common = ca; /* struct copy */ + + read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + read_arg.rda_eis.eis_allattributes = TRUE; + read_arg.rda_eis.eis_select = NULLATTR; + read_arg.rda_object = dn; + + if (ds_read (&read_arg, &error, &result) != DS_OK) + ds_error(ps,&error); + + cache_entry (&result.rdr_entry,FALSE,TRUE); + + as_print (ps,result.rdr_entry.ent_attr,READOUT); +} + +add_list_request (ps,where, listname, owner) +PS ps; +DN where; +char * listname; +DN owner; +{ +struct ds_addentry_arg add_arg; +struct DSError error; +Attr_Sequence as,nas; +char buffer [LINESIZE]; +DN obj; +DN dnc; +static CommonArgs ca = default_common_args; + + add_arg.ada_common = ca; /* struct copy */ + + (void) sprintf (buffer, "cn=%s-request",listname); + if ((as = str2as (buffer)) == NULLATTR) + return FALSE; + if ((dnc = str2dn (buffer)) == NULLDN) + return FALSE; + + (void) sprintf (buffer, "ObjectClass=ppRole&quipuobject"); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, "roleOccupant=%s",dn2str(owner)); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, "mhsORAddresses=%s-request",listname); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, + "acl=others # read # entry & others # read # default & group #"); + strcat (buffer, dn2str(owner)); + strcat (buffer, "# write # entry & group #"); + strcat (buffer, dn2str(owner)); + strcat (buffer, "# write # default"); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + obj = dn_cpy (where); + dn_append (obj,dn_cpy(dnc)); + add_arg.ada_object = obj; + add_arg.ada_entry = as; + + if (ds_addentry (&add_arg, &error) != DS_OK) { + ds_error (ps,&error); + dn_free (obj); + as_free (as); + return FALSE; + } + + dn_free (obj); + as_free (as); + + return TRUE; +} + +add_new_list (ps, where,listname, owner, description,members) +PS ps; +DN where; +char * listname; +DN owner; +char *description; +Attr_Sequence members; +{ +struct ds_addentry_arg add_arg; +struct DSError error; +Attr_Sequence as,nas; +char buffer [LINESIZE]; +DN obj; +DN dnc; +static CommonArgs ca = default_common_args; + + add_arg.ada_common = ca; /* struct copy */ + + (void) sprintf (buffer, "cn=%s",listname); + if ((as = str2as (buffer)) == NULLATTR) + return FALSE; + if ((dnc = str2dn (buffer)) == NULLDN) + return FALSE; + + (void) sprintf (buffer, "ObjectClass=ppDistributionList&quipuobject"); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, "owner=%s@cn=%s-request",dn2str(where),listname); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + if (members) + as = as_merge (as,members); + else { + (void) sprintf (buffer, "mhsDLmembers=%s",dn2str(owner)); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + } + + if (description && *description != 0) { + (void) sprintf (buffer, "description=%s",description); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + } + + (void) sprintf (buffer, "mhsDLSubmitPermissions=ALL"); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, + "acl=others # read # entry & others # read # default & group #"); + strcat (buffer, dn2str(owner)); + strcat (buffer, "# write # entry & group #"); + strcat (buffer, dn2str(owner)); + strcat (buffer, "# write # default"); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + (void) sprintf (buffer, "mhsORAddresses=%s",listname); + if ((nas = str2as (buffer)) == NULLATTR) + return FALSE; + as = as_merge (as,nas); + + obj = dn_cpy (where); + dn_append (obj,dn_cpy(dnc)); + add_arg.ada_object = obj; + add_arg.ada_entry = as; + + if (ds_addentry (&add_arg, &error) != DS_OK) { + ds_error (ps,&error); + dn_free (obj); + as_free (as); + return FALSE; + } + + dn_free (obj); + as_free (as); + + return TRUE; +} + + + diff --git a/Chans/lists/dlist.h b/Chans/lists/dlist.h new file mode 100644 index 0000000..64a966e --- /dev/null +++ b/Chans/lists/dlist.h @@ -0,0 +1,62 @@ +/* dlist.h: */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/lists/RCS/dlist.h,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: dlist.h,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_DIRLIST_DLIST +#define _H_DIRLIST_DLIST + +#include "util.h" +#include +#include "or.h" +#include "DL-types.h" +#include "MD-types.h" + +typedef struct dl_policy { + char dp_expand; + + int dp_convert; +#define DP_ORIGINAL 1 /* default */ +#define DP_FALSE 2 +#define DP_TRUE 3 + + int dp_priority; +/* #define DP_ORIGINAL 1 */ +#define DP_LOW 2 /* default */ +#define DP_NORMAL 3 +#define DP_HIGH 4 + +} dl_policy; + + + +typedef struct dl_permit { + + int dp_type; +#define DP_INDIVIDUAL 1 +#define DP_MEMBER 2 +#define DP_PATTERN 3 +#define DP_GROUP 4 + + union { + ORName * dp_un_or; + DN dp_un_dn; + } dp_un; + +#define dp_or dp_un.dp_un_or +#define dp_dn dp_un.dp_un_dn + +} dl_permit; + + + +#endif diff --git a/Chans/lists/hack.c b/Chans/lists/hack.c new file mode 100644 index 0000000..8d128f9 --- /dev/null +++ b/Chans/lists/hack.c @@ -0,0 +1,258 @@ +/* hack.c - taken from quipu/dish/fred.c */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/hack.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/hack.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: hack.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ISODE < 69 +#define s_filter filter +#endif + +struct dn_seq *dl_interact (); + +Filter joinfilter (), ocfilter (); + +struct dn_seq *dn_seq_push (); + +/* DM2DN SUPPORT */ + +static int dlevel = 0; +static int dsa_status; + +struct dn_seq *dm2dn_seq (); +struct dn_seq *dm2dn_seq_aux (); +Filter make_filter (); + +/* */ + +DN str2ufn_here (ufn,dn) +char * ufn; +DN dn; +{ +struct ds_search_arg search_arg; +static struct ds_search_result result; +struct DSError err; +static CommonArgs ca = default_common_args; +Filter filtcn, filtoc, filtand, filtor, filtuid, strfilter(); + + filtcn = strfilter (AttrT_new("cn"),ufn,FILTERITEM_APPROX); + filtuid = strfilter (AttrT_new("uid"),ufn,FILTERITEM_EQUALITY); + filtoc = ocfilter ("person"); + + filtuid->flt_next = filtcn; + filtor = joinfilter (filtuid, FILTER_OR); + + filtoc->flt_next = filtor; + filtand = joinfilter (filtoc,FILTER_AND); + + search_arg.sra_baseobject = dn; + search_arg.sra_filter = filtand; + search_arg.sra_subset = SRA_ONELEVEL; + search_arg.sra_searchaliases = FALSE; + search_arg.sra_common = ca; /* struct copy */ + search_arg.sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + search_arg.sra_eis.eis_allattributes = FALSE; + search_arg.sra_eis.eis_select = NULLATTR; + + if (ds_search (&search_arg, &err, &result) != DS_OK) { + filter_free (filtoc); + log_ds_error (&err); + ds_error_free (&err); + return NULLDN; + } + filter_free (filtoc); + + if (result.CSR_entries) { + if (result.CSR_entries->ent_next) + /* could ask user to select here - leave that for UCL */ + return NULLDN; + return result.CSR_entries->ent_dn ; + } + + return NULLDN; + +} + +DN do_dm_match (vec) +char *vec; +{ + int seqno; + char *cp, + mbox[BUFSIZ]; + register struct dn_seq *dlist, + *dp; + DN dn; + extern char * local_dit; + DN localdn; + + localdn = str2dn (local_dit); + + if ((cp = index (vec, '@')) && cp != vec) { + *cp++ = NULL; + (void) strcpy (mbox, vec); + if (*cp == NULL) + return NULLDN; + } + else + return str2ufn_here(vec,localdn); + + if ((dlist = dm2dn_seq (cp)) == NULLDNSEQ) { +/* + ps_printf (OPT, "Unable to resolve domain.\n"); +*/ + return NULLDN; + } + + if ((! dlist) || dlist->dns_next) + NULLDN; + + if ((dn = str2ufn_here(mbox,dlist->dns_dn)) != NULLDN) + return dn; + + return NULLDN; +} + +/* */ + +static struct dn_seq *dm2dn_seq (dm) +char *dm; +{ + register char *dp; + + for (dp = dm; *dp; dp++) + if (isupper (*dp)) + *dp = tolower (*dp); + + dlevel = 0; + dsa_status = OK; + + return dm2dn_seq_aux (dm, NULLDN, NULLDNSEQ); +} + +/* */ + +static struct dn_seq *dm2dn_seq_aux (dm, dn, dlist) +char *dm; +DN dn; +struct dn_seq *dlist; +{ + register char *dp; + struct ds_search_arg search_arg; + register struct ds_search_arg *sa = &search_arg; + struct ds_search_result search_result; + register struct ds_search_result *sr = &search_result; + struct DSError error; + register struct DSError *se = &error; + + bzero ((char *) sa, sizeof *sa); + + sa -> sra_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; + sa -> sra_common.ca_servicecontrol.svc_timelimit = SVC_NOTIMELIMIT; + sa -> sra_common.ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT; + + sa -> sra_baseobject = dn; + sa -> sra_subset = SRA_ONELEVEL; + sa -> sra_searchaliases = FALSE; + + sa -> sra_eis.eis_allattributes = FALSE; + sa -> sra_eis.eis_select = NULLATTR; + sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + + dp = dm; + for (;;) { + int i; + EntryInfo *ptr; + register struct s_filter *fi; + + if ((i = strlen (dp)) < dlevel) + break; + + sa -> sra_filter = fi = filter_alloc (); + + bzero ((char *) fi, sizeof *fi); + fi -> flt_type = FILTER_ITEM; + fi -> FUITEM.fi_type = FILTERITEM_EQUALITY; + if ((fi -> FUITEM.UNAVA.ava_type = AttrT_new ("associateddomain")) == NULL) + fatal (-100, "associatedDomain: invalid attribute type"); + fi -> FUITEM.UNAVA.ava_value = str2AttrV (dp, str2syntax("IA5string")); + + if (ds_search (sa, se, sr) != DS_OK) + goto free_filter; + + if (sr -> srr_correlated != TRUE) + correlate_search_results (sr); + + if (sr -> CSR_entries == NULLENTRYINFO) { + filter_free (sa -> sra_filter); + if (dp = index (dp, '.')) + dp++; + if (dp == NULL) + break; + continue; + } + + for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) + cache_entry (ptr, sa -> sra_eis.eis_allattributes, + sa -> sra_eis.eis_infotypes); + + if (i > dlevel) { + dlevel = i; + if (dlist) + dn_seq_free (dlist), dlist = NULLDNSEQ; + } + + if (i == dlevel) + for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) { + struct dn_seq *dprev = dlist; + + dlist = dm2dn_seq_aux (dm, ptr -> ent_dn, dlist); + + if (dprev == dlist) + dlist = dn_seq_push (ptr -> ent_dn, dlist); + else + if (i < dlevel) + break; + } + + dn_free (sr -> CSR_object); + entryinfo_free (sr -> CSR_entries, 0); + crefs_free (sr -> CSR_cr); + +free_filter: ; + filter_free (sa -> sra_filter); + break; + } + + return dlist; +} + diff --git a/Chans/lists/init.c b/Chans/lists/init.c new file mode 100644 index 0000000..ea974f7 --- /dev/null +++ b/Chans/lists/init.c @@ -0,0 +1,118 @@ +/* init.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/init.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/init.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: init.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include + +AttributeType at_Member; +AttributeType at_Owner; +AttributeType at_Permit; +AttributeType at_Policy; +AttributeType at_ORAddress; +AttributeType at_RFC822; +AttributeType at_GroupMember; +AttributeType at_RoleOccupant; + +OID dl_oc; +OID role_oc; + +extern LLog * log_dsap; + +pp_quipu_init (str) +char * str; +{ + pp_syntaxes (); + pp_initialise(str, 0); + or_myinit(); +} + +mhs_syntaxes () +{ + orAddr_syntax (); + orName_syntax (); + permit_syntax (); + policy_syntax (); +} + +pp_syntaxes () { + mhs_syntaxes (); + policy_syntax (); +} + +pp_quipu_run () +{ +int result = TRUE; +int ufn_init (); + + if ((dl_oc = name2oid ("ppDistributionList")) == NULLOID) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("ppDistributionList unknown Objectclass")); + } + if ((role_oc = name2oid ("organizationalRole")) == NULLOID) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("organizationalRole unknown Objectclass")); + } + + /* DL Mandatory */ + if ((at_Member = AttrT_new ("mhsDLMembers")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("mhsDLMembers attribute unknown")); + } + if ((at_Owner = AttrT_new ("Owner")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("Owner attribute unknown")); + } + if ((at_Permit = AttrT_new ("mhsDLSubmitPermissions")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("mhsDLSubmitPermissions attribute unknown")); + } + + /* DL Optional */ + if ((at_Policy = AttrT_new ("dl-policy")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("dl-policy attribute unknown")); + } + + /* MHS mail box attrs */ + if ((at_ORAddress = AttrT_new ("mhsORAddresses")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("mhsORAddresses attribute unknown")); + } + if ((at_RFC822 = AttrT_new ("rfc822Mailbox")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("rfc822Mailbox attribute unknown")); + } + + /* X500 group member */ + if ((at_GroupMember = AttrT_new ("member")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("member attribute unknown")); + } + if ((at_RoleOccupant = AttrT_new ("RoleOccupant")) == NULLAttrT) { + result = FALSE; + LLOG (log_dsap,LLOG_EXCEPTIONS,("RoleOccupant attribute unknown")); + } + + if (result) + result = ufn_init(); + else + (void) ufn_init (); + + return result; +} + + diff --git a/Chans/lists/list.c b/Chans/lists/list.c new file mode 100644 index 0000000..365c311 --- /dev/null +++ b/Chans/lists/list.c @@ -0,0 +1,1301 @@ +/* list.c: list processor channel (both directory and table) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/list.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/list.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: list.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "head.h" +#include "qmgr.h" +#include "chan.h" +#include "q.h" +#include "dr.h" +#include "or.h" +#include "prm.h" + +#include +#include +#ifdef SYS5 +#include +#endif + + +#ifdef DIRLIST + +#include "dlist.h" +#include + +#else + +#include "dl.h" + +#endif + +#include "retcode.h" +#include "sys.file.h" +#include + +extern void rd_end(), sys_init(), err_abrt(); +extern struct type_Qmgr_DeliveryStatus *delivery_resetDRs(); + +extern ADDR *adr_new(); +extern char *ad_getlocal(); +extern char *quedfldir; +extern char *loc_dom_site; +extern OR_ptr or_std2or(), + or_default(), + or_std2or(); + +extern LLog *log_dsap; +#ifndef DIRLIST +extern ADDR *tb_getModerator(); +#endif + +static int expandList(); +static char *get_adrstr(); +static int get_adrtype(); +static void dirinit(); +static void set_success(); +static int initialise(), endfunc (); +static ADDR *getnthrecip(); +static int submit_error(); +static int processMsg(); +static int expansionLoop; +static struct type_Qmgr_DeliveryStatus *process(); +static Q_struct qs; + +static int processDR(); + +#ifdef DIRLIST + +static ADDR *construct_sender(); +Attr_Sequence this_list = NULLATTR; +extern int dir_getdl(); +extern AttributeType at_Owner; +extern AttributeType at_Policy; +extern AttributeType at_Member; +extern ADDR *ORName2ADDR(); + +#endif + +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; +int start_submit; +int first_successDR, first_failureDR; +int adrno; +int expandSublists = FALSE; +int linked = TRUE; + +/* ----------------------- Begin Routines ------------------------------- */ + + +main (argc, argv) +int argc; +char **argv; +{ +#ifdef DIRLIST +int n = 1; +#endif + +#ifdef PP_DEBUG + char pp_debug = FALSE; +#endif + + sys_init (argv[0]); + or_myinit(); + dirinit(); + +#ifdef DIRLIST + quipu_syntaxes (); + pp_syntaxes(); +#endif + +#ifdef PP_DEBUG + if (argc>1 && (strcmp (argv[1], "debug") == 0)) + pp_debug = TRUE; +#endif + +#ifdef DIRLIST + dsap_init (&n, &argv); + log_dsap -> ll_file = strdup ("dsap.log"); + + (void) pp_quipu_run (); +#endif + +#ifdef PP_DEBUG + if (pp_debug) + debug_channel_control (argc,argv,initialise,process,endfunc); + else +#endif + channel_control (argc,argv,initialise,process,endfunc); +} + + + +/* ----------------------- Static Routines ------------------------------- */ + + + +/* --- routine to move to correct place in file system --- */ +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", quedfldir); +} + + +/* ARGSUSED */ +static int endfunc (arg) +struct type_Qmgr_Channel *arg; +{ + if (start_submit == FALSE) + io_end (OK); + start_submit = TRUE; + +#ifdef DIRLIST + dl_unbind(); +#endif +} + + + +/* --- channel initialise routine --- */ + +DN bindas = NULLDN; +char *bindpasswd = NULLCP; + +static void do_ch_info_flags(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + if ((margc = sstr2arg(info_copy, 20, margv, ",")) > 0) { + for (ix = 0; ix < margc; ix++) { + if (lexequ(margv[ix], "dosublists") == 0) + expandSublists = TRUE; + else if (lexequ(margv[ix], "notlinked") == 0) + linked = FALSE; + else if (lexequ(margv[ix], "linked") == 0) + linked = TRUE; +#ifdef DIRLIST + else if (lexnequ(margv[ix], "DN", strlen("DN")) == 0) { + char *dn = index(margv[ix], '='); + + if (dn == NULLCP) + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrectly formatted info field '%s' expecting key=value", + margv[ix])); + else { + dn++; + if ((bindas = str2dn(dn)) == NULLDN) + PP_LOG(LLOG_EXCEPTIONS, + ("Invalid DN '%s'", + dn)); + } + } + else if (lexnequ(margv[ix], "passwd", strlen("passwd")) == 0) { + char *pd = index(margv[ix], '='); + + if (pd == NULLCP) + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrectly formatted info field '%s' expecting key=value", + margv[ix])); + else { + pd++; + bindpasswd = strdup(pd); + } + } +#endif + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown ch_info flag '%s'", + margv[ix])); + } + } + free(info_copy); +} + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str (arg); + + if ((mychan = ch_nm2struct (name)) == NULLCHAN) { + PP_OPER (NULLCP, ("Channel '%s' not known", name)); + if (name != NULLCP) + free (name); + return NOTOK; + } + + start_submit = TRUE; + if (mychan -> ch_out_info != NULLCP) + do_ch_info_flags(mychan->ch_out_info); + + /* --- check if a list channel --- */ + if (name != NULLCP) + free (name); + +#ifdef DIRLIST + if (dl_bind (bindas, bindpasswd) != OK) + return NOTOK; +#endif + + return OK; +} + + + +/* --- routine to check if allowed to list process this message --- */ + +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULLCP, + *msg_chan = NULLCP; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp (msg_chan,mychan->ch_name) !=0)) { + PP_LOG (LLOG_EXCEPTIONS, + ("channel err: '%s'", msg_chan)); + result = FALSE; + } + + if (msg_file != NULLCP) free (msg_file); + if (msg_chan != NULLCP) free (msg_chan); + + return result; +} + + + + +/* --- routine called to do list processing --- */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, + retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + RP_Buf reply; + + + bzero ((char *)&prm, sizeof (prm)); + bzero ((char *)&que, sizeof (que)); + + delivery_init (arg->users); + delivery_setall (int_Qmgr_status_messageFailure); + first_failureDR = first_successDR = TRUE; + + if (security_check (arg) != TRUE) + return deliverystate; + + if (this_msg != NULLCP) free (this_msg); + if (this_chan != NULLCP) free (this_chan); + + this_msg = qb2str (arg->qid); + this_chan = qb2str (arg->channel); + + PP_LOG (LLOG_NOTICE, + ("processing msg '%s' through '%s'",this_msg, this_chan)); + + if (rp_isbad (rd_msg (this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Chans/list rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "Can't read message"); + } + + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip (&que, ix->RecipientId->parm)) == NULL) { + + PP_LOG (LLOG_EXCEPTIONS, + ("failed to find recipient %d of msg '%s'", + ix->RecipientId->parm, this_msg)); + + delivery_setstate (ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + if (start_submit == TRUE && rp_isbad (io_init (&reply))) { + submit_error (adr,"io_init",&reply); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Unable to start submit"); + } + else + start_submit = FALSE; + + switch (dchan_acheck (adr, sender, mychan, 1, (char **)NULL)) { + default: + case NOTOK: + break; + case OK: + switch (que.msgtype) { + case MT_UMPDU: + default: + processMsg (this_msg,&prm,&que,adr,sender); + break; + case MT_DMPDU: + processDR (this_msg,&prm,&que,adr,sender); + break; + } + break; + } + + } + + if (rp_isbad (retval = wr_q2dr (&que, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + (void) delivery_resetDRs (int_Qmgr_status_messageFailure); + } + + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + + + + +/* --- --- */ +static int submit_error (recip, proc, reply) +ADDR *recip; +char *proc; +RP_Buf *reply; +{ + char buf[BUFSIZ]; + PP_LOG (LLOG_EXCEPTIONS, + ("Chans/list %s failure [%s]", proc, reply->rp_line)); + + if (recip != NULLADDR) { + (void) sprintf (buf, + "'%s' failure for '%s' [%s]", + proc, + this_msg, + reply -> rp_line); + PP_OPER(NULLCP,("%s", buf)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + buf); + } + + start_submit = TRUE; + io_end (NOTOK); + + return OK; +} + +static int processMsg (msg, prm, que, recip, origsender) +char *msg; +struct prm_vars *prm; +Q_struct *que; +ADDR *recip; +ADDR *origsender; +{ + ADDR *expanded, + *ix, + *sender; + RP_Buf reply; + char *msgdir = NULLCP, + file[MAXPATHLENGTH], + buf[BUFSIZ], + *strippedname; + int dirlen, + n, + fd_in; + int size; + struct stat st; + struct timeval data_time; +#ifdef DIRLIST + Attr_Sequence policy_as; +#else + char *local; +#endif + + if (qid2dir (msg, recip, TRUE, &msgdir) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("msg dir not found for recip %d of msg '%s'", + recip->ad_no, msg)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + "source directory not found"); + return 0; + } + + if (que->dl_expansion_prohibited == TRUE) { + delivery_set (recip -> ad_no, + (first_failureDR == TRUE) ? + int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + (void) sprintf (buf, "DL expansion prohibited for this message"); + set_1dr (que, recip -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, DRD_DL_EXPANSION_PROHIBITED, + buf); + return 0; + } + + /* --- expand list and resubmit message --- */ + q_init (&qs); + + q_almost_dup (&qs, que); + + if (recip -> ad_content != NULLCP) { + if (qs.cont_type) free(qs.cont_type); + qs.cont_type = strdup(recip -> ad_content); + } else if (qs.cont_type != NULLCP) { + free(qs.cont_type); + qs.cont_type = NULLCP; + } + + if (recip -> ad_eit != NULLIST_BPT) + qs.encodedinfo.eit_types = list_bpt_dup (recip->ad_eit); + else + qs.encodedinfo.eit_types = list_bpt_dup (que->encodedinfo.eit_types); + + if (qs.ua_id) { + free(qs.ua_id); + qs.ua_id = NULLCP; + } + qs.priority = PRIO_NONURGENT; + qs.disclose_recips = FALSE; + adrno = 1; + + expansionLoop = FALSE; + switch (expandList (recip,&expanded,& (qs.dl_expansion_history))) { + case NOTOK: + delivery_set (recip->ad_no, + (first_failureDR == TRUE) ? + int_Qmgr_status_negativeDR : + int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + (void) sprintf (buf, "Unable to expand list '%s'",get_adrstr (recip)); + set_1dr (que, recip->ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, DRD_DL_EXPANSION_FAILURE, buf); + return 0; + case DONE: + delivery_setstate (recip->ad_no, + (mychan -> ch_sort[0] == CH_SORT_USR) ? + int_Qmgr_status_mtaFailure : + int_Qmgr_status_messageFailure, + "temporary list processing failure (better check the logs)"); + return 0; + default: + break; + } + + + /* --- expands to nothing so done --- */ + if (expanded == NULLADDR) { + if (expansionLoop == TRUE) + set_success(recip, que, 0); + PP_LOG(LLOG_EXCEPTIONS, + ("list '%s' is an empty list", recip->ad_value)); + return 0; + } + +#ifdef DIRLIST + if (check_dl_permission (origsender,this_list) == NOTOK) { + delivery_set(recip->ad_no, + (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + (void) sprintf(buf, "Distribution list policy prevents expansion of '%s'",get_adrstr(recip)); + set_1dr(que, recip->ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_DL_EXPANSION_FAILURE, + buf); + return 0; + } + + if (((policy_as = as_find_type(this_list,at_Policy)) != NULLATTR) && + (policy_as->attr_value != NULLAV)) { + struct dl_policy * policy; + + policy = (struct dl_policy *) policy_as->attr_value->avseq_av.av_struct; + + if (policy->dp_expand) + qs.dl_expansion_prohibited = FALSE; + else + qs.dl_expansion_prohibited = TRUE; + + switch (policy->dp_priority) { + case DP_LOW: + qs.priority = PRIO_NONURGENT; break; + case DP_HIGH: + qs.priority = PRIO_URGENT; break; + case DP_NORMAL: + qs.priority = PRIO_NORMAL; break; + case DP_ORIGINAL: + qs.priority = que->priority; break; + } + + switch (policy->dp_convert) { + case DP_ORIGINAL: + qs.implicit_conversion_prohibited = que->implicit_conversion_prohibited ; break; + case DP_FALSE: + qs.implicit_conversion_prohibited = FALSE; break; + case DP_TRUE: + qs.implicit_conversion_prohibited = TRUE; break; + } + + } else { + /* Assume default policy */ + qs.dl_expansion_prohibited = FALSE; + qs.priority = PRIO_NONURGENT; + qs.implicit_conversion_prohibited = que->implicit_conversion_prohibited; + } + + if ((sender = construct_sender (this_list)) == NULLADDR) + return submit_error(recip,"construct sender",&reply); +#else + if ((local = ad_getlocal (recip->ad_r822adr, AD_822_TYPE)) == NULLCP) + sender = tb_getModerator(recip->ad_r822adr); + else { + sender = tb_getModerator (local); + free (local); + } + if (sender == NULLADDR) + return 0; +#endif + qs.inbound = list_rchan_new (loc_dom_site,mychan->ch_name); + sender->ad_status = AD_STAT_DONE; + sender->ad_resp = NO; + prm->prm_opts = prm->prm_opts | PRM_ACCEPTALL | PRM_NOTRACE; + /* --- now resubmit --- */ + + timer_start(&data_time); + if (rp_isbad (io_wprm (prm, &reply))) + return submit_error (recip,"io_wprm",&reply); + + if (rp_isbad (io_wrq (&qs, &reply))) + return submit_error (recip,"io_wrq",&reply); + + if (sender->ad_redirection_history != (Redirection *) NULL) { + /* free of existing redirection history */ + redirect_free(sender->ad_redirection_history); + sender->ad_redirection_history = (Redirection *) NULL; + } + if (rp_isbad (io_wadr (sender, AD_ORIGINATOR, &reply))) { + char nbuf[BUFSIZ]; + (void) sprintf(nbuf, "io_wadr(%s)", sender->ad_value); + return submit_error (recip,nbuf,&reply); + } + + ix = expanded; + while (ix != NULL) { + if (ix->ad_redirection_history != (Redirection *) NULL) { + /* free of existing redirection history */ + redirect_free(ix->ad_redirection_history); + ix->ad_redirection_history = (Redirection *) NULL; + } + ix->ad_explicitconversion = recip->ad_explicitconversion; + if (rp_isbad (io_wadr (ix, AD_RECIPIENT, &reply))) { + char nbuf[BUFSIZ]; + (void) sprintf(nbuf, "io_wadr(%s)", + ix -> ad_value); + return submit_error (recip,nbuf, &reply); + } + ix = ix->ad_next; + } + + if (rp_isbad (io_adend (&reply))) + return submit_error (recip,"io_adend", &reply); + + /* --- send over body --- */ + if (rp_isbad (io_tinit (&reply))) + return submit_error (recip,"io_tinit",&reply); + + dirlen = strlen (msgdir) +1; + + msg_rinit (msgdir); + + size = 0; + while (msg_rfile (file) != RP_DONE) { + + /* --- transmit file --- */ + strippedname = file + dirlen; + if (stat (file, &st) != NOTOK) + size += st.st_size; + if (linked == TRUE) { + (void) sprintf(buf, "%s %s",strippedname, file); + if (rp_isbad (io_tpart (buf, TRUE, &reply))) + return submit_error (recip,"io_tpart",&reply); + } else { + if (rp_isbad (io_tpart (strippedname, FALSE, &reply))) + return submit_error (recip,"io_tpart",&reply); + + if ((fd_in = open (file, O_RDONLY)) == -1) { + (void) strcpy (reply.rp_line,file); + return submit_error (recip,"open",&reply); + } + while ((n = read (fd_in, buf, BUFSIZ)) > 0) { + if (rp_isbad (io_tdata (buf, n))) { + (void) strcpy (reply.rp_line,"???"); + return submit_error (recip,"io_tdata",&reply); + } + } + + close (fd_in); + if (rp_isbad (io_tdend (&reply))) + return submit_error (recip,"io_tdend", &reply); + } + } + msg_rend(); + if (rp_isbad (io_tend (&reply))) + return submit_error (recip,"io_tend", &reply); + set_success (recip,que, size); + timer_end(&data_time, size, "Data submitted"); + return 0; +} + + + +static void set_success (recip, que, size) +ADDR *recip; +Q_struct *que; +int size; +{ + if (recip->ad_usrreq == AD_USR_CONFIRM || + recip->ad_mtarreq == AD_MTA_CONFIRM || + recip->ad_mtarreq == AD_MTA_AUDIT_CONFIRM) + { + set_1dr (que, recip->ad_no, this_msg, + DRR_NO_REASON, -1, NULLCP); + delivery_set (recip->ad_no, + (first_successDR == TRUE) ? + int_Qmgr_status_positiveDR : + int_Qmgr_status_successSharedDR); + first_successDR = FALSE; + } + else { + (void) wr_ad_status (recip, AD_STAT_DONE); + (void) wr_stat (recip, que, this_msg, size); + delivery_set (recip->ad_no, int_Qmgr_status_success); + } +} + + + +/* --- --- */ +static ADDR *getnthrecip (que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + + +/* */ +#ifdef DIRLIST +static ADDR *construct_sender(as) +Attr_Sequence as; +{ + ADDR *ret = NULLADDR; + ADDR *get_manager(); + ADDR *get_postmaster(); + + if ((ret = get_manager(as)) == NULLADDR) + return (get_postmaster()); + + return ret; +} +#endif + +/* --- --- */ +static char *getORname (adr) +ADDR *adr; +{ + OR_ptr tree = NULLOR, + new = NULLOR; + char buf[BUFSIZ], + *value; + + bzero (buf, BUFSIZ); + if (adr -> ad_r400adr != NULLCP) + return strdup(adr -> ad_r400adr); + + value = adr -> ad_value; + + if ((or_rfc2or (value, &tree) != OK) || tree == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, + ("getORname: Failed to parse '%s'", value)); + if (adr->ad_dn) + return strdup(adr->ad_dn); + return NULLCP; + } + + new = or_default (tree); + or_or2std (new, buf, 0); + if (new) or_free (new); + + return strdup (buf); +} + + + +static void postExpansion (adr, pdlh) +ADDR *adr; +DLHistory **pdlh; +{ + char *orname; + + if ((orname = getORname (adr)) == NULLCP) + return; + dlh_add (pdlh,dlh_new (orname, NULLCP, NULLUTC)); + free (orname); +} + + + +static int expandedBefore (adr, dlh) +ADDR *adr; +DLHistory *dlh; +{ + char *orname; + int found = FALSE; + + if ((orname = getORname (adr)) == NULLCP) + return FALSE; + + while (found == FALSE && dlh != NULL) { + if (strcmp (orname, dlh->dlh_addr) == 0) + found = TRUE; + else + dlh = dlh -> dlh_next; + } + + free (orname); + return found; +} + + +#ifdef DIRLIST +static ADDR *dl2addr(as, pnum) +Attr_Sequence as; +int *pnum; +{ +Attr_Sequence tmp; +ADDR *ret = NULLADDR; +ADDR *next; +AV_Sequence avs; +int num = 0; + + /* Find mhsDLmembers */ + if ((tmp = as_find_type(as,at_Member)) == NULLATTR) + return NULLADDR; + + /* Convert to ADDR */ + for (avs=tmp->attr_value; avs!= NULLAV; avs=avs->avseq_next) { + if ((next = ORName2ADDR ((ORName *)avs->avseq_av.av_struct,TRUE)) == NULLADDR) + return NULLADDR; + next->ad_extension = num; + next->ad_no = num; + num++; + adr_add(&ret, next); + } + *pnum = num; + return ret; + +} +#else +static ADDR *dl2addr (indl, pnum) +dl *indl; +int *pnum; +{ + ADDR *ret = NULLADDR; + Name *list = indl -> dl_list; + int type = AD_ANY_TYPE; + + for (*pnum=0; list != NULL; list = list -> next, (*pnum)++) + adr_add (&ret, adr_new (list->name, type, adrno++)); + + return ret; +} +#endif + + +static int attemptExpansion (key, type, padr, complain) +char *key; +int type; +ADDR **padr; +int complain; +{ +#ifndef DIRLIST + dl *list; +#endif + char *local; + int count; + *padr = NULLADDR; + + if ((local = ad_getlocal (key,type)) != NULLCP) { + PP_NOTICE(("Attempting to expand list '%s'", local)); +#ifdef DIRLIST + switch (dir_getdl(local, &this_list)) { + case OK: + *padr = dl2addr(this_list, &count); + PP_NOTICE(("Expanded list '%s' to %d recipient%s", + local, count, + (count == 1) ? "" : "s")); + free(local); + return OK; + case DONE: + PP_NOTICE (("Temporary failure to expand list '%s'", + local)); + free (local); + return DONE; + default: + PP_NOTICE (("Failed to find list '%s' in the directory", local)); + free (local); + break; + } +#else + switch (tb_getdl (local, &list,complain)) { + case OK: + *padr = dl2addr (list, &count); + dl_free (list); + PP_NOTICE(("Expanded list '%s' to %d recipient%s", + local, count, + (count == 1) ? "" : "s")); + free (local); + return OK; + case DONE: + if (list != NULL) + dl_free(list); + PP_NOTICE (("Temporary failure to expand list '%s'", + local)); + free(local); + return DONE; + default: + if (list != NULL) + dl_free(list); + PP_NOTICE (("Failed to expand list '%s'", local)); + free (local); + break; + } +#endif + } + +#ifdef DONT_WANT_THIS_ANYMORE + + PP_NOTICE(("Attempting to expand list '%s'", key)); + +#ifdef DIRLIST + switch (dir_getdl(key, &this_list)) { + case OK: + *padr = dl2addr(this_list, &count); + PP_NOTICE(("Expanded list '%s' to %d recipient%s", + key, count, + (count == 1) ? "" : "s")); + return OK; + case DONE: + PP_NOTICE (("Temporary failure to expand list '%s'", + key)); + return DONE; + default: + PP_NOTICE (("Failed to expand list '%s'", key)); + break; + } +#else + + switch (tb_getdl (key,&list,complain)) { + case OK: + *padr = dl2addr (list, &count); + dl_free (list); + PP_NOTICE(("Expanded list '%s' to %d recipients", + key, count)); + return OK; + case DONE: + if (list != NULL) + dl_free(list); + PP_NOTICE (("Temporary failure to expand list '%s'", + key)); + return DONE; + default: + if (list != NULL) + dl_free(list); + PP_NOTICE (("Failed to expand list '%s'", key)); + break; + } +#endif + +#endif + return NOTOK; +} + + + +/* --- rm this from the list --- */ +static adr_rm (this, list) +ADDR *this, + **list; +{ + ADDR *ix; + + /* --- bullet proofing --- */ + if (this == NULLADDR || list == NULL) + return; + + if (this == *list) + /* --- first in list (easy) --- */ + *list = (*list) -> ad_next; + else { + ix = *list; + while ( ix != NULLADDR + && ix -> ad_next != this) + ix = ix -> ad_next; + if (ix != NULLADDR) + ix -> ad_next = this -> ad_next; + } +} + + + +static int expandList (orig, plist, pdlh) +ADDR *orig, + **plist; +DLHistory **pdlh; +{ + ADDR *new, + *temp, + *ix; + RP_Buf rp; + int do_next = TRUE; + +#ifdef DIRLIST + Attr_Sequence save_as; +#endif + + *plist = NULLADDR; + + if (expandedBefore (orig, *pdlh) == TRUE) { + expansionLoop = TRUE; + return TRUE; + } + switch(attemptExpansion (get_adrstr (orig), + get_adrtype (orig), + &new, + OK)) { + case OK: + postExpansion (orig,pdlh); + break; + case DONE: + /* temporary failure */ + return DONE; + default: + /* --- cannot expand starting list --- */ + return NOTOK; + } + + adr_add (plist, new); + ix = new; +#ifdef DIRLIST + save_as = this_list; +#endif + + while (expandSublists == TRUE && ix != NULLADDR) { +#ifdef UKORDER + if (!rp_isbad(ad_parse(ix, &rp, CH_UK_PREF)) +#else + if (!rp_isbad(ad_parse(ix, &rp, CH_USA_PREF)) +#endif + && ix->ad_outchan + && ix->ad_outchan->li_chan + && lexequ(ix->ad_outchan->li_chan->ch_name, + mychan->ch_name) == 0) { + /* attempt to expand sublist */ + if (expandedBefore (ix, *pdlh) == TRUE) { + temp = ix; + ix = ix -> ad_next; + do_next = FALSE; + expansionLoop = TRUE; + adr_rm (temp, plist); + adr_free (temp); + } + else if (attemptExpansion (get_adrstr(ix), + get_adrtype(ix), + &new, + NOTOK) == OK) { + postExpansion (ix, pdlh); + temp = ix; + adr_rm (temp, plist); + adr_free (temp); + adr_add (plist, new); + ix = new; + do_next = FALSE; + } + } + if (do_next == TRUE) + ix = ix -> ad_next; + else + do_next = TRUE; + } +#ifdef DIRLIST + this_list = save_as; +#endif + return OK; +} + + +static char *get_adrstr (adr) +ADDR *adr; +{ + char *key; + + switch (mychan->ch_out_ad_type) { + case AD_X400_TYPE: + key = adr->ad_r400adr; + break; + case AD_822_TYPE: + key = adr->ad_r822adr; + break; + default: + switch (adr->ad_type) { + case AD_X400_TYPE: + key = adr->ad_r400adr; + break; + case AD_822_TYPE: + key = adr->ad_r822adr; + break; + default: + key = adr->ad_value; + break; + } + break; + } + + return key; +} + +static int get_adrtype (adr) +ADDR *adr; +{ + switch (mychan->ch_out_ad_type) { + case AD_X400_TYPE: + case AD_822_TYPE: + return mychan->ch_out_ad_type; + default: + return adr->ad_type; + } +} + +/* */ +/* DR to list maintainer */ + +static int processDR (msg, prm, que, recip, origsender) +char *msg; +struct prm_vars *prm; +Q_struct *que; +ADDR *recip; +ADDR *origsender; +{ + DRmpdu drs, *dr = &drs; + char *msgdir, *key, *local, file[MAXPATHLENGTH], + *strippedname, buf[BUFSIZ]; + ADDR *moderator = NULLADDR; + RP_Buf reply; + int retval, size, dirlen, fd_in, n; + struct stat st; + struct timeval data_time; + + /* read in DR */ + dr_init(dr); + if (rp_isbad(get_dr(recip->ad_no, + this_msg, + dr))) { + PP_LOG (LLOG_EXCEPTIONS, + ("report.%d not found for msg '%s'", + recip->ad_no, msg)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + "DR not found"); + return 0; + } + /* get Moderator of list (copied from above) */ + key = (origsender->ad_type == AD_X400_TYPE) ? origsender->ad_r400adr : + origsender->ad_r822adr; + if ((local = ad_getlocal(key, origsender->ad_type, YES)) == NULLCP) + local = strdup(key); + +#ifdef DIRLIST + switch (dir_getdl(local, &this_list)) { + case OK: + break; + + case DONE: + /* temp failure */ + PP_LOG (LLOG_EXCEPTIONS, + ("Tempory failure to access list '%s'", + local)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + "temporary X.500 problem"); + return 0; + + default: + /* perm failure */ + /* hack up moderator and send to postmaster */ + moderator = adr_new(getpostmaster(AD_822_TYPE), + AD_822_TYPE, 0); + } + if (moderator == NULLADDR + && (moderator = construct_sender (this_list)) == NULLADDR) + return submit_error(recip,"construct sender",&reply); +#else + moderator = tb_getModerator(local); +#endif + free(local); + + timer_start(&data_time); + if (rp_isbad (io_wprm (prm, &reply))) + return submit_error (recip,"io_wprm",&reply); + + if (rp_isbad (io_wrq (que, &reply))) + return submit_error (recip,"io_wrq",&reply); + + if (moderator->ad_redirection_history != (Redirection *) NULL) { + /* free of existing redirection history */ + redirect_free(moderator->ad_redirection_history); + moderator->ad_redirection_history = (Redirection *) NULL; + } + if (rp_isbad (io_wadr (moderator, AD_ORIGINATOR, &reply))) { + char nbuf[BUFSIZ]; + (void) sprintf(nbuf, "io_wadr(%s)", + moderator -> ad_value); + return submit_error (recip,nbuf, &reply); + } + + if (rp_isbad (io_wadr (recip, AD_RECIPIENT, &reply))) { + char nbuf[BUFSIZ]; + (void) sprintf(nbuf, "io_wadr(%s)", recip->ad_value); + return submit_error (recip,nbuf,&reply); + } + + if (rp_isbad (io_adend (&reply))) + return submit_error (recip,"io_adend", &reply); + + if (rp_isbad (io_wdr (dr, &reply))) + return submit_error(recip, "io_wdr", &reply); + + if (rp_isbad (io_tinit (&reply))) + return submit_error (recip, "io_tinit", &reply); + + if (qid2dir (msg, recip, TRUE, &msgdir) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("msg dir not found for recip %d of msg '%s'", + recip->ad_no, msg)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + "source directory not found"); + return 0; + } + + dirlen = strlen (msgdir) +1; + + if (msg_rinit(msgdir) != NOTOK) { + size = 0; + while (msg_rfile (file) != RP_DONE) { + + /* --- transmit file --- */ + strippedname = file + dirlen; + if (stat (file, &st) != NOTOK) + size += st.st_size; + if (linked == TRUE) { + (void) sprintf(buf, "%s %s",strippedname, file); + if (rp_isbad (io_tpart (buf, TRUE, &reply))) + return submit_error (recip,"io_tpart",&reply); + } else { + if (rp_isbad (io_tpart (strippedname, FALSE, &reply))) + return submit_error (recip,"io_tpart",&reply); + + if ((fd_in = open (file, O_RDONLY)) == -1) { + (void) strcpy (reply.rp_line,file); + return submit_error (recip,"open",&reply); + } + while ((n = read (fd_in, buf, BUFSIZ)) > 0) { + if (rp_isbad (io_tdata (buf, n))) { + (void) strcpy (reply.rp_line,"???"); + return submit_error (recip,"io_tdata",&reply); + } + } + + close (fd_in); + if (rp_isbad (io_tdend (&reply))) + return submit_error (recip,"io_tdend", &reply); + } + } + msg_rend(); + } + + if (rp_isbad (io_tend (&reply))) + return submit_error (recip, "io_tend", &reply); + set_success (recip, que, size); + timer_end(&data_time, size, "Data submitted"); + return 0; +} + +#ifndef lint + +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + (void) _ll_log (log_dsap, code, ap); + + va_end (ap); +} + +#else +/* VARARGS */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Chans/lists/lmnpq_dish.c b/Chans/lists/lmnpq_dish.c new file mode 100644 index 0000000..916fdd4 --- /dev/null +++ b/Chans/lists/lmnpq_dish.c @@ -0,0 +1,78 @@ +/* lmnpq_dish.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/lmnpq_dish.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/lmnpq_dish.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: lmnpq_dish.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include +#include + +extern Entry current_entry; +extern char frompipe; +extern DN dn, current_dn; + +#define OPT (!frompipe || rps -> ps_byteno == 0 ? opt : rps) +#define RPS (!frompipe || opt -> ps_byteno == 0 ? rps : opt) +extern PS opt, rps; + +call_dlist (argc, argv) +int argc; +char **argv; +{ +int x; +char dn_check = FALSE; +char or_check = FALSE; +char or_update = FALSE; + + for (x=1; xe_attributes,dn_check,or_check,or_update,FALSE); + return OK; + } + + dl_print (RPS,current_dn); + return OK; +} diff --git a/Chans/lists/make b/Chans/lists/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/lists/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/lists/md.py b/Chans/lists/md.py new file mode 100644 index 0000000..8a5cfef --- /dev/null +++ b/Chans/lists/md.py @@ -0,0 +1,93 @@ +-- md.py + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/lists/RCS/md.py,v 6.0 1991/12/18 20:10:43 jpo Rel $ +-- +-- $Log: md.py,v $ +-- Revision 6.0 1991/12/18 20:10:43 jpo +-- Release 6.0 +-- +-- + +MD + { + joint-iso-ccitt + mhs-motis(6) + arch (5) + modules(0) + directory(1) + } + +DEFINITIONS IMPLICIT TAGS ::= + +%{ +static orname_decode (pparm, pe) +struct dl_permit **pparm; +PE pe; +{ + PElementClass class; + PElementID id; + int result = OK; + + class = pe -> pe_class; + pe -> pe_class = PE_CLASS_APPL; + id = pe -> pe_id; + pe -> pe_id = 0; + if (((*pparm)->dp_or = pe2orn(pe)) == NULL) + result = NOTOK; + pe -> pe_id = id; + pe -> pe_class = class; + return result; +} + +static orname_encode (parm, ppe) +struct dl_permit *parm; +PE *ppe; +{ + if ((*ppe = orn2pe (parm->dp_or)) == NULL) + return NOTOK; + return OK; +} + +%} + +PREFIXES encode decode print + +BEGIN + +IMPORTS + Name + FROM IF + { + joint-iso-ccitt + ds(5) + modules(1) + informationFramework(1) + } + ORName + FROM IOB + { + joint-iso-ccitt + mts (3) + modules(0) + mts-abstract-service(1) + }; + +ORNamePattern [[P ORName *]] ::= ORName [[p *]] + +DLSubmitPermission [[P struct dl_permit *]] + ::= + CHOICE <> + { + individual [0] + --ORName [[p dp_or]], + *ANY [[a dp_or]] [[D orname_decode]] [[E orname_encode]], + member-of-dl [1] + -- ORName [[p dp_or]], + *ANY [[a dp_or]] [[D orname_decode]] [[E orname_encode]], + pattern-match [2] + --ORNamePattern [[p dp_or]], + *ANY [[a dp_or]] [[D orname_decode]] [[E orname_encode]], + member-of-group [3] + Name [[p dp_dn]] + } +END diff --git a/Chans/lists/or2addr.c b/Chans/lists/or2addr.c new file mode 100644 index 0000000..7195b7c --- /dev/null +++ b/Chans/lists/or2addr.c @@ -0,0 +1,128 @@ +/* or2addr.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/or2addr.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/or2addr.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: or2addr.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include "retcode.h" +#include "or.h" +#include "adr.h" +#include + +extern char * dn2str (); + +static ADDR *OR_Ptr2ADDR (or,parse,orig) +OR_ptr or; +char parse; +char orig; +{ + ADDR * ptr; + char buf[BUFSIZ]; + RP_Buf rp; + + or_or2std(or,buf,0); + + ptr = adr_new (buf,AD_X400_TYPE,1); + + if (orig) { + ptr->ad_resp = FALSE; + ptr->ad_status = AD_STAT_DONE; + } + + if (parse && (rp_isbad(ad_parse(ptr, &rp, CH_USA_ONLY)))) + return NULLADDR; + + return ptr; + +} + +ADDR *dn2ADDR (dn,orig) +DN dn; +char orig; +{ +Attr_Sequence as; +OR_ptr newor, as2or (); +ADDR * ptr; + + if (dn2addr (dn, &as) != OK) + return NULLADDR; + + newor = as2or (as); + if (newor) { + if ((ptr = OR_Ptr2ADDR (newor,TRUE,orig)) == NULLADDR) + return NULLADDR; + if (dn) + ptr->ad_dn = dn2str (dn); + +/* + if (as->attr_value->avseq_next != NULLAV) { + newor = (OR_ptr) as->attr_value->avseq_next->avseq_av.av_struct; + or_or2std(newor,buf,0); + ptr->ad_orig_req_alt = strdup (buf); + } +*/ + + return ptr; + } + return NULLADDR; +} + +ADDR *ORName2ADDR (or,dnlookup) +ORName *or; +char dnlookup; /* allow DN look up if addr missing */ +{ +ADDR * ptr; + + if (or->on_or) { + ptr = OR_Ptr2ADDR (or->on_or,FALSE,FALSE); + if (or->on_dn) + ptr->ad_dn = dn2str (or->on_dn); + } else if (or->on_dn) { + if (dnlookup) + if ((ptr = dn2ADDR(or->on_dn,FALSE)) != NULLADDR) + return ptr; + + ptr = (ADDR *) smalloc (sizeof(ADDR)); + adr_init (ptr); + ptr->ad_type = AD_ANY_TYPE; + ptr->ad_dn = dn2str (or->on_dn); + } + + return ptr; +} + + +orAddr_check (or,buf) +OR_ptr or; +char * buf; +{ +ADDR * ad; +RP_Buf rp; +char adr[BUFSIZ]; + + or_or2std(or,adr,0); + + ad = adr_new (adr,AD_X400_TYPE,1); + + if (rp_isbad(ad_parse(ad, &rp, CH_USA_ONLY))) { + (void) strcpy (buf,ad->ad_parse_message); + return NOTOK; + } + + adr_free (ad); + + return OK; +} + diff --git a/Chans/lists/syn_oraddr.c b/Chans/lists/syn_oraddr.c new file mode 100644 index 0000000..640e582 --- /dev/null +++ b/Chans/lists/syn_oraddr.c @@ -0,0 +1,177 @@ +/* syn_oraddr.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_oraddr.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_oraddr.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: syn_oraddr.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +/* LINTLIBRARY */ + +#include "util.h" +#include +#include "retcode.h" +#include "adr.h" +#include "ap.h" +#include "dlist.h" +#include + +int gl_addr_parse_full = 1; /* do full check */ + +OR_ptr orAddr_parse (ptr) +char * ptr; +{ +OR_ptr or; +char * str; +ADDR * ad; +RP_Buf rp; + + if (gl_addr_parse_full == 0) { + if ((or = or_std2or(ptr)) == NULLOR) { + parse_error ("std2or failed %s",ptr); + return (NULLOR); + } + return or; + } + + ad = adr_new (ptr, (or_str_isps(ptr)) ? AD_X400_TYPE : AD_822_TYPE, 1); + ad->ad_resp = NO; + +#ifdef UKORDER + (void) ad_parse(ad, &rp, CH_UK_PREF); +#else + (void) ad_parse(ad, &rp, CH_USA_PREF); +#endif + if (ad->ad_r400adr == NULLCP) { + parse_error ("bad address %s",ad->ad_parse_message); + return NULLOR; + } + + if ((or = or_std2or(ad->ad_r400adr)) == NULLOR) { + parse_error ("std2or failed %s",ad->ad_r400adr); + adr_free (ad); + return (NULLOR); + } + + adr_free (ad); + + return (or); +} + +OR_ptr orAddr_parse_user (ptr) +char * ptr; +{ +OR_ptr or; +ADDR * ad; +RP_Buf rp; + + /* as above but normalize address */ + + ad = adr_new (ptr, (*ptr == '/') ? AD_X400_TYPE : AD_822_TYPE, 0); + ad->ad_resp = YES; + +#ifdef UKORDER + (void) ad_parse(ad, &rp, CH_UK_PREF); +#else + (void) ad_parse(ad, &rp, CH_USA_PREF); +#endif + if (ad->ad_r400adr == NULLCP) { + parse_error ("bad address %s",ad->ad_parse_message); + return NULLOR; + } + + if ((or = or_std2or(ad->ad_r400adr)) == NULLOR) { + parse_error ("std2or failed %s",ad->ad_r400adr); + adr_free (ad); + return (NULLOR); + } + + adr_free (ad); + + return (or); +} + +/* ARGSUSED */ +orAddr_print (ps,or,format) +PS ps; +OR_ptr or; +int format; +{ +char buf[LINESIZE]; + +/* + if ((format == READOUT) || (format == UFNOUT)) + or_or2rfc (or,buf); + else +*/ + or_or2std (or,buf,0); + + ps_printf (ps,"%s",buf); +} + +OR_ptr or_cpy (a) +OR_ptr a; +{ +OR_ptr top = NULLOR; + + for (; a != NULLOR; a=a->or_next) + top = or_add (top,or_dup(a),FALSE); + + return (top); +} + +static int my_or_cmp (or1, or2) +OR_ptr or1; +OR_ptr or2; +{ +int res; + + if (or1 -> or_type != or2 -> or_type) + return (or1 -> or_type > or2 -> or_type) ? 1 : -1; + + if ((res = lexequ (or1 -> or_value, or2 -> or_value)) != 0) + return res; + + if (or1 -> or_type == OR_DD + && (res = lexequ (or1 -> or_ddname, or2 -> or_ddname)) != 0) + return res; + + return 0; +} + +orAddr_cmp (a,b) +OR_ptr a,b; +{ +int res; + + for (; (a != NULLOR) && (b != NULLOR) ; a = a->or_next, b = b->or_next) + if ((res = my_or_cmp (a,b)) != 0) + return res; + + if (( a == NULLOR) && (b == NULLOR)) + return 0; + else + return (a == NULLOR) ? 1 : -1; +} + +extern OR_ptr pe2ora(); +extern PE ora2pe(); + +orAddr_syntax () +{ + (void) add_attribute_syntax ("ORAddress", + (IFP) ora2pe, (IFP) pe2ora, + (IFP) orAddr_parse, orAddr_print, + (IFP) or_cpy, orAddr_cmp, + (IFP) or_free, NULLCP, + NULLIFP, TRUE); +} diff --git a/Chans/lists/syn_orname.c b/Chans/lists/syn_orname.c new file mode 100644 index 0000000..697285f --- /dev/null +++ b/Chans/lists/syn_orname.c @@ -0,0 +1,142 @@ +/* syn_orname.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_orname.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_orname.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: syn_orname.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +/* LINTLIBRARY */ + +#include "util.h" +#include +#include "retcode.h" +#include "adr.h" +#include "ap.h" +#include "dlist.h" + +extern OR_ptr orAddr_parse(); +extern OR_ptr or_cpy(); +extern ORName *pe2orn(); +extern PE orn2pe(); + +ORName * orName_parse (str) +char * str; +{ +ORName * or; +char * ptr; + + or = (ORName *) smalloc (sizeof (ORName)); + + if ( (ptr=index (str,'$')) == NULLCP) { + if ((or->on_dn = str2dn (str)) == NULLDN) + return (NULLORName); + or->on_or = NULLOR; + return or; + } + + *ptr--= 0; + if (isspace (*ptr)) { + *ptr = 0; + } + ptr++; + ptr++; + + if (*str == 0) + or->on_dn = NULLDN; + else + if ((or->on_dn = str2dn (str)) == NULLDN) + return (NULLORName); + + ptr = SkipSpace(ptr); + if (*ptr == 0) + or->on_or = NULLOR; + else if ((or->on_or = orAddr_parse (ptr)) == NULLOR) + return (NULLORName); + + return (or); +} + +orName_print (ps,or,format) +PS ps; +ORName * or; +int format; +{ + if (or == NULLORName) + return; + if (or->on_dn != NULLDN) { + + dn_print (ps,or->on_dn,format); + + if ((format == UFNOUT) || format == READOUT) + return; + } + + if ((format != READOUT) && (format != UFNOUT)) + ps_print (ps," $ "); + else if (or->on_dn == NULLDN) + ps_print (ps,"X.400 Address: "); + + if (or->on_or) + orAddr_print (ps,or->on_or,format); + +} + +ORName * orName_cpy (a) +ORName * a; +{ +ORName * top; + + top = (ORName *) smalloc (sizeof (ORName)); + top->on_or = or_cpy (a->on_or); + top->on_dn = dn_cpy (a->on_dn); + + return (top); +} + +orName_cmp (a,b) +ORName *a, *b; +{ +int res; + if ( a == NULLORName) + return (b == NULLORName ? 0 : -1); + if ( b == NULLORName) + return 1; + + if ((res = dn_cmp (a->on_dn,b->on_dn)) == 0) + return orAddr_cmp (a->on_or,b->on_or); + else + return res; +} + +orName_cmp_user (a,b) +ORName *a, *b; +{ + /* IF DN's equal -> match OK */ + + if ((a->on_dn == NULLDN) || (b->on_dn == NULLDN)) + return orAddr_cmp (a->on_or,b->on_or); + + return dn_cmp (a->on_dn,b->on_dn); +} + +extern IFP orName_free(); + +orName_syntax () +{ + (void) add_attribute_syntax ("ORName", + (IFP) orn2pe, (IFP) pe2orn, + (IFP) orName_parse, orName_print, + (IFP) orName_cpy, orName_cmp, + ORName_free, NULLCP, + NULLIFP, TRUE); +} diff --git a/Chans/lists/syn_permit.c b/Chans/lists/syn_permit.c new file mode 100644 index 0000000..1597dee --- /dev/null +++ b/Chans/lists/syn_permit.c @@ -0,0 +1,196 @@ +/* syn_permit.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_permit.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_permit.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: syn_permit.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include + +extern ORName * orName_cpy(); +extern ORName * orName_parse(); + +static permit_free (ptr) +struct dl_permit * ptr; +{ + if (ptr->dp_type == DP_GROUP) + dn_free (ptr->dp_dn); + else + ORName_free (ptr->dp_or); +} + + +static struct dl_permit * permit_cpy (a) +struct dl_permit * a; +{ +struct dl_permit * result; + + result = (struct dl_permit *) smalloc (sizeof (struct dl_permit)); + if ( (result->dp_type = a->dp_type) == DP_GROUP) + result->dp_dn = dn_cpy (a->dp_dn); + else + result->dp_or = orName_cpy (a->dp_or); + + return (result); +} + +static permit_cmp (a,b) +struct dl_permit * a; +struct dl_permit * b; +{ + if (a->dp_type != b->dp_type) + return (a->dp_type > b->dp_type ? 1 : -1); + + if (a->dp_type == DP_GROUP) + return (dn_cmp (a->dp_dn,b->dp_dn)); + else + return (orName_cmp (a->dp_or,b->dp_or)); +} + + +static permit_print (ps,p,format) +register PS ps; +struct dl_permit* p; +int format; +{ + if ((format == READOUT) || (format == UFNOUT)) { + if (p->dp_type == DP_GROUP) { + ps_print (ps,"Members of the X.500 Group:\n "); + dn_print (ps,p->dp_dn,EDBOUT); + return; + } + switch (p->dp_type) { + case DP_INDIVIDUAL: + ps_print (ps,"The individual:\n "); + break; + case DP_MEMBER: + ps_print (ps,"The members of the mail list:\n "); + break; + case DP_PATTERN: + if ((p->dp_or != NULLORName) && (p->dp_or->on_or == NULLOR)) { + ps_print (ps,"Anybody"); + return; + } + ps_print (ps,"Entities matching the OR pattern:\n "); + break; + } + orName_print (ps, p->dp_or,UFNOUT); + } else { + switch (p->dp_type) { + case DP_GROUP: + ps_print (ps,"GROUP#"); + dn_print (ps,p->dp_dn,format); + return; + case DP_INDIVIDUAL: + ps_print (ps,"INDIVIDUAL#"); + break; + case DP_MEMBER: + ps_print (ps,"MEMBER#"); + break; + case DP_PATTERN: + ps_print (ps,"PATTERN#"); + break; + } + orName_print (ps, p->dp_or,format); + } +} + + +static struct dl_permit* str2permit (str) +char * str; +{ +struct dl_permit * result; +char * ptr; +static CMD_TABLE permit_table [] = { + "GROUP", DP_GROUP, + "INDIVIDUAL", DP_INDIVIDUAL, + "MEMBER", DP_MEMBER, + "PATTERN", DP_PATTERN, + 0, -1, +}; + + if ( (ptr=index (str,'#')) == NULLCP) { + if (lexequ (str,"ALL") == 0) { + result = (struct dl_permit *) smalloc (sizeof (struct dl_permit)); + result->dp_type = DP_PATTERN; + result->dp_or = (ORName *) smalloc (sizeof (ORName)); + result->dp_or->on_dn = NULLDN; + result->dp_or->on_or = NULLOR; + return result; + } + parse_error ("seperator missing in permit '%s'",str); + return ((struct dl_permit *) NULL); + } + + result = (struct dl_permit *) smalloc (sizeof (struct dl_permit)); + *ptr-- = 0; + if (isspace (*ptr)) + *ptr = 0; + ptr++,ptr++; + + if ((result->dp_type = cmd_srch (str,permit_table)) == -1) { + parse_error ("unknown permit choice '%s'",str); + return ((struct dl_permit *) NULL); + } + + if (result->dp_type == DP_GROUP) { + if ((result->dp_dn = str2dn(ptr)) == NULLDN) + return ((struct dl_permit *) NULL); + } else { + if ((result->dp_or = orName_parse(ptr)) == NULLORName) + return ((struct dl_permit *) NULL); + } + + if (result->dp_type == DP_MEMBER) { + if (result->dp_or->on_dn == NULLDN) { + parse_error ("Must specify X.500 name for member permission",NULLCP); + return ((struct dl_permit *) NULL); + } + } + + return (result); +} + +static PE permit_enc (m) +struct dl_permit * m; +{ +PE ret_pe; + + (void) encode_MD_DLSubmitPermission (&ret_pe,0,0,NULLCP,m); + + return (ret_pe); +} + +static struct dl_permit * permit_dec (pe) +PE pe; +{ + struct dl_permit * m; + + if (decode_MD_DLSubmitPermission (pe,1,NULLIP,NULLVP,&m) == NOTOK) { + free ((char *)m); + return ((struct dl_permit *) NULL); + } + + return (m); +} + +permit_syntax () +{ + (void) add_attribute_syntax ("DLSubmitPermission", + (IFP) permit_enc, (IFP) permit_dec, + (IFP) str2permit, permit_print, + (IFP) permit_cpy, permit_cmp, + permit_free, NULLCP, + NULLIFP, TRUE); +} diff --git a/Chans/lists/syn_policy.c b/Chans/lists/syn_policy.c new file mode 100644 index 0000000..b20121c --- /dev/null +++ b/Chans/lists/syn_policy.c @@ -0,0 +1,215 @@ +/* syn_policy.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_policy.c,v 6.0 1991/12/18 20:10:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/lists/RCS/syn_policy.c,v 6.0 1991/12/18 20:10:43 jpo Rel $ + * + * $Log: syn_policy.c,v $ + * Revision 6.0 1991/12/18 20:10:43 jpo + * Release 6.0 + * + */ + + + +#include "dlist.h" +#include + +static CMD_TABLE expand_table [] = { + "FALSE", FALSE, + "TRUE", TRUE, + 0, -1, +}; + +static CMD_TABLE convert_table [] = { + "ORIGINAL", DP_ORIGINAL, + "FALSE", DP_FALSE, + "TRUE", DP_TRUE, + 0, -1, +}; + +static CMD_TABLE priority_table [] = { + "ORIGINAL", DP_ORIGINAL, + "LOW", DP_LOW, + "NORMAL", DP_NORMAL, + "HIGH", DP_HIGH, + 0, -1, +}; + +static dl_policy_free (ptr) +struct dl_policy * ptr; +{ + free ((char *) ptr); +} + + +static struct dl_policy * dl_policy_cpy (a) +struct dl_policy * a; +{ +struct dl_policy * result; + + result = (struct dl_policy *) smalloc (sizeof (struct dl_policy)); + *result = *a; /* struct copy */ + return (result); +} + +static dl_policy_cmp (a,b) +struct dl_policy * a; +struct dl_policy * b; +{ + if (a == (struct dl_policy *) NULL) + if (b == (struct dl_policy *) NULL) + return (0); + else + return (-1); + + if (b == (struct dl_policy *) NULL) + return 1; + + if (a->dp_expand != b->dp_expand) + return ( a->dp_expand > b->dp_expand ? 1 : -1); + + if (a->dp_priority != b->dp_priority) + return ( a->dp_priority > b->dp_priority ? 1 : -1); + + if (a->dp_convert != b->dp_convert) + return ( a->dp_convert > b->dp_convert ? 1 : -1); + + return (0); +} + + +static dl_policy_print (ps,p,format) +register PS ps; +struct dl_policy* p; +int format; +{ + + if (format == READOUT) + ps_print (ps,"Expansion: "); + + ps_printf (ps,"%s",rcmd_srch(p->dp_expand,expand_table)); + + if (format == READOUT) + ps_print (ps,", Conversion: "); + else + ps_print (ps,"$"); + + ps_printf (ps,"%s",rcmd_srch(p->dp_convert,convert_table)); + + if (format == READOUT) + ps_print (ps,", Priority: "); + else + ps_print (ps,"$"); + + ps_printf (ps,"%s",rcmd_srch(p->dp_priority,priority_table)); +} + +static struct dl_policy* str2dl_policy (str) +char * str; +{ +struct dl_policy * result; +char * ptr; +char * mark = NULLCP; +char * prtparse (); + + + + if ( (ptr=index (str,'$')) == NULLCP) { + parse_error ("seperator missing in dl_policy '%s'",str); + return ((struct dl_policy *) NULL); + } + + result = (struct dl_policy *) smalloc (sizeof (struct dl_policy)); + *ptr--= 0; + if (isspace (*ptr)) { + *ptr = 0; + mark = ptr; + } + ptr++; + + if (*str == 0) + result->dp_expand = TRUE; + else if ((result->dp_expand = cmd_srch(str,expand_table)) == -1) { + parse_error ("%s unrecognised",str); + return ((struct dl_policy *) NULL); + } + *ptr++ = '$'; + + if (mark != NULLCP) + *mark = ' '; + + str = SkipSpace(ptr); + + if ( (ptr=index (str,'$')) == NULLCP) { + parse_error ("2nd seperator missing in dl_policy '%s'",str); + return ((struct dl_policy *) NULL); + } + + *ptr--= 0; + if (isspace (*ptr)) { + *ptr = 0; + mark = ptr; + } else + mark = NULLCP; + + ptr++; + + if (*str == 0) + result->dp_convert = DP_ORIGINAL; + else if ((result->dp_convert = cmd_srch(str,convert_table)) == -1) { + parse_error ("%s unrecognised (2)",str); + return ((struct dl_policy *) NULL); + } + + *ptr++ = '$'; + + if (mark != NULLCP) + *mark = ' '; + + ptr = SkipSpace (ptr); + + if (*ptr == 0) + result->dp_priority = DP_LOW; + else if ((result->dp_priority = cmd_srch(ptr,priority_table)) == -1) { + parse_error ("%s unrecognised (3)",ptr); + return ((struct dl_policy *) NULL); + } + + return (result); +} + +static PE dl_policy_enc (m) +struct dl_policy * m; +{ +PE ret_pe; + + (void) encode_DL_DlPolicy (&ret_pe,0,0,NULLCP,m); + + return (ret_pe); +} + +static struct dl_policy * dl_policy_dec (pe) +PE pe; +{ + struct dl_policy * m; + + if (decode_DL_DlPolicy (pe,1,NULLIP,NULLVP,&m) == NOTOK) { + free ((char *)m); + return ((struct dl_policy *) NULL); + } + return (m); +} + +policy_syntax () +{ + (void) add_attribute_syntax ("DlPolicy", + (IFP) dl_policy_enc, (IFP) dl_policy_dec, + (IFP) str2dl_policy, dl_policy_print, + (IFP) dl_policy_cpy, dl_policy_cmp, + dl_policy_free, NULLCP, + NULLIFP, TRUE); +} diff --git a/Chans/make b/Chans/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Chans/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/msg-clean/Makefile b/Chans/msg-clean/Makefile new file mode 100644 index 0000000..ddaf5d9 --- /dev/null +++ b/Chans/msg-clean/Makefile @@ -0,0 +1,146 @@ +# Makefile for msg_clean channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/msg-clean/RCS/Makefile,v 6.0 1991/12/18 20:11:18 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:11:18 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = msg-clean.c +OBJS = msg-clean.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xmsg_clean + +############################################################ +# +# Building Rules +# +############################################################ + +default: msg_clean + +############################################################ +# +# Msg clean out +# +############################################################ + +msg_clean: xmsg-clean + +xmsg-clean: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +sh_rmmsg: ; + +############################################################ +# +# Misc stuff +# +############################################################ + +install: inst-msg-clean + +inst-msg-clean: inst-dir $(CHANDIR)/msg-clean +$(CHANDIR)/msg-clean:xmsg-clean + -$(BACKUP) $@ zxmsg-clean + rm -f $@ + $(INSTALL) xmsg-clean $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "msg-clean channel installed normally"; echo "" + +$(CHANDIR)/sh_rmmsg: sh_rmmsg inst-dir + $(INSTALL) sh_rmmsg $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core a.out Makefile.old xmsg-clean zxmsg-clean *.BAK + +lint: l-msg_clean + +l-msg_clean: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +msg-clean.o: msg-clean.c +msg-clean.o: ../../h/util.h +msg-clean.o: ../../h/config.h +msg-clean.o: ../../h/ll_log.h +msg-clean.o: ../../h/head.h +msg-clean.o: ../../h/util.h +msg-clean.o: ../../h/retcode.h +msg-clean.o: ../../h/qmgr.h +msg-clean.o: ../../h/Qmgr-types.h +msg-clean.o: ../../h/Qmgr-ops.h +msg-clean.o: ../../h/q.h +msg-clean.o: ../../h/adr.h +msg-clean.o: ../../h/list_rchan.h +msg-clean.o: ../../h/chan.h +msg-clean.o: ../../h/table.h +msg-clean.o: ../../h/list_bpt.h +msg-clean.o: ../../h/auth.h +msg-clean.o: ../../h/list_bpt.h +msg-clean.o: ../../h/extension.h +msg-clean.o: ../../h/mta.h +msg-clean.o: ../../h/adr.h +msg-clean.o: ../../h/list_bpt.h +msg-clean.o: ../../h/aparse.h +msg-clean.o: ../../h/ap.h +msg-clean.o: ../../h/util.h +msg-clean.o: ../../h/or.h +msg-clean.o: ../../h/chan.h +msg-clean.o: ../../h/auth.h +msg-clean.o: ../../h/list_rchan.h +msg-clean.o: ../../h/mta.h +msg-clean.o: ../../h/prm.h +msg-clean.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/msg-clean/make b/Chans/msg-clean/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/msg-clean/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/msg-clean/msg-clean.c b/Chans/msg-clean/msg-clean.c new file mode 100644 index 0000000..5943ae1 --- /dev/null +++ b/Chans/msg-clean/msg-clean.c @@ -0,0 +1,216 @@ +/* msg_clean.c: message cleanout channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/msg-clean/RCS/msg-clean.c,v 6.0 1991/12/18 20:11:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/msg-clean/RCS/msg-clean.c,v 6.0 1991/12/18 20:11:18 jpo Rel $ + * + * $Log: msg-clean.c,v $ + * Revision 6.0 1991/12/18 20:11:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include +#include +#include "sys.file.h" +#include + + +extern char *quedfldir; +extern char *chndfldir; +extern CHAN *ch_nm2struct(); +extern void getfpath(), rd_end(), sys_init(), err_abrt(); +/* CHANGE LATER */ +CHAN *mychan; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static int security_check (); +static void dirinit (); +int error; +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise, process, NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + /* check if a cleanout channel */ + if (mychan -> ch_chan_type != CH_DELETE) { + PP_OPER (NULLCP, + ("Channel '%s' is not a msg deletion channel", + name)); + if (name) free (name); + return NOTOK; + } + if (name != NULL) free(name); + return OK; +} + +/* */ +/* routine called to do clean out */ +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + char *this_msg = NULL; + struct stat statbuf; + + dirinit (); + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + /* ok-you asked for it-remove message */ + this_msg = qb2str (arg->qid); + + PP_LOG(LLOG_NOTICE, + ("Cleaning out msg %s", this_msg)); + + + error = FALSE; + + /* + * This stuff here to try and win efficiency. + * In a crowded queue, the chdir business should cut down + * the time spent in kernel namei routine. + */ + if (chdir (this_msg) == 0) { + (void) recrm ("."); + dirinit (); + if (rmdir (this_msg) == NOTOK) + error = TRUE; + } + else if (stat(this_msg, &statbuf) == OK) { + if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { + if (unlink (this_msg) == NOTOK) + error = TRUE; + } + } + if (error == TRUE) + PP_SLOG (LLOG_EXCEPTIONS, this_msg, + ("Unable to remove directory")); + + if (this_msg != NULL) free(this_msg); + /* create return values */ + if (error == FALSE) + delivery_setall(int_Qmgr_status_success); + return deliverystate; + +} + +/* */ +/* routine to check if allowed to remove this message */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, + result; + ADDR *ix = NULL; + char msgname[MAXPATHLENGTH]; + struct stat statbuf; + extern char *aquefile; + + prm_init (&prm); + q_init (&que); + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Wrong channel name '%s'",msg_chan)); + result = FALSE; + } + + if (rp_isbad(rd_msg_file(msg_file,&prm,&que, + &sender,&recips,&rcount, + RDMSG_RDONLY))) { + (void) sprintf (msgname, "%s/%s", msg_file, aquefile); + if (stat(msgname, &statbuf) != OK) { + /* does not exist so effectively removed */ + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return TRUE; + } + PP_LOG(LLOG_EXCEPTIONS, + ("Can't read message '%s'",msg_file)); + result = FALSE; + } + + /* unlock file */ + rd_end(); + + /* now check the recips */ + if (result == TRUE) { + ix = que.Raddress; + while ((ix != NULL) && (ix->ad_status == AD_STAT_DONE)) + ix = ix->ad_next; + if (ix != NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("recipient %d status not DONE: '%s'", + ix->ad_no,msg_file)); + result = FALSE; + } + } + + /* free all storage used */ + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + q_free (&que); + prm_free(&prm); + return result; +} diff --git a/Chans/qmgr-load/Makefile b/Chans/qmgr-load/Makefile new file mode 100644 index 0000000..fb53edb --- /dev/null +++ b/Chans/qmgr-load/Makefile @@ -0,0 +1,200 @@ +# makefile for qmgr loading activities +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/Makefile,v 6.0 1991/12/18 20:11:26 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:11:26 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + + + +SRCS = qmgr-load.c qmgr-start.c ryinitiator.c ryresponder.c +OBJS = qmgr-load.o qmgr-start.o ryinitiator.o ryresponder.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -u -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +all: xqmgr-load + +############################################################ +# +# Q start up +# +############################################################ + +QSOBJS = qmgr-start.o ryinitiator.o +QSSRCS = qmgr-start.c ryinitiator.c + +qmgr-start: xqstart + +xqstart: $(QSOBJS) + $(CC) $(LDFLAGS) -o $@ $(QSOBJS) $(LIBPP) $(LIBSYS) + +qmgr-start.o: ryinitiator.h + +ryinitiator.o: ryinitiator.h + +############################################################ +# +# Qmgr loading channel +# +############################################################ + +QLOBJS = qmgr-load.o ryresponder.o +QLSRCS = qmgr-load.c ryresponder.c + +qmgr-load: xqmgr-load + +xqmgr-load: $(QLOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(QLOBJS) $(LIBPP) \ + $(LIBSYS) + +saber_src: $(QLSRCS) + #load -C $(CFLAGS) $(QLSRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(QLOBJS) + #load -C $(QLOBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + +install: inst-dir inst-qmgr-load + +inst-qmgr-load: $(CHANDIR)/qmgr-load +$(CHANDIR)/qmgr-load: xqmgr-load + -$(BACKUP) $@ zxqmgr-load + rm -f $@ + $(INSTALL) xqmgr-load $(CHANDIR)/qmgr-load + -$(CHMOD) $(PGMPROT) $(CHANDIR)/qmgr-load + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $(CHANDIR)/qmgr-load + -@echo "qmgr-load channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core a.out *.BAK *.old xqstart xqmgr-load zxqmgr-load + +lint: l-load + +l-load: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +qmgr-load.o: qmgr-load.c +qmgr-load.o: ../../h/util.h +qmgr-load.o: ../../h/config.h +qmgr-load.o: ../../h/ll_log.h +qmgr-load.o: ../../h/retcode.h +qmgr-load.o: ../../h/Qmgr-ops.h +qmgr-load.o: ../../h/Qmgr-types.h +qmgr-load.o: ryresponder.h +qmgr-load.o: ../../h/q.h +qmgr-load.o: ../../h/adr.h +qmgr-load.o: ../../h/list_rchan.h +qmgr-load.o: ../../h/chan.h +qmgr-load.o: ../../h/table.h +qmgr-load.o: ../../h/list_bpt.h +qmgr-load.o: ../../h/auth.h +qmgr-load.o: ../../h/list_bpt.h +qmgr-load.o: ../../h/extension.h +qmgr-load.o: ../../h/mta.h +qmgr-load.o: ../../h/adr.h +qmgr-load.o: ../../h/list_bpt.h +qmgr-load.o: ../../h/aparse.h +qmgr-load.o: ../../h/ap.h +qmgr-load.o: ../../h/util.h +qmgr-load.o: ../../h/or.h +qmgr-load.o: ../../h/chan.h +qmgr-load.o: ../../h/auth.h +qmgr-load.o: ../../h/list_rchan.h +qmgr-load.o: ../../h/mta.h +qmgr-load.o: ../../h/prm.h +qmgr-start.o: qmgr-start.c +qmgr-start.o: ../../h/util.h +qmgr-start.o: ../../h/config.h +qmgr-start.o: ../../h/ll_log.h +qmgr-start.o: ../../h/retcode.h +qmgr-start.o: ../../h/Qmgr-ops.h +qmgr-start.o: ../../h/Qmgr-types.h +qmgr-start.o: ryinitiator.h +qmgr-start.o: ../../h/q.h +qmgr-start.o: ../../h/adr.h +qmgr-start.o: ../../h/list_rchan.h +qmgr-start.o: ../../h/chan.h +qmgr-start.o: ../../h/table.h +qmgr-start.o: ../../h/list_bpt.h +qmgr-start.o: ../../h/auth.h +qmgr-start.o: ../../h/list_bpt.h +qmgr-start.o: ../../h/extension.h +qmgr-start.o: ../../h/mta.h +qmgr-start.o: ../../h/adr.h +qmgr-start.o: ../../h/list_bpt.h +qmgr-start.o: ../../h/aparse.h +qmgr-start.o: ../../h/ap.h +qmgr-start.o: ../../h/util.h +qmgr-start.o: ../../h/or.h +qmgr-start.o: ../../h/chan.h +qmgr-start.o: ../../h/auth.h +qmgr-start.o: ../../h/list_rchan.h +qmgr-start.o: ../../h/mta.h +qmgr-start.o: ../../h/prm.h +ryinitiator.o: ryinitiator.c +ryinitiator.o: ../../h/Qmgr-types.h +ryinitiator.o: ryinitiator.h +ryinitiator.o: ../../h/qmgr.h +ryinitiator.o: ../../h/Qmgr-types.h +ryinitiator.o: ../../h/Qmgr-ops.h +ryresponder.o: ryresponder.c +ryresponder.o: ../../h/Qmgr-ops.h +ryresponder.o: ../../h/util.h +ryresponder.o: ../../h/config.h +ryresponder.o: ../../h/ll_log.h +ryresponder.o: ryresponder.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/qmgr-load/make b/Chans/qmgr-load/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/qmgr-load/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/qmgr-load/qmgr-load.c b/Chans/qmgr-load/qmgr-load.c new file mode 100644 index 0000000..3906ba9 --- /dev/null +++ b/Chans/qmgr-load/qmgr-load.c @@ -0,0 +1,292 @@ +/* qmgr-load.c: load the queue manager via readqueue */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/qmgr-load.c,v 6.0 1991/12/18 20:11:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/qmgr-load.c,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: qmgr-load.c,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "retcode.h" +#include +#include +#include "Qmgr-ops.h" /* operation definitions */ +#include "Qmgr-types.h" /* type definitions */ +#include "ryresponder.h" /* for generic idempotent responders */ + +/* Sumbit types */ +#include "q.h" +#include "prm.h" + +#define DEFAULT_MSG_CHUNKS 50 + + +/* Outside routines */ +struct type_Qmgr_MsgStruct *qstruct2qmgr(); +void qinit(); +CHAN *mychan = NULLCHAN; +int msg_chunks; +extern char *quedfldir; +extern void rd_end(), sys_init(), err_abrt(), getfpath(); +static char *myservice = "qmgr-load"; + +/* OPERATIONS */ +static int op_readqueue(); + +static struct server_dispatch dispatches[] = { + "readqueue", operation_Qmgr_readqueue, op_readqueue, + NULL + }; + +static int get_msg_list(); +static struct type_Qmgr_MsgStructList *get_n_messages(); +static void dirinit (); +static struct type_Qmgr_MsgStruct *readInMsg(); + +/* MAIN */ + +/* ARGSUSED */ +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + register CHAN **chp; + sys_init (argv[0]); + dirinit (); + + for (chp = ch_all; + *chp != NULLCHAN && (*chp) -> ch_chan_type != CH_QMGR_LOAD; + chp++) + continue; + + if (*chp != NULLCHAN) + mychan = *chp; + + if (mychan == NULLCHAN + || mychan->ch_out_info == NULLCP + || (msg_chunks = atoi(mychan->ch_out_info)) <= 0) + msg_chunks = DEFAULT_MSG_CHUNKS; + +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) { + do_debug (); + exit (0); + } +#endif + ryresponder (argc, argv, PLocalHostName(), myservice, dispatches, + table_Qmgr_Operations, NULLIFP, NULLIFP); + exit (0); /* NOT REACHED */ +} + +/* routine to move to correct place in file system */ +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +#ifdef PP_DEBUG +do_debug () +{ + struct type_Qmgr_MsgStructList *ml, *mp; + struct type_Qmgr_MsgList *mlp; + + mlp = (struct type_Qmgr_MsgList *) smalloc (sizeof *mlp); + mlp -> deleted = NULL; + + printf ("start load\n"); + while ((ml = get_n_messages (msg_chunks)) != NULL) { + mlp -> msgs = ml; + + printf ("\tstart batch\n"); + for (mp = ml; mp; mp = mp -> next) { + char *p = qb2str(mp -> MsgStruct -> + messageinfo -> queueid); + printf ("\t\tload %s\n", p); + free (p); + } + printf ("\tend batch\n"); + free_Qmgr_MsgList (mlp); + mlp = (struct type_Qmgr_MsgList *) smalloc (sizeof *mlp); + mlp -> deleted = NULL; + } + printf ("end load\n"); +} +#endif + + +/* OPERATIONS */ + +/* ARGSUSED */ +static int op_readqueue (ad, ryo, rox, in, roi) +int ad; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + if (rox->rox_nolinked == 0) { + PP_LOG (LLOG_NOTICE, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + ad, ryo->ryo_name, rox->rox_linkid)); + return ureject (ad, ROS_IP_LINKED, rox, roi); + } + PP_LOG (LLOG_NOTICE, + ("RO-INVOKE.INDICATION/%d: %s",ad, ryo -> ryo_name)); + return get_msg_list(ad, rox, roi); +} + +static int get_msg_list(ad, rox, roi) +int ad; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgList *base; + + PP_TRACE(("get_msg_list ()")); + + if ((base = (struct type_Qmgr_MsgList *) calloc (1, sizeof(*base))) + == NULL) + return error (ad, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + /* now make list */ + if ((base->msgs = get_n_messages(msg_chunks)) == + (struct type_Qmgr_MsgStructList *) NOTOK) { + base->msgs = NULL; + return error (ad, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + } + + if (RyDsResult (ad, rox->rox_id, (caddr_t) base, ROS_NOPRIO, roi) + == NOTOK) + ros_adios(&roi->roi_preject,"RESULT"); + free_Qmgr_MsgList (base); + return OK; +} + +#define SIZE_INCR 1000 +static int count = 0, noEntries = 0, maxnumb = 0; +static char **msgs = NULLVP; + +static struct type_Qmgr_MsgStructList *get_n_messages(num) +int num; +{ + struct type_Qmgr_MsgStructList *head, *tail, *temp; + struct type_Qmgr_MsgStruct *msg; + extern char *quedfldir; + int i; + + head = tail = NULL; + + if (noEntries > 0 && count == noEntries) { + return head; + } + + if (noEntries == 0) { + if (msgs) { + free_hier(msgs, noEntries); + msgs = NULLVP; + } + maxnumb = 0; + hier_scanQ (quedfldir, NULLCP, + &noEntries, &msgs, + &maxnumb, NULLIFP); + count = 0; + } + + i = 0; + while (count < noEntries && i < num) { + PP_TRACE (("reading message %s", msgs[count])); + if ((msg = readInMsg(msgs[count++])) != NULL) { + /* add to list */ + temp = (struct type_Qmgr_MsgStructList *) + calloc(1,sizeof(*temp)); + temp->MsgStruct = msg; + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = temp; + } + i++; + } + } + return head; +} + +static struct type_Qmgr_MsgStruct *readInMsg(name) +char *name; +{ + struct type_Qmgr_MsgStruct *arg = NULL; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, result; + + result = OK; + + prm_init (&prm); + q_init (&que); + qinit (&que); + + if ((result == OK) + && (rp_isbad(rd_msg(name,&prm,&que,&sender,&recips,&rcount)))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/qmgr-load rd_msg err: '%s'",name)); + result = NOTOK; + } + /* unlock message */ + rd_end(); + + if ((result == OK) + && ((arg = qstruct2qmgr(name,&prm,&que,sender,recips,rcount)) == NULL)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/qmgr-load qstruct2qmgr err: '%s'",name)); + result = NOTOK; + } + + /* free all storage */ + q_free (&que); + + return result == NOTOK ? NULL : arg; +} + + +/* ERROR */ + +int error (sd, err, param, rox, roi) +int sd, + err; +caddr_t param; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (RyDsError (sd, rox -> rox_id, err, param, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "ERROR"); + + return OK; +} + +int ureject (sd, reason, rox, roi) +int sd, reason; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if ( RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "U-REJECT"); + return OK; +} diff --git a/Chans/qmgr-load/qmgr-start.c b/Chans/qmgr-load/qmgr-start.c new file mode 100644 index 0000000..e0de15c --- /dev/null +++ b/Chans/qmgr-load/qmgr-start.c @@ -0,0 +1,271 @@ +/* qmgr_start.c: routines to read in Q from addr dir and pass on to Qmgr */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/qmgr-start.c,v 6.0 1991/12/18 20:11:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/qmgr-start.c,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: qmgr-start.c,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "retcode.h" +#include "Qmgr-ops.h" /* operation definitions */ +#include "Qmgr-types.h" /* type definitions */ +#include "ryinitiator.h" /* for generic interactive initiators */ + +/* Sumbit types */ +#include "q.h" +#include "prm.h" + +/* */ +/* Outside routines */ +extern struct type_Qmgr_MsgStruct *qstruct2qmgr(); +extern void qinit(), sys_init(), rd_end(); + + +/* */ +/* DATA */ +static char *myservice = "pp qmgr"; + +/* OPERATIONS */ +static int do_newmessage(), + do_help(), + do_quit(); + +/* RESULTS */ +int newmessage_result(); + +/* ERRORS */ +int general_error (); + +#define newmessage_error general_error + +static struct client_dispatch dispatches[] = { +{ + "newmessage", operation_Qmgr_newmessage, +#ifdef PEPSY_VERSION + do_newmessage, &_ZQmgr_mod, _ZPseudo_newmessageQmgr, +#else + do_newmessage, free_Qmgr_newmessage_argument, +#endif + newmessage_result, newmessage_error, + "Re-add message to the queue" +}, +{ + "help", 0, + do_help, +#ifdef PEPSY_VERSION + NULL, 0, +#else + NULLIFP, +#endif + NULLIFP, NULLIFP, + "print this information", +}, +{ + "quit", 0, do_quit, +#ifdef PEPSY_VERSION + NULL, 0, +#else + NULLIFP, +#endif + NULLIFP, NULLIFP, + "terminate the association and exit", +}, +{ + NULL +} +}; + + +extern char *pptailor; + +/* */ +/* MAIN */ + +/* ARGSUSED */ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + int opt; + extern char *optarg; + extern int optind; + char *myname, + *hostname; + + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + hostname = PLocalHostName (); + + while ((opt = getopt (argc, argv, "h:t:")) != EOF) { + switch (opt) { + case 'h': + hostname = optarg; + break; + case 't': + pptailor = optarg; + break; + default: + fprintf(stderr, + "usage: %s [-h hostname] [-t tailor] msg ...\n", + myname); + exit(1); + } + } + argv += optind; + argc -= optind; + if (argc < 1) { + fprintf(stderr, + "usage: %s [-h hostname] [-t tailor] msg ...\n", + myname); + exit(1); + } + + sys_init(myname); + + (void) ryinitiator (myname, hostname, + argc, argv, myservice, + table_Qmgr_Operations, dispatches, do_quit); + + exit(0); /* NOT REACHED */ +} + +/* */ +/* OPERATIONS */ + +/* ARGSUSED */ +static int do_newmessage (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_MsgStruct **arg; +{ + char *file = NULL; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, result; + + result = OK; + + qinit (&que); + bzero ((char *)&prm, sizeof(prm)); + + if ((file = *args++) == NULLCP) + result = NOTOK; + + if ((result == OK) + && (rp_isbad(rd_msg(file,&prm,&que,&sender,&recips,&rcount)))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/qmgr-load/xqstart rd_msg err: '%s'",file)); + result = NOTOK; + } + + /* unlock message */ + rd_end(); + + if ((result == OK) + && ((*arg = qstruct2qmgr(file,&prm,&que,sender,recips,rcount)) == NULL)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/qmgr-load/xqstart qstruct2qmgr err: '%s'",file)); + result = NOTOK; + } + + /* free all storage */ + q_init(&que); + + return result; +} + +/* ARGSUSED */ +static int do_help (sd, ds, args) +int sd; +register struct client_dispatch *ds; +char **args; +{ + printf("\nCommands are:\n"); + for (ds = dispatches; ds->ds_name; ds++) + printf("%s\t%s\n", ds->ds_name, ds->ds_help); + return NOTOK; +} + +/* ARGSUSED */ +static int do_quit (sd, ds, args) +int sd; +struct client_dispatch *ds; +char **args; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, + NOTOK, acr, aci) == NOTOK) + acs_adios (aca, "A-RELEASE.REQUEST"); + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + adios (NULLCP, "Release rejected by peer: %d", acr -> acr_reason); + } + + ACRFREE (acr); + + exit (0); + +} + +/* */ +/* RESULTS */ + +/* ARGSUSED */ +newmessage_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +struct type_Qmgr_Pseudo__newmessage *result; +struct RoSAPindication *roi; +{ + return OK; +} + +/* */ +/* ERRORS */ + +/* ARGSUSED */ +general_error (sd, id, error, parameter, roi) +int sd, + id, + error; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + + if (error == RY_REJECT) { + advise (NULLCP, "%s", RoErrString ((int) parameter)); + return OK; + } + + if (rye = finderrbyerr (table_Qmgr_Errors, error)) + advise (NULLCP, "%s", rye -> rye_name); + else + advise (NULLCP, "Error %d", error); + + return OK; +} diff --git a/Chans/qmgr-load/ryinitiator.c b/Chans/qmgr-load/ryinitiator.c new file mode 100644 index 0000000..48ea40c --- /dev/null +++ b/Chans/qmgr-load/ryinitiator.c @@ -0,0 +1,375 @@ +/* ryinitiator.c - generic interactive initiator */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryinitiator.c,v 6.0 1991/12/18 20:11:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryinitiator.c,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: ryinitiator.c,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + */ + + + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + +#include +#include +#include "Qmgr-types.h" +#include "ryinitiator.h" +#include "qmgr.h" + +/* DATA */ + +static char *myname = "ryinitiator"; + +static int invoke(); + +extern char *isodeversion; + +/* INITIATOR */ + +/* ARGSUSED */ +ryinitiator (myname, host, argc, argv, myservice, ops, dispatches, quit) +char *myname, + *host; +int argc; +char **argv, + *myservice; +struct RyOperation ops[]; +struct client_dispatch *dispatches; +IFP quit; +{ + int sd; + register struct client_dispatch *ds; + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + AEI aei; + OID ctx, + pci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + + if ((aei = _str2aei (host, myservice, QMGR_CTX_OID, + 0, dap_user, dap_passwd)) == NULLAEI) + adios (NULLCP, "%s-%s: unknown application-entity", + host, myservice); + if ((pa = aei2addr (aei)) == NULLPA) + adios (NULLCP, "address translation failed"); + + if ((ctx = QMGR_AC) == NULLOID) + adios (NULLCP, "out of memory"); + if ((ctx = oid_cpy (ctx)) == NULLOID) + adios (NULLCP, "out of memory"); + if ((pci = QMGR_PCI) == NULLOID) + adios (NULLCP, "out of memory"); + if ((pci = oid_cpy (pci)) == NULLOID) + adios (NULLCP, "out of memory"); + pc -> pc_nctx = 1; + pc -> pc_ctx[0].pc_id = 1; + pc -> pc_ctx[0].pc_asn = pci; + pc -> pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (host)) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + + for (ds = dispatches; ds -> ds_name; ds++) + if (strcmp (ds -> ds_name, "newmessage") == 0) + break; + if (ds -> ds_name == NULL) + adios (NULLCP, "unknown operation \"%s\"", "newmessage"); + + if (AcAssocRequest (ctx, NULLAEI, aei, NULLPA, pa, pc, NULLOID, + 0, ROS_MYREQUIRE, SERIAL_NONE, 0, sf, NULLPEP, 0, NULLQOS, + acc, aci) + == NOTOK) + acs_adios (aca, "A-ASSOCIATE.REQUEST"); + + if (acc -> acc_result != ACS_ACCEPT) { + adios (NULLCP, "Association rejected: [%s]", + AcErrString (acc -> acc_result)); + } + sd = acc -> acc_sd; + ACCFREE (acc); + + if (RoSetService (sd, RoPService, roi) == NOTOK) + ros_adios (rop, "set RO/PS fails"); + + invoke (sd, ops, ds, argv); + + (*quit) (sd, (struct client_dispatch *) NULL, (char **) NULL, (caddr_t *) NULL); +} + +/* */ + +static int invoke (sd, ops, ds, args) +int sd; +struct RyOperation ops[]; +register struct client_dispatch *ds; +char **args; +{ + int result; + caddr_t in; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + +/* multiple arguments */ +while (*args != NULLCP) { + + in = NULL; + + if (ds -> ds_argument && (*ds -> ds_argument) (sd, ds, args, &in) != OK) { + printf("Failed in attempting %s\n",*args); + args++; + continue; + } + + printf("Doing %s\n",*args); + switch (result = RyStub (sd, ops, ds -> ds_operation, RyGenID (sd), + NULLIP, in, ds -> ds_result, + ds -> ds_error, ROS_SYNC, roi)) { + case NOTOK: /* failure */ + if (ROS_FATAL (rop -> rop_reason)) + ros_adios (rop, "STUB"); + ros_advise (rop, "STUB"); + break; + + case OK: /* got a result/error response */ + break; + + case DONE: /* got RO-END? */ + adios (NULLCP, "got RO-END.INDICATION"); + /* NOTREACHED */ + + default: + adios (NULLCP, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + } + +#ifdef PEPSY_VERSION + if (ds -> ds_fr_mod && in) + fre_obj (in, ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod); +#else + if (ds -> ds_free && in) + (void) (*ds -> ds_free) (in); +#endif + args++; +} +} + +/* */ + +static int getline (buffer) +char *buffer; +{ + register int i; + register char *cp, + *ep; + static int sticky = 0; + + if (sticky) { + sticky = 0; + return NOTOK; + } + + printf ("%s> ", myname); + (void) fflush (stdout); + + for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) { + if (i == EOF) { + printf ("\n"); + clearerr (stdin); + if (cp != buffer) { + sticky++; + break; + } + + return NOTOK; + } + + if (cp < ep) + *cp++ = i; + } + *cp = NULL; + + return OK; +} + +/* */ + +void ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + _exit (1); +} + + +void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + advise (NULLCP, "%s: %s", event, buffer); +} + +/* */ + +void acs_adios (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + acs_advise (aca, event); + + _exit (1); +} + + +void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); + + advise (NULLCP, "%s: %s (source %d)", event, buffer, + aca -> aca_source); +} + +/* */ + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + + +#ifndef lint +void ryr_advise (va_alist) +va_dcl +{ + char *what; + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} +#else +/* VARARGS */ + +void ryr_advise (what, fmt) +char *what, + *fmt; +{ + ryr_advise (what, fmt); +} +#endif diff --git a/Chans/qmgr-load/ryinitiator.h b/Chans/qmgr-load/ryinitiator.h new file mode 100644 index 0000000..6099559 --- /dev/null +++ b/Chans/qmgr-load/ryinitiator.h @@ -0,0 +1,44 @@ +/* ryinitiator.h - include file for the generic interactive initiator */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryinitiator.h,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: ryinitiator.h,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGRLOAD_RYINITIATOR +#define _H_QMGRLOAD_RYINITIATOR + +#include + + +static struct client_dispatch { + char *ds_name; + int ds_operation; + + IFP ds_argument; +#ifdef PEPSY_VERSION + modtyp *ds_fr_mod; + int ds_fr_index; +#else + IFP ds_free; +#endif + IFP ds_result; + IFP ds_error; + + char *ds_help; +} Client_dispatch; + + +void adios(), advise(); +void acs_adios(), acs_advise(); +void ros_adios(), ros_advise(); +int ryinitiator(); + +#endif diff --git a/Chans/qmgr-load/ryresponder.c b/Chans/qmgr-load/ryresponder.c new file mode 100644 index 0000000..6d1d2dc --- /dev/null +++ b/Chans/qmgr-load/ryresponder.c @@ -0,0 +1,410 @@ +/* ryresponder.c - generic idempotent responder */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryresponder.c,v 6.0 1991/12/18 20:11:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryresponder.c,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: ryresponder.c,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + */ + + + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + +#include "Qmgr-ops.h" /* operation definitions */ +#include "util.h" +#include +#include "ryresponder.h" +#include /* for listening */ + +/* DATA */ + +static char *myname = "ryresponder"; +static jmp_buf toplevel; +static IFP startfnx; +static IFP stopfnx; +static int ros_init (), + ros_work (), + ros_indication (), + ros_lose (); +extern int errno; + + + +/* RESPONDER */ + +/* ARGSUSED */ +int ryresponder (argc, argv, host, myservice, dispatches, ops, start, stop) +int argc; +char **argv, + *host, + *myservice; +struct server_dispatch *dispatches; +struct RyOperation *ops; +IFP start, + stop; +{ + register struct server_dispatch *ds; + AEI aei = NULLAEI; + struct TSAPdisconnect tds; + struct TSAPdisconnect *td = &tds; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if ((myname = rindex (argv[0], '/')) != NULLCP) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + PP_TRACE(("starting")); + + for (ds = dispatches; ds -> ds_name; ds++) + if (RyDispatch (NOTOK, ops, ds -> ds_operation, ds -> ds_vector, roi) + == NOTOK) + ros_adios (rop, ds -> ds_name); + + startfnx = start; + stopfnx = stop; + + if (isodeserver (argc, argv, aei, ros_init, ros_work, ros_lose, td) + == NOTOK) { + if (td -> td_cc > 0) + adios (NULLCP, "isodeserver: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, td -> td_data); + else + adios (NULLCP, "isodeserver: [%s]", + TErrString (td -> td_reason)); + } + + return 0; +} + +/* */ + +static int ros_init (vecp, vec) +int vecp; +char **vec; +{ + int reply, + result, + sd; + struct AcSAPstart acss; + register struct AcSAPstart *acs = &acss; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + register struct PSAPstart *ps = &acs -> acs_start; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (AcInit (vecp, vec, acs, aci) == NOTOK) { + acs_advise (aca, "initialization fails"); + return NOTOK; + } + PP_LOG( LLOG_NOTICE, + ("A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>", + acs -> acs_sd, sprintoid (acs -> acs_context), + sprintaei (&acs -> acs_callingtitle), + sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo)); + + sd = acs -> acs_sd; + + for (vec++; *vec; vec++) + PP_LOG( LLOG_EXCEPTIONS, ("unknown argument \"%s\"", *vec)); + + reply = startfnx ? (*startfnx) (sd, acs) : ACS_ACCEPT; + + result = AcAssocResponse (sd, reply, + reply != ACS_ACCEPT ? ACS_USER_NOREASON : ACS_USER_NULL, + NULLOID, NULLAEI, NULLPA, NULLPC, ps -> ps_defctxresult, + ps -> ps_prequirements, ps -> ps_srequirements, SERIAL_NONE, + ps -> ps_settings, &ps -> ps_connect, NULLPEP, 0, aci); + + ACSFREE (acs); + + if (result == NOTOK) { + acs_advise (aca, "A-ASSOCIATE.RESPONSE"); + return NOTOK; + } + if (reply != ACS_ACCEPT) + return NOTOK; + + if (RoSetService (sd, RoPService, roi) == NOTOK) + ros_adios (rop, "set RO/PS fails"); + + return sd; +} + +/* */ + +static int ros_work (fd) +int fd; +{ + int result; + caddr_t out; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + (*stopfnx) (fd, (struct AcSAPfinish *) 0); + case DONE: + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + return NOTOK; + } + + switch (result = RyWait (fd, NULLIP, &out, OK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + case OK: + case DONE: + ros_indication (fd, roi); + break; + + default: + adios (NULLCP, "unknown return from RoWaitRequest=%d", result); + } + + return OK; +} + +/* */ + +static int ros_indication (sd, roi) +int sd; +register struct RoSAPindication *roi; +{ + int reply, + result; + + switch (roi -> roi_type) { + case ROI_INVOKE: + case ROI_RESULT: + case ROI_ERROR: + adios (NULLCP, "unexpected indication type=%d", roi -> roi_type); + break; + + case ROI_UREJECT: + { + register struct RoSAPureject *rou = &roi -> roi_ureject; + + if (rou -> rou_noid) + PP_LOG( LLOG_NOTICE, + ("RO-REJECT-U.INDICATION/%d: %s", + sd, RoErrString (rou -> rou_reason))); + else + PP_LOG( LLOG_NOTICE, + ("RO-REJECT-U.INDICATION/%d: %s (id=%d)", + sd, RoErrString (rou -> rou_reason), + rou -> rou_id)); + } + break; + + case ROI_PREJECT: + { + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (ROS_FATAL (rop -> rop_reason)) + ros_adios (rop, "RO-REJECT-P.INDICATION"); + ros_advise (rop, "RO-REJECT-P.INDICATION"); + } + break; + + case ROI_FINISH: + { + register struct AcSAPfinish *acf = &roi -> roi_finish; + struct AcSAPindication acis; + register struct AcSAPabort *aca = &acis.aci_abort; + + PP_LOG( LLOG_NOTICE, + ("A-RELEASE.INDICATION/%d: %d", + sd, acf -> acf_reason)); + + reply = stopfnx ? (*stopfnx) (sd, acf) : ACS_ACCEPT; + + result = AcRelResponse (sd, reply, ACR_NORMAL, NULLPEP, 0, + &acis); + + ACFFREE (acf); + + if (result == NOTOK) + acs_advise (aca, "A-RELEASE.RESPONSE"); + else + if (reply != ACS_ACCEPT) + break; + longjmp (toplevel, DONE); + } + /* NOTREACHED */ + + default: + adios (NULLCP, "unknown indication type=%d", roi -> roi_type); + } +} + +/* */ + +static int ros_lose (td) +struct TSAPdisconnect *td; +{ + if (td -> td_cc > 0) + PP_LOG( LLOG_NOTICE, + ("TNetAccept: [%s] %*.*s", + TErrString (td -> td_reason), td -> td_cc, td -> td_cc, + td -> td_data)); + else + PP_LOG( LLOG_NOTICE, + ("TNetAccept: [%s]",TErrString (td -> td_reason))); +} + +/* ERRORS */ + +void ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + longjmp (toplevel, NOTOK); +} + + +void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + PP_LOG( LLOG_NOTICE, ("%s: %s", event, buffer)); +} + +/* */ + +void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); + + PP_LOG( LLOG_NOTICE, + ("%s: %s (source %d)", event, buffer,aca -> aca_source)); +} + +/* */ + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} + + +#else +/* VARARGS */ + +void advise (what, code, fmt) +char *what, + *fmt; +int code; +{ + advise (what, code, fmt); +} +#endif + + +/* VARARGS */ + +#ifndef lint +void ryr_advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_NOTICE, ap); + + va_end (ap); +} +#else +void ryr_advise (what, fmt) +char *what, + *fmt; +{ + ryr_advise (what, fmt); +} +#endif diff --git a/Chans/qmgr-load/ryresponder.h b/Chans/qmgr-load/ryresponder.h new file mode 100644 index 0000000..db9fddf --- /dev/null +++ b/Chans/qmgr-load/ryresponder.h @@ -0,0 +1,38 @@ +/* ryresponder.h - include file for the generic idempotent responder */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/qmgr-load/RCS/ryresponder.h,v 6.0 1991/12/18 20:11:26 jpo Rel $ + * + * $Log: ryresponder.h,v $ + * Revision 6.0 1991/12/18 20:11:26 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGRLOAD_RYRESPONDER +#define _H_QMGRLOAD_RYRESPONDER + + +#include +#include + + +static struct server_dispatch { + char *ds_name; + int ds_operation; + IFP ds_vector; +} Server_dispatch; + + +extern int debug; + +void adios(), advise(); +void acs_advise(); +void ros_adios(), ros_advise(); +void ryr_advise(); +int ryresponder(); + +#endif diff --git a/Chans/shell/Makefile b/Chans/shell/Makefile new file mode 100644 index 0000000..f233da1 --- /dev/null +++ b/Chans/shell/Makefile @@ -0,0 +1,144 @@ +# Makefile for Shell channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/shell/RCS/Makefile,v 6.0 1991/12/18 20:11:52 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:11:52 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = shell.c tb_getprog.c +OBJS = shell.o tb_getprog.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xshell + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# Shell channel +# +############################################################ + +xshell: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-dir inst-shell + +inst-shell: $(CHANDIR)/shell +$(CHANDIR)/shell: xshell + -$(BACKUP) $@ zxshell + rm -f $@ + $(INSTALL) xshell $@ + -$(CHOWN) $(ROOTUSER) $@ + -$(CHMOD) 4755 $@ + -@ls -ls $@ + -@echo "shell channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core a.out *.old zxshell $(PROGS) *.BAK + +lint: l-shell + +l-shell: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +shell.o: shell.c +shell.o: ../../h/util.h +shell.o: ../../h/config.h +shell.o: ../../h/ll_log.h +shell.o: ../../h/expand.h +shell.o: ../../h/head.h +shell.o: ../../h/util.h +shell.o: ../../h/retcode.h +shell.o: ../../h/qmgr.h +shell.o: ../../h/Qmgr-types.h +shell.o: ../../h/Qmgr-ops.h +shell.o: ../../h/q.h +shell.o: ../../h/adr.h +shell.o: ../../h/list_rchan.h +shell.o: ../../h/chan.h +shell.o: ../../h/table.h +shell.o: ../../h/list_bpt.h +shell.o: ../../h/auth.h +shell.o: ../../h/list_bpt.h +shell.o: ../../h/extension.h +shell.o: ../../h/mta.h +shell.o: ../../h/adr.h +shell.o: ../../h/list_bpt.h +shell.o: ../../h/aparse.h +shell.o: ../../h/ap.h +shell.o: ../../h/util.h +shell.o: ../../h/or.h +shell.o: ../../h/chan.h +shell.o: ../../h/auth.h +shell.o: ../../h/list_rchan.h +shell.o: ../../h/mta.h +shell.o: ../../h/dr.h +shell.o: ../../h/extension.h +shell.o: ../../h/mta.h +shell.o: ../../h/prm.h +shell.o: prog.h +tb_getprog.o: tb_getprog.c +tb_getprog.o: ../../h/util.h +tb_getprog.o: ../../h/config.h +tb_getprog.o: ../../h/ll_log.h +tb_getprog.o: ../../h/table.h +tb_getprog.o: prog.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/shell/README b/Chans/shell/README new file mode 100644 index 0000000..ded57f6 --- /dev/null +++ b/Chans/shell/README @@ -0,0 +1,2 @@ +Initially copied filtercontrol source +and manipulated to Shell program. diff --git a/Chans/shell/make b/Chans/shell/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/shell/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/shell/prog.h b/Chans/shell/prog.h new file mode 100644 index 0000000..d06a523 --- /dev/null +++ b/Chans/shell/prog.h @@ -0,0 +1,40 @@ +/* prog.h: structures for the program/shell channel */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Chans/shell/RCS/prog.h,v 6.0 1991/12/18 20:11:52 jpo Rel $ + * + * $Log: prog.h,v $ + * Revision 6.0 1991/12/18 20:11:52 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_SHELL_PROG +#define _H_SHELL_PROG + + +#include + +typedef struct prog_struct { + unsigned int timeout_in_secs; /* in seconds */ + int solo; + char *cmd_line; + int uid; + int gid; + + char *username; + char *home; + char *shell; +} ProgInfo; + + +#define NULLPROG ((ProgInfo *) 0) + +ProgInfo *tb_getprog(); +void prog_free(); + + +#endif diff --git a/Chans/shell/shell.c b/Chans/shell/shell.c new file mode 100644 index 0000000..3af2aa4 --- /dev/null +++ b/Chans/shell/shell.c @@ -0,0 +1,789 @@ +/* shell.c: shell or program channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/shell/RCS/shell.c,v 6.0 1991/12/18 20:11:52 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/shell/RCS/shell.c,v 6.0 1991/12/18 20:11:52 jpo Rel $ + * + * $Log: shell.c,v $ + * Revision 6.0 1991/12/18 20:11:52 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "expand.h" +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "dr.h" +#include "prm.h" +#include "prog.h" +#include +#include +#include +#include + +#ifdef __STDC__ +#define VOLATILE volatile +#else +#define VOLATILE +#endif + +#ifndef WCOREDUMP +#define WCOREDUMP(x) (((union wait *)&(x))->w_coredump) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif +#ifndef WTERMSIG +#define WTERMSIG(x) (((union wait *)&(x)) -> w_termsig) +#endif + +extern void sys_init(), err_abrt(), rd_end(); +extern struct type_Qmgr_DeliveryStatus *delivery_resetDRs(); +extern char *quedfldir; +extern char *chndfldir; +extern char *logdfldir; +extern char *ad_getlocal(); +extern CHAN *ch_nm2struct(); +extern char *expand_dyn (); +extern void or_myinit (); +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; +static int first_successDR, first_failDR, err_fatal = FALSE; +static int data_bytes; +static char buf[BUFSIZ], *fatalbuf = NULLCP; + +static struct type_Qmgr_DeliveryStatus *process (); +static int toProcess (); +static int processMsg (); +static int doProcess (); +static int write_to_child (); +static int send_to_child(); +static int do_child_logging(); +static void set_success(); +static int initialise (); +static char *get_adrstr(); +static int security_check (); +static void dirinit (); +static ADDR *getnthrecip (); +static int pipe_signaled; +static jmp_buf toplevel; + +static SFD sig_pipe(sig) +int sig; +{ + pipe_signaled = TRUE; + longjmp (toplevel, DONE); +} + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + or_myinit(); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process, NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, ("Chan/shell : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + (void) signal (SIGCHLD, SIG_DFL); + if (name != NULL) free(name); + return OK; +} + +/* */ +/* routine to check if allowed to filter this message through this channel */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/shell channel err: '%s'",msg_chan)); + result = FALSE; + } + + /* free all storage used */ + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to do shell */ + +Expand expand_macros[] = { + "SENDER", NULLCP, /* 0 */ + "822SENDER", NULLCP, /* 1 */ + "400SENDER", NULLCP, /* 2 */ + "QID", NULLCP, /* 3 */ + "UA-ID", NULLCP, /* 4 */ + "P1-ID", NULLCP, /* 5 */ + "RECIP", NULLCP, /* 6 */ + "822RECIP", NULLCP, /* 7 */ + "400RECIP", NULLCP, /* 8 */ + "RECIPIENT", NULLCP, /* 9 */ + "USERID", NULLCP, /* 10 */ + "GROUPID", NULLCP, /* 11 */ + "SIZE", NULLCP, /* 12 */ + "CHANNELNAME", NULLCP, /* 13 */ + NULLCP, NULLCP}; + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + char sizebuf[20]; + char uidbuf[20], gidbuf[20]; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + static char *local = NULLCP; + char *key; + ProgInfo *info = NULLPROG; + + bzero((char *) &que,sizeof(que)); + bzero((char *) &prm,sizeof(prm)); + + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + first_successDR = TRUE; + first_failDR = TRUE; + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_NOTICE, + ("%s processing msg '%s'",mychan->ch_name,this_msg)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s rd_msg err: '%s'",mychan->ch_name,this_msg)); + rd_end(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "Can't read message"); + } + + expand_macros[0].expansion = que.Oaddress->ad_value; + expand_macros[1].expansion = que.Oaddress->ad_r822adr; + expand_macros[2].expansion = que.Oaddress->ad_r400adr; + expand_macros[3].expansion = this_msg; + expand_macros[4].expansion = que.ua_id; + expand_macros[5].expansion = que.msgid.mpduid_string; + /* 6-11 filled in below */ + (void) sprintf (sizebuf, "%d", que.msgsize); + expand_macros[12].expansion = sizebuf; + expand_macros[13].expansion = mychan -> ch_name; + + if (arg->users == NULL) + PP_LOG(LLOG_NOTICE, + ("%s : passed a NULL user list for message '%s'", + mychan->ch_name, + this_msg)); + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + err_fatal = FALSE; + if (fatalbuf != NULLCP) { + free(fatalbuf); + fatalbuf = NULLCP; + } + if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s : failed to find recipient %d of msg '%s'", + mychan->ch_name,ix->RecipientId->parm, + this_msg)); + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + buf[0] = '\0'; + key = get_adrstr(adr); + if (local) { + free (local); + local = NULLCP; + } + if ((local = ad_getlocal(key, adr -> ad_type)) != NULLCP) + info = tb_getprog(local, mychan->ch_table); + + if (info == NULLPROG) + info = tb_getprog (key, mychan -> ch_table); + + if (info == NULLPROG) { + PP_LOG(LLOG_EXCEPTIONS, + ("table lookup failed for '%s' in '%s'", + key, mychan -> ch_table -> tb_name)); + (void) sprintf (buf, + "Failed to find entry for '%s' in table '%s'", + key, mychan -> ch_table -> tb_name); + delivery_setstate(ix -> RecipientId -> parm, + int_Qmgr_status_messageFailure, + buf); + continue; + } + + expand_macros[6].expansion = adr -> ad_value; + expand_macros[7].expansion = adr -> ad_r822adr; + expand_macros[8].expansion = adr -> ad_r400adr; + expand_macros[9].expansion = local; + if (info -> username) + expand_macros[10].expansion = info -> username; + else { + (void) sprintf (uidbuf, "%d", info -> uid); + expand_macros[10].expansion = uidbuf; + } + (void) sprintf (gidbuf, "%d", info -> gid); + expand_macros[11].expansion = gidbuf; + + + switch (lchan_acheck (adr, mychan, 1, NULLVP)) { + default: + case NOTOK: + break; + case OK: + if (processMsg(this_msg, adr, info) == NOTOK) { + if (err_fatal == TRUE) { + /* DR it */ + set_1dr (&que, adr->ad_no, this_msg, + DRR_TRANSFER_FAILURE, + DRD_UA_UNAVAILABLE, + fatalbuf); + delivery_set (adr->ad_no, + (first_failDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failDR = FALSE; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("%s : failed to process msg '%s' for recip '%d' on channel '%s'", + mychan->ch_name,this_msg, adr->ad_no, this_chan)); + delivery_setstate(adr->ad_no, + int_Qmgr_status_messageFailure, + buf); + } + } else { + PP_LOG(LLOG_NOTICE, + ("%s : processed '%s' for recipient %d", + mychan->ch_name,this_msg,adr->ad_no)); + set_success(adr, &que); + } + } + prog_free (info); + info = NULLPROG; + } + if (fatalbuf != NULLCP) { + free(fatalbuf); + fatalbuf = NULLCP; + } + + if (rp_isbad(retval = wr_q2dr(&que, this_msg))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs(int_Qmgr_status_messageFailure); + } + + rd_end(); + return deliverystate; +} + +static void set_success(recip, que) +ADDR *recip; +Q_struct *que; +{ + if (recip->ad_usrreq == AD_USR_CONFIRM || + recip->ad_mtarreq == AD_MTA_CONFIRM || + recip->ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr(que, recip->ad_no, this_msg, + DRR_NO_REASON, -1, NULLCP); + delivery_set(recip->ad_no, + (first_successDR == TRUE) ? + int_Qmgr_status_positiveDR : + int_Qmgr_status_successSharedDR); + } else { + (void) wr_ad_status(recip, AD_STAT_DONE); + (void) wr_stat (recip, que, this_msg, data_bytes); + delivery_set(recip->ad_no, int_Qmgr_status_success); + } +} + +/* */ +static int toProcess (msg, recip) +/* returns true if should process msg for recip on mychan */ +char *msg; +ADDR *recip; +{ + LIST_RCHAN *chan; + if ((chan = recip->ad_outchan) == NULL) { + PP_OPER(NULLCP, + ("%s : no outbound channel specified for recipient %d of msg '%s'", + mychan -> ch_name, + recip->ad_no, + msg)); + exit(1); + } + + if (strcmp(chan->li_chan->ch_name, mychan->ch_name) == 0) + return TRUE; + else { + PP_LOG(LLOG_EXCEPTIONS, + ("Channel mismatch for recip %d of msg '%s'", + recip->ad_no, + msg)); + return FALSE; + } +} + +/* */ +static int processMsg (msg,recip, info) +/* returns OK if managed to process msg for recip on mychan */ +char *msg; +ADDR *recip; +ProgInfo *info; +{ + char *origdir = NULL; + int result = OK; + char file[MAXPATHLENGTH]; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s no message directory for recip %d of message '%s'", + mychan->ch_name,recip->ad_no, msg)); + (void) sprintf(buf, + "Unable to find source directory"); + result = NOTOK; + } + + if (info->solo == TRUE) { + msg_rinit(origdir); + while (result == OK && msg_rfile(file) == RP_OK) + if (doProcess(file, info) != OK) + result = NOTOK; + msg_rend(); + } else { + if ((result == OK) && (doProcess(origdir, info) != OK)) + result = NOTOK; + } + + if (origdir != NULL) free(origdir); + return result; +} + +/* */ + +static int sigpiped, sigalarmed; +static SFD alarmed(), piped(); +static jmp_buf pipe_alrm_jmp; +static char env_home[LINESIZE], env_user[LINESIZE], env_shell[LINESIZE]; +static char *env[] = { + env_home, env_user, env_shell, NULLCP + }; + +extern char *dupfpath (); +/* processes orig directory contents through mychan */ +static int doProcess (orig, info) +char *orig; /* original directory */ +ProgInfo *info; +{ + int fd[2], + fd_stderr[2], + result = OK, + pid, + pgmresult; + char *expanded, + *program = NULL, + *margv[20]; + SFP oldalarm, oldpipe; + VOLATILE int killed = 0; + struct stat statbuf; + + if ((expanded = expand_dyn (info->cmd_line, expand_macros)) == NULLCP) { + PP_OPER (NULLCP, + ("%s : failed to expand '%s'", info->cmd_line)); + (void) sprintf(buf, + "Failed to expand '%s'", + info -> cmd_line); + return NOTOK; + } + + PP_NOTICE(("%s",expanded)); + if (sstr2arg(expanded, 20, margv, " \t") < 1) { + PP_OPER(NULLCP, ("%s : no arguments in info string", + mychan->ch_name)); + (void) sprintf (buf, + "No arguments in info string '%s'", + expanded); + free(expanded); + return NOTOK; + } + + program = dupfpath (chndfldir, margv[0]); + + if (stat(program, &statbuf) != OK) { + PP_OPER(NULLCP, ("%s : missing program '%s'", + mychan -> ch_name, program)); + (void) sprintf (buf, + "Missing program '%s", + program); + free(expanded); + return NOTOK; + } + (void) sprintf (env_home, "HOME=%s", info -> home); + (void) sprintf (env_user, "USER=%s", info -> username ? + info -> username : "anon"); + (void) sprintf (env_shell, "SHELL=%s", info -> shell); + + if (pipe(fd) != 0) { + PP_SLOG(LLOG_EXCEPTIONS, "pipe", + ("pipe failed")); + (void) sprintf(buf, + "Pipe failed"); + free(expanded); + return NOTOK; + } + if (pipe(fd_stderr) != 0) { + PP_SLOG(LLOG_EXCEPTIONS, "pipe", + ("stderr pipe failed")); + free(expanded); + (void) sprintf (buf, + "standard error pipe failed"); + (void) close (fd[0]); + (void) close (fd[1]); + return NOTOK; + } + if ((pid = tryfork()) == 0) { + /* in child so redirect input and stderr */ + (void) dup2 (fd[0], 0); + (void) dup2 (fd_stderr[1], 1); + (void) dup2 (fd_stderr[1], 2); + (void) close(fd[0]); + (void) close(fd[1]); + (void) close(fd_stderr[0]); + (void) close(fd_stderr[1]); + (void) setpgrp(0, getpid()); + + if(chdir (info -> home) == NOTOK) + chdir ("/tmp"); + + if (info -> username) + (void) initgroups (info -> username, info -> gid); +#ifdef SYS5 + if (setgid (info->gid) == -1 || + setuid (info->uid) == -1) { +#else + if (setregid (info->gid, info->gid) == -1 || + setreuid (info->uid, info->uid) == -1) { +#endif + PP_SLOG (LLOG_EXCEPTIONS, "user", + ("Can't set uid/gid %d/%d", + info -> uid, info -> gid)); + _exit(1); + } + + execve (program,margv, env); + _exit (1); + + } else if (pid == -1) { + PP_SLOG(LLOG_EXCEPTIONS, this_msg, + ("tryfork failed")); + (void) sprintf(buf, + "Tryfork failed"); + (void) close(fd_stderr[1]); + (void) close(fd[1]); + (void) close(fd_stderr[0]); + (void) close(fd[0]); + result = NOTOK; + } else { +#ifdef SVR4 + int w; +#else + union wait w; +#endif + + (void) close(fd_stderr[1]); + (void) close(fd[0]); + + data_bytes = 0; + oldalarm = signal(SIGALRM, alarmed); + oldpipe = signal(SIGPIPE, piped); + sigpiped = 0; + sigalarmed = 0; + + if (info -> timeout_in_secs > 0) { + alarm(info -> timeout_in_secs); + PP_TRACE(("alarm set for %d secs", + info -> timeout_in_secs)); + } + if (setjmp(pipe_alrm_jmp) != DONE) { + send_to_child(orig, fd[1], info->solo); + (void) close(fd[1]); + } else { + if (sigalarmed) + PP_TRACE(("alarm went off")); + if (sigpiped) + PP_TRACE(("pipe went off")); + } + + if (sigpiped) { /* pipe died - reset for timeout */ + sigpiped = 0; + if (setjmp (pipe_alrm_jmp) == DONE) + PP_TRACE(("Timeout")); + } + + if (sigalarmed) { /* alarm went off */ + PP_NOTICE (("Process taking too long ... killing")); + (void) sprintf(buf, + "Process took to long - killed"); + killed = 1; + (void) killpg (pid, SIGTERM); + sleep(2); + (void) killpg (pid, SIGKILL); + } + do_child_logging (fd_stderr[0]); + + while ((pgmresult = wait(&w)) != pid && pgmresult != -1) + PP_TRACE(("process %d returned", pgmresult)); + + alarm(0); + + PP_TRACE(("pid %d term=%d retcode=%d core=%d killed=%d", + pid, WTERMSIG(w), WEXITSTATUS(w), + WCOREDUMP(w), killed)); + + (void) signal (SIGPIPE, oldpipe); + (void) signal (SIGALRM, oldalarm); + do_child_logging(fd_stderr[0]); + (void) close(fd[1]); + (void) close (fd_stderr[0]); + + if (pgmresult == pid && !killed && WIFEXITED(w) && rp_gbval(WEXITSTATUS(w)) == RP_BNO) + err_fatal = TRUE; + + if ((pgmresult == pid) && (WEXITSTATUS(w) == 0) && (killed == 0)) + result = OK; + else + result = NOTOK; + } + + free(expanded); + return result; +} + +static int do_child_logging(fd) +int fd; +{ + fd_set rfds, ifds; + char buf[80]; /* smallish */ + int n; + struct timeval timer; + char *newfatal; + timerclear(&timer); + + PP_TRACE (("suckuperrors (%d)", fd)); + FD_ZERO (&rfds); + FD_SET (fd, &rfds); + +#define the_universe_exists 1 + + while (the_universe_exists) { + ifds = rfds; + + if (select (fd + 1, &ifds, NULLFD, NULLFD, &timer) <= 0) + break; + + PP_TRACE (("select fired")); + if (FD_ISSET (fd, &ifds)) { + if((n = read (fd, buf, sizeof buf - 1)) > 0) { + buf[n] = 0; + PP_LOG (LLOG_EXCEPTIONS, + ("Output from process '%s'", buf)); + if (fatalbuf == NULLCP) + fatalbuf = strdup(buf); + else { + newfatal = malloc(strlen(fatalbuf) + strlen(buf) + 1); + strcat (newfatal, fatalbuf); + strcat (newfatal, buf); + free(fatalbuf); + fatalbuf = newfatal; + } + } + else break; + } + else break; + } +} + +static SFD alarmed(sig) +int sig; +{ + sigalarmed = 1; + longjmp(pipe_alrm_jmp, DONE); +} + +static SFD piped (sig) +int sig; +{ + sigpiped = 1; + longjmp(pipe_alrm_jmp, DONE); +} + +/* */ +static int write_to_child(file, fd_out) +char *file; +int fd_out; +{ + char buf[BUFSIZ]; + int fd_in, + num; + + if ((fd_in = open(file, O_RDONLY, 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + return NOTOK; + } + + while ((num = read(fd_in, buf, BUFSIZ)) > 0) { + if (write (fd_out, buf, num) == -1) { + (void) close(fd_in); + return NOTOK; + } + data_bytes += num; + } + (void) close(fd_in); + return OK; +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + + +static char *get_adrstr(adr) +ADDR *adr; +{ + char *key; + switch (adr->ad_type) { + case AD_X400_TYPE: + key = adr->ad_r400adr; + break; + case AD_822_TYPE: + key = adr->ad_r822adr; + break; + default: + key = adr->ad_value; + break; + } + return key; +} + +static int is822hdr(file) +char *file; +{ + char *ix = rindex(file, '/'); + + if (ix == NULL + || (strncmp((ix+1),"hdr.822",strlen("hdr.822")) != 0)) + return FALSE; + else + return TRUE; +} + +static int send_to_child(orig, fd, solo) +char *orig; +int fd; +int solo; +{ + int result = OK; + char file[MAXPATHLENGTH]; + SFP old_sig; + + pipe_signaled = FALSE; + + /* set signal handler */ + old_sig = signal (SIGPIPE, sig_pipe); + + /* set long jump */ + setjmp(toplevel); + + if (solo == TRUE) + result = write_to_child(orig, fd); + else { + msg_rinit(orig); + + while (pipe_signaled == FALSE + && msg_rfile(file) == RP_OK) { + write_to_child(file, fd); + if (is822hdr(file) == TRUE) { + write(fd, "\n", 1); + data_bytes ++; + } + } + + msg_rend(); + } + /* unset signal handler */ + signal (SIGPIPE, old_sig); + + return result; +} diff --git a/Chans/shell/tb_getprog.c b/Chans/shell/tb_getprog.c new file mode 100644 index 0000000..b889526 --- /dev/null +++ b/Chans/shell/tb_getprog.c @@ -0,0 +1,131 @@ +/* tb_getprog.c: get prog/shell channel entry */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/shell/RCS/tb_getprog.c,v 6.0 1991/12/18 20:11:52 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/shell/RCS/tb_getprog.c,v 6.0 1991/12/18 20:11:52 jpo Rel $ + * + * $Log: tb_getprog.c,v $ + * Revision 6.0 1991/12/18 20:11:52 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "table.h" +#include "prog.h" + +extern char *compress(); + +#define DEFAULT_TIMEOUT 5*60 /* 5 mins */ + +ProgInfo *tb_getprog (key, tbl) +char *key; +Table *tbl; + +{ + char buf[BUFSIZ], + *timeout_value, + *ix,*ix2; + struct passwd *pwd; + char *cp; + ProgInfo *prog; + + PP_DBG(("tb_getprog (%s)", key)); + + if (tbl == NULLTBL) { + PP_LOG(LLOG_FATAL, ("tb_getprog (no table)")); + return NULLPROG; + } + + if (tb_k2val (tbl, key, buf, TRUE) == NOTOK) + return (NULLPROG); + + /* syntax uid,timeout,cmd line */ + + if ((ix = index(buf,',')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("incorrect table syntax for entry '%s' (missing ,)", + key)); + return NULLPROG; + } + *ix++ = '\0'; + + prog = (ProgInfo *) smalloc (sizeof *prog); + bzero ((char *)prog, sizeof *prog); + + /* uid is either a name or a uid/gid pair */ + if (isdigit (*buf) && (cp = index (buf, '/'))) { + prog -> username = NULLCP; + *cp ++ = NULL; + prog -> uid = atoi (buf); + prog -> gid = atoi (cp); + prog -> home = strdup ("/tmp"); + } + else { + prog->username = strdup(buf); + + if ((pwd = getpwnam(prog->username)) == NULL) { + PP_OPER(NULLCP, + ("tb_getprog no user '%s' with key '%s'", + prog->username, key)); + + prog_free (prog); + return NULLPROG; + } + prog -> uid = pwd -> pw_uid; + prog -> gid = pwd -> pw_gid; + prog -> home = strdup (pwd -> pw_dir); + if (pwd -> pw_shell) + prog -> shell = strdup (pwd -> pw_shell); + } + if (prog -> shell == NULLCP) + prog -> shell = strdup ("/bin/sh"); + + timeout_value = ix; + if ((ix = index(timeout_value, ',')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("incorrect table syntax for '%s' entry (missing ,:)", + key)); + prog_free (prog); + return NULLPROG; + } + *ix++ = '\0'; + (void) compress(timeout_value, timeout_value); + if ((ix2 = index(timeout_value, '|')) != NULLCP) + *ix2++ = '\0'; + + if (timeout_value[0] == '\0') + prog -> timeout_in_secs = DEFAULT_TIMEOUT; + else + prog -> timeout_in_secs = atoi(timeout_value); + + if (ix2 != NULLCP + && lexnequ(ix2, "solo", strlen("solo")) == 0) + prog -> solo = TRUE; + else + prog -> solo = FALSE; + + prog -> cmd_line = strdup(ix); + return prog; +} + +void prog_free (prog) +ProgInfo *prog; +{ + if (prog == NULLPROG) + return; + if (prog -> cmd_line) + free (prog -> cmd_line); + if (prog -> username) + free (prog -> username); + if (prog -> home) + free (prog -> home); + if (prog -> shell) + free (prog -> shell); + free ((char *)prog); +} diff --git a/Chans/slocal/Makefile b/Chans/slocal/Makefile new file mode 100644 index 0000000..419e6c7 --- /dev/null +++ b/Chans/slocal/Makefile @@ -0,0 +1,134 @@ +# slocal - structured local delivery channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/slocal/RCS/Makefile,v 6.0 1991/12/18 20:12:09 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:09 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = slocal.c loc_proto.c +OBJS = slocal.o loc_proto.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xslocal + +default: xslocal + +slocal: xslocal + +xslocal: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(OBJS) $(LIBPP) $(LIBSYS) -o $@ + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f $(PROGS) core a.out *old *.BAK zxslocal + +lint: l-slocal +l-slocal: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + + +install: inst-slocal +inst-slocal: $(CHANDIR)/slocal +$(CHANDIR)/slocal: xslocal + -$(BACKUP) $@ zxslocal + rm -f $@ + $(INSTALL) xslocal $@ + -$(CHOWN) $(ROOTUSER) $@ + -$(CHMOD) 4755 $@ + -@ls -ls $@ + -@echo "Slocal channel installed normally"; echo "" + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +slocal.o: slocal.c +slocal.o: ../../h/head.h +slocal.o: ../../h/util.h +slocal.o: ../../h/config.h +slocal.o: ../../h/ll_log.h +slocal.o: ../../h/retcode.h +slocal.o: ../../h/util.h +slocal.o: ../../h/prm.h +slocal.o: ../../h/q.h +slocal.o: ../../h/adr.h +slocal.o: ../../h/list_rchan.h +slocal.o: ../../h/chan.h +slocal.o: ../../h/table.h +slocal.o: ../../h/list_bpt.h +slocal.o: ../../h/auth.h +slocal.o: ../../h/list_bpt.h +slocal.o: ../../h/extension.h +slocal.o: ../../h/mta.h +slocal.o: ../../h/adr.h +slocal.o: ../../h/list_bpt.h +slocal.o: ../../h/aparse.h +slocal.o: ../../h/ap.h +slocal.o: ../../h/util.h +slocal.o: ../../h/or.h +slocal.o: ../../h/chan.h +slocal.o: ../../h/auth.h +slocal.o: ../../h/list_rchan.h +slocal.o: ../../h/mta.h +slocal.o: ../../h/qmgr.h +slocal.o: ../../h/Qmgr-types.h +slocal.o: ../../h/Qmgr-ops.h +slocal.o: ../../h/dr.h +slocal.o: ../../h/extension.h +slocal.o: ../../h/mta.h +slocal.o: ../../h/loc_user.h +slocal.o: ../../h/sys.file.h +loc_proto.o: loc_proto.c +loc_proto.o: ../../h/util.h +loc_proto.o: ../../h/config.h +loc_proto.o: ../../h/ll_log.h +loc_proto.o: ../../h/retcode.h +loc_proto.o: ../../h/sys.file.h +loc_proto.o: ../../h/loc_user.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/slocal/alert-script b/Chans/slocal/alert-script new file mode 100755 index 0000000..cd5830e --- /dev/null +++ b/Chans/slocal/alert-script @@ -0,0 +1,40 @@ +#!/bin/csh -f + +################################################################################ +# +# alert script for PP messages (PODA) - used by slocal +# +# slocal calls : +# alert username messagenumber message +# +################################################################################ + + +if ($#argv) then + set tlist=`w | awk '/^'$1'/ {print $2}'` + set message=~$1/PPMail/inbox/$2 + chmod777 $message + set header=$message/hdr.822 + set filelist=`ls -F $message` + foreach i ($tlist) + echo "" >/dev/$i + echo '******************************************************' >/dev/$i + echo $argv[3-] '('message $2')' >/dev/$i + echo "" >/dev/$i + if (-e $header) then + awk '\ + /^Subject/ {printf "%s\n",$0 } \ + /^Date/ {printf "%s\n",$0 } \ + /^From/ {printf "%s\n",$0 } \ + '\ + $header >/dev/$i + echo "" >/dev/$i + else + echo No hdr.822 file in $message >/dev/$i + endif + echo 'Files: '$filelist >/dev/$i + echo "" >/dev/$i + echo '******************************************************' >/dev/$i + echo "" >/dev/$i + end +endif diff --git a/Chans/slocal/loc_proto.c b/Chans/slocal/loc_proto.c new file mode 100644 index 0000000..93ba6b6 --- /dev/null +++ b/Chans/slocal/loc_proto.c @@ -0,0 +1,532 @@ +/* loc_proto.c: subroutines to help with local delivery */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/slocal/RCS/loc_proto.c,v 6.0 1991/12/18 20:12:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/slocal/RCS/loc_proto.c,v 6.0 1991/12/18 20:12:09 jpo Rel $ + * + * $Log: loc_proto.c,v $ + * Revision 6.0 1991/12/18 20:12:09 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include +#include "sys.file.h" +#include "loc_user.h" +#include +#include +#ifdef masscomp +#include +#endif + +#define P_READ 0 +#define P_WRITE 1 +#define NULLDIR ((DIR*)0) +#define NULLDCT ((struct dirent *)0) + +static char *next_message(); +static int fdin = NOTOK, fdout = NOTOK; +static int pid, sysreply; +static FILE *cur_fp = NULL; +static DIR *mb_dp = NULL; +static int copy(); + +static struct loc_packet { + int command; +#define LP_OPEN 1 +#define LP_CLOSE 2 +#define LP_CD 3 +#define LP_WRITE 4 +#define LP_MOVE 5 +#define LP_MKDIR 6 +#define LP_OPENDIR 7 +#define LP_CLOSEDIR 8 +#define LP_SYSTEM 9 +#define LP_NEXTMESS 10 +#define LP_ISDIR 11 + char s1 [MAXPATHLENGTH]; + char s2 [MAXPATHLENGTH]; + int size; +}; + + + +/* ------------------- Begin Routines ------------------------------------- */ + + +loc_init (loc) +LocUser *loc; +{ + int p1[2], p2[2]; + + if (fdin != NOTOK || fdout != NOTOK) + loc_end(); + + if (pipe(p1) == NOTOK) + return RP_BAD; + + if (pipe (p2) == NOTOK) { + (void) close (p1[P_READ]); + (void) close (p1[P_WRITE]); + return RP_BAD; + } + + ll_close (pp_log_norm); + if ((pid = tryfork()) == NOTOK) { + (void) close (p1[P_READ]); + (void) close (p1[P_WRITE]); + (void) close (p2[P_READ]); + (void) close (p2[P_WRITE]); + return RP_BAD; + } + + if (pid) { + (void) close (p1[P_READ]); + fdout = p1[P_WRITE]; + (void) close (p2[P_WRITE]); + fdin = p2[P_READ]; + return RP_OK; + } + + (void) close (p1[P_WRITE]); + (void) close (p2[P_READ]); + + fdin = p1[P_READ]; + fdout = p2[P_WRITE]; + + if ((loc -> username && + initgroups (loc -> username, loc -> gid) == -1) || + setregid (loc -> gid, loc -> gid) == -1 || + setreuid (loc -> uid, loc -> uid) == -1) { + PP_SLOG (LLOG_EXCEPTIONS, "user", + ("Can't set uid/gid")); + _exit(1); + } + + if (chdir (loc -> directory) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "chdir", + ("Can't change directory to %s", loc -> directory)); + _exit (1); + } + + do_child_stuff(); + + /* NOTREACHED */ +} + + +int loc_cd (dir, rp) +char *dir; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_CD; + (void) strcpy (packet.s1, dir); + return send_pac (&packet, rp); +} + + +int loc_mkdir (dir, mode, rp) +char *dir; +int mode; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_MKDIR; + (void) strcpy (packet.s1, dir); + packet.size = mode; + return send_pac (&packet, rp); +} + + +int loc_write (buf, size, rp) +char *buf; +int size; +RP_Buf *rp; +{ + struct loc_packet packet; + packet.command = LP_WRITE; + packet.size = size; + if (write (fdout, (char *)&packet, sizeof packet) != sizeof packet) + return loc_set (rp, RP_FIO, "Can't write"); + if (write (fdout, buf, size) != size) + return loc_set (rp, RP_FIO, "Can't write"); + if (read (fdin, (char *)rp, sizeof *rp) != sizeof *rp) + return loc_set (rp, RP_LIO, "Can't get response"); + return loc_set (rp, RP_OK, "OK"); +} + + +int loc_close (rp) +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_CLOSE; + return send_pac (&packet, rp); +} + + +int loc_open (file, mode, flag, rp) +char *file; +char *mode; +int flag; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_OPEN; + (void) strcpy (packet.s1, file); + (void) strcpy (packet.s2, mode); + packet.size = flag; + return send_pac (&packet, rp); +} + + +loc_move (s1, s2, rp) +char *s1, *s2; +RP_Buf *rp; +{ + struct loc_packet packet; + packet.command = LP_MOVE; + (void) strcpy (packet.s1, s1); + (void) strcpy (packet.s2, s2); + return send_pac (&packet, rp); +} + + + +int loc_opendir (dir, rp) +char *dir; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_OPENDIR; + (void) strcpy (packet.s1, dir); + return send_pac (&packet, rp); +} + + +int loc_closedir (rp) /* Close previous OPENDIR */ +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_CLOSEDIR; + return send_pac (&packet, rp); +} + + + +int loc_system (str, rp) +char *str; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_SYSTEM; + (void) strcpy (packet.s1, str); + return send_pac (&packet, rp); +} + + +int loc_isdir (dir, rp) +char *dir; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_ISDIR; + (void) strcpy (packet.s1, dir); + return send_pac (&packet, rp); +} + + + +int loc_nextmess (dir, rp) +char *dir; +RP_Buf *rp; +{ + struct loc_packet packet; + + packet.command = LP_NEXTMESS; + (void) strcpy (packet.s1, dir); + return send_pac (&packet, rp); +} + + +loc_end() +{ + int cpid; + + if (fdout != NOTOK) { + (void) close (fdout); + fdout = NOTOK; + } + if (fdin != NOTOK) { + (void) close (fdin); + fdin = NOTOK; + } + + while ((cpid = wait ( (union wait *)0 )) != pid && cpid != -1) + continue; + return RP_OK; +} + + + +/* ------------------- Static Routines ------------------------------------ */ + + + + +static int loc_set (rp, val, str) +RP_Buf *rp; +int val; +char *str; +{ + rp -> rp_val = val; + (void) strcpy (rp -> rp_line, str); + return val; +} + + +static int send_pac (pp, rp) +struct loc_packet *pp; +RP_Buf *rp; +{ + if (write (fdout, (char *)pp, sizeof *pp) != sizeof *pp) + return loc_set (rp, RP_FIO, "Can't write"); + if (read (fdin, (char *)rp, sizeof *rp) != sizeof *rp) + return loc_set (rp, RP_LIO, "Can't get response"); + return rp -> rp_val; +} + + +static do_child_stuff() +{ + struct loc_packet packet; + struct loc_packet *pp = &packet; + RP_Buf rps, *rp = &rps; + + while (read (fdin, (char *)pp, sizeof (*pp)) == sizeof (*pp)) { + (void) do_packet (pp, rp); + if (write (fdout, (char *)rp, sizeof *rp) != sizeof *rp) { + PP_SLOG (LLOG_EXCEPTIONS, "write", + ("Write error on packet")); + exit (1); + } + } + exit (0); +} + + + +static int do_packet (pp, rp) +struct loc_packet *pp; +RP_Buf *rp; +{ + switch (pp->command) { + case LP_OPEN: + if (cur_fp != NULL) + (void) fclose (cur_fp); + if ((cur_fp = fopen(pp -> s1, pp -> s2)) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, "fopen", + ("Can't open file %s mode %s", + pp -> s1, pp -> s2)); + return loc_set (rp, RP_FOPN, "Can't open file"); + } + if (pp -> size) { + if (flock (fileno (cur_fp), LOCK_EX) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "flock", + ("Can't lock file %s", pp -> s1)) + (void) fclose (cur_fp); + cur_fp = NULL; + return loc_set (rp, RP_LOCK, "Can't lock file"); + } + } + return loc_set (rp, RP_OK, "OK"); + + case LP_CLOSE: + if (cur_fp != NULL) { + (void) fclose (cur_fp); + cur_fp = NULL; + } + return loc_set (rp, RP_OK, "OK"); + + case LP_CD: + if (chdir (pp -> s1) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "chdir", + ("Can't change directory to %s", pp -> s1)); + return loc_set (rp, RP_LIO, "Can't chdir"); + } + return loc_set (rp, RP_OK, "OK"); + + case LP_WRITE: + if (cur_fp == NULL) + return loc_set (rp, RP_FIO, "No file open"); + return copy (fdin, cur_fp, pp -> size, rp); + + case LP_MOVE: + if (rename (pp -> s1, pp-> s2) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "rename", + ("Can't move %s to %s", pp -> s1, pp -> s2)); + return loc_set (rp, RP_LIO, "Can't move file"); + } + return loc_set (rp, RP_OK, "OK"); + + case LP_MKDIR: + if (mkdir (pp -> s1, pp -> size) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "mkdir", + ("Can't make directory %s mode %o", + pp->s1, pp->size)); + return loc_set (rp, RP_LIO, "Can't make directory"); + } + return loc_set (rp, RP_OK, "OK"); + + case LP_OPENDIR: + if (mb_dp != NULL) + (void) closedir (mb_dp); + if ((mb_dp = opendir(pp -> s1)) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, "opendir", + ("Can't open directory %s", pp->s1)); + return loc_set (rp, RP_LIO, "Can't open directory"); + } + return loc_set (rp, RP_OK, "OK"); + + case LP_CLOSEDIR: + if (mb_dp != NULL) { + (void) closedir (mb_dp); + mb_dp = NULL; + } + return loc_set (rp, RP_OK, "OK"); + + case LP_SYSTEM: + if ((sysreply = system(pp -> s1)) ) { + PP_SLOG (LLOG_EXCEPTIONS, "system", + ("system() call returns value %d",sysreply)); + } + + /* I'm not sure if I should do this */ + return loc_set (rp, sysreply, "OK"); + + case LP_NEXTMESS: + if (mb_dp == NULL) { + return loc_set (rp, RP_FIO, "No directory open"); + } + return loc_set (rp, RP_OK, next_message (mb_dp, pp -> s1) ); + + case LP_ISDIR: + if (!isdir (pp -> s1)) { + return loc_set (rp, RP_MECH, "Not a directory"); + } + return loc_set (rp, RP_OK, "OK"); + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown command %d")); + return loc_set (rp, RP_PARM, "Unknown command"); + } +} + + +static int copy (in, out, size, rp) +int in; +FILE *out; +int size; +RP_Buf *rp; +{ + char buffer[BUFSIZ]; + int n; + + (void) loc_set (rp, RP_OK, "OK"); + while (size > 0) { + n = read (in, buffer, + size > sizeof buffer ? sizeof buffer : size); + if (n <= 0) + return loc_set (rp, RP_FIO, "Read error"); + if (out) + if (fwrite (buffer, 1, n, out) != n) + (void) loc_set (rp, RP_FIO, "Write error"); + size -= n; + } + return rp -> rp_val; +} + + + +/* --- generate next message number for this directory --- */ +static char* next_message(mb_dp,dir) +DIR *mb_dp; +char *dir; +{ + struct dirent *dp; + int i,biggest=0; + char fullname[MAXPATHLENGTH]; + + for(dp = readdir(mb_dp); dp != NULLDCT; dp = readdir(mb_dp)) { + + sprintf(fullname,"%s/%s",dir,dp->d_name); + if (isdir(fullname)) { + i = val(dp->d_name); + if (i > biggest) + biggest=i; + } + } + PP_DBG (("loc_proto/next_message number in %s = %d",dir,biggest+1)); + sprintf(fullname,"%d", (biggest + 1) ); + return(fullname); +} + + + +/* return value of s iff composed of digits, else 0 */ +static val(s) +char *s; +{ + int i,n; + + for(i=0,n=0; s[i] != NULL ; ++i) { + if (s[i] >= '0' && s[i] <= '9') + n = 10 * n + s[i] - '0'; + else { + n=0; + break; + } + } + PP_DBG (("loc_proto/val(%s)=%d", s,n)); + return(n); +} + + +static isdir (name) +char *name; +{ + struct stat st_rec; + + if (!isstr (name)) + return (FALSE); + + if (stat (name, &st_rec) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, name, ("isdir: Unable to stat")); + return (FALSE); + } + + switch (st_rec.st_mode & S_IFMT) { + case S_IFDIR: + PP_DBG (("loc_proto/isdir (%s = TRUE)", name)); + return (TRUE); + default: + PP_DBG (("loc_proto/isdir (%s = FALSE)", name)); + return (FALSE); + } +} diff --git a/Chans/slocal/local.c b/Chans/slocal/local.c new file mode 100644 index 0000000..c6e371f --- /dev/null +++ b/Chans/slocal/local.c @@ -0,0 +1,390 @@ +/* local: local delivery channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/slocal/RCS/local.c,v 6.0 1991/12/18 20:12:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/slocal/RCS/local.c,v 6.0 1991/12/18 20:12:09 jpo Rel $ + * + * $Log: local.c,v $ + * Revision 6.0 1991/12/18 20:12:09 jpo + * Release 6.0 + * + */ + + + +/*********************************************************************\ +* * +* local channel - deliver to people * +* * +\*********************************************************************/ + + +#include "head.h" +#include "util.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include +#include +#include +#include "sys.file.h" + +#define TESTVERSION + +extern char *quedfldir; +extern CHAN *ch_nm2struct (); +extern char *mboxname; +extern char *delim1; +extern char *delim2; + +static CHAN *mychan; +static char *this_msg; +static struct passwd *pwd; + +static int initproc (); +static int douser (); +static int deliver (); +static void dirinit (); +static struct type_Qmgr_DeliveryStatus *process (); +static Q_struct Qstruct; +static int copy (); + + + +/* --------------------- Begin Routines --------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + char *p; + + p = argv[0]; + if (*p == '/') { + p = rindex (p, '/'); + p++; + } + + + /* -- Init the channel - and find out who we are -- */ + chan_init (p); + + + dirinit (); +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, + initproc, process, NULLIFP); + else +#endif + channel_control (argc, argv, initproc, process, NULLIFP); + exit (0); +} + + + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + char *p; + + p = qb2str (arg); + + PP_TRACE (("initproc (%s)", p)); + if ((mychan = ch_nm2struct (p)) == NULLCHAN) + err_abrt (RP_PARM, "Channel '%s' not known", p); + + PP_NOTICE (("Starting %s (%s)", + mychan -> ch_name, mychan -> ch_show)); + + if (p) + free (p); + + return OK; +} + + + + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + struct prm_vars prm; + Q_struct *qp = &Qstruct; + ADDR *ad_sendr = NULL, + *ad_recip = NULL; + int ad_count, + retval; + + + bzero ((char *)&prm, sizeof prm); + bzero ((char *)qp, sizeof *qp); + + if (this_msg) + free (this_msg); + + this_msg = qb2str (arg -> qid); + + PP_NOTICE (("Processing msg %s", this_msg)); + + delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("local/rd_msg err: %s", this_msg)); + return delivery_setall (int_Qmgr_status_messageFailure); + } + + for (up = arg -> users; up; up = up -> next) { + retval = douser (up -> RecipientId -> parm, ad_recip, + this_msg); + if (rp_isbad (retval)) + break; + } + + rd_end(); + prm_free (&prm); + q_free (qp); + + return deliverystate; +} + + + +/* +Change into pp queue space +*/ + +static void dirinit () +{ + PP_TRACE (("dirinit ()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Uanble to change directory to '%s'", + quedfldir); +} + + +/* + * process one extension-id for this message + */ + +static int douser (rno, ad_recip, msgd) +int rno; +ADDR *ad_recip; +char *msgd; +{ + ADDR *ap; + + PP_TRACE (("douser (%d, ad_recip, %s)", rno, msgd)); + + for (ap = ad_recip; ap ; ap = ap->ad_next) { + if (ap-> ad_status == AD_STAT_DONE) + continue; + if ( rno == ap -> ad_no) + return (deliver (ap, msgd)); + } + + PP_LOG (LLOG_EXCEPTIONS, + ("local/user not recipient of %s", this_msg)); + + delivery_set (rno, int_Qmgr_status_messageFailure); + return RP_MECH; +} + + +static char *formatdir = NULLCP; + +/* +Do the delivery +*/ +static int deliver (ap, msgd) +ADDR *ap; +char *msgd; +{ + char *username = NULLCP, + *diry = NULLCP, + *mbox = NULLCP, + mailbox[MAXPATHLENGTH], + filename[MAXPATHLENGTH]; + int first = 0, + retval; + RP_Buf rps, + *rp = &rps; + + + PP_TRACE (("local/deliver msgd=%s", msgd)); + + if (ap->ad_outchan->li_chan != mychan) { + PP_LOG (LLOG_EXCEPTIONS, + ("local/this extension-id (%d) is not for this chan", + ap->ad_extension)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_BAD; + } + + if (tb_getlocal (ap -> ad_r822adr, mychan, &username, + &diry, &mbox) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("User %s not registered in chan %s table", + ap -> ad_r822adr, mychan -> ch_name)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UA_UNAVAILABLE, + "User not registered in delivery table"); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + return RP_USER; + } + + PP_TRACE (("Found entry for '%s' uid '%s' directory '%s'", + ap -> ad_r822adr, username, diry)); + + if (pwd && strcmp (pwd -> pw_name, username) == 0) + PP_TRACE (("Same user")); + else { + if (pwd) + (void) loc_end (); + + if ((pwd = getpwnam (username)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("local/user '%s' not in passwd file", + username)); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UA_UNAVAILABLE, + "user not registered in passwd file"); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + return RP_USER; + } + + if (rp_isbad (loc_init (pwd, diry ? diry : pwd->pw_dir))) { + PP_LOG (LLOG_EXCEPTIONS, ("loc_init error")); + delivery_set (ap -> ad_no, + int_Qmgr_status_mtaFailure); + return RP_MECH; + } + + } + + /* + Find the correctly formatted version of the message + */ + + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't locate message %s", this_msg)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + PP_DBG (("local: mboxname : '%s'", mboxname)); + PP_DBG (("local: delim1 : '%s'", delim1)); + PP_DBG (("local: delim2 : '%s'", delim2)); + + (void) sprintf (mailbox, "%s/%s", + diry ? diry : pwd->pw_dir, + mbox ? mbox : mboxname); + + PP_TRACE (("delivering to mailbox='%s'", mailbox)); + + if (loc_open (mailbox, "a", 1, rp) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't open mailbox %s", + rp -> rp_line)); + delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure); + return RP_MECH; + } + + if (rp_isbad (retval = msg_rinit (formatdir))) { + PP_LOG (LLOG_EXCEPTIONS, ("local/msg_rinit can't init %s", + formatdir)); + (void) loc_close (rp); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + + PP_TRACE (("Mailbox opened")); + + if (loc_write (delim1, strlen (delim1), rp) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("loc_write can't write delim1 [%s]", + rp -> rp_line)); + delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure); + return rp -> rp_val; + } + + first = 0; + while ((retval = msg_rfile (filename)) == RP_OK) { + if (rp_isbad (retval = copy (filename))) + break; + if (first++ == 0) + loc_write ("\n", 1, rp); + } + + if (loc_write (delim2, strlen (delim2), rp) != RP_OK) + PP_LOG (LLOG_EXCEPTIONS, ("loc_write can't write delim2 [%s]", + rp -> rp_line)); + + loc_close (rp); + + retval = msg_rend (); + if (retval != RP_OK) { + delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure); + return retval; + } + + PP_NOTICE ((">>> local : Message delivered to %s", username)); + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_NO_REASON, + -1, NULLCP); + if (!rp_isbad(wr_q2dr (&Qstruct, this_msg))) + delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + } + else { + (void) wr_ad_status (ap, AD_STAT_DONE); + delivery_set (ap -> ad_no, int_Qmgr_status_success); + } + return RP_OK; +} + + +static int copy (fname) +char *fname; +{ + FILE *ifp; + char buf[BUFSIZ]; + int n, retval = RP_OK; + RP_Buf rps, *rp = &rps; + + PP_TRACE (("copy (%s, fp)", fname)); + + if ((ifp = fopen (fname,"r")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("local/can't read file '%s'", fname)); + return (RP_FOPN); + } + + while ((n = fread (buf, sizeof (char), sizeof (buf), ifp)) > 0) + if (loc_write (buf, n, rp) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("loc_write can't write error [%s]", + rp -> rp_line)); + retval = rp -> rp_val; + break; + } + (void) fclose (ifp); + return (retval); +} diff --git a/Chans/slocal/make b/Chans/slocal/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/slocal/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/slocal/slocal.c b/Chans/slocal/slocal.c new file mode 100644 index 0000000..400e53e --- /dev/null +++ b/Chans/slocal/slocal.c @@ -0,0 +1,646 @@ +/* slocal.c: structured message local delivery channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/slocal/RCS/slocal.c,v 6.0 1991/12/18 20:12:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/slocal/RCS/slocal.c,v 6.0 1991/12/18 20:12:09 jpo Rel $ + * + * $Log: slocal.c,v $ + * Revision 6.0 1991/12/18 20:12:09 jpo + * Release 6.0 + * + */ + + + +/*********************************************************************\ +* * +* local channel - deliver as structured messages * +* (based on local.c 10/01/89) * +* * +* * +\*********************************************************************/ + + +#include "head.h" +#include "util.h" +#include "prm.h" +#include "q.h" +#include "qmgr.h" +#include "dr.h" +#include +#include +#include "loc_user.h" +#include "sys.file.h" +#include + +#define NULLDIR ((DIR*)0) +#define NULLDCT ((struct dirent *)0) + +extern char *ad_getlocal(); +extern char *quedfldir; +extern CHAN *ch_nm2struct(); +extern void err_abrt(), getfpath(), rd_end(), chan_init(); +static Q_struct Qstruct; +static char *basename(); +static CHAN *mychan; +static char *this_msg; +static char *formatdir=NULLCP; +static int initproc(); +static void dirinit(); +static struct type_Qmgr_DeliveryStatus *process(); + +static char mboxdir[] = "PPMail"; /* main PP mail directory */ +static char inboxdir[] = "inbox"; /* inbox */ +static char tempdir[] = "slocal"; /* temporary directory name */ +static char alert_file[] = "/alert"; /* alert script in PPMail */ +static char alert_message[] = "You have new mail from PP"; /* system call */ +static char base_string[] = "base"; /* basename target in file */ + /* from msg_rfile */ + +int firstSuccessDR = TRUE; + + +/* ----------------------- Begin Routines ------------------------------ */ + + + +main (argc, argv) +int argc; +char **argv; +{ + char *p; + + p = argv[0]; + if (*p == '/') { + p = rindex (p, '/'); + p++; + } + + /* Init the channel - and find out who we are */ + chan_init (p); + + dirinit(); + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc,argv, initproc, process, NULLIFP); + else +#endif + + channel_control (argc, argv, initproc, process, NULLIFP); + + exit (0); +} + + + + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + char *p; + + p = qb2str (arg); + + PP_TRACE (("initproc (%s)", p)); + if ((mychan = ch_nm2struct (p)) == NULLCHAN) + err_abrt (RP_PARM, "Channel '%s' not known", p); + + free (p); + return OK; +} + + + + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + struct prm_vars prm; + Q_struct *qp = &Qstruct; + ADDR *ad_sendr = NULL, + *ad_recip = NULL; + int ad_count, + retval; + + bzero ((char *) qp, sizeof (*qp)); + if (this_msg) free (this_msg); + + this_msg = qb2str (arg -> qid); + + PP_TRACE (("slocal/processing msg %s", this_msg)); + + + delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("slocal/rd_msg err: %s", this_msg)); + return delivery_setall (int_Qmgr_status_messageFailure); + } + + for (up = arg -> users; up; up = up -> next) + douser (up -> RecipientId -> parm, ad_recip, this_msg); + + rd_end(); + + return deliverystate; +} + + + +static void dirinit() /* Change into pp queue space */ +{ + PP_TRACE (("dirinit()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Uanble to change directory to '%s'", + quedfldir); +} + + + +/* process one extension-id for this msg */ + +static int douser (rno, ad_recip, msgd) +int rno; +ADDR *ad_recip; +char *msgd; +{ + ADDR *ap; + + PP_TRACE (("douser (%d, ad_recip, %s)", rno, msgd)); + + for (ap = ad_recip; ap ; ap = ap->ad_next) { + if (rno != ap -> ad_no) + continue; + if (lchan_acheck (ap, mychan, 1, NULLVP) == NOTOK) + return RP_MECH; + else { + deliver (ap, msgd); + return RP_OK; + } + } + + PP_LOG (LLOG_EXCEPTIONS, ("slocal/user not recipient of %s", + this_msg)); + + delivery_set (rno, int_Qmgr_status_messageFailure); + return RP_MECH; +} + + + +static int deliver (ap, msgd) +ADDR *ap; +char *msgd; +{ + static LocUser *loc; + + char umaildir[MAXPATHLENGTH]; /* usr structured mail dir - PPMail */ + char uinboxdir[MAXPATHLENGTH]; /* usr structured inbox dir - PPMail*/ + char utempdir[MAXPATHLENGTH]; /* temp dir - PPMail/inbox/.slocal */ + char newname [MAXPATHLENGTH]; /* new name i.e. 12/, 13/ etc. */ + char fname [MAXPATHLENGTH]; /* filename */ + char fnameout[MAXPATHLENGTH]; /* output name */ + /* PPMail/inbox/.slocal/filename */ + char new_directory[MAXPATHLENGTH]; /* place for new dir names to */ + /* be generated in message */ + char ualert_file[MAXPATHLENGTH]; /* users alert file name */ + char s_string[BUFSIZ]; /* system call string */ + char *p,*q; + char *user; + int next_msgno; + int alert_exists; + int i; + int retval,sysreply; + RP_Buf rps, *rp = &rps; + + + PP_TRACE (("slocal/deliver msgd=%s", msgd)); + + if (ap->ad_outchan->li_chan != mychan) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/this extension-id (%d) is not for this channel", + ap->ad_extension)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_BAD; + } + + if ((user = ad_getlocal (ap -> ad_r822adr, AD_822_TYPE)) == NULLCP) { + char buffer[BUFSIZ]; + (void) sprintf (buffer, "User %s not local!", ap -> ad_r822adr); + PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); + delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, DRD_UA_UNAVAILABLE, buffer); + wr_q2dr (&Qstruct, this_msg); + return RP_USER; + } + + if ((loc = tb_getlocal (user, mychan)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("User %s not registered in chan %s table", + user, mychan -> ch_name)); + free (user); + delivery_set (ap -> ad_no, int_Qmgr_status_negativeDR); + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UA_UNAVAILABLE, + "User not registered in delivery table"); + wr_q2dr (&Qstruct, this_msg); + return RP_USER; + } + + + PP_TRACE (("Found entry for '%s' uid '%s' (%d) directory '%s'", + ap -> ad_r822adr, + loc -> username ? loc -> username : "", + loc -> uid, loc -> directory)); + + if (rp_isbad (loc_init (loc))) { + PP_LOG (LLOG_EXCEPTIONS, ("loc_init error")); + delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure); + return RP_MECH; + } + + /* + Find the correctly formatted version of the message + */ + + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't locate message %s", this_msg)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + + /* --- *** --- + Try to cd into umaildir - if unable to do so then create + the directory and log it. Then try opening. + --- *** --- */ + + (void) sprintf (umaildir, "%s/%s", loc -> directory, mboxdir); + + if (rp_isbad (loc_cd (umaildir, rp))) { + if (rp_isbad (loc_mkdir (umaildir, 0700, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Unable to create '%s'", umaildir)); + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_FOPN; + } + + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Created directory '%s'", umaildir)); + } + + + if (rp_isbad (loc_opendir (umaildir, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Unable to open directory '%s'", umaildir)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_FOPN; + } + + + if (rp_isbad (loc_closedir (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Unable to close directory '%s'", umaildir)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_FOPN; + } + + getfpath (mychan -> ch_out_info, umaildir, ualert_file); + (void) strcat (ualert_file, alert_file); + + if (rp_isbad (loc_open (ualert_file, "r", 1, rp))) { + alert_exists=FALSE; + loc_close (rp); + } + else + alert_exists=TRUE; + + (void) sprintf (uinboxdir, "%s/%s", umaildir, inboxdir); + + /* + Try to open uinboxdir - if unable then create in user's + directory and log it. Retry open - fail if cannot open. + */ + + if (rp_isbad (loc_cd (uinboxdir, rp))) { + if (rp_isbad (loc_mkdir (uinboxdir, 0700, rp))) { + + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Unable to create user inbox directory '%s'", + uinboxdir)); + + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_FOPN; + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/Created user inbox directory '%s'", + uinboxdir)); + } + } + + + if (rp_isbad (loc_opendir (uinboxdir, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't open user inbox '%s'", uinboxdir)); + return RP_FOPN; + } + + /* Generate new (temp) dir, then copy all body part files into it. */ + (void) sprintf (utempdir, "%s/%s", uinboxdir, tempdir); + + if (rp_isbad (loc_mkdir (utempdir, 0700, rp))) { + + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't create user mail temporary directory '%s'", + utempdir)); + + if (rp_isbad (loc_isdir (utempdir, rp))) { + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_FOPN; + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/using existing temporary directory %s", + utempdir)); + } + } + PP_TRACE (("delivering to mail temporary directory %s", utempdir)); + + if (rp_isbad (retval = msg_rinit (formatdir))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/msg_rinit can't init %s", formatdir)); + + loc_closedir (rp); /* close directory */ + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + + + PP_TRACE (("slocal msg_rinit formatdir %s", formatdir)); + + /* --- *** --- + * Strategy for decoding filenames from queue : + * look for first occurence of `base' in name - then skip + * to the next `/' - all that follows is the structure + * of the message itself. + * basename() returns the path/filename component + * following the `/' + --- *** --- */ + + if (dump_mtsparams (&Qstruct, utempdir, ap) != OK) { + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_FIO; + } + + while ((retval = msg_rfile (fname)) == RP_OK) { + PP_TRACE (("slocal msg_rfile returned %s", fname)); + + if ((p = basename (fname)) == NULLCP ) { + + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/basename() cannot extract real message")); + + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_FOPN; + } + + q = p; + + while (q = index (q,'/')) { /* keep making directories */ + strcpy (new_directory,utempdir); + strcat (new_directory,"/"); + strncat (new_directory,p,q-p); + + if (rp_isbad (loc_mkdir (new_directory, 0700, rp))) { + + if (rp_isbad (loc_isdir (new_directory, rp))) { + + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/'%s' is not a directory", + new_directory)); + + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_FOPN; + } + else { + PP_DBG (("slocal/using existing message directory %s",new_directory)); + } + } + else { + PP_TRACE (("slocal/created message directory %s", new_directory)); + } + q++; /* step past current '/' */ + } + + (void) sprintf (fnameout,"%s/%s",utempdir,p); + + if ((i = slocal_copy (fname, fnameout)) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/slocal_copy from %s to %s failed - error %d", fname, fnameout,i)); + delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return RP_MECH; + } + } + + retval = msg_rend(); + if (retval != RP_OK) { + delivery_set (ap -> ad_no, int_Qmgr_status_mtaFailure); + return retval; + } + + if (rp_isbad (loc_nextmess (uinboxdir, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/cannot determine next message number for %s", uinboxdir)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + + PP_DBG (("slocal/next message number in %s = %s", + uinboxdir,rp -> rp_line)); + + next_msgno = atoi (rp ->rp_line); + (void) sprintf (newname, "%s/%d\0", uinboxdir, next_msgno); + + if (rp_isbad (loc_closedir (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't close directory '%s'", uinboxdir)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_FOPN; + } + + PP_TRACE (("slocal/renaming temp. dir. %s to %s", utempdir,newname)); + if (rp_isbad (loc_move (utempdir, newname, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't rename user mail temporary directory %s to %s", utempdir,newname)); + delivery_set (ap -> ad_no, int_Qmgr_status_messageFailure); + return RP_MECH; + } + + PP_NOTICE ((">>> slocal: Message delivered to %s", user)); + + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (&Qstruct, ap -> ad_no, this_msg, + DRR_NO_REASON, + -1, NULLCP); + if (!rp_isbad (wr_q2dr (&Qstruct, this_msg))) { + PP_NOTICE ((">>> slocal: Setting positive DR")); + delivery_set (ap -> ad_no, + (firstSuccessDR == TRUE) ? + int_Qmgr_status_positiveDR : + int_Qmgr_status_successSharedDR); + firstSuccessDR = FALSE; + } + + } + else { + retval = wr_ad_status (ap, AD_STAT_DONE); + (void) wr_stat (ap, &Qstruct, this_msg, Qstruct.msgsize); + delivery_set (ap -> ad_no, + rp_isbad(retval) ? + int_Qmgr_status_messageFailure : + int_Qmgr_status_success); + } + + if (alert_exists) { + (void) sprintf (s_string,"%s %s %d %s &\n", + ualert_file, loc -> username, + next_msgno, alert_message); + + PP_TRACE (("slocal/calling system with '%s'", s_string)); + + if (sysreply = loc_system (s_string, rp)) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/system() call returns value %d", + sysreply)); + } + } + + + /* --- free locations --- */ + if (loc) { + (void) loc_end(); + free_loc_user (loc); + } + if (user) + free (user); + + + return retval; +} + + +/* --- open fname, copy to fnameout in smailbox --- */ + +static slocal_copy (fname, fnameout) +char *fname; +char *fnameout; +{ + FILE *ifp; + char buf[BUFSIZ]; + int n, retval = RP_OK; + RP_Buf rps, *rp = &rps; + + PP_TRACE (("slocal_copy (%s, fp)", fname)); + + if ((ifp = fopen (fname,"r")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't read file '%s'", fname)); + return (RP_FOPN); + } + + if (rp_isbad (loc_open (fnameout, "w", 1, rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't open file '%s'", fnameout)); + return (RP_FOPN); + } + + while ((n = fread (buf, sizeof (char), sizeof (buf), ifp)) > 0) + if (loc_write (buf, n, rp) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("slocal/can't write to file %s [%s]", + fnameout, rp ->rp_line)); + retval = rp ->rp_val; + break; + } + + (void) fclose (ifp); + (void) loc_close (rp); + return (retval); +} + + +/* --- extract basename from full path --- */ +static char *basename (f) +char *f; +{ + char *ret; + + ret = f + strlen(formatdir); + while (isstr(ret) && *ret == '/') + ret++; + return ret; +} + + +static dump_mtsparams (qp, tmp, ap2) +Q_struct *qp; +char *tmp; +ADDR *ap2; +{ + char buf[BUFSIZ], buf2[BUFSIZ]; + ADDR *ap; + FILE *fp; + + (void) strcpy (buf, "/tmp/mtsXXXXXX"); + mktemp (buf); + if ((fp = fopen (buf, "w+")) == NULL) + return NOTOK; + if (rp_isbad (wr_q (qp, fp))) { + (void) fclose (fp); + (void) unlink (buf); + return NOTOK; + } + if (rp_isbad (wr_adr (qp -> Oaddress, fp, AD_ORIGINATOR))) { + (void) fclose (fp); + (void) unlink (buf); + return NOTOK; + } + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) { + if (ap -> ad_no != ap2 -> ad_no) + ap -> ad_resp = FALSE; + if (rp_isbad (wr_adr (ap, fp, AD_RECIPIENT))) { + (void) fclose (fp); + (void) unlink (buf); + return NOTOK; + } + } + (void) fflush (fp); + (void) fclose (fp); + + + (void) sprintf (buf2, "%s/MTS-parameters", tmp); + if (rp_isbad (slocal_copy (buf, buf2))) { + (void) unlink (buf); + return NOTOK; + } + (void) unlink (buf); + return OK; +} diff --git a/Chans/smtp/Makefile b/Chans/smtp/Makefile new file mode 100644 index 0000000..43c67d9 --- /dev/null +++ b/Chans/smtp/Makefile @@ -0,0 +1,274 @@ +# Smtp channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/Makefile,v 6.0 1991/12/18 20:12:19 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:19 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = sm_ns.c sm_wtmail.c smtp.c smtpd.c smtpsrvr.c +OBJS = sm_ns.o sm_wtmail.o smtp.o smtpd.o smtpsrvr.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS=xsmtp xsmtpsrvr xsmtpd + +default: all + +all: $(PROGS) + +lint: l-smtp l-smtpsrvr l-smtpd + +############################################################ +# +# Smtp outbound channel +# +############################################################ + +SMTPSRCS = smtp.c sm_wtmail.c sm_ns.c +SMTPOBJS = smtp.o sm_wtmail.o sm_ns.o + + +smtp: xsmtp + +xsmtp: $(SMTPOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(SMTPOBJS) $(LIBPP) $(LIBRESOLV) $(LIBSYS) + +saber_smtp_src: $(SMTPSRCS) + #load -C $(CFLAGS) $(SMTPSRCS) $(LIBPP) $(LIBRESOLV) $(LIBSYS) + +saber_smtp_obj:$(SMTPOBJS) + #load -C smtp.o $(SMTPOBJS) $(LIBPP) $(LIBRESOLV) $(LIBSYS) + +l-smtp: $(SMTPSRCS) + $(LINT) $(LLFLAGS) $(SMTPSRCS) $(LINTLIBS) + +############################################################ +# +# SMTP stub dameon +# +############################################################ + +SMTPDSRCS = smtpd.c +SMTPDOBJS = smtpd.o + +smtpd: xsmtpd + +xsmtpd: $(SMTPDOBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(SMTPDOBJS) $(LIBPP) \ + $(LIBSYS) -o xsmtpd + +saber_smtpd_src: $(SMTPDSRCS) + #load -C $(CFLAGS) $(SMTPDSRCS) $(LIBPP) $(LIBSYS) + +saber_smtpd_obj:$(SMTPDOBJS) + #load -C $(SMTPDOBJS) $(LIBPP) $(LIBSYS) + +l-smtpd: $(SMTPDSRCS) + $(LINT) $(LLFLAGS) $(SMTPDSRCS) $(LINTLIBS) + +############################################################ +# +# smtp server process +# +############################################################ + +SMTPSRVRSRCS = smtpsrvr.c sm_ns.c +SMTPSRVROBJS = smtpsrvr.o sm_ns.o +smtpsrvr: xsmtpsrvr + +xsmtpsrvr: $(SMTPSRVROBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(SMTPSRVROBJS) \ + $(LIBPP) $(LIBSYS) $(LIBRESOLV) + +saber_smtpsrvr_src: $(SMTPSRVRSRCS) + #load -C $(CFLAGS) $(SMTPSRVRSRCS) $(LIBPP) $(LIBSYS) $(LIBRESOLV) + +saber_smtpsrvr_obj:$(SMTPSRVROBJS) + #load -C $(SMTPSRVROBJS) $(LIBPP) $(LIBSYS) $(LIBRESOLV) + +l-smtpsrvr: $(SMTPSRVRSRCS) + $(LINT) $(LLFLAGS) $(SMTPSRVRSRCS) $(LINTLIBS) + +############################################################ +# +# misc things +# +############################################################ + +install: inst-dir inst-smtp inst-smtpsrvr inst-smtpd + +inst-dir: $(CHANDIR) + +inst-smtp: $(CHANDIR)/smtp + +$(CHANDIR)/smtp: xsmtp + -$(BACKUP) $@ zxsmtp + rm -f $@ + $(INSTALL) xsmtp $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "smtp channel installed normally"; echo "" + +inst-smtpsrvr: $(CHANDIR)/smtpsrvr + +$(CHANDIR)/smtpsrvr: xsmtpsrvr + -$(BACKUP) $@ zxsmtpsrvr + rm -f $@ + $(INSTALL) xsmtpsrvr $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "smtp server installed normally"; echo " " + +inst-smtpd: $(CHANDIR)/smtpd + +$(CHANDIR)/smtpd: xsmtpd + -$(BACKUP) $@ zxsmtpd + rm -f $@ + $(INSTALL) xsmtpd $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "smtp daemon installed normally"; echo " " + + +clean: tidy + rm -f $(OBJS) $(PROGS) core a.out *old *.BAK zxsmtp* + +tidy: + rm -f $(PROGS) zxsmtp* core a.out *old *.BAK + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + + + ############################################################ + # + # End of Building Rules + # + ############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +sm_ns.o: sm_ns.c +sm_ns.o: ../../h/util.h +sm_ns.o: ../../h/config.h +sm_ns.o: ../../h/ll_log.h +sm_ns.o: ../../h/retcode.h +sm_ns.o: ../../h/chan.h +sm_ns.o: ../../h/table.h +sm_ns.o: ../../h/list_bpt.h +sm_wtmail.o: sm_wtmail.c +sm_wtmail.o: ../../h/util.h +sm_wtmail.o: ../../h/config.h +sm_wtmail.o: ../../h/ll_log.h +sm_wtmail.o: ../../h/retcode.h +sm_wtmail.o: ../../h/chan.h +sm_wtmail.o: ../../h/table.h +sm_wtmail.o: ../../h/list_bpt.h +sm_wtmail.o: ../../h/ap.h +sm_wtmail.o: ../../h/util.h +smtp.o: smtp.c +smtp.o: ../../h/head.h +smtp.o: ../../h/util.h +smtp.o: ../../h/config.h +smtp.o: ../../h/ll_log.h +smtp.o: ../../h/retcode.h +smtp.o: ../../h/chan.h +smtp.o: ../../h/table.h +smtp.o: ../../h/list_bpt.h +smtp.o: ../../h/prm.h +smtp.o: ../../h/q.h +smtp.o: ../../h/adr.h +smtp.o: ../../h/list_rchan.h +smtp.o: ../../h/chan.h +smtp.o: ../../h/auth.h +smtp.o: ../../h/list_bpt.h +smtp.o: ../../h/extension.h +smtp.o: ../../h/mta.h +smtp.o: ../../h/adr.h +smtp.o: ../../h/list_bpt.h +smtp.o: ../../h/aparse.h +smtp.o: ../../h/ap.h +smtp.o: ../../h/util.h +smtp.o: ../../h/or.h +smtp.o: ../../h/chan.h +smtp.o: ../../h/auth.h +smtp.o: ../../h/list_rchan.h +smtp.o: ../../h/mta.h +smtp.o: ../../h/dr.h +smtp.o: ../../h/extension.h +smtp.o: ../../h/mta.h +smtp.o: ../../h/qmgr.h +smtp.o: ../../h/Qmgr-types.h +smtp.o: ../../h/Qmgr-ops.h +smtp.o: ../../h/sys.file.h +smtpd.o: smtpd.c +smtpd.o: ../../h/util.h +smtpd.o: ../../h/config.h +smtpd.o: ../../h/ll_log.h +smtpd.o: ../../h/sys.file.h +smtpsrvr.o: smtpsrvr.c +smtpsrvr.o: ../../h/head.h +smtpsrvr.o: ../../h/util.h +smtpsrvr.o: ../../h/config.h +smtpsrvr.o: ../../h/ll_log.h +smtpsrvr.o: ../../h/retcode.h +smtpsrvr.o: ../../h/prm.h +smtpsrvr.o: ../../h/q.h +smtpsrvr.o: ../../h/adr.h +smtpsrvr.o: ../../h/list_rchan.h +smtpsrvr.o: ../../h/chan.h +smtpsrvr.o: ../../h/table.h +smtpsrvr.o: ../../h/list_bpt.h +smtpsrvr.o: ../../h/auth.h +smtpsrvr.o: ../../h/list_bpt.h +smtpsrvr.o: ../../h/extension.h +smtpsrvr.o: ../../h/mta.h +smtpsrvr.o: ../../h/adr.h +smtpsrvr.o: ../../h/list_bpt.h +smtpsrvr.o: ../../h/aparse.h +smtpsrvr.o: ../../h/ap.h +smtpsrvr.o: ../../h/util.h +smtpsrvr.o: ../../h/or.h +smtpsrvr.o: ../../h/chan.h +smtpsrvr.o: ../../h/auth.h +smtpsrvr.o: ../../h/list_rchan.h +smtpsrvr.o: ../../h/mta.h +smtpsrvr.o: ../../h/dl.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/smtp/make b/Chans/smtp/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/smtp/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/smtp/sm_ns.c b/Chans/smtp/sm_ns.c new file mode 100644 index 0000000..bf643de --- /dev/null +++ b/Chans/smtp/sm_ns.c @@ -0,0 +1,474 @@ +/* sm_ns.c */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/smtp/RCS/sm_ns.c,v 6.0 1991/12/18 20:12:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/sm_ns.c,v 6.0 1991/12/18 20:12:19 jpo Rel $ + * + * $Log: sm_ns.c,v $ + * Revision 6.0 1991/12/18 20:12:19 jpo + * Release 6.0 + * + */ + + + +/* Steve Kille, based on code from Phil Cockcroft and Craig Partridge + September 1989 */ + + + +#include "util.h" +#include "retcode.h" +#include "chan.h" +#include +#ifdef NAMESERVER +#include + +#include +#ifdef XOS_2 +#include +#else +#include +#endif + + +/* T_UNSPEC was defined only in more recent versions of BIND */ + +#ifdef T_UNSPEC +#define BSD4_3 +#define getshort _getshort +#endif T_UNSPEC + + +#ifndef MAXADDR +#define MAXADDR 30 +#endif + +#ifndef MAXADDR_PER +#define MAXADDR_PER 4 +#endif + +#ifndef MAXDATA +#define MAXDATA (4 * PACKETSZ) /* tcp tried after udp */ +#endif + +#ifndef MAXMX +#define MAXMX 20 /* shouldn't be < MAXADDR */ +#endif + + +union ansbuf { /* potentially huge */ + HEADER ab1; + char ab2[MAXDATA]; +}; + +union querybuf { /* just for outbound stuff */ + HEADER qb1; /* didn't want to clobber stack */ + char qb2[2 * MAXDNAME]; +}; + +extern char *loc_dom_mta; + +static char dn_name[MAXDNAME]; + +static struct hostent hval; +static struct in_addr addrbuf[MAXADDR+1]; +static char *addrptrs [MAXADDR+1]; +static char addrarray[MAXADDR + 1][sizeof(struct in_addr) + 1]; +extern int h_errno; + +ns_gethost (key, hptr, errstr) +char *key; +struct hostent **hptr; +char *errstr; +{ + register char *cp; + register int i, j, n; + HEADER *hp; + struct hostent *he; + union querybuf qbuf; + union ansbuf abuf; + u_short type, dsize; + int pref, localpref; + int count, mxcount; + int sawmx; /* are we actually processing mx's? */ + char *eom; + char buf[MAXDNAME]; /* for expanding in dn_expand */ + char newkey[MAXDNAME]; /* in case we get a CNAME RR back... */ + struct { /* intermediate table */ + char *mxname; + u_short mxpref; + } mx_list[MAXMX]; + + int acount; + + extern char *ns_skiphdr(); + + *errstr = '\0'; + + PP_TRACE (("DNS resolve host %s", key)); + + for (i = 0; i <= MAXADDR; i++) + addrptrs[i] = (char *) addrarray[i]; + *hptr = &hval; + hval.h_addr_list = addrptrs; + hval.h_name = key; + hval.h_aliases = 0; + + +restart: + + mxcount = 0; + acount = 0; + localpref = -1; + sawmx = 0; + + n = res_mkquery(QUERY, key, C_IN, T_MX, (char *)0, 0, (char *)0, + (char *)&qbuf, sizeof(qbuf)); + + /* what else can we do? */ + if (n < 0) + { + (void) sprintf (errstr, "Unable to send query"); + PP_NOTICE (("No answers from res_mkquery")); + return(RP_NO); + } + + PP_TRACE (("ns_gethost: sending ns query (%d bytes)",n)); + + n = res_send((char *)&qbuf,n,(char *)&abuf, sizeof(abuf)); + + if (n < 0) + { + (void) sprintf (errstr, "Unable to contact the DNS"); + PP_SLOG (LLOG_EXCEPTIONS, "res_send", ("DNS resolver error: ")); + return(RP_TIME); + } + + hp = (HEADER *)&abuf; + + if (hp->rcode != NOERROR) + return(ns_error(hp, errstr, key)); + + + if (ntohs(hp->ancount) == 0) + { + mxcount = 1; + mx_list[0].mxname = strdup(key); + mx_list[0].mxpref = 0; + goto doaddr; + } + + /* read MX list */ + sawmx = 1; + count = ntohs(hp->ancount); + + + /* skip header */ + eom = ((char *)&abuf) + n; + if ((cp = ns_skiphdr((char *)&abuf, hp, eom))==0) + { + (void) sprintf (errstr, "No useful answers to query of %s", key); + PP_NOTICE (("ns_gethost: no useful answers to query")); + return(RP_TIME); + } + + PP_TRACE (("ns_gethost: %d answers to query",count)); + for (i = 0; i < MAXMX; i++) + mx_list[i].mxname = NULL; + + while ((cp < eom) && (count--)) + { + n = dn_expand((char *)&abuf,eom, cp, buf, sizeof(buf)); + if (n < 0) + goto quit; + + cp += n; + type = getshort(cp); + /* get to datasize */ + cp += (2 * sizeof(u_short)) + sizeof(u_long); + dsize = getshort(cp); + cp += sizeof(u_short); + + /* + * is it an MX ? + * it could be a CNAME + */ + + if (type == T_CNAME) + { + if (key == newkey) { + /* CNAME -> CNAME: illegal */ + PP_LOG (LLOG_EXCEPTIONS, ("recursive CNAME on MX query of %s", + key)); + goto quit; + } + PP_TRACE (("ns_gethost: CNAME answer to MX query")); + n = dn_expand((char *)&abuf,eom, cp, newkey, sizeof(newkey)); + cp += dsize; + if (n < 0) + continue; /* pray? */ + PP_TRACE (("ns_gethost: `%s` -> `%s` (new query)",key,newkey)); + key = newkey; + goto restart; + } + + if (type != T_MX) + { + PP_NOTICE (("ns_gethost: RR of type %d in response",type)); + cp += dsize; + continue; /* keep trying */ + } + + pref = getshort(cp); + cp += sizeof(u_short); + + n = dn_expand((char *)&abuf,eom, cp, buf, sizeof(buf)); + if (n < 0) + goto quit; + + cp += n; + + /* is it local? */ + if ((lexequ(loc_dom_mta, buf) == 0) && + ((localpref < 0) || (pref < localpref))) + { + localpref = pref; + for(i=(mxcount-1); i >= 0; i--) + { + if (mx_list[i].mxpref < localpref) + break; + + (void) free(mx_list[i].mxname); + mxcount--; + } + continue; + } + + /* now, see if we keep it */ + if ((localpref >= 0) && (pref >= localpref)) + continue; + + /* find where it belongs */ + for(i=0; i < mxcount; i++) + if (mx_list[i].mxpref > pref) + break; + + /* not of interest */ + if (i == MAXMX) + continue; + + /* shift stuff to make space */ + for(j= min(mxcount,MAXMX-1); j > i; j--) + { + if (j == (MAXMX-1) && mx_list[j].mxname) + (void) free(mx_list[j].mxname); + + mx_list[j].mxname = mx_list[j-1].mxname; + mx_list[j].mxpref = mx_list[j-1].mxpref; + } + + mx_list[i].mxname = strdup(buf); + mx_list[i].mxpref = pref; + + if (mxcount < MAXMX) + mxcount ++; + } + + /* + * should read additional RR section for addresses and cache them + * but let's hold on that. + */ + +doaddr: + /* now build the address list */ + + + PP_TRACE (("ns_gethost: using %d mx hosts",mxcount)); + + for(i=0,j=0; (i < mxcount) && (j < MAXADDR); i++) + { + /* + * note that gethostbyname() is slow -- we should cache so + * we don't ask for an address repeatedly + */ + + he = gethostbyname(mx_list[i].mxname); + + if (he == 0) + { + PP_NOTICE (("ns_gethost: no addresses for %s", + mx_list[i].mxname)); + /* nope -- were trying special case and no address */ + if ((!sawmx) && (h_errno != TRY_AGAIN)) { + sprintf (errstr, "No nameserver addresses for %s", + mx_list[i].mxname); + return(RP_NO); + } + + continue; + } + + if (j == 0) + { + hval.h_length = he -> h_length; + hval.h_addrtype = he -> h_addrtype; + } + + for(n=0; (j < MAXADDR) && (n < MAXADDR_PER); n++, j++) + { + if (he->h_addr_list[n] == 0) + break; + + bcopy(he->h_addr_list[n],hval.h_addr_list[j],sizeof(struct in_addr)); + + } + PP_TRACE (("ns_gethost: %d addresses saved for %s", + n, mx_list[i].mxname)); + } + acount = j; + hval.h_addr_list[j] = 0; + +quit: + for(i=0; i < mxcount; i++) + (void) free(mx_list[i].mxname); + + if (acount == 0) { + (void) sprintf (errstr, "Nameserver lookup of %s: No address found", key); + PP_NOTICE (("ns_gethost: No addresess derived from MX query")); + } + else + PP_NOTICE (("DNS resolves %s to %d address%s", key, acount, + acount > 1 ? "es" : "")); + /* if localpref is set, then we got an answer */ + return (acount == 0 ? (localpref < 0 ? RP_TIME : RP_NO) : RP_OK); +} + +static char *prcode (n) +int n; +{ + static char tbuf[40]; + + switch (n) { + case NOERROR: + return "No Error (NOERROR)"; + + case FORMERR: + return "Format Error (FORMERR)"; + + case SERVFAIL: + return "Server failure (SERVFAIL)"; + + case NXDOMAIN: + return "Non existant host/domain (NXDOMAIN)"; + + case NOTIMP: + return "Not implemented (NOTIMP)"; + + case REFUSED: + return "Query Refused (REFUSED)"; + + default: + (void) sprintf (tbuf, "Unknown code %d", n); + return tbuf; + } +} + +/* + * figure out proper error code to return given an error + */ + +static +ns_error(hp, errstr, key) +register HEADER *hp; +char *errstr; +char *key; +{ + + PP_NOTICE (("DNS error: %s",prcode(hp->rcode))); + switch (hp->rcode) + { + case NXDOMAIN: + (void) sprintf (errstr, "Nameserver error for %s: %s", key, + prcode (hp -> rcode)); + return(RP_NO); /* even if not authoritative */ + + case SERVFAIL: + return(RP_TIME); + + default: + break; + } + (void) sprintf (errstr, "Nameserver error for %s: %s", + key, prcode(hp->rcode)); + return(RP_NO); +} + +/* + * skip header of query and return pointer to first answer RR. + */ + +static +char *ns_skiphdr(answer, hp, eom) +char *answer; +HEADER *hp; +register char *eom; +{ + register int qdcount; + register char *cp; + register int n; + char tmp[MAXDNAME]; + + qdcount = ntohs(hp->qdcount); + + cp = answer + sizeof(HEADER); + + while ((qdcount-- > 0) && (cp < eom)) + { + n = dn_expand(answer,eom,cp,tmp,sizeof(tmp)); + if (n < 0) + return(0); + cp += (n + QFIXEDSZ); + } + + return((cp < eom)? cp : 0); +} + +/* + * routine to set the resolver timeouts + * takes maximum number of seconds you are willing to wait + */ + +ns_settimeo(ns_time) +int ns_time; +{ + static int called = 0; + static struct state oldres; + + if ((_res.options & RES_INIT) == 0) + res_init (); + + /* always start afresh */ + if (called) + { + bcopy((char *)&oldres,(char *)&_res,sizeof(oldres)); + } + else + { + called = 1; + bcopy((char *)&_res,(char *)&oldres,sizeof(oldres)); + } + + /* + * bind uses an exponential backoff + */ + + _res.retrans = ns_time >> _res.retry; + + PP_TRACE (("ns_timeo: servers(%d), retrans(%d), retry(%d)", + _res.nscount, _res.retrans, _res.retry)); +} +#endif diff --git a/Chans/smtp/sm_wtmail.c b/Chans/smtp/sm_wtmail.c new file mode 100644 index 0000000..eb104d0 --- /dev/null +++ b/Chans/smtp/sm_wtmail.c @@ -0,0 +1,603 @@ +/* sm_wtmail: mail-commands for smtp mail */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/smtp/RCS/sm_wtmail.c,v 6.0 1991/12/18 20:12:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/sm_wtmail.c,v 6.0 1991/12/18 20:12:19 jpo Rel $ + * + * $Log: sm_wtmail.c,v $ + * Revision 6.0 1991/12/18 20:12:19 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include "chan.h" +#include +#include +#include "ap.h" + +extern CHAN *chanptr; +extern char *loc_dom_mta; +extern char *strdup(); + +extern char *open_host; + +struct sm_rstruct /* save last reply obtained */ +{ /* for holding a net reply */ + int sm_rval; /* rp.h value for reply */ + int sm_rlen; /* current lengh of reply string */ + char sm_rgot; /* true, if have a reply */ + char sm_rstr[LINESIZE]; /* human-oriented reply text */ +} sm_rp; +#define smtp_error(def) (sm_rp.sm_rgot ? sm_rp.sm_rstr : (def)) + +static CHAN *sm_chptr; /* structure for channel that we are */ +FILE *sm_rfp, *sm_wfp; +static char sm_rnotext[] = "No reply text given"; +static int sm_rrec (); + +#define SM_HTIME 180 /* Time allowed for HELO command */ +#define SM_OTIME 300 /* Time allowed for a netopen */ +#define SM_ATIME 120 /* Time allowed for answer after open */ +#define SM_STIME 300 /* Time allowed for MAIL command */ +#define SM_TTIME 300 /* Time allowed for RCPT command */ +#define SM_DTIME 120 /* Time allowed for a DATA command */ +#define SM_PTIME 600 /* Time allowed for the "." command */ + +#define SM_QTIME 60 /* Time allowed for QUIT command */ + +int data_bytes = 0; + +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ +#define inet_ntoa myinet_ntoa + +static char *myinet_ntoa (in) +struct in_addr in; +{ + static char buf[80]; + + (void) sprintf (buf, "%d.%d.%d.%d", + (in.s_addr >> 24) & 0xff, + (in.s_addr >> 16) & 0xff, + (in.s_addr >> 8 ) & 0xff, + (in.s_addr ) & 0xff); + return buf; +} +#else +extern char *inet_ntoa (); +#endif + +sm_wfrom (sender) +char *sender; +{ + char linebuf[LINESIZE]; + + (void) sprintf (linebuf, "MAIL FROM:<%s>", sender); + if (rp_isbad (sm_cmd (linebuf, SM_STIME))) + return (RP_DHST); + + switch( sm_rp.sm_rval ) { + case 250: + break; /* We're off and running! */ + + case 500: + case 501: + case 552: + return RP_PARM; + + case 421: + case 450: + case 451: + case 452: + return RP_AGN; + + default: + return RP_BHST; + } + return RP_OK; +} + +sm_wto (adr) /* send one address spec to local */ +char adr[]; /* rest of address */ +{ + char linebuf[LINESIZE]; + + if( isstr(adr)) + (void) sprintf (linebuf, "RCPT TO:<%s>", adr); + else + (void) strcpy(linebuf, "RCPT TO:<>"); + + if (rp_isbad (sm_cmd (linebuf, SM_TTIME))) + return (RP_DHST); + + switch (sm_rp.sm_rval) + { + case 250: + case 251: + return RP_AOK; + + case 421: + case 450: + case 451: + case 452: + return RP_AGN; + + case 550: + case 551: + case 552: + case 553: + case 554: /* BOGUS: sendmail is out of spec! */ + return RP_USER; + + case 500: + case 501: + return RP_PARM; + + } + return RP_RPLY; + +} + +sm_wrdata () +{ + if (rp_isbad (sm_cmd ("DATA", SM_DTIME))) + return RP_DHST; + + switch (sm_rp.sm_rval) { + case 354: + return RP_OK; + + case 500: + case 501: + case 503: + case 554: + return RP_NDEL; + + case 421: + case 451: + return RP_AGN; + + } + return RP_RPLY; +} + +sm_wrdot (naddr) +int naddr; +{ + if (rp_isbad (sm_cmd (".", SM_PTIME + (3 * naddr)))) + return RP_DHST; + + switch (sm_rp.sm_rval) { + case 250: + case 251: + return RP_OK; + + case 552: + case 554: + return RP_NDEL; + + case 421: + case 451: + case 452: + return RP_AGN; + } + return RP_AGN; +} + + +sm_init (curchan) /* session initialization */ +CHAN *curchan; /* name of channel */ +{ + sm_chptr = curchan; + /* phs_note (sm_chptr, PHS_CNSTRT); */ + return (RP_OK); /* generally, a no-op */ +} + + +static + sm_irdrply () /* get net reply & stuff into sm_rp */ +{ + static char sep[] = "; "; /* for sticking multi-lines together */ + short len, + tmpreply, + retval; + char linebuf[LINESIZE]; + char tmpmore; + register char *linestrt; /* to bypass bad initial chars in buf */ + register short i; + register char more; /* are there continuation lines? */ + +newrply: + for (more = FALSE, sm_rp.sm_rgot = FALSE, sm_rp.sm_rlen = 0; + rp_isgood (retval = sm_rrec (linebuf, sizeof linebuf, &len));) + { + PP_LOG (LLOG_PDUS, ("<- %s", linebuf)); + /* 1st col in linebuf gets reply code */ + for (linestrt = linebuf; /* skip leading baddies, probably */ + len > 0 && /* from a lousy Multics */ + (!isascii ((char) *linestrt) || + !isdigit ((char) *linestrt)); + linestrt++, len--) + continue; + + tmpmore = FALSE; /* start fresh */ + tmpreply = atoi (linestrt); + if ((len -= 3) > 0) + { + linestrt += 3; + if (len > 0 && *linestrt == '-') + { + tmpmore = TRUE; + linestrt++; + if (--len > 0) + for (; len > 0 && isspace (*linestrt); linestrt++, len--) + continue; + } + } + + if (more) /* save reply value from 1st line */ + { /* we at end of continued reply? */ + if (tmpreply != sm_rp.sm_rval || tmpmore) + continue; + more = FALSE; /* end of continuation */ + } + else /* not in continuation state */ + { + sm_rp.sm_rval = tmpreply; + + more = tmpmore; /* more lines to follow? */ + + if (len <= 0) + { /* fake it, if no text given */ + bcopy (sm_rnotext, linestrt = linebuf, + (sizeof sm_rnotext) - 1); + len = (sizeof sm_rnotext) - 1; + } + } + + if ((i = MIN (len, (LINESIZE - 1) - sm_rp.sm_rlen)) > 0) + { /* if room left, save the human text */ + bcopy (linestrt, &sm_rp.sm_rstr[sm_rp.sm_rlen], i); + sm_rp.sm_rlen += i; + sm_rp.sm_rstr[sm_rp.sm_rlen] = 0; + if (more && sm_rp.sm_rlen < (LINESIZE - 4)) + { /* put a separator between lines */ + bcopy (sep, &(sm_rp.sm_rstr[sm_rp.sm_rlen]), (sizeof sep)); + sm_rp.sm_rlen += (sizeof sep) - 1; + } + } + + if (!more) + { + if (sm_rp.sm_rval < 100) + goto newrply; /* skip info messages */ + + sm_rp.sm_rgot = TRUE; + return (RP_OK); + } + } + return (retval); /* error return */ +} + + +static sm_rrec (linebuf, blen, len) /* read a reply record from net */ +char *linebuf; /* where to stuff text */ +int blen; +short *len; /* where to stuff length */ +{ + extern int errno; + int c, n; + char *cp; + + *len = 0; /* for clean logging if nothing read */ + linebuf[0] = '\0'; + + for (n = blen, cp = linebuf; n > 0;) { + if ((c = getc (sm_rfp)) == EOF || c == '\n') + break; + *cp ++ = c; + n --; + } + *cp = '\0'; + *len = blen - n; + + if (ferror (sm_rfp) || feof (sm_rfp)) + { /* error or unexpected eof */ + PP_LOG (LLOG_EXCEPTIONS, + ("netread: ret=%d, fd=%d", *len, fileno (sm_rfp))); + sm_nclose (NOTOK); /* since it won't work anymore */ + return (RP_BHST); + } + if (n <= 0) + { + PP_LOG (LLOG_EXCEPTIONS, ("net input overflow")); + while (getc (sm_rfp) != '\n' + && !ferror (sm_rfp) && !feof (sm_rfp)) + continue; + } + else + if (linebuf[*len - 1] == '\r') + *len -= 1; /* get rid of crlf or just lf */ + + return (RP_OK); +} + +sm_cmd (cmd, time) /* Send a command */ +char *cmd; +int time; /* Max time for sending and getting reply */ +{ + short retval; + + PP_LOG (LLOG_PDUS, ("-> %s", cmd)); + + if (sm_wfp == NULL) + return sm_rp.sm_rval = RP_DHST; + if (timeout((unsigned)time)) { + PP_TRACE (("sm_cmd(): host died?")); + sm_nclose (NOTOK); + return (sm_rp.sm_rval = RP_DHST); + } + fprintf (sm_wfp, "%s\r\n", cmd); + if (!ferror (sm_wfp)) + (void) fflush (sm_wfp); + + if (ferror (sm_wfp)) + { + PP_TRACE (("sm_cmd(): host died?")); + sm_nclose (NOTOK); + return (sm_rp.sm_rval = RP_DHST); + } + + if (rp_isbad (retval = sm_irdrply ())) + return( sm_rp.sm_rval = retval ); + + timeout (0); + return RP_OK; +} + +sm_wstm (buf, len) /* write some message text out */ +char *buf; /* what to write */ +register int len; /* how long it is */ +{ + static char lastchar = 0; + short retval; + register char *bufptr; + register char newline; + + if (buf == 0 && len == 0) { /* end of text */ + if (lastchar != '\n') { /* make sure it ends cleanly */ + fputs ("\r\n", sm_wfp); + data_bytes += 2; + } + if (ferror (sm_wfp)) + return (RP_DHST); + lastchar = 0; /* reset for next message */ + retval = RP_OK; + } + else + { + newline = (lastchar == '\n') ? TRUE : FALSE; + for (bufptr = buf; len--; bufptr++) + { + switch (*bufptr) /* cycle through the buffer */ + { + case '\n': /* Telnet requires crlf */ + newline = TRUE; + putc ('\r', sm_wfp); + data_bytes ++; + break; + + case '.': /* Insert extra period at beginning */ + if (newline) { + putc ('.', sm_wfp); + data_bytes ++; + } + /* DROP ON THROUGH */ + default: + newline = FALSE; + } + if (ferror (sm_wfp)) + break; + /* finally send the data character */ + putc ((lastchar = *bufptr), sm_wfp); + data_bytes ++; + if (ferror (sm_wfp)) + break; + } + retval = ferror(sm_wfp) ? RP_DHST : RP_OK; + } + + return (retval); +} + +static int start_conn (sp, name, errstr) +struct sockaddr_in *sp; +char *name; +char *errstr; +{ + int s; + + s = socket (AF_INET, SOCK_STREAM, 0); + if( s < 0 ) { + (void) strcpy (errstr, "Can't get socket"); + PP_SLOG (LLOG_EXCEPTIONS, "socket", + ("%s", errstr)); + return NOTOK; + } + + if (timeout(SM_OTIME)) { + (void) sprintf (errstr, "[%s] open timeout", name, + inet_ntoa (sp -> sin_addr)); + PP_LOG (LLOG_EXCEPTIONS, + ("%s", errstr)); + return NOTOK; + } + + if( connect (s, (struct sockaddr *)sp, sizeof *sp) < 0 ) { + (void) close (s); + (void) sprintf (errstr, "Connection failed to %s [%s]", + name, inet_ntoa (sp -> sin_addr)); + PP_SLOG (LLOG_EXCEPTIONS, "connect", + ("%s", errstr)); + timeout (0); + return NOTOK; + } + timeout (0); + return s; +} + +sm_nopen(hostnam, errstr) +char *hostnam; +char *errstr; +{ + int fds[2], skt; + short retval; + char linebuf[LINESIZE]; + static char *us, *official(); + extern int smtpport; + struct hostent *hp, *gethostbyname (); + struct sockaddr_in s_in; + char **aptr; + + PP_TRACE (("[ %s ]", hostnam)); + + *errstr = 0; + + if ( ! us ) { + us = official (loc_dom_mta); + if(us == NULLCP) { + PP_OPER (NULLCP, + ("Cannot find my own 'official' name '%s'\n", + loc_dom_mta)); + (void) sprintf (errstr, "Who am I %s ?", loc_dom_mta); + return RP_BHST; + } + } +#ifdef NAMESERVER + if (rp_isbad (retval = ns_gethost (hostnam, &hp, errstr))) + return (retval); +#else NAMESERVER + if ((hp = gethostbyname (hostnam)) == NULL) { + (void) sprintf (errstr, "Host lookup of %s failed", hostnam); + return RP_BHST; + } +#endif NAMESERVER + + if (smtpport == 0) { + struct servent *sp; + + if ((sp = getservbyname ("smtp", "tcp")) == NULL) { + (void) sprintf (errstr, "Can't determine smtp port"); + return RP_AGN; + } + smtpport = (short)sp->s_port; + } + bzero ((char *)&s_in, sizeof s_in); + s_in.sin_family = AF_INET; + s_in.sin_port = smtpport; + + + /* SEK - try all addresses */ + for (aptr = hp -> h_addr_list; *aptr; aptr++) + { + bcopy (*aptr, (char *)&s_in.sin_addr, hp -> h_length); + PP_NOTICE (("Attempting open to [%s]", + inet_ntoa (s_in.sin_addr))); + + if ((skt = start_conn (&s_in, hp -> h_name, errstr)) == NOTOK) + continue; + + fds[0] = skt; + fds[1] = dup (skt); + + if ((sm_rfp = fdopen (fds[0], "r")) == NULL || + (sm_wfp = fdopen (fds[1], "w")) == NULL) { + return (RP_LIO); + } + + if (timeout(SM_ATIME)) { + (void) sprintf (errstr, "Timeout opening %s", hostnam); + sm_nclose (NOTOK); + return( RP_BHST ); + } + if (rp_isbad (retval = sm_irdrply ())) { + (void) sprintf (errstr, "Bad response from %s: %s", + hostnam, smtp_error ("bad reply")); + timeout (0); + sm_nclose (NOTOK); + return(retval); + } + timeout (0); + + if( sm_rp.sm_rval != 220 ) { + sm_nclose (NOTOK); + return( RP_BHST ); + } + + /* HELO is part of protocol - all commands are 4 letters long */ + (void) sprintf (linebuf, "HELO %s", us); + if (rp_isbad (sm_cmd( linebuf, SM_HTIME)) + || sm_rp.sm_rval != 250 ) { + (void) sprintf (errstr, "Bad response to helo: %s", + smtp_error("bad helo")); + sm_nclose (NOTOK); + return (RP_RPLY); + } + PP_NOTICE (("Connected to %s [%s]", hostnam, + inet_ntoa (s_in.sin_addr))); + return (RP_OK); + } + return (RP_BHST); /* No addresses OK */ + +} + +sm_nclose (type) /* end current connection */ +short type; /* clean or dirty ending */ +{ + if (type == OK && sm_wfp) + sm_cmd ("QUIT", SM_QTIME); + + if (sm_rfp == NULL && sm_wfp == NULL) + return; + PP_NOTICE (("Closing connection to %s", open_host)); + if (open_host) + free(open_host); + open_host = NULLCP; + + if (timeout(15)) { + return; + } + if (sm_rfp != NULL) + (void) fclose (sm_rfp); + if (sm_wfp != NULL) + (void) fclose (sm_wfp); + timeout (0); + sm_rfp = sm_wfp = NULL; +} + +static char *official (name) +char *name; +{ + struct hostent *hp; +#ifdef NAMESERVER + int i; + + for(i = 0 ; i < 10 ; i++){ + hp = gethostbyname(name); + if(hp != NULL) + break; + PP_TRACE (("Timeout looking up %s", name)); + if(i > 2) + sleep((unsigned) i*2); + } +#else + hp = gethostbyname(name); +#endif + return hp == NULL ? NULLCP : strdup (hp -> h_name); +} diff --git a/Chans/smtp/smtp.c b/Chans/smtp/smtp.c new file mode 100644 index 0000000..f3e5379 --- /dev/null +++ b/Chans/smtp/smtp.c @@ -0,0 +1,622 @@ +/* smtp: as invoked by qmgr to deliver smtp stuff*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtp.c,v 6.0 1991/12/18 20:12:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtp.c,v 6.0 1991/12/18 20:12:19 jpo Rel $ + * + * $Log: smtp.c,v $ + * Revision 6.0 1991/12/18 20:12:19 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "chan.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include +#include "sys.file.h" +#include +#include +#ifdef SYS5 +#include +#endif + +extern char *quedfldir; +extern void rd_end(), chan_init(), err_abrt(), timer_start(), timer_end(); +FILE *msg_fp; +CHAN *mychan; +char *this_msg; +int smtpport = 0; + +extern struct sm_rstruct { /* save last reply obtained */ + int sm_rval; /* rp.h value for reply */ + int sm_rlen; /* current lengh of reply string */ + char sm_rgot; /* true, if have a reply */ + char sm_rstr[LINESIZE]; /* human-oriented reply text */ +} sm_rp; +#define smtp_error(def) (sm_rp.sm_rgot ? sm_rp.sm_rstr : (def)) + +extern int data_bytes; +extern time_t time(); + + +#define SM_RTIME 15 /* Time allowed for a RSET command */ +#define SM_TTIME 180 /* Time allowed for a block of text */ + + +static struct type_Qmgr_DeliveryStatus *process(); +static void dirinit(); +static int chaninit(); +static int endproc (); +static int dotext (); +static int copy (); + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + char *p; + int opt; + extern char *optarg; + + if ((p = rindex (argv[0], '/')) != NULLCP) + p ++; + if (p == NULLCP || *p == NULL) + p = argv[0]; + + chan_init (p); /* init the channel - and find out who we are */ + + while ((opt = getopt (argc, argv, "p:")) != EOF) { + switch (opt) { + case 'p': + smtpport = htons (atoi (optarg)); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Bad argument -%c", opt)); + break; + } + } + + + dirinit(); /* get to the right directory */ + (void) signal (SIGPIPE, SIG_IGN); +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, chaninit, process, endproc); + else +#endif + channel_control (argc, argv, chaninit, process, endproc); + exit (0); +} + + + +static int chaninit (arg) +struct type_Qmgr_Channel *arg; +{ + char *p = qb2str (arg); + + if ((mychan = ch_nm2struct (p)) == (CHAN *)0) + err_abrt (RP_PARM, "Channel '%s' not known", p); + + rename_log(p); + sm_init (mychan); + PP_NOTICE (("starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); + free (p); + return OK; +} + +char *cur_host; +char *open_host; +int open_state; /* defines meaning of open_host */ +#define STATE_INITIAL 0 +#define STATE_OPEN 1 +#define STATE_BAD_HOST 2 +#define STATE_TIMED_OUT 3 +char *sender; +char *formatdir; + +static int endproc () +{ + if (cur_host) + sm_nclose (OK); +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + struct type_Qmgr_UserList *up; + Q_struct Qstruct, *qp = &Qstruct; + int retval; + ADDR *ap, + *ad_sendr = NULLADDR, + *ad_recip = NULLADDR, + *alp = NULLADDR, + *ad_list = NULLADDR; + int ad_count; + + if (this_msg) free (this_msg); + + this_msg = qb2str (arg -> qid); + + bzero ((char *)&prm, sizeof prm); + bzero ((char *)qp, sizeof *qp); + + (void) delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg err: %s", this_msg)); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + sender = ad_sendr -> ad_r822adr; + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + for (up = arg ->users; up; up = up -> next) { + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + switch (chan_acheck (ap, mychan, + ad_list == NULLADDR, &cur_host)) { + default: + case NOTOK: + continue; + + case OK: + break; + } + break; + } + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = alp = (ADDR *) calloc (1, sizeof *alp); + else { + alp -> ad_next = (ADDR *) calloc (1, sizeof *alp); + alp = alp -> ad_next; + } + *alp = *ap; + alp -> ad_next = NULLADDR; + } + + if (ad_list == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list")); + rd_end (); + q_free (qp); + return deliverystate; + } + + PP_NOTICE (("processing msg %s to %s", this_msg, cur_host)); + + deliver (ad_list, qp); + + q_free (qp); + rd_end(); + + return deliverystate; +} + +static void dirinit() /* Change into pp queue space */ +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change directory to '%s'", + quedfldir); +} + +deliver (ad_list, qp) +ADDR *ad_list; +Q_struct *qp; +{ + ADDR *ap; + int naddrs; + char buf [LINESIZE]; + + PP_TRACE (("deliver ()")); + + + if (lexequ (cur_host, open_host) != 0) { + /* Brand new host */ + + if (open_host != NULLCP) { + free (open_host); + if (open_state == STATE_OPEN) + sm_nclose (OK); + } + open_host = strdup (cur_host); + + switch (sm_nopen (cur_host, buf)) + { + case RP_OK: + open_state = STATE_OPEN; + break; + case RP_NO: + open_state = STATE_BAD_HOST; + break; + default: + open_state = STATE_TIMED_OUT; + break; + } + } + + switch (open_state) + { + case STATE_OPEN: + break; /* just carry on */ + case STATE_BAD_HOST: + PP_NOTICE ((buf)); + set_all_dr (qp, ad_list, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + buf); + if (rp_isgood(wr_q2dr (qp, this_msg))) + (void) delivery_setall (int_Qmgr_status_negativeDR); + return; + case STATE_TIMED_OUT: + PP_NOTICE (("Connection failed to '%s': %s", + cur_host, buf)); + (void) delivery_setallstate + (int_Qmgr_status_mtaFailure, + buf); + return; + } + + naddrs = 0; + + if (do_sender (sender) == NOTOK) { + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs(int_Qmgr_status_messageFailure); + return; + } + + for (ap = ad_list; ap; ap = ap -> ad_next) { + switch (do_recip (ap, qp) ){ + case OK: + naddrs ++; + break; + + case NOTOK: + break; + + default: + return; + } + } + + if (naddrs == 0) { + (void) reset (); + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + PP_NOTICE ((">>> Message %s transfered to no recipients", + this_msg, naddrs)); + return; + } + + if (dotext (qp, ad_list, naddrs) == NOTOK) { + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs(int_Qmgr_status_messageFailure); + return; + } + + for (ap = ad_list; ap; ap = ap -> ad_next) { + if (ap -> ad_resp) { + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (qp, ap -> ad_no, this_msg, + DRR_NO_REASON, -1, NULLCP); + delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + } + else { + (void) wr_ad_status (ap, AD_STAT_DONE); + (void) wr_stat (ap, qp, this_msg, data_bytes); + delivery_set (ap -> ad_no, + int_Qmgr_status_success); + } + } + } + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs(int_Qmgr_status_messageFailure); + PP_NOTICE ((">>> Message %s transfered to %d recipients", + this_msg, naddrs)); +} + +do_recip (ap, qp) +ADDR *ap; +Q_struct *qp; +{ + int retval; + char errbuf[BUFSIZ]; + + PP_NOTICE (("Recipient %s", ap -> ad_r822adr)); + + if (rp_isbad (retval = sm_wto (ap ->ad_r822adr))) { + switch (retval) { + case RP_DHST: + PP_LOG (LLOG_EXCEPTIONS, ("Host died")); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + "Host died"); + return DONE; + + case RP_AOK: + ap -> ad_resp = 1; + return OK; + + case RP_AGN: + (void) delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + smtp_error ("temporary failure")); + PP_LOG (LLOG_EXCEPTIONS, ("Temporary failure: %s", + smtp_error ("cause not known"))); + ap -> ad_resp = 0; + return NOTOK; + + case RP_USER: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + (void) sprintf (errbuf, + "MTA '%s' gives error message %s", + cur_host, smtp_error ("problem with user")); + PP_LOG (LLOG_EXCEPTIONS, ("User error: %s", errbuf)); + set_1dr (qp, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + errbuf); + ap -> ad_resp = 0; + return NOTOK; + + case RP_PARM: + ap -> ad_resp = 0; + PP_LOG (LLOG_EXCEPTIONS, ("Parameter problem: %s", + smtp_error("bad paramter"))); + (void) delivery_setstate (ap -> ad_no, + int_Qmgr_status_messageFailure, + smtp_error ("bad parameter")); + return NOTOK; + + case RP_RPLY: + default: + PP_LOG (LLOG_EXCEPTIONS, ("Message failure: %s", + smtp_error ("bad reply"))); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + smtp_error ("bad reply")); + (void) reset (); + return DONE; + } + } + return OK; +} + +do_sender (sndr) +char *sndr; +{ + int retval; + + PP_NOTICE (("sender %s", sndr)); + + if (rp_isbad (retval = sm_wfrom (sndr))) { + switch (retval) { + case RP_DHST: + PP_LOG (LLOG_EXCEPTIONS, ("Host connection died")); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + "host connection failed"); + sm_nclose (NOTOK); + return NOTOK; + + case RP_PARM: + PP_LOG (LLOG_EXCEPTIONS, ("Parameter problem: %s", + smtp_error("bad param"))); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + smtp_error ("bad param")); + sm_nclose (NOTOK); + return NOTOK; + + case RP_AGN: + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + smtp_error ("temp error")); + PP_LOG (LLOG_EXCEPTIONS, ("Temporary error: %s", + smtp_error ("temp error"))); + (void) reset (); + return NOTOK; + + case RP_OK: + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Protocol error: %s", + smtp_error(""))); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + smtp_error ("protocol problem")); + sm_nclose (NOTOK); + return NOTOK; + } + } + return OK; +} + + +static int dotext (qp, ap, naddrs) +Q_struct *qp; +ADDR *ap; +int naddrs; +{ + extern FILE *sm_wfp; + int retval; + char filename[MAXPATHLENGTH]; + struct timeval data_time; + int first = 1; + char errbuf[BUFSIZ]; + + if (qid2dir (this_msg, ap, TRUE, &formatdir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message %s", + this_msg)); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Cant find message"); + (void) reset (); + return NOTOK; + } + + + if (rp_isbad (retval = msg_rinit (formatdir))) { + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + reset (); + return NOTOK; + } + + if (rp_isbad (retval = sm_wrdata ())) { + switch (retval) { + case RP_DHST: + PP_LOG (LLOG_EXCEPTIONS, ("Host connection died")); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + "Connection died"); + + break; + + case RP_NDEL: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_negativeDR); + (void) sprintf (errbuf, + "DATA transfer to host failed permanently: %s", + smtp_error ("reason unknown")); + PP_LOG (LLOG_EXCEPTIONS, ("DATA error: %s", errbuf)); + set_1dr (qp, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + errbuf); + break; + + default: + + + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + smtp_error ("dead host?")); + + break; + } + sm_nclose (NOTOK); + return NOTOK; + } + + data_bytes = 0; + timer_start (&data_time); + + while ((retval = msg_rfile (filename)) == RP_OK) { + if (rp_isbad (copy (filename))) { + (void) delivery_setallstate(int_Qmgr_status_mtaAndMessageFailure, + "Can't transfer data"); + sm_nclose (NOTOK); + return NOTOK; + } + if (first) { + sm_wstm ("\n", 1); + first = 0; + } + } + if (rp_isbad (retval)) { + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Message transfer failed"); + sm_nclose (NOTOK); + return NOTOK; + } + + if (rp_isbad (sm_wstm (NULLCP, 0))) { + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + "Bad temination of data"); + sm_nclose (NOTOK); + return NOTOK; + } + + if (rp_isbad (retval = sm_wrdot (naddrs))) { + switch (retval) { + case RP_DHST: + PP_LOG (LLOG_EXCEPTIONS, ("Host connection died")); + (void) delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + "Connection died"); + + break; + + case RP_NDEL: + (void) delivery_setall (int_Qmgr_status_negativeDR); + (void) sprintf (errbuf, + "DATA transfer to host failed permanently"); + PP_LOG (LLOG_EXCEPTIONS, ("DATA error: %s", errbuf)); + set_1dr (qp, ap -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + errbuf); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Temporary failure: %s", + smtp_error ("bad data"))); + (void) delivery_setallstate (int_Qmgr_status_messageFailure, + smtp_error ("bad data")); + break; + } + return NOTOK; + } + timer_end (&data_time, data_bytes, "Data Transfered"); + msg_rend(); + + return OK; +} + +static int copy (fname) +char *fname; +{ + FILE *ifp; + char buf[BUFSIZ]; + int n, retval = RP_OK; + + if ((ifp = fopen (fname,"r")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't read file '%s'", fname)); + return RP_FOPN; + } + + while ((n = fread (buf, sizeof (char), sizeof (buf), ifp)) > 0) + if (rp_isbad (retval = sm_wstm (buf, n))) + break; + (void) fclose (ifp); + return retval; +} + +reset () +{ + int retval; + + if (rp_isbad (retval = sm_cmd ("RSET", SM_RTIME))) { + switch (retval) { + default: + (void) delivery_setallstate (int_Qmgr_status_mtaFailure, + smtp_error ("reset failed")); + sm_nclose (NOTOK); + return NOTOK; + + case RP_OK: + break; + } + } + return OK; +} diff --git a/Chans/smtp/smtp.start b/Chans/smtp/smtp.start new file mode 100755 index 0000000..9f4f4eb --- /dev/null +++ b/Chans/smtp/smtp.start @@ -0,0 +1,2 @@ +#! /bin/sh +xsmtpd `pwd`/xsmtpsrvr smtp diff --git a/Chans/smtp/smtpd.c b/Chans/smtp/smtpd.c new file mode 100644 index 0000000..a69b2b7 --- /dev/null +++ b/Chans/smtp/smtpd.c @@ -0,0 +1,380 @@ +/* smtpd: daemon for smtp */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtpd.c,v 6.0 1991/12/18 20:12:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtpd.c,v 6.0 1991/12/18 20:12:19 jpo Rel $ + * + * $Log: smtpd.c,v $ + * Revision 6.0 1991/12/18 20:12:19 jpo + * Release 6.0 + * + */ + + + +/* + * new version - detects if it is running under inetd. + */ + + +#include "util.h" +#include +#include "sys.file.h" +#ifdef SYS5 +#ifdef vfork +#undef vfork +#endif +#include +#endif +#include +#include +#include +#include +#include +#ifdef SYS5 +#include +#endif + +static char usage[] = "usage: smptd [-p port] [-i maxconn] \ +program channel"; + +static int smtpport; +static int maxconn = 5; +static struct sockaddr_in rmtaddr, laddr; +static int numconnections = 0; +static char thishost[LINESIZE]; +static char *Channel, Smtpserver[BUFSIZ]; +static char *nstimeout; + +static void envinit (); +static SFD reaper (); + +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ +#define inet_ntoa myinet_ntoa + +static char *myinet_ntoa (in) +struct in_addr in; +{ + static char buf[80]; + + (void) sprintf (buf, "%d.%d.%d.%d", + (in.s_addr >> 24) & 0xff, + (in.s_addr >> 16) & 0xff, + (in.s_addr >> 8 ) & 0xff, + (in.s_addr ) & 0xff); + return buf; +} +#else +extern char *inet_ntoa (); +#endif + +extern int errno; + +char *myname; +int debug; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + struct servent *sp; + int alen, i, skt; + + myname = argv[0]; + sys_init (myname); + + if ((sp = getservbyname ("smtp", "tcp")) == NULL) + smtpport = htons (25); + else smtpport = sp -> s_port; + + while((opt = getopt(argc, argv, "p:i:t:")) != EOF) + switch (opt) { + case 'i': + maxconn = atoi (optarg); + break; + case 'p': + smtpport = htons ((short)atoi (optarg)); + break; + case 't': + nstimeout = optarg; + break; + default: + fprintf (stderr, "bad switch -%c: %s\n", opt, usage); + PP_OPER (NULLCP, ("Bad argument -%c: %s", opt, usage)); + exit (1); + } + argc -= optind; + argv += optind; + + initialise (argc, argv); + + alen = sizeof rmtaddr; + if (getpeername (0, (struct sockaddr *)&rmtaddr, + &alen) == 0) { /* under inetd */ + PP_TRACE (("Running under inetd...")); + doit (0); + _exit (0); + } + + envinit (); + + laddr.sin_family = AF_INET; + laddr.sin_addr.s_addr = INADDR_ANY; + laddr.sin_port = smtpport; + + for (i = 0; i < 10; sleep ((unsigned) 2 * ++i)) { + if ((skt = socket (AF_INET, SOCK_STREAM, 0)) == -1) { + PP_SLOG (LLOG_EXCEPTIONS, "socket", + ("can't create ")); + continue; + } + + if (bind (skt, (struct sockaddr *)&laddr, + sizeof laddr) == -1) { + PP_SLOG (LLOG_EXCEPTIONS, "bind", + ("socket can't ")); + (void) close (skt); + continue; + } + + if (listen (skt, 5) == -1) { + PP_SLOG (LLOG_EXCEPTIONS, "listen", + ("socket can't ")); + (void) close (skt); + continue; + } + break; + } + + PP_NOTICE (("%s listening on port %d", myname, ntohs(smtpport))); +#define tcp_still_alive_and_kicking 1 + + while (tcp_still_alive_and_kicking) { + int snew; + int pid; + + alen = sizeof (rmtaddr); + if ((snew = accept (skt, (struct sockaddr *)&rmtaddr, + &alen)) == NOTOK) { + if (errno != EINTR) + PP_SLOG (LLOG_EXCEPTIONS, "failed", + ("accept ")); + continue; + } + PP_TRACE (("Accepted new connection from %s", + inet_ntoa (rmtaddr.sin_addr))); + if ((pid = tryfork ()) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "failed", ("fork ")); + sleep (10); + continue; + } + if (pid == 0) { /* child */ + doit (snew); + _exit(0); + } + (void) close (snew); + + numconnections ++; + + while (numconnections >= maxconn) { + PP_TRACE (("Too many connections -- waiting")); +#ifdef SYS5 + reaper(0); +#else + sigpause (0); +#endif + PP_TRACE (("Finished waiting")); + } + } +} + +/* ARGSUSED */ +static SFD reaper (sig) +int sig; +{ +#ifndef WNOHANG + int status; + alarm(2); + while (wait(&status) != -1) + numconnections --; + alarm (0); +#else +#ifdef SYS5 + int status; +#else + union wait status; +#endif + while (wait3 (&status, WNOHANG, (caddr_t)0) > 0) + numconnections --; +#endif +} + +#ifdef SYS5 +SFD alarmtrap (sig) +int sig; +{ + (void) signal (SIGALRM, alarmtrap); +} +#endif + +doit (fd) +int fd; +{ + char *argv[10]; + int argc = 0; + + if (fd != 0) + (void) dup2 (fd, 0); + if (fd != 1) + (void) dup2 (fd, 1 ); + if (fd != 2) + (void) dup2 (fd, 2 ); + if (fd > 2 ) + (void) close (fd); + argv[argc++] = Channel; /* argv[0] */ + if (nstimeout) { + argv[argc++] = "-t"; + argv[argc++] = nstimeout; + } + argv[argc++] = Channel; + argv[argc] = NULLCP; + execv (Smtpserver, argv); + PP_OPER (Smtpserver, ("server exec ")); + _exit (99); +} + +static void envinit () +{ + int i, + nbits, + sd; + + nbits = getdtablesize (); + + if (!(debug = isatty (2))) { + for (i = 0; i < 5; i++) { + switch (fork ()) { + case NOTOK: + sleep (5); + continue; + + case OK: + break; + + default: + _exit (0); + } + break; + } + + if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) { + PP_OPER ("/dev/null", ("unable to read")); + exit (3); + } + if (sd != 0) + (void) dup2 (sd, 0), (void) close (sd); + (void) dup2 (0, 1); + (void) dup2 (0, 2); + +#ifdef TIOCNOTTY + if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) { + (void) ioctl (sd, TIOCNOTTY, NULLCP); + (void) close (sd); + } +#else +#ifdef SYS5 + (void) setpgrp (); + (void) signal (SIGINT, SIG_IGN); + (void) signal (SIGQUIT, SIG_IGN); +#endif +#endif + } + else + ll_dbinit (pp_log_norm, myname); + +#ifdef notdef /* damn YP... */ + for (sd = 3; sd < nbits; sd++) + (void) close (sd); +#endif + + (void) signal (SIGPIPE, SIG_IGN); + + ll_hdinit (pp_log_norm, myname); +#ifndef SYS5 + (void) signal (SIGCHLD, reaper); +#endif + + PP_TRACE (("starting")); +} + +initialise (argc, argv) +int argc; +char **argv; +{ + int i; + struct hostent *hp; + extern char *chndfldir; + + if (argc > 0) + { + getfpath (chndfldir, argv[0], Smtpserver); + + if (access (Smtpserver, X_OK) < 0 ) { /* execute privs? */ + PP_OPER (Smtpserver, ("Cannot access server program")); + fprintf (stderr, "Cannot access server program %s\n", + Smtpserver); + exit (99); + } + PP_TRACE (("server is '%s'", Smtpserver )); + } else { + fprintf (stderr, "Smtpserver program not specified! (%s)\n", + usage); + PP_OPER (NULLCP, ("Smtpserver program not specified! (%s)", + usage)); + exit (99); + } + + if( argc > 1 ) { + Channel = argv[1]; + PP_TRACE (("channel is '%s'", Channel)); + } else { + PP_OPER (NULLCP, ("Channel not specified! (%s)", usage)); + fprintf (stderr, "Channel not specified! (%s)\n", usage); + exit (99); + } + + /* + * must get full name for this host from nameserver (or file) + */ + + if (gethostname (thishost, sizeof thishost) == -1) + PP_SLOG (LLOG_EXCEPTIONS, "gethostname", + ("Can't find out who I am")); + + for(i = 0 ; i < 10 ; i++){ + hp = gethostbyname(thishost); + if(hp != NULL) + break; + if(i > 2) + sleep((unsigned)i*2); + } + if(hp == NULL) { + PP_OPER (NULLCP, + ("Cannot find 'official' name of host '%s'\n", + thishost)); + fprintf(stderr, + "Cannot find 'official' name of host '%s'\n", + thishost); + exit(-1); + } + (void) strcpy(thishost, hp->h_name); +#ifdef SYS5 + (void) signal (SIGALRM, alarmtrap); +#endif +} diff --git a/Chans/smtp/smtpsrvr.c b/Chans/smtp/smtpsrvr.c new file mode 100644 index 0000000..28c65e2 --- /dev/null +++ b/Chans/smtp/smtpsrvr.c @@ -0,0 +1,1121 @@ +/* smtpsrvr.c: server for smtp requests */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtpsrvr.c,v 6.0 1991/12/18 20:12:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/smtp/RCS/smtpsrvr.c,v 6.0 1991/12/18 20:12:19 jpo Rel $ + * + * $Log: smtpsrvr.c,v $ + * Revision 6.0 1991/12/18 20:12:19 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "dl.h" +#include +#include +#include +#include +#include + + + +/* -- external variables -- */ + +extern char *hdr_822_bp, *ia5_bp; +extern char *ctime(), + *quedfldir, + *postmaster, + *pptailor, + *getpostmaster(); +extern time_t time(); +extern ADDR *adr_new (); + +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ +#define inet_ntoa myinet_ntoa + +static char *myinet_ntoa (in) +struct in_addr in; +{ + static char buf[80]; + + (void) sprintf (buf, "%d.%d.%d.%d", + (in.s_addr >> 24) & 0xff, + (in.s_addr >> 16) & 0xff, + (in.s_addr >> 8 ) & 0xff, + (in.s_addr ) & 0xff); + return buf; +} +#else +extern char *inet_ntoa (); +#endif + + + +/* -- internal definitions -- */ + +#define BUFL 8096 /* -- length of buf -- */ +#define CNULL '\0' /* -- null -- */ +#define CR '\r' /* -- carriage return -- */ +#define LF '\n' /* -- line feed -- */ +#define NTIMEOUT 300 /* -- 5 minute timeout on net I/O -- */ + + + +/* -- internal variables -- */ + +static char + buf [BUFL], /* -- for general usage -- */ + *getline(), + netbuf [BUFL], /* -- contains the valid characters -- */ + *adrfix(), + *arg, /* -- 0 if no arg - pts to comm param -- */ + *channel = "smtp", + *netptr = netbuf, /* -- next char to come out of netbuf -- */ + *progname, + *sender = NULLCP, + *them, + *realthem, + *us; + +static int + hellod = 0, + nstimeout = 30, + dont_mung = 0, /* -- used by getline() to limit munging -- */ + net_count = 0, /* -- no of valid characters in netbuf -- */ + no_recip = 0; /* -- no of valid recipients accepted -- */ + +CHAN *chanptr, + *ch_nm2struct(); + +extern CMD_TABLE qtbl_con_type[]; + +static void byebye (), pprestart (), ppbegin (), ppstart (), + netreply (), rset (); + +static void initialise (), dispatch (); +static char *official (); + + + +/* -------------------------------------------------------------- + . . + . C o m m a n d D i s p a t c h T a b l e . + . . + * ------------------------------------------------------------ */ + +static void data (), helo (), help (), mail (), confirm (), + quit (), rcpt (), vrfy (), expn (); + +static struct comarr /* -- the command table -- */ +{ + char *cmdname; /* -- ascii name -- */ + void (*cmdfunc)(); /* -- cmd func to call -- */ +} commands [] = { + "data", data, + "helo", helo, + "help", help, + "mail", mail, + "noop", confirm, + "quit", quit, + "rcpt", rcpt, + "rset", rset, + "vrfy", vrfy, + "expn", expn, + NULLCP, NULL +}; + +static char usage[] = "Usage: smtp [-t timeout] [-T tailor] channel"; + +main (argc, argv) +int argc; +char **argv; +{ + char replybuf [BUFSIZ]; + char *cp; + int isnumeric; + int opt; + extern char *optarg; + extern int optind; + + progname = argv [0]; + + (void) signal (SIGQUIT,SIG_IGN); + (void) signal (SIGTERM,quit); + + while ((opt = getopt (argc, argv, "t:T:")) != EOF) { + switch (opt) { + case 't': + nstimeout = atoi (optarg); + break; + + case 'T': + pptailor = optarg; + break; + + default: + sys_init (progname); + fprintf (stderr, "bad switch -%c: %s\n", opt, usage); + PP_OPER (NULLCP, ("Bad argument -%c: %s", opt, usage)); + exit (1); + } + } + + argc -= optind; + argv += optind; + +#ifdef NAMESERVER + ns_settimeo (nstimeout); /* don't wait forever! */ +#endif + + if (argc != 1) { + sys_init (progname); + PP_OPER (NULLCP, ("smtpsrvr - no channel given!")); + exit (NOTOK); + } + channel = *argv; + sys_init (channel); + (void) chdir (quedfldir); + + + initialise (); /* fill in us & them */ + /* SEK - force validation of IP address */ + + for (isnumeric = TRUE, cp=them; *cp++ != '\0';) + if (!isdigit(*cp) && *cp != '.' && *cp != '\0') { + isnumeric = FALSE; + break; + } + + /* -- find out who you are I might even believe you. -- */ + + if ((chanptr = ch_mta2struct (channel, them)) == NULLCHAN) { + PP_LOG (LLOG_EXCEPTIONS, + ("unknown channel: %s", channel)); + (void) sprintf (replybuf, + "421 %s: channel '%s' is unknown to PP. (Complain to: %s)\r\n", + us, channel, postmaster); + netreply (replybuf); + exit (NOTOK); + } + + if (isnumeric && + lexequ (chanptr -> ch_in_info, "sloppy") != 0) { + PP_OPER (NULLCP, ("can't resolve '%s'", them)); + (void) sprintf (replybuf, + "421 %s: PP cannot resolve your address. '%s' (Help from: %s)\r\n", + us, them, postmaster); + netreply (replybuf); + exit (NOTOK); + } + + + channel = chanptr -> ch_name; + rename_log (channel); + + PP_NOTICE (("Connection from %s channel %s", realthem, channel)); + + ppbegin (); + + /* -- say we're listening -- */ + + (void) sprintf (replybuf, + "220 %s PP Here - Pleased to meet you (Complaints/bugs to: %s)\r\n", + us, postmaster); + netreply (replybuf); + + while (cp = getline()) { + PP_LOG (LLOG_PDUS, ("<- %s", buf)); + + dispatch (buf); + } + byebye (net_count < 0 ? 1 : 0); +} + + +/* --------------------- Static Routines ------------------------------- */ + +static void dispatch (str) +char *str; +{ + register struct comarr *comp; + + for (comp = commands;comp->cmdname != NULL; comp ++) { + if (strcmp (str, comp->cmdname) == 0) { + (*comp->cmdfunc)(); /* call comm proc */ + return; + } + } + PP_LOG (LLOG_EXCEPTIONS, ("Unknown command: %s", buf)); + netreply ("500 Unknown or unimplemented command\r\n"); +} + +static void initialise () +{ +#ifdef NAMESERVER + int i; +#endif + char workarea[BUFSIZ]; + struct sockaddr_in rmtaddr; + int len; + struct hostent *hp; + + if (gethostname (workarea, sizeof workarea) == -1) + PP_SLOG (LLOG_EXCEPTIONS, "gethostname", + ("Can't find out who I am")); + + us = official (workarea); + if(us == NULLCP) { + PP_OPER (NULLCP, + ("Cannot find 'official' name of host '%s'\n", + workarea)); + exit(-1); + } + + len = sizeof rmtaddr; + if (getpeername (0, (struct sockaddr *)&rmtaddr, &len) != 0) { + PP_SLOG (LLOG_EXCEPTIONS, "getpeername", ("Can't figure out who called us")); + exit (-1); + } +#ifdef NAMESERVER + for (i = 0 ; i < 4 ; i++) { + hp = gethostbyaddr((char *)&rmtaddr.sin_addr, + sizeof(rmtaddr.sin_addr), AF_INET); + if(hp != NULL) + break; + } +#else + hp = gethostbyaddr((char *)&rmtaddr.sin_addr, + sizeof(rmtaddr.sin_addr), AF_INET); +#endif + if (hp == NULL) { + (void) strcpy(workarea, inet_ntoa(rmtaddr.sin_addr)); + them = strdup (workarea); + + PP_LOG (LLOG_EXCEPTIONS, + ("lookup failed for address '%s'", workarea)); + } else + them = strdup (hp->h_name); + realthem = them; + (void) signal (SIGPIPE, SIG_IGN); +} + +/* +name: getline() + +function: + - get commands from the standard input terminated by . + - afix a pointer (arg) to any arguments passed. + - ignore carriage returns. + - map UPPER case to lower case. + - manage the netptr and net_count variables. + +algorithm: + while we havent received a line feed and buffer not full + + if net_count is zero or less + get more data from net + error: return 0 + check for delimiter character + null terminate first string + set arg pointer to next character + check for carriage return + ignore it + if looking at command name + convert upper case to lower case + + if command line (not mail) + null terminate last token + manage netptr + +returns: + 0 for EOF + -1 when an error occurs on network connection + ptr to last character (null) in command line + + +variables: + dont_mung + net_count + netptr + buf + + +--------------------------------------------------------------------------- */ + +static char *getline() +{ + register char *inp; /* -- input pointer in netbuf -- */ + static char *outp; /* -- output pointer in buf -- */ + register int c; /* -- temporary char -- */ + + + inp = netptr; + outp = buf; + arg = NULLCP; + + do { + if (--net_count <= 0) { + if (timeout (NTIMEOUT)) { + PP_SLOG (LLOG_EXCEPTIONS, "read", + ("%s net input", realthem)); + return (NULLCP); + } + + net_count = read (0, netbuf, sizeof netbuf); + timeout (0); + + if (net_count == 0) /* -- EOF -- */ + return NULLCP; + if (net_count < 0) { /* -- error -- */ + PP_SLOG (LLOG_EXCEPTIONS, "read", + ("%s net input", realthem)); + return NULLCP; + } + inp = netbuf; + } + + c = *inp++ & 0377; + + if (c == '\r') /* -- ignore CR -- */ + continue; /* -- try to sneak through -- */ +#ifdef TELNET_SMTP + if (c >= 0200) /* skip telnet codes */ + continue; +#endif + + + if (dont_mung == 0 && arg == NULL) { + /* -- if char is a delim afix token -- */ + + if (c == ' ' || c == ',') { + c = CNULL; /* -- make null term'ed -- */ + arg = outp + 1; /* -- set arg ptr -- */ + } + else if (isupper (c)) + /* -- do case mapping (UPPER -> lower) -- */ + c = tolower(c); + } + + *outp++ = c; + + } while (c != '\n' && outp < &buf [BUFL]); + + + if (dont_mung == 0) + *--outp = 0; /* -- null term the last token -- */ + + /* -- scan off blanks in argument -- */ + if (arg) { + while (*arg == ' ') + arg++; + if (*arg == '\0') + arg = 0; /* -- if all blanks, no argument -- */ + } + + if (dont_mung == 0) + PP_DBG (("'%s', '%s'", + buf, arg == 0 ? "" : arg)); + + /* -- reset netptr for next trip in -- */ + netptr = inp; + + /* -- return success -- */ + return (outp); +} + + + +/* +The helo command +*/ + +static void helo() +{ + char replybuf [BUFSIZ]; + char *cp; + + if (arg == NULLCP || *arg == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("No argument to HELO")); + netreply ("501 No argument to HELO\r\n"); + return; + } + (void) compress (arg, arg); + for (cp = arg; *cp; cp++) { + switch (*cp) { + case '\\': + cp++; + break; + case '[': + while (*cp && *cp != ']') + cp ++; + break; + + default: + if (isascii(*cp) && (!iscntrl(*cp) && !isspace (*cp))) + break; + /* fall */ + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '"': + PP_LOG (LLOG_EXCEPTIONS, + ("Bad character '%c' in domain name '%s'", + *cp, arg)); + netreply ("501 Bad hostname in HELO.\r\n"); + return; + } + } + + hellod ++; + if (lexequ (arg, them) != 0) { + (void) sprintf (replybuf, + "250 %s: You are bluffing - `%s` expected\r\n", + us, them); + PP_NOTICE (("%s claims to be %s", realthem, arg)); + } + else + (void) sprintf (replybuf, "250 %s: Looks good to me\r\n", us); + + netreply (replybuf); +} + + + +/* +handle the MAIL command ("MAIL from:") +*/ + +static void mail() +{ + static Q_struct qstruct; + Q_struct *qp = &qstruct; + ADDR *ap; + char replybuf [BUFSIZ]; + RP_Buf thereply; + LIST_BPT *new; + + if (hellod == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Expecting a HELO command")); + hellod ++; /* MH < 6.7 breaks this! */ + } + + if (arg == 0 || *arg == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("No argument to MAIL supplied")); + netreply ("501 No argument supplied\r\n"); + return; + } + else if (sender) { + PP_LOG (LLOG_EXCEPTIONS, + ("MAIL command already supplied")); + netreply ("503 MAIL command already accepted\r\n"); + return; + } + else if (!prefix ("from:", arg)) { + PP_LOG (LLOG_EXCEPTIONS, + ("No sender given in MAIL")); + netreply ("501 No sender named\r\n"); + return; + } + + /* -- Scan FROM: parts of arg -- */ + + sender = index (arg, ':') + 1; + sender = adrfix (sender); + + q_init (qp); + new = list_bpt_new (hdr_822_bp); + list_bpt_add (&qp -> encodedinfo.eit_types, new); + new = list_bpt_new (ia5_bp); + list_bpt_add (&qp -> encodedinfo.eit_types, new); + qp -> inbound = list_rchan_new (them, channel); + + ppstart (); + + if (rp_isbad (io_wrq (qp, &thereply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't write Q struct %s", thereply.rp_line)); + netreply ("451 Temporary problem initialising\r\n"); + pprestart (); + return; + } + + if (sender == NULLCP || *sender == NULL) + sender = getpostmaster(AD_822_TYPE); + + PP_NOTICE (("Sender %s", sender)); + + ap = adr_new (sender, AD_822_TYPE, 0); + + (void) io_wadr (ap, AD_ORIGINATOR, &thereply); + adr_tfree (ap); + + switch (thereply.rp_val) { + case RP_BHST: + thereply.rp_val = RP_NDEL; + break; + } + if (rp_gbval (thereply.rp_val) == RP_BNO) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't write sender address %s [PERM]", + thereply.rp_line)); + (void) sprintf (replybuf, "501 %s\r\n", thereply.rp_line); + netreply (replybuf); + pprestart(); + } + else if (rp_gbval (thereply.rp_val) == RP_BTNO) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't write sender address %s [TEMP]", + thereply.rp_line)); + (void) sprintf (replybuf, "451 %s\r\n", thereply.rp_line); + netreply (replybuf); + pprestart(); + } + else + netreply ("250 OK\r\n"); + + no_recip = 0; +} + + + +/* +The RCPT command ("RCPT TO:") +*/ + +static void rcpt() +{ + RP_Buf thereply; + register char *p; + char replybuf [BUFSIZ]; + ADDR *ap; + + /* -- parse destination arg -- */ + + if (hellod == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Expecting a HELO command")); + hellod ++; /* MH bug */ + } + + if (sender == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("RCPT but no MAIL")); + netreply ("503 You must give a MAIL command first\r\n"); + return; + } + else if (arg == NULLCP || !prefix ("to:", arg)) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipient named in RCPT")); + netreply ("501 No recipient named.\r\n"); + return; + } + + p = index (arg, ':') + 1; + p = adrfix (p); + if (p == NULLCP || *p == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipient in RCPT")); + netreply ("501 No recipient named.\r\n"); + return; + } + + PP_NOTICE (("Recipient Address '%s'", p)); + + + ap = adr_new (p, AD_822_TYPE, no_recip + 1); + + (void) io_wadr (ap, AD_RECIPIENT, &thereply); + + adr_tfree (ap); + + if (thereply.rp_val == RP_BHST || + rp_gbval (thereply.rp_val) == RP_BNO) { + PP_LOG (LLOG_EXCEPTIONS, + ("Problems writing address %s [PERM]", + thereply.rp_line)); + (void) sprintf (replybuf, "550 %s\r\n", + thereply.rp_line); + netreply (replybuf); + } + else if (rp_gbval (thereply.rp_val) == RP_BTNO) { + PP_LOG (LLOG_EXCEPTIONS, + ("Problems writing address %s [TEMP]", + thereply.rp_line)); + (void) sprintf (replybuf, "451 %s\r\n", + thereply.rp_line); + netreply (replybuf); + } + else { + netreply ("250 Recipient OK.\r\n"); + no_recip++; + } + +} + + + +/*---------------------------------------------------------------------------- + + +ADDRFIX() -- This function takes the SMTP "path" and removes the leading +and trailing "<>"'s which would make the address illegal to RFC822 mailers. +Note that although the specification states that the angle brackets are +required, we will accept addresses without them. (DPK@BRL, 4 Jan 83) + + +----------------------------------------------------------------------------*/ + + +static char *adrfix (addrp) +char *addrp; +{ + register char *cp; + + + PP_TRACE (("adrfix %s", addrp)); + if (cp = index (addrp, '<')) { + addrp = ++cp; + + if (cp = rindex (addrp, '>')) + *cp = 0; + } + + (void) compress (addrp, addrp); + + PP_TRACE (("adrfix(): '%s'", addrp)); + + return (addrp); +} + + +/* +The DATA command. Send text to Submit. +*/ + +static void data() +{ + char tbuf[LINESIZE]; + struct rp_bufstruct thereply; + struct timeval data_time; + register char *p, + *bufptr; + int errflg, + werrflg, + size = 0, + doing_header = 1; + + errflg = 0; + werrflg = 0; + + timer_start (&data_time); + + if (no_recip == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients for DATA")); + netreply ("503 No recipients have been specified.\r\n"); + return; + } + + if (rp_isbad (io_adend(&thereply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad address end %s", thereply.rp_line)); + netreply ("451 Unknown mail system trouble.\r\n"); + return; + } + + if (rp_isbad (io_tinit (&thereply)) || + rp_isbad (io_tpart (hdr_822_bp, FALSE, &thereply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad text init %s", thereply.rp_line)); + netreply ("451 Unknown text initialisation failure.\r\n"); + return; + } + + netreply ("354 Enter Mail, end by a line with only '.'\r\n"); + + dont_mung = 1; /* -- tell getline only to drop cr -- */ + + + PP_TRACE (("body of message")); + + while (1) { /* -- forever -- */ + + if ((p = getline()) == 0) { + p = "\n***Sender closed connection***\n"; + errflg++; + break; + } + + if (p == (char *)NOTOK) { + p = "\n***Error on net connection***\n"; + if (!errflg++) + PP_LOG (LLOG_EXCEPTIONS, + ("netread error from host %s", + realthem)); + break; + } + + /* -- are we done? -- */ + + if (buf [0] == '.') + if (buf [1] == '\n') + break; /* -- yep -- */ + else + bufptr = &buf [1]; /* -- skip leading . -- */ + else + bufptr = &buf [0]; + + /* -- If write err occurs, stop writing but keep reading -- */ + + if (!werrflg) { + size += p-bufptr; + + if (doing_header && buf [0] == '\n') { + /* + do we need to go convert into body parts ?? + */ + + doing_header = 0; + + if (rp_isbad (io_tdend (&thereply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("io_tdend - %s", + thereply.rp_line)); + netreply ("451 Data input problem.\r\n"); + return; + } + + (void) sprintf (tbuf, "1.%s", ia5_bp); + if (rp_isbad (io_tpart (tbuf, FALSE, &thereply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("io_tpart - %s", + thereply.rp_line)); + netreply ("451 Body input failure.\r\n"); + return; + } + } + else if (rp_isbad (io_tdata (bufptr, (p-bufptr)))) { + werrflg++; + PP_LOG (LLOG_EXCEPTIONS, + ("error from submit")); + } + + } + } + if (doing_header) { + (void) sprintf (tbuf, "1.%s", ia5_bp); + if (rp_isbad (io_tdend (&thereply)) || + rp_isbad (io_tpart (tbuf, FALSE, &thereply))) { + netreply ("451 Data Input problem.\r\n"); + return; + } + } + dont_mung = 0; /* -- set getline to normal operation -- */ + + PP_TRACE (("Finished receiving text.")); + timer_end (&data_time, size, "Data Received"); + + if (werrflg) { + netreply ("451-Mail trouble (write error to mailsystem)\r\n"); + netreply ("451 Please try again later.\r\n"); + byebye (1); + } + + if (errflg) + byebye (1); + + if (rp_isbad (io_tdend (&thereply))) { + PP_LOG (LLOG_EXCEPTIONS, ("io_tdend - %s", thereply.rp_line)); + netreply ("451 Data termination problems.\r\n"); + return; + } + + (void) io_tend (&thereply); + + if (rp_isgood (rp_gval (thereply.rp_val))) { + (void) sprintf (buf, "250 %s\r\n", thereply.rp_line); + netreply (buf); + } + else if (rp_gbval (thereply.rp_val) == RP_BNO) { + PP_LOG (LLOG_EXCEPTIONS, + ("io_tend failed %s", thereply.rp_line)); + (void) sprintf (buf, "554 %s\r\n", thereply.rp_line); + netreply (buf); + return; + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("io_tend failed %s", thereply.rp_line)); + (void) sprintf (buf, "451 %s\r\n", thereply.rp_line); + netreply (buf); + return; + } + + PP_NOTICE (("<<< Message received from %s (%d recipients, %d bytes)", + realthem, no_recip, size)); + sender = NULLCP; + no_recip = 0; +} + + + +/* +The RSET command +*/ + +static void rset() +{ + pprestart (); + confirm(); +} + +static void pprestart () +{ + io_end (NOTOK); + ppbegin (); +} + +static void ppbegin () +{ + RP_Buf reply; + + if (rp_isbad (io_init(&reply))) { + PP_LOG (LLOG_EXCEPTIONS, + ("can't reinitialize mail system [%s]", + reply.rp_line)); + netreply ("421 Server can't initialize mail system (PP)\r\n"); + byebye (2); + } + sender = NULLCP; + no_recip = 0; +} + +static void ppstart() +{ + RP_Buf reply; + struct prm_vars prm; + + prm_init (&prm); + if (rp_isbad (io_wprm (&prm, &reply))) { + PP_LOG (LLOG_EXCEPTIONS, ("can't set parameters [%s]", + reply.rp_line)); + netreply ("421 Server can't initialize mail system (PP)\r\n"); + byebye (2); + } + + no_recip = 0; +} + + + +/* +The QUIT command +*/ + +static void quit() +{ + time_t timenow; + + PP_NOTICE (("smtp server quit")); + + time (&timenow); + + (void) sprintf (buf, "221 %s says goodbye to %s at %.19s.\r\n", + us, them, ctime (&timenow)); + netreply (buf); + + byebye (0); +} + + +static void byebye (retval) +int retval; +{ + /* + if (retval == OK) + mm_sbend(); + */ + if (rp_isbad (retval)) + PP_LOG (LLOG_EXCEPTIONS, ("Smtp server aborting")); + + io_end (retval == 0 ? OK : NOTOK); + exit (retval); +} + + +/* +Reply that the current command has been logged and noted +*/ + +static void confirm() +{ + netreply ("250 OK\r\n"); +} + + + +/* +The help command gives a list of valid commands +*/ +static void help() +{ + register int i; + register struct comarr *p; + char replybuf [BUFSIZ]; + + netreply ("214-The following commands are accepted:\r\n214-"); + + for (p=commands, i=1; p->cmdname; p++, i++) { + (void) sprintf (replybuf, "%s%s", p->cmdname, + ((i%10) ? " " : "\r\n214-" )); + netreply (replybuf); + } + + (void) sprintf (replybuf, "\r\n214 Send complaints/bugs to: %s\r\n", + postmaster); + netreply (replybuf); +} + +/* vrfy - attempt to verify user is OK */ + +static void vrfy () +{ + RP_Buf rp; + ADDR *adr; + char buffer[BUFSIZ]; + + if (hellod == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Expecting a HELO command")); + hellod ++; /* MH bug */ + } + + if (arg == NULLCP || *arg == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("No argument to VRFY command")); + netreply ("501 No argument supplied\r\n"); + return; + } + adr = adr_new (arg, AD_822_TYPE, 1); + if (rp_isbad (ad_parse (adr, &rp, CH_USA_PREF))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Failed to VRFY '%s' [%s]", arg, rp.rp_line)); + (void) sprintf (buffer, + "550 User unknown [%s]\r\n", + rp.rp_line); + netreply (buffer); + } + else { + (void) sprintf (buffer, "250 <%s>\r\n", + adr -> ad_type == AD_822_TYPE ? + adr -> ad_r822adr : adr -> ad_r400adr); + netreply (buffer); + } + adr_free (adr); +} + +static void expn () +{ + dl *list; + Name *np; + struct stat statbuf; + char buffer[BUFSIZ]; + + if (hellod == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Expecting a HELO command")); + hellod ++; /* MH bug */ + } + + if (arg == NULLCP || *arg == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("No argument to VRFY command")); + netreply ("501 No argument supplied\r\n"); + return; + } + switch (tb_getdl (arg, &list, OK)) { + case DONE: + if (list != NULL) + dl_free(list); + PP_NOTICE (("No such list %s", arg)); + netreply ("550 No such list\r\n"); + return; + + case NOTOK: + if (list != NULL) + dl_free(list); + PP_LOG (LLOG_EXCEPTIONS, ("Error locating list %s", arg)); + netreply ("550 List Error\r\n"); + return; + } + + if (list -> dl_file == NULLCP || + stat (list -> dl_file, &statbuf) == NOTOK || + (statbuf.st_mode & (~S_IFMT)) == SECRMODE) { + netreply ("550 Access Denied to you\r\n"); + dl_free (list); + return; + } + + for (np = list -> dl_list; np; np = np -> next) { + (void) sprintf (buffer, "250%c%s\r\n", + np -> next == NULL ? ' ' : '-', + np -> name); + netreply (buffer); + } + dl_free (list); +} + +/* +Send appropriate ascii responses over the network connection. +*/ + +static void netreply (str) +char *str; +{ + PP_LOG (LLOG_PDUS, ("-> %s", str)); + + if (timeout (NTIMEOUT)) + byebye (1); + + if (write (1, str, strlen (str)) < 0) { + timeout (0); + PP_SLOG (LLOG_EXCEPTIONS, "write", + ("(netreply) in writing [%s]", str)); + byebye (1); + } + + timeout (0); + + PP_TRACE (("%s", str)); +} + +static char *official (name) +char *name; +{ + struct hostent *hp; +#ifdef NAMESERVER + int i; + + for(i = 0 ; i < 10 ; i++){ + hp = gethostbyname(name); + if(hp != NULL) + break; + PP_TRACE (("Timeout looking up %s", name)); + if(i > 2) + sleep(i*2); + } +#else + hp = gethostbyname(name); +#endif + return hp == NULL ? NULLCP : strdup (hp -> h_name); +} diff --git a/Chans/splitter/Makefile b/Chans/splitter/Makefile new file mode 100644 index 0000000..e53ca0d --- /dev/null +++ b/Chans/splitter/Makefile @@ -0,0 +1,112 @@ +# Preliminary comments +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/splitter/RCS/Makefile,v 6.0 1991/12/18 20:12:36 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:36 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = splitter.c +OBJS = splitter.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xsplitter + +default: $(PROGS) + +xsplitter: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj:$(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-splitter inst-dir + +inst-splitter: $(CHANDIR)/splitter +$(CHANDIR)/splitter: xsplitter + -$(BACKUP) $@ zxsplitter + rm -f $@ + $(INSTALL) xsplitter $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "splitter channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +clean: tidy +tidy: + rm -f $(OBJS) xsplitter core a.out Makefile.old + +lint: l-targets + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +splitter.o: splitter.c +splitter.o: ../../h/util.h +splitter.o: ../../h/config.h +splitter.o: ../../h/ll_log.h +splitter.o: ../../h/qmgr.h +splitter.o: ../../h/Qmgr-types.h +splitter.o: ../../h/Qmgr-ops.h +splitter.o: ../../h/q.h +splitter.o: ../../h/adr.h +splitter.o: ../../h/list_rchan.h +splitter.o: ../../h/chan.h +splitter.o: ../../h/table.h +splitter.o: ../../h/list_bpt.h +splitter.o: ../../h/auth.h +splitter.o: ../../h/list_bpt.h +splitter.o: ../../h/extension.h +splitter.o: ../../h/mta.h +splitter.o: ../../h/adr.h +splitter.o: ../../h/list_bpt.h +splitter.o: ../../h/aparse.h +splitter.o: ../../h/ap.h +splitter.o: ../../h/util.h +splitter.o: ../../h/or.h +splitter.o: ../../h/chan.h +splitter.o: ../../h/auth.h +splitter.o: ../../h/list_rchan.h +splitter.o: ../../h/mta.h +splitter.o: ../../h/prm.h +splitter.o: ../../h/retcode.h +splitter.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/splitter/make b/Chans/splitter/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/splitter/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/splitter/splitter.c b/Chans/splitter/splitter.c new file mode 100644 index 0000000..4009baf --- /dev/null +++ b/Chans/splitter/splitter.c @@ -0,0 +1,409 @@ +/* splitter.c: resubmit messages so as to have indivual processes for recips */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/splitter/RCS/splitter.c,v 6.0 1991/12/18 20:12:36 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/splitter/RCS/splitter.c,v 6.0 1991/12/18 20:12:36 jpo Rel $ + * + * $Log: splitter.c,v $ + * Revision 6.0 1991/12/18 20:12:36 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "retcode.h" +#include +#include +#include "sys.file.h" + +static void dirinit(); +static int initialise(); +static int endfunc(); +static struct type_Qmgr_DeliveryStatus *process(); +static ADDR *getnthrecip (); +static int submit_error (); +static void set_success(); +static int processAddr(); + +CHAN *mychan; +char *this_msg = NULLCP, *this_chan = NULLCP; +int first_successDR, first_failureDR, start_submit; +int linked = TRUE; + +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); + dirinit(); + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc,argv,initialise,process,endfunc); + else +#endif + channel_control (argc,argv,initialise,process,endfunc); +} + +/* */ +/* move to correct place in file system */ + +extern char *quedfldir; + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialisation routine */ + +static void parse_ch_info(); + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + name = qb2str (arg); + + if ((mychan = ch_nm2struct (name)) == NULLCHAN) { + PP_OPER (NULLCP, ("Channel '%s' not known", name)); + if (name != NULLCP) free(name); + return NOTOK; + } + + if (name != NULLCP) free(name); + if (mychan->ch_out_info != NULLCP) + parse_ch_info (mychan->ch_out_info); + + start_submit = TRUE; + return OK; +} + +/* parse the info string and set the global variables */ +static void parse_ch_info(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + + if ((margc = sstr2arg (info_copy, 20, margv, ",")) > 0) { + for (ix = 0; ix < margc; ix++) { + /* check each entry in info string */ + if (lexequ(margv[ix], "notlinked") == 0) + linked = FALSE; + else if (lexequ(margv[ix], "linked") == 0) + linked = TRUE; + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown ch_info flag '%s'", + margv[ix])); + } + } + free(info_copy); +} + +/* */ +/* channel termination routine */ + +static int endfunc (arg) +struct type_Qmgr_Channel *arg; +{ + if (start_submit == FALSE) + io_end (OK); + start_submit = TRUE; +} + +/* */ +/* channel work routine */ + +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + if (this_msg) free(this_msg); + this_msg = qb2str (msg->qid); + + if (this_chan) free(this_chan); + this_chan = qb2str (msg->channel); + + if (mychan == NULLCHAN + || strcmp (this_chan, mychan->ch_name) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("channel error: '%s'", + this_chan)); + return FALSE; + } + + return TRUE; +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULLADDR; + ADDR *recips = NULLADDR; + ADDR *adr; + int rcount, retval; + struct type_Qmgr_UserList *ix; + RP_Buf *reply; + + bzero ((char *)&prm, sizeof (prm)); + bzero ((char *)&que, sizeof (que)); + + delivery_init (arg->users); + delivery_setall (int_Qmgr_status_messageFailure); + first_failureDR = first_successDR = TRUE; + + if (security_check (arg) != TRUE) + return deliverystate; + + PP_LOG (LLOG_NOTICE, + ("processing msg '%s' through '%s'", + this_msg, this_chan)); + + /* read in message */ + if (rp_isbad (rd_msg (this_msg, &prm, &que, + &sender, &recips, &rcount))) { + PP_LOG (LLOG_EXCEPTIONS, + ("rd_msg error: '%s'", this_msg)); + rd_end(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "Can't read message"); + } + + /* process recipients individually */ + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip (&que, ix->RecipientId->parm)) == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, + ("failed to find recipient %d of msg '%s'", + ix->RecipientId->parm, this_msg)); + delivery_setstate (ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + if (start_submit == TRUE && rp_isbad (io_init (&reply))) { + submit_error (adr, "io_init", reply); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Unable to start submit"); + } else + start_submit = FALSE; + + switch (chan_acheck (adr, mychan, 1, (char **)NULL)) { + default: + case NOTOK: + break; + case OK: + processAddr (this_msg, &prm, &que, adr); + break; + } + } + + /* write results of processing */ + + if (rp_isbad (retval = wr_q2dr (&que, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'", + mychan->ch_name, retval)); + (void) delivery_resetDRs (int_Qmgr_status_messageFailure); + } + + rd_end (); + q_free(&que); + prm_free (&prm); + + return deliverystate; +} + +/* */ +/* do processing for specified recip */ + +static int processAddr (msg, prm, qp, recip) +char *msg; +struct prm_vars *prm; +Q_struct *qp; +ADDR *recip; +{ + ADDR *sender = adr_new((qp->Oaddress->ad_type == AD_X400_TYPE) ? + qp->Oaddress->ad_r400adr : + qp->Oaddress->ad_r822adr, + qp->Oaddress->ad_type, + 0); + + ADDR *recipient = adr_new((recip->ad_type == AD_X400_TYPE) ? + recip->ad_r400adr : + recip->ad_r822adr, + recip->ad_type, + 1); + Q_struct qs; + struct timeval data_time; + struct stat st; + RP_Buf reply; + char *msgdir = NULLCP, + file[MAXPATHLENGTH], + buf[BUFSIZ], + *strippedname; + int dirlen, + size, + fd_in, n; + + if (qid2dir (msg, recip, TRUE, &msgdir) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("msg dir not found for recip %d of msg '%s'", + recip->ad_no, msg)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + "source directory not found"); + return 0; + } + + q_init (&qs); + q_almost_dup (&qs, qp); + qs.encodedinfo.eit_types = list_bpt_dup(qp->encodedinfo.eit_types); + + qs.inbound = list_rchan_new (qp->inbound->li_mta, + qp->inbound->li_chan->ch_name); + prm->prm_opts = prm->prm_opts | PRM_NOTRACE | PRM_ACCEPTALL; + + /* now resubmit */ + timer_start(&data_time); + + if (rp_isbad (io_wprm (prm, &reply))) + return submit_error (recip, "io_wprm", &reply); + + if (rp_isbad (io_wrq (&qs, &reply))) + return submit_error (recip, "io_wrq", &reply); + + if (rp_isbad (io_wadr (sender, AD_ORIGINATOR, &reply))) { + (void) sprintf (buf, "io_wadr(%s)", sender->ad_value); + return submit_error(recip, buf, &reply); + } + + if (rp_isbad (io_wadr (recipient, AD_RECIPIENT, &reply))) { + (void) sprintf (buf, "io_wadr(%s)", recipient->ad_value); + return submit_error(recip, buf, &reply); + } + + if (rp_isbad (io_adend (&reply))) + return submit_error (recip, "io_adend", &reply); + + /* submit body of message */ + + if (rp_isbad (io_tinit (&reply))) + return submit_error (recip, "io_tinit", &reply); + dirlen = strlen (msgdir) +1; + + msg_rinit (msgdir); + + size = 0; + while (msg_rfile (file) != RP_DONE) { + + /* --- transmit file --- */ + strippedname = file + dirlen; + if (stat (file, &st) != NOTOK) + size += st.st_size; + if (linked == TRUE) { + (void) sprintf(buf, "%s %s",strippedname, file); + if (rp_isbad (io_tpart (buf, TRUE, &reply))) + return submit_error (recip,"io_tpart",&reply); + } else { + if (rp_isbad (io_tpart (strippedname, FALSE, &reply))) + return submit_error (recip,"io_tpart",&reply); + + if ((fd_in = open (file, O_RDONLY)) == -1) { + (void) strcpy (reply.rp_line,file); + return submit_error (recip,"open",&reply); + } + while ((n = read (fd_in, buf, BUFSIZ)) > 0) { + if (rp_isbad (io_tdata (buf, n))) { + (void) strcpy (reply.rp_line,"???"); + return submit_error (recip,"io_tdata",&reply); + } + } + + close (fd_in); + if (rp_isbad (io_tdend (&reply))) + return submit_error (recip,"io_tdend", &reply); + } + } + msg_rend(); + if (rp_isbad (io_tend (&reply))) + return submit_error (recip,"io_tend", &reply); + set_success (recip,qp, size); + + q_free (&qs); + + timer_end (&data_time, size, "Data submitted"); + + return 0; +} + +/* */ + +static void set_success (recip, que, size) +ADDR *recip; +Q_struct *que; +int size; +{ + (void) wr_ad_status (recip, AD_STAT_DONE); + (void) wr_stat (recip, que, this_msg, size); + delivery_set (recip->ad_no, int_Qmgr_status_success); +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + +static int submit_error (recip, proc, reply) +ADDR *recip; +char *proc; +RP_Buf *reply; +{ + char buf[BUFSIZ]; + PP_LOG (LLOG_EXCEPTIONS, + ("Chans/list %s failure [%s]", proc, reply->rp_line)); + + if (recip != NULLADDR) { + (void) sprintf (buf, + "'%s' failure for '%s' [%s]", + proc, + this_msg, + reply -> rp_line); + PP_OPER(NULLCP,("%s", buf)); + delivery_setstate (recip->ad_no, + int_Qmgr_status_messageFailure, + buf); + } + + start_submit = TRUE; + io_end (NOTOK); + + return OK; +} diff --git a/Chans/testchan/Makefile b/Chans/testchan/Makefile new file mode 100644 index 0000000..5604dcf --- /dev/null +++ b/Chans/testchan/Makefile @@ -0,0 +1,140 @@ +# test channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/testchan/RCS/Makefile,v 6.0 1991/12/18 20:12:42 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:42 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = testchan.c +OBJS = testchan.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +default: testchan + +lint: l-testchan + +############################################################ +# +# test channel +# +############################################################ + +testchan: xtestchan + +xtestchan: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj:$(OBJS) + #load -C smtp.o $(SMTPOBJS) $(LIBPP) $(LIBSYS) + +l-testchan: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +install: inst-dir inst-testchan + +inst-dir: $(CHANDIR) + +inst-testchan: $(CHANDIR)/testchan + +$(CHANDIR)/testchan: xtestchan + -$(BACKUP) $@ zxtestchan + rm -f $@ + $(INSTALL) xtestchan $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "testchan channel installed normally"; echo "" + + +clean: tidy + rm -f $(OBJS) $(PROGS) core a.out *old *.BAK z* x* + +tidy: + rm -f $(PROGS) core a.out *old *.BAK + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + + + ############################################################ + # + # End of Building Rules + # + ############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +testchan.o: testchan.c +testchan.o: ../../h/head.h +testchan.o: ../../h/util.h +testchan.o: ../../h/config.h +testchan.o: ../../h/ll_log.h +testchan.o: ../../h/retcode.h +testchan.o: ../../h/chan.h +testchan.o: ../../h/table.h +testchan.o: ../../h/list_bpt.h +testchan.o: ../../h/prm.h +testchan.o: ../../h/q.h +testchan.o: ../../h/adr.h +testchan.o: ../../h/list_rchan.h +testchan.o: ../../h/chan.h +testchan.o: ../../h/auth.h +testchan.o: ../../h/list_bpt.h +testchan.o: ../../h/extension.h +testchan.o: ../../h/mta.h +testchan.o: ../../h/adr.h +testchan.o: ../../h/list_bpt.h +testchan.o: ../../h/aparse.h +testchan.o: ../../h/ap.h +testchan.o: ../../h/util.h +testchan.o: ../../h/or.h +testchan.o: ../../h/chan.h +testchan.o: ../../h/auth.h +testchan.o: ../../h/list_rchan.h +testchan.o: ../../h/mta.h +testchan.o: ../../h/dr.h +testchan.o: ../../h/extension.h +testchan.o: ../../h/mta.h +testchan.o: ../../h/qmgr.h +testchan.o: ../../h/Qmgr-types.h +testchan.o: ../../h/Qmgr-ops.h +testchan.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/testchan/README b/Chans/testchan/README new file mode 100644 index 0000000..ba6e67c --- /dev/null +++ b/Chans/testchan/README @@ -0,0 +1,4 @@ +This is a fake channel used for profiling and testing purposes + +It is not suitable for general use. + diff --git a/Chans/testchan/dogen b/Chans/testchan/dogen new file mode 100755 index 0000000..b22d615 --- /dev/null +++ b/Chans/testchan/dogen @@ -0,0 +1,34 @@ +#! /bin/sh +count=10000 +sleep=1 +while [ $# -gt 0 ] +do + case "$1" in + -s) sleep=0; shift;; + [0-9]*) count="$1" ; shift;; + *) break 2;; + esac +done + +nawk ' +BEGIN { FS = ":"; srand() } +$1 !~ /^#/ && NF == 2 { host[hcount++] = $1 } +func do_addr(count, i) { + printf "mail -s \"mesg %d\" ", msgcount ++ + for (i = 0; i < count; i++) { + printf "foo@%s ", host[random(hcount)] + } + printf "< /etc/hosts\n" +} +func random(n) { return int(rand*n); } +END { + print "#! /bin/sh" + print "echo hcount is", hcount, "producing", tcount, "records" + for(n = 0;n < tcount;n++) { + if (random(4) == 1) + do_addr(random(10)+1) + else do_addr(1) + if(sleep) + print "sleep", random(5)+1 + } +}' sleep="$sleep" tcount="$count" $* diff --git a/Chans/testchan/make b/Chans/testchan/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/testchan/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/testchan/testchan.c b/Chans/testchan/testchan.c new file mode 100644 index 0000000..3ebf383 --- /dev/null +++ b/Chans/testchan/testchan.c @@ -0,0 +1,606 @@ +/* testchan.c: as invoked by qmgr to do benchmarking stuff*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/testchan/RCS/testchan.c,v 6.0 1991/12/18 20:12:42 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/testchan/RCS/testchan.c,v 6.0 1991/12/18 20:12:42 jpo Rel $ + * + * $Log: testchan.c,v $ + * Revision 6.0 1991/12/18 20:12:42 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "chan.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include +#include "sys.file.h" +#include +#include + +extern char *quedfldir; +extern void rd_end(), chan_init(), err_abrt(), timer_start(), timer_end(); +FILE *msg_fp; +CHAN *mychan; +char *this_msg; + + +static char *files[] = { + "/usr/dict/words", + "/etc/passwd", + "/usr/adm/messages", + "/etc/motd", + "/etc/hosts", + "/etc/printcap", + "/etc/rc.local", + NULLCP + }; +#define RANDFILE() (files[random() % (sizeof(files)/sizeof(*files) -1)]) + +static int data_bytes; +extern time_t time(); + + +static struct type_Qmgr_DeliveryStatus *process(); +static void dirinit(); +static int chaninit(); +static int endproc (); +static int dotext (); +static int copy (); +static struct hostent *find_host (); +static FILE *serv_open(); +#define OPT_RANDOM 1 +#define OPT_SLEEP 2 +#define OPT_NETECHO 3 +int option = OPT_RANDOM; +/* --------------------- Begin Routines -------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + char *p; + int opt; + + if ((p = rindex (argv[0], '/')) != NULLCP) + p ++; + if (p == NULLCP || *p == NULL) + p = argv[0]; + + chan_init (p); /* init the channel - and find out who we are */ + + dirinit(); /* get to the right directory */ + (void) signal (SIGPIPE, SIG_IGN); + + while ((opt = getopt (argc, argv, "es")) != EOF) { + switch (opt) { + case 's': + option = OPT_SLEEP; + break; + case 'e': + option = OPT_NETECHO; + break; + } + } + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, chaninit, process, endproc); + else +#endif + channel_control (argc, argv, chaninit, process, endproc); + exit (0); +} + + + +static int chaninit (arg) +struct type_Qmgr_Channel *arg; +{ + char *p = qb2str (arg); + + if ((mychan = ch_nm2struct (p)) == (CHAN *)0) + err_abrt (RP_PARM, "Channel '%s' not known", p); + + srandom (getpid()); + rename_log(p); + PP_NOTICE (("starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); + free (p); + return OK; +} + +static int endproc () +{ + PP_NOTICE (("Closing %s", mychan -> ch_name)); +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + struct type_Qmgr_UserList *up; + Q_struct Qstruct, *qp = &Qstruct; + int retval; + ADDR *ap, + *ad_sendr = NULLADDR, + *ad_recip = NULLADDR, + *alp = NULLADDR, + *ad_list = NULLADDR; + int ad_count; + char *cur_host = NULLCP; + + if (this_msg) free (this_msg); + + this_msg = qb2str (arg -> qid); + + bzero ((char *)&prm, sizeof prm); + bzero ((char *)qp, sizeof *qp); + + (void) delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg err: %s", this_msg)); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + for (up = arg ->users; up; up = up -> next) { + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + switch (chan_acheck (ap, mychan, + ad_list == NULLADDR, &cur_host)) { + default: + case NOTOK: + continue; + + case OK: + break; + } + break; + } + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = alp = (ADDR *) calloc (1, sizeof *alp); + else { + alp -> ad_next = (ADDR *) calloc (1, sizeof *alp); + alp = alp -> ad_next; + } + *alp = *ap; + alp -> ad_next = NULLADDR; + } + + if (ad_list == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list")); + rd_end (); + q_free (qp); + return deliverystate; + } + + PP_NOTICE (("processing msg %s to %s", this_msg, cur_host)); + + deliver (ad_list, qp); + + q_free (qp); + rd_end(); + + return deliverystate; +} + +static void dirinit() /* Change into pp queue space */ +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change directory to '%s'", + quedfldir); +} + +deliver (ad_list, qp) +ADDR *ad_list; +Q_struct *qp; +{ + ADDR *ap; + + PP_TRACE (("deliver ()")); + + switch (option) { + case OPT_NETECHO: + do_echo ("/usr/dict/words"); + break; + case OPT_SLEEP: + do_sleep (5); + break; + case OPT_RANDOM: + do_random (); + break; + } + if (option == OPT_RANDOM) { + if (random()% 100 == 1) { + for (ap = ad_list; ap; ap = ap -> ad_next) { + delivery_setall (int_Qmgr_status_negativeDR); + PP_LOG (LLOG_EXCEPTIONS, ("problem with user")); + set_1dr (qp, ap -> ad_no, +#ifndef PP52 + this_msg, +#endif + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, + "problem with recipient"); + ap -> ad_resp = 0; + } + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + return; + } + else if (random () % 50 < 10) { + PP_LOG (LLOG_EXCEPTIONS, ("problem with message")); + delivery_setallstate (int_Qmgr_status_messageFailure, + "problem with message"); + return; + } + else if (random() % 50 < 10) { + PP_LOG (LLOG_EXCEPTIONS, ("problem with MTA")); + delivery_setallstate (int_Qmgr_status_mtaFailure, "MTA missing"); + return; + } + else if (random() % 50 < 10) { + PP_LOG (LLOG_EXCEPTIONS, ("problem with message & MTA")); + delivery_setallstate (int_Qmgr_status_mtaAndMessageFailure, + "MTA died"); + return; + } + } + + for (ap = ad_list; ap; ap = ap -> ad_next) { + if (ap -> ad_resp) { + if (ap -> ad_usrreq == AD_USR_CONFIRM || + ap -> ad_mtarreq == AD_MTA_CONFIRM || + ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (qp, ap -> ad_no, +#ifndef PP52 + this_msg, +#endif + DRR_NO_REASON, -1, NULLCP); + delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + } + else { + PP_NOTICE (("address OK")); + (void) wr_ad_status (ap, AD_STAT_DONE); +#ifndef PP52 + (void) wr_stat (ap, qp, this_msg, data_bytes); +#endif + delivery_set (ap -> ad_no, + int_Qmgr_status_success); + } + } + } + if (rp_isbad(wr_q2dr (qp, this_msg))) + delivery_resetDRs(int_Qmgr_status_messageFailure); + PP_NOTICE ((">>> Message %s transfered", + this_msg)); +} + +do_random () +{ + switch (random() % 5) { + case 0: + do_sleep (random()%60); + break; + case 2: + mess_with_network (); + break; + case 3: + cpu_intensive (); + break; + case 4: + mem_intensize (); + break; + default: + mess_with_files (RANDFILE()); + break; + } +} +do_sleep (secs) +int secs; +{ + PP_NOTICE (("sleeping %d", secs)); + sleep (secs); +} + +mess_with_files (infile) +char *infile; +{ + char *outfile; + FILE *fp, *fpo; + int n; + + if ((fp = fopen (infile, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, infile, ("Can't open ")); + return; + } + if (random() % 2 == 0) { + outfile = "/dev/null"; + if ((fpo = fopen (outfile, "w")) == NULL ) { + PP_SLOG (LLOG_EXCEPTIONS, infile, ("Can't open ")); + fclose (fp); + return; + } + PP_NOTICE (("mess_with_files %s->/dev/null", infile)); + } + else { + PP_NOTICE (("mess_with_files %s -> temp", infile)); + + fpo = tmpfile (); + } + + n = copy (fp, fpo); + PP_NOTICE (("copied %d bytes", n)); + (void) fclose (fp); + (void) fclose (fpo); +} + + +mess_with_network () +{ + switch (random() % 3) { + case 0: + do_echo (RANDFILE()); + break; + case 1: + do_sink (RANDFILE()); + break; + default: + do_chargen (); + break; + } +} + +jmp_buf jmpbuf; + +static SFD alarmed() +{ + longjmp (jmpbuf, 1); +} + +do_echo (infile) +char *infile; +{ + FILE *fp; + FILE *fpi; + char buf[BUFSIZ]; + int n; + int total = 0; + SFP pstat; + + PP_NOTICE (("do echo of %s", infile)); + if ((fp = serv_open ("echo")) == NULL) + return; + if ((fpi = fopen (infile, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, infile, ("Can't open ")); + fclose (fp); + return; + } + pstat = signal (SIGALRM, alarmed); + if (setjmp (jmpbuf) == 0) { + alarm (60); + while ((n = fread (buf, 1, sizeof buf, fpi)) > 0) { + if (fwrite (buf, 1, n, fp) != n) { + PP_SLOG (LLOG_EXCEPTIONS, "error", ("write")); + break; + } + total += n; + if (fread (buf, 1, n, fp) != n) + PP_LOG (LLOG_EXCEPTIONS, ("copy back failed")); + } + alarm(0); + } + PP_NOTICE (("Echoed %d bytes", total)); + (void) fclose (fpi); + (void) fclose (fp); + signal(SIGALRM, pstat); +} + +do_sink (infile) +char *infile; +{ + FILE *fp, *fpi; + int n; + + PP_NOTICE (("do_sink of %s", infile)); + if ((fp = serv_open ("sink")) == NULL) + return; + + if ((fpi = fopen(infile, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, infile, ("Can't open ")); + fclose (fp); + return; + } + n = copy (fpi, fp); + PP_NOTICE (("Sunk %d bytes", n)); + (void) fclose (fpi); + (void) fclose (fp); +} + +do_chargen () +{ + FILE *fp; + char buf[BUFSIZ]; + int i; + int n; + int total = 0; + int iter = random () % 2000; + + PP_NOTICE (("do_chargen %d buffers", iter)); + if ((fp = serv_open ("chargen")) == NULL) + return; + + for (i = iter; i > 0; i--) { + if ((n = fread (buf, 1, sizeof buf, fp)) <= 0) + break; + total += n; + } + (void) fclose (fp); + PP_NOTICE (("Received %d bytes", total)); +} + +static int copy (fp1, fp2) +FILE *fp1, *fp2; +{ + char buf[BUFSIZ]; + int total = 0; + int n; + + while ((n = fread (buf, 1, sizeof buf, fp1)) > 0) { + if (fwrite (buf, 1, n, fp2) != n) { + PP_SLOG (LLOG_EXCEPTIONS, "write", ("problems with ")); + return NOTOK; + } + total += n; + } + if (n == 0) + return total; + PP_SLOG (LLOG_EXCEPTIONS, "read", ("problems with ")); + return NOTOK; +} + + + +static FILE *serv_open (name) +char *name; +{ + struct servent *sp; + struct sockaddr_in s_in; + struct hostent *hp; + int sd; + + if ((sp = getservbyname (name, "tcp")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("No such service %s", name)); + return NULL; + } + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, "socket", ("Can't create")); + return NULL; + } + s_in.sin_family = AF_INET; + s_in.sin_port = sp -> s_port; + + if ((hp = find_host ()) == NULL) { + close (sd); + return NULL; + } + + + bcopy (hp -> h_addr, (char *)&s_in.sin_addr, hp -> h_length); + if (connect (sd, &s_in, sizeof s_in) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, "connect", ("Can't ")); + close (sd); + return NULL; + } + + return fdopen (sd, "r+"); +} + +static char *host_list[500] = { + "localhost" + }; +static int n_hosts = 1; +#define RANDHOST() (host_list[random() % n_hosts]) + +static struct hostent *find_host () +{ + static int inited = 0; + char *host; + static void init_hosts (); + int i; + struct hostent *hp; + + if (!inited) { + init_hosts (); + inited ++; + } + for (i = 0;i < 20; i++) { + if ((hp = gethostbyname (host = RANDHOST())) == NULL) + continue; + PP_NOTICE (("Using host %s", host)); + return hp; + } + return NULL; +} + +static void init_hosts () +{ + char path[BUFSIZ]; + extern char *tbldfldir; + FILE *fp; + char *cp; + + getfpath (tbldfldir, "hosts", path); + + if ((fp = fopen (path, "r")) == NULL) + return; + while (fgets(path, sizeof path, fp)) { + if ((cp = index(path, '\n')) != NULL) + *cp = 0; + host_list[n_hosts++] = strdup (path); + } + fclose (fp); +} + +static double fact(n) +int n; +{ + if (n <= 1) + return 1; + return fact(n-1) * (double)n; +} + +cpu_intensive () +{ + int niter = random()%1000; + int i; + double result = 1.0; + + PP_NOTICE (("working out e with %d iterations", niter)); + /* work out e for now */ + for (i = 1; i < niter; i++) { + result = result + (double)1 / fact(i); + } + PP_NOTICE (("result e is %.20lf", result)); +} + + +mem_intensize () +{ + int ps = getpagesize (); + int npages = random() % 100; + char **pages; + int i, j; + char c; + + PP_NOTICE (("memory stuff based on %d pages", npages)); + pages = (char **) calloc(npages, sizeof (char **)); + for (i = 0; i < npages; i++) + pages[i] = malloc (ps); + for (j = random() % 100; j > 0; j--) + for (i = 0; i < npages; i++) { + c = pages[i][0] % 4; + fact(c); + } +} diff --git a/Chans/timeout/Makefile b/Chans/timeout/Makefile new file mode 100644 index 0000000..4a5ace5 --- /dev/null +++ b/Chans/timeout/Makefile @@ -0,0 +1,145 @@ +# Makefile for timeout channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/timeout/RCS/Makefile,v 6.0 1991/12/18 20:12:51 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:51 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = timeout.c +OBJS = timeout.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xtimeout + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# Msg timeout +# +############################################################ + +timeout: xtimeout + +xtimeout: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + + +install: inst-dir inst-timeout + +inst-timeout: $(CHANDIR)/timeout +$(CHANDIR)/timeout: xtimeout + -$(BACKUP) $@ zxtimeout + rm -f $@ + $(INSTALL) xtimeout $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "timeout channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f $(PROGS) zxtimeout *.BAK core a.out *.old + +lint: l-timeout + +l-timeout: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +timeout.o: timeout.c +timeout.o: ../../h/head.h +timeout.o: ../../h/util.h +timeout.o: ../../h/config.h +timeout.o: ../../h/ll_log.h +timeout.o: ../../h/retcode.h +timeout.o: ../../h/dbase.h +timeout.o: ../../h/config.h +timeout.o: ../../h/qmgr.h +timeout.o: ../../h/Qmgr-types.h +timeout.o: ../../h/Qmgr-ops.h +timeout.o: ../../h/q.h +timeout.o: ../../h/adr.h +timeout.o: ../../h/list_rchan.h +timeout.o: ../../h/chan.h +timeout.o: ../../h/table.h +timeout.o: ../../h/list_bpt.h +timeout.o: ../../h/auth.h +timeout.o: ../../h/list_bpt.h +timeout.o: ../../h/extension.h +timeout.o: ../../h/mta.h +timeout.o: ../../h/adr.h +timeout.o: ../../h/list_bpt.h +timeout.o: ../../h/aparse.h +timeout.o: ../../h/ap.h +timeout.o: ../../h/util.h +timeout.o: ../../h/or.h +timeout.o: ../../h/chan.h +timeout.o: ../../h/auth.h +timeout.o: ../../h/list_rchan.h +timeout.o: ../../h/mta.h +timeout.o: ../../h/dr.h +timeout.o: ../../h/extension.h +timeout.o: ../../h/mta.h +timeout.o: ../../h/prm.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/timeout/make b/Chans/timeout/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/timeout/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/timeout/timeout.c b/Chans/timeout/timeout.c new file mode 100644 index 0000000..843275f --- /dev/null +++ b/Chans/timeout/timeout.c @@ -0,0 +1,199 @@ +/* timeout.c: message timeout channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/timeout/RCS/timeout.c,v 6.0 1991/12/18 20:12:51 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/timeout/RCS/timeout.c,v 6.0 1991/12/18 20:12:51 jpo Rel $ + * + * $Log: timeout.c,v $ + * Revision 6.0 1991/12/18 20:12:51 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "dbase.h" +#include "qmgr.h" +#include "q.h" +#include "dr.h" +#include "prm.h" + + +extern char *quedfldir; +extern CHAN *ch_nm2struct(); +extern void sys_init(), rd_end(), err_abrt(); +CHAN *mychan; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static void dirinit (); +static int security_check (); +static ADDR *get_address (); + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process,NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process,NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/timeout : Channel '%s' not known",name)); + if (name) free(name); + return NOTOK; + } + + /* check if a timeout channel */ + if (mychan->ch_chan_type != CH_TIMEOUT) { + PP_OPER(NULLCP, + ("timeout: Channel '%s' not specified as type timeout", + name)); + if (name) free(name); + return NOTOK; + } + if (name) free(name); + return OK; +} + +/* */ +/* routine called to clean do timeout out */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender; + ADDR *recips; + int rcount; + char *this_msg; + ADDR *adr; + + prm_init (&prm); + q_init (&que); + + sender = NULLADDR; + recips = NULLADDR; + + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + /* ok-timeout message */ + this_msg = qb2str (arg->qid); + + PP_LOG(LLOG_NOTICE, + ("timing out msg %s", this_msg)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/timeout rd_msg err: '%s'",this_msg)); + rd_end(); + /* free all storage used */ + if (this_msg != NULL) free(this_msg); + q_free (&que); + + return deliverystate; + } + + for (adr = que.Raddress; adr; adr = adr -> ad_next) + if (adr -> ad_status == AD_STAT_PEND) + set_1dr(&que, adr -> ad_no, this_msg, + DRR_UNABLE_TO_TRANSFER, + DRD_MAX_TIME_EXPIRED, + NULLCP); + if (arg->users != NULL + && (adr = get_address(arg->users->RecipientId->parm, &que)) != 0 + && !rp_isbad(wr_q2dr(&que, this_msg))) + delivery_set(adr -> ad_no, int_Qmgr_status_negativeDR); + else + delivery_set(adr -> ad_no, int_Qmgr_status_messageFailure); + + /* unlock file */ + rd_end(); + + + /* free all storage used */ + if (this_msg != NULL) free(this_msg); + q_free (&que); + prm_free(&prm); + + return deliverystate; +} + +/* */ +/* routine to check if alloqid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/timeout channel err: '%s'",msg_chan)); + result = FALSE; + } + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* routine to extract the required address from the Q_struct */ +static ADDR *get_address (usr, que) +int usr; +Q_struct *que; +{ + ADDR *ix; + + if (usr == 0) + /* originator */ + return que->Oaddress; + + ix = que->Raddress; + while ((ix != 0) && (--usr > 0)) + ix = ix->ad_next; + + return ix; +} diff --git a/Chans/trashman/Makefile b/Chans/trashman/Makefile new file mode 100644 index 0000000..6a9997f --- /dev/null +++ b/Chans/trashman/Makefile @@ -0,0 +1,142 @@ +# Makefile for trash channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/trashman/RCS/Makefile,v 6.0 1991/12/18 20:12:57 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:12:57 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = trash.c +OBJS = trash.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) # -DDBG_CHAN +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xtrash + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# trash clean out +# +############################################################ + +trash: xtrash + +xtrash: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + + +install: inst-dir inst-trash + +inst-trash: $(CHANDIR)/trash +$(CHANDIR)/trash: xtrash + -$(BACKUP) $@ zxtrash + rm -f $@ + $(INSTALL) xtrash $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "trash channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f $(PROGS) zxtrash core a.out Makefile.old *.BAK + +lint: l-trash_channel + +l-trash_channel: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +trash.o: trash.c +trash.o: ../../h/head.h +trash.o: ../../h/util.h +trash.o: ../../h/config.h +trash.o: ../../h/ll_log.h +trash.o: ../../h/retcode.h +trash.o: ../../h/qmgr.h +trash.o: ../../h/Qmgr-types.h +trash.o: ../../h/Qmgr-ops.h +trash.o: ../../h/q.h +trash.o: ../../h/adr.h +trash.o: ../../h/list_rchan.h +trash.o: ../../h/chan.h +trash.o: ../../h/table.h +trash.o: ../../h/list_bpt.h +trash.o: ../../h/auth.h +trash.o: ../../h/list_bpt.h +trash.o: ../../h/extension.h +trash.o: ../../h/mta.h +trash.o: ../../h/adr.h +trash.o: ../../h/list_bpt.h +trash.o: ../../h/aparse.h +trash.o: ../../h/ap.h +trash.o: ../../h/util.h +trash.o: ../../h/or.h +trash.o: ../../h/chan.h +trash.o: ../../h/auth.h +trash.o: ../../h/list_rchan.h +trash.o: ../../h/mta.h +trash.o: ../../h/prm.h +trash.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/trashman/make b/Chans/trashman/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/trashman/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/trashman/trash.c b/Chans/trashman/trash.c new file mode 100644 index 0000000..a6b83e7 --- /dev/null +++ b/Chans/trashman/trash.c @@ -0,0 +1,299 @@ +/* trash_channel.c: message trash collection channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/trashman/RCS/trash.c,v 6.0 1991/12/18 20:12:57 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/trashman/RCS/trash.c,v 6.0 1991/12/18 20:12:57 jpo Rel $ + * + * $Log: trash.c,v $ + * Revision 6.0 1991/12/18 20:12:57 jpo + * Release 6.0 + * + */ + + + +#include +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include +#include "sys.file.h" +#include + + +extern char *quedfldir, *aquefile; +extern char *chndfldir; +extern CHAN *ch_nm2struct(); +extern void rd_end(), sys_init(), err_abrt(); +extern time_t time(); +CHAN *mychan; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static void dirinit (); +static int okayToTrash(); +static void rec_rmdir(); + +int testing = FALSE; + +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc > 2 && (strcmp(argv[2],"test") == 0)) + testing = TRUE; + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process,NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* routine to initialise channel */ +/* also does all the work */ + +char fullname[MAXPATHLEN]; +time_t interval, + current; + +#define DEFAULT_INTERVAL (60*60*24*3) /* 3 days for normal files */ + +static int my_unlink(file) +char *file; +{ + if (testing == TRUE) { + fprintf(stdout, "Trash channel would unlink file '%s'", file); + return 0; + } else + return unlink(file); +} + +static void my_recrm(name) +char *name; +{ + if (testing == TRUE) + fprintf(stdout, "Trash channel would recrm directory '%s'", + name); + else { + if (chdir(name) == 0) { + (void) recrm("."); + dirinit(); + if (rmdir(name) == NOTOK) + PP_SLOG(LLOG_EXCEPTIONS,name, + ("unable to remove directory")); + } + } +} + +static void rmNonMsg (name) +char *name; +{ + struct stat statbuf; + if (stat (name, &statbuf) == NOTOK) + PP_SLOG(LLOG_EXCEPTIONS, name, + ("unable to stat file")); + else if (current - statbuf.st_mtime > interval) { + PP_NOTICE(("Removing non message entry '%s'", name)); + if (S_ISDIR(statbuf.st_mode)) { + my_recrm(name); + } else + if (my_unlink(name) == NOTOK) + PP_SLOG(LLOG_EXCEPTIONS, name, + ("Can't unlink file")); + } +} + +static time_t parsetime(s) +char *s; +{ + int n; + if (s == NULLCP || *s == NULL) return 0; + while(*s != NULL && isspace(*s)) s++; + n = 0; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + s++; + } + while (*s != NULL && isspace(*s)) s++; + if (*s != NULL && isalpha(*s)) { + switch (*s) { + case 's': + case 'S': + break; + case 'm': + case 'M': + n *= 60; + break; + case 'h': + case 'H': + n *= 3600; + break; + case 'd': + case 'D': + n *= 86400; + break; + case 'w': + case 'W': + n *= 604800; + break; + default: + break; + } + return n + parsetime(s+1); + } + else return n + parsetime(s); +} + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + int i, noEntries, maxnumb; + char **msgs; + struct stat statbuf; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + if (name != NULL) free(name); + if (mychan->ch_chan_type != CH_DEBRIS) { + PP_OPER(NULLCP, + ("Channel '%s' incorrect type [expecting type=debris (%d)]", + mychan->ch_name, mychan->ch_chan_type)); + return NOTOK; + } + + if (mychan->ch_out_info != NULLCP) + interval = parsetime(mychan->ch_out_info); + else if (mychan->ch_in_info != NULLCP) + interval = parsetime(mychan->ch_in_info); + else + interval = DEFAULT_INTERVAL; + + (void) time(¤t); + + /* scan the directory */ + + msgs = NULLVP; + noEntries = maxnumb = 0; + + hier_scanQ (quedfldir, NULLCP, + &noEntries, &msgs, + &maxnumb, rmNonMsg); + + for (i = 0; i < noEntries; i++) { + if (stat(msgs[i], &statbuf) != OK) { + PP_SLOG (LLOG_EXCEPTIONS, msgs[i], + ("Can't stat ")); + continue; /* just have got zapped? */ + } + if ((current - statbuf.st_mtime) < interval) { + if (testing == TRUE) + printf ("Ignore %s\n", msgs[i]); + continue; /* not yet ... */ + } + if (!S_ISDIR(statbuf.st_mode)) { + PP_OPER(NULLCP, + ("Msg entry for '%s' is not a directory", + msgs[i])); + continue; + } + if (okayToTrash(msgs[i]) == OK) + /* remove */ + my_recrm(msgs[i]); + } + + if (msgs) + free_hier(msgs, noEntries); + + return OK; +} + +static int okayToTrash(name) +char *name; +{ + struct stat statbuf; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + ADDR *ix = NULL; + + bzero ((char *)&prm, sizeof(prm)); + bzero ((char *)&que, sizeof(que)); + + /* test time for addr file */ + (void) sprintf(fullname, "%s/%s", name, aquefile); + if (stat(fullname,&statbuf) == OK) { + if ((current - statbuf.st_mtime) > interval) { + /* check to see if all recipients are done */ + + if (rp_isbad(rd_msg_file(name,&prm,&que, + &sender,&recips,&rcount, + RDMSG_RDONLY))) { + PP_LOG(LLOG_EXCEPTIONS, + ("rd_msg failure: '%s'", name)); + /* don't delete */ + return NOTOK; + } + rd_end(); + + /* now the recips */ + ix = que.Raddress; + while ((ix != NULL) && (ix->ad_status == AD_STAT_DONE)) + ix = ix->ad_next; + if (ix != NULL) + /* don't trash as some work needs to be done */ + return NOTOK; + + q_free(&que); + prm_free(&prm); + } else + return NOTOK; + } + return OK; +} + +/* */ +/* all work done in initialise */ +/* process is just a dummy routine */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_success); + return deliverystate; +} diff --git a/Chans/uucp/Makefile b/Chans/uucp/Makefile new file mode 100644 index 0000000..3a962fb --- /dev/null +++ b/Chans/uucp/Makefile @@ -0,0 +1,214 @@ +# Makefile for UUCP channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/uucp/RCS/Makefile,v 6.0 1991/12/18 20:13:06 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:13:06 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = uucp_out.c rfc8222uu.c rmail.c +OBJS = uucp_out.o rfc8222uu.o rmail.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xuucp_out xrmail + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# UUCP out channel +# +############################################################ + +xuucp_out: rfc8222uu.o uucp_out.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ rfc8222uu.o uucp_out.o $(LIBPP) $(LIBSYS) + +xt-rfc8222uu: rfc8222uu.o t-rfc8222uu.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ rfc8222uu.o t-rfc8222uu.o $(LIBPP) $(LIBSYS) + +saber_src: rfc8222uu.c uucp_out.c + #load -C $(CFLAGS) rfc8222uu.c uucp_out.c $(LIBPP) $(LIBSYS) + +install: inst-dir inst-uucp-out inst-uucp-in +inst-uucp-out: $(CHANDIR)/uucp-out +$(CHANDIR)/uucp-out: xuucp_out + -$(BACKUP) $@ zxuucp_out + rm -f $@ + $(INSTALL) xuucp_out $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "UUCP outbound channel installed normally"; echo "" + +inst-uucp-in: $(CHANDIR)/rmail +$(CHANDIR)/rmail: xrmail + -$(BACKUP) $@ zxrmail + rm -f $@ + $(INSTALL) xrmail $@ + -$(CHOWN) $(PPUSER) $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHMOD) u+s $@ + -@ls -ls $@ + -@echo "UUCP inbound channel (rmail) installed normally"; echo "" + +inst-dir: $(CHANDIR) + +############################################################ +# +# UUCP in channel +# +############################################################ + +xrmail: rmail.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ rmail.o $(LIBPP) $(LIBSYS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core a.out *.old zxuucp_out $(PROGS) *.BAK + +lint: l-uucp-out l-rmail + +l-uucp-out: rfc8222uu.c uucp_out.c true + $(LINT) $(LLFLAGS) rfc8222uu.c uucp_out.c $(LINTLIBS) + +l-rmail: rmail.c true + $(LINT) $(LLFLAGS) rmail.c $(LINTLIBS) + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +uucp_out.o: uucp_out.c +uucp_out.o: ../../h/util.h +uucp_out.o: ../../h/config.h +uucp_out.o: ../../h/ll_log.h +uucp_out.o: ../../h/head.h +uucp_out.o: ../../h/util.h +uucp_out.o: ../../h/retcode.h +uucp_out.o: ../../h/qmgr.h +uucp_out.o: ../../h/Qmgr-types.h +uucp_out.o: ../../h/Qmgr-ops.h +uucp_out.o: ../../h/q.h +uucp_out.o: ../../h/adr.h +uucp_out.o: ../../h/list_rchan.h +uucp_out.o: ../../h/chan.h +uucp_out.o: ../../h/table.h +uucp_out.o: ../../h/list_bpt.h +uucp_out.o: ../../h/auth.h +uucp_out.o: ../../h/list_bpt.h +uucp_out.o: ../../h/extension.h +uucp_out.o: ../../h/mta.h +uucp_out.o: ../../h/adr.h +uucp_out.o: ../../h/list_bpt.h +uucp_out.o: ../../h/aparse.h +uucp_out.o: ../../h/ap.h +uucp_out.o: ../../h/util.h +uucp_out.o: ../../h/or.h +uucp_out.o: ../../h/chan.h +uucp_out.o: ../../h/auth.h +uucp_out.o: ../../h/list_rchan.h +uucp_out.o: ../../h/mta.h +uucp_out.o: ../../h/dr.h +uucp_out.o: ../../h/extension.h +uucp_out.o: ../../h/mta.h +uucp_out.o: ../../h/prm.h +rfc8222uu.o: rfc8222uu.c +rfc8222uu.o: ../../h/util.h +rfc8222uu.o: ../../h/config.h +rfc8222uu.o: ../../h/ll_log.h +rfc8222uu.o: ../../h/chan.h +rfc8222uu.o: ../../h/table.h +rfc8222uu.o: ../../h/list_bpt.h +rfc8222uu.o: ../../h/ap.h +rfc8222uu.o: ../../h/util.h +rfc8222uu.o: ../../h/adr.h +rfc8222uu.o: ../../h/list_rchan.h +rfc8222uu.o: ../../h/chan.h +rfc8222uu.o: ../../h/auth.h +rfc8222uu.o: ../../h/list_bpt.h +rfc8222uu.o: ../../h/extension.h +rfc8222uu.o: ../../h/mta.h +rfc8222uu.o: ../../h/adr.h +rfc8222uu.o: ../../h/list_bpt.h +rfc8222uu.o: ../../h/aparse.h +rfc8222uu.o: ../../h/ap.h +rfc8222uu.o: ../../h/or.h +rfc8222uu.o: ../../h/chan.h +rfc8222uu.o: ../../h/auth.h +rfc8222uu.o: ../../h/list_rchan.h +rmail.o: rmail.c +rmail.o: ../../h/util.h +rmail.o: ../../h/config.h +rmail.o: ../../h/ll_log.h +rmail.o: ../../h/head.h +rmail.o: ../../h/util.h +rmail.o: ../../h/retcode.h +rmail.o: ../../h/q.h +rmail.o: ../../h/adr.h +rmail.o: ../../h/list_rchan.h +rmail.o: ../../h/chan.h +rmail.o: ../../h/table.h +rmail.o: ../../h/list_bpt.h +rmail.o: ../../h/auth.h +rmail.o: ../../h/list_bpt.h +rmail.o: ../../h/extension.h +rmail.o: ../../h/mta.h +rmail.o: ../../h/adr.h +rmail.o: ../../h/list_bpt.h +rmail.o: ../../h/aparse.h +rmail.o: ../../h/ap.h +rmail.o: ../../h/util.h +rmail.o: ../../h/or.h +rmail.o: ../../h/chan.h +rmail.o: ../../h/auth.h +rmail.o: ../../h/list_rchan.h +rmail.o: ../../h/mta.h +rmail.o: ../../h/prm.h +rmail.o: ../../h/ap.h +rmail.o: ../../h/adr.h +rmail.o: ../../h/chan.h +rmail.o: ../../h/retcode.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/uucp/make b/Chans/uucp/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/uucp/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/uucp/rfc8222uu.c b/Chans/uucp/rfc8222uu.c new file mode 100644 index 0000000..4048569 --- /dev/null +++ b/Chans/uucp/rfc8222uu.c @@ -0,0 +1,249 @@ +/* rfc8222uu.c: routine to convert from rfc822 style address to a +uucp style address via uucp chan table lookup - code adapted from mmdf +original */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/uucp/RCS/rfc8222uu.c,v 6.0 1991/12/18 20:13:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/uucp/RCS/rfc8222uu.c,v 6.0 1991/12/18 20:13:06 jpo Rel $ + * + * $Log: rfc8222uu.c,v $ + * Revision 6.0 1991/12/18 20:13:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "ap.h" +#include "adr.h" +extern char *strdup(); +extern CHAN *mychan; +extern char *uuxstr, *rindex(); + +extern int ap_outtype; +static char nextnode[LINESIZE]; +static char who[LINESIZE]; +static char *MakeUucpFrom(); +static int ScanUucpFrom(); + +extern char *loc_dom_site, *loc_dom_mta; + +int rfc8222uu(host, orig, into) +char *host, + *orig, + **into; +{ + char *bangptr; + char linebuf[LINESIZE]; + char *atp, *percentp, *lp; + + AP_ptr loc_ptr, /* -- in case fake personal name needed -- */ + dom_ptr, + ap; + char adr[LINESIZE]; + + ap_outtype = AP_PARSE_733; + + ap_norm_all_domains(); + ap_use_percent (); + + if ((ap = ap_s2t(orig)) == NULLAP) + { + PP_LOG(LLOG_EXCEPTIONS, + ("Failure to parse address '%s'",orig)); + return NOTOK; + } + + (void) ap_t2p(ap, (AP_ptr *) NULL, (AP_ptr *) NULL, /*&group_ptr, &name_ptr,*/ + &loc_ptr, &dom_ptr, (AP_ptr *) NULL); /*&route_ptr);*/ + lp = ap_p2s_nc(NULLAP, NULLAP, loc_ptr, dom_ptr, NULLAP); /*route_ptr);*/ + + atp = index(lp, '@'); + if (atp != NULLCP) + *atp++ = '\0'; + if (!lexequ(atp, host)) + atp = NULLCP; /* don't make path-to-foo!foo.uucp!user */ + percentp = rindex(lp, '%'); + if (percentp != NULLCP) { + *percentp = '\0'; + if (atp) + (void) sprintf(adr, "%s!%s!%s", atp, ++percentp, lp); + else + (void) sprintf(adr, "%s!%s", ++percentp, lp); + } else if (atp) { + (void) sprintf(adr, "%s!%s", atp, lp); + } else + (void) strcpy(adr,lp); + PP_TRACE(("address = '%s'",adr)); + if (!isstr(host)) + (void) strcpy(who, adr); + else { + if (tb_k2val(mychan->ch_table, host, nextnode, TRUE) == NOTOK) { + return NOTOK; + } + (void) sprintf(who, nextnode, adr); + } + + /* Extract first host name for destination */ + if ((bangptr=index(who, '!')) != NULLCP) + { + /* at least one realy machine */ + *bangptr++ = '\0'; + (void) strcpy(nextnode, who); + (void) strcpy(who, bangptr); + } else (void) strcpy(nextnode, ""); + + (void) sprintf(linebuf, "%s %s!rmail \\(%s%s\\)", + uuxstr, nextnode, *who=='~' ? "\\\\" : "", who); + PP_TRACE(("Queuing UUCP mail for %s via %s...\n", + who, nextnode)); + *into = strdup(linebuf); + return OK; +} + +/* */ +/* routine to create realfrom string */ + +char * +findfrom (sender) +char *sender; +{ + int aptypesav; + char *adr; + AP_ptr ap; + AP_ptr local, + domain, + route; + +/* SEK have axed looking at top of file. */ +/* This may not be wise - but very much neater */ +/* Delver has no business being given UUCP style messsages */ + + if ((ap = ap_s2t (sender)) == NULLAP) + { + PP_LOG(LLOG_EXCEPTIONS, + ("Failure to parse address '%s'", sender)); + return (strdup (sender)); + } + + ap = ap_normalize (ap, CH_USA_PREF); + if(ap == (AP_ptr)MAYBE) + return( (char *)MAYBE); + ap_t2p (ap, (AP_ptr *) NULL, (AP_ptr *) NULL, &local, &domain, &route); + aptypesav = ap_outtype; + ap_outtype = AP_PARSE_733; + adr = ap_p2s_nc (NULLAP, NULLAP, local, domain, route); + if(adr == (char *)MAYBE){ + ap_outtype = aptypesav; + return(adr); + } + if (route == NULLAP) + { + if (domain->ap_islocal == TRUE) + { + free (adr); + adr = strdup (local -> ap_obvalue); + } + } + PP_TRACE(("sender = '%s'", adr)); + ap_outtype = aptypesav; + + lowerfy(adr); + return(MakeUucpFrom(adr)); +} + +/* + * This added by pc (UKC) to generate correct 'From' lines with + * `!' separated routes for uucp sites + * the rules + * a@b -> b!a + * a%b@c -> c!b!a + * etc + * a%b%c%d%e@x -> x!e!d!c!b!a + * This is done by a call to a recursive routine which I hope is OK + */ +static +char * +MakeUucpFrom(adr) +char *adr; +{ char *new; + register char *site; + + /*NOSTRICT*/ + if ((new = malloc((unsigned)strlen(adr)+1)) == (char *)0) + return ((char *)NOTOK); + /* + * Can we assume that this is a legal 733 address ? + * look for the first site + */ + site = rindex(adr, '@'); + if (site) + { *site++ = '\0'; + /* + * some input channels (notably ni_niftp) will add the + * name of the local machine into this address + * so we look for it and delete it if found + */ + /* + * if not the same then put back a % to let ScanUucpFrom work + */ + if (lexequ (loc_dom_site, site) != 0 + && lexequ (loc_dom_mta, site) != 0) + site[-1] = '%'; + } + ScanUucpFrom(new, adr); + free(adr); +#ifdef DEBUG + PP_TRACE(("sender (From line) = '%s'", new)); +#endif + return(new); +} + +static int +ScanUucpFrom(new, adr) +register char *new; +register char *adr; +{ register char *site; + + /* + * This presumes that the address we are scanning is somewhat + * legal - but the @ has been replaced by a % + */ + site = rindex(adr, '%'); + if (site == (char *)0) + { (void) strcpy(new, adr); + return; + } + *site++ = '\0'; + (void) strcpy(new, site); + new += strlen(site); + *new++ = '!'; + *new = '\0'; + ScanUucpFrom(new, adr); +} + +int getrealfrom(orig, realfrom) +ADDR *orig; +char **realfrom; +{ + if ((*realfrom = findfrom(orig->ad_r822adr)) != NULLCP) + return OK; + return NOTOK; +} + +/* */ + +/* + * LOWERFY() - convert string to lower case + */ +lowerfy (strp) + char *strp; +{ + while (*strp = uptolow (*strp)) + strp++; +} diff --git a/Chans/uucp/rmail.c b/Chans/uucp/rmail.c new file mode 100644 index 0000000..cf5d4e1 --- /dev/null +++ b/Chans/uucp/rmail.c @@ -0,0 +1,1286 @@ +/* rmail.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/uucp/RCS/rmail.c,v 6.0 1991/12/18 20:13:06 jpo Rel $"; +static char sccsid[] = "@(#)rmail.c 1.4 (UKNET Altered by pb/pc) 7/23/91"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/uucp/RCS/rmail.c,v 6.0 1991/12/18 20:13:06 jpo Rel $ + * + * $Log: rmail.c,v $ + * Revision 6.0 1991/12/18 20:13:06 jpo + * Release 6.0 + * + */ + + + +/* + * R M A I L . C + * + * Developed from the Berkeley mail program of the same name + * by Mike Obrien at RAND to run with the MMDF mail system. + * Rewritten by Doug Kingston, US Army Ballistics Research Laboratory + * Hacked a lot by Steve Bellovin (smb@unc) + * + * This program runs SETUID to Opr so that it can set effective and + * real [ug]ids to mmdflogin. + * + * Steve Kille - Aug 84 + * Take machete to it. Use protocol mode, + * and always go thru submit - phew + * Lee McLoughlin Oct 84. + * Address munges some header lines into 822 format. + * Peter Collinson Dec 85. + * Lee's version was dependent on + * (a) the uucp channel + * (b) the domain tables associated with the uucp channel + * This version costs more cycles (but there is generally + * only one of these running on a machine at a time) and + * uses mmdf's tables to dis-assemble bang routes converting + * them into a domain address. + * Peter Cowen Sept 89 + * PP'ised + * Julian Onions July 90 + * Choked to death on it! + * Piete Brooks June 90 + * converted ! recipient addresses to % and @ + * Peter Collinson July 1991 + * put things back to where they were when the mmdf version + * was done. Make a number of comments true again. + */ +#undef RUNALON + +#include "util.h" +#include "head.h" +#include "q.h" +#include "prm.h" +#include "ap.h" +#include "adr.h" +#include "chan.h" +#include "table.h" +#include "retcode.h" +#include +#include +#include +#include + +#define VERSION "3.0" +#define NAMESZ 256 /* Limit on component name size. + * LMCL was 64 */ +#define ungetline(s) ((void) strcpy (tmpline,s),usetmp=1) +#define MAXADRS 6 /* Max no. of adrs to output on a + * single line. */ + +#define NEED_QUOTE ": " /* chars in mailbox name that need `"'ing */ + +char debug = 0; + +extern char *loc_dom_site, *pplogin, *supportaddr, *hdr_822_bp, *ia5_bp, *cont_822; + + +extern char *index (); +extern char *rindex (); +extern char *getenv (); /* get the Accounting system from + * the environment */ +extern char *strdup (); +extern char *malloc (); +extern char *compress (); + +static char * canon_name(); + +FILE *rm_msgf; /* temporary out for message text */ +CHAN *chanptr; +int Tmpmode = 0600; +char Msgtmp[LINESIZE]; +char rm_date[LINESIZE]; /* date of origination from uucp + * header */ +char rm_from[LINESIZE]; /* accumulated path of sender */ +char origsys[NAMESZ]; /* originating system */ +char origpath[LINESIZE]; /* path from us to originating + * system */ +char Mailsys[LINESIZE]; /* Mail system signature */ +char tmpline[LINESIZE]; /* Temporary buffer for + * continuations and such */ +char usetmp = 0; /* Wether tmpline should be used */ +char linebuf[LINESIZE]; /* scratchpad */ +char nextdoor[LINESIZE]; /* The site nextdoor who sent the + * mail */ +char uchan[LINESIZE]; /* Channel to use for submission */ + +main (argc, argv) +char **argv; +int argc; +{ + char fromwhom[NAMESZ]; /* user on remote system */ + char *fromptr; + char sys[NAMESZ]; /* an element in the uucp path */ + char *cp, *d; + int fd; + + sys_init (argv[0]); + + while (argc > 2 && strcmp (argv[1], "-d") == 0) { + debug ++; + argc--; + argv++; + } + + if (argc < 2) { + fprintf (stderr, "Usage: rmail user [user ...]\n"); + exit (1); + } + (void) umask (0); + + pp_setuserid (); + (void) sprintf (Mailsys, "<%s@%s>", pplogin, loc_dom_site); + + /* Create temp file for body of message */ + (void) strcpy (Msgtmp, "/tmp/rmail.XXXXXX"); + (void) mktemp (Msgtmp); + if ((fd = creat (Msgtmp, Tmpmode)) < 0) + bomb ("Can't create %s\n", Msgtmp); + (void) close (fd); + + if ((rm_msgf = fopen (Msgtmp, "r+")) == NULL) + bomb ("Can't reopen %s\n", Msgtmp); + + (void) unlink (Msgtmp); + + /* + * Unravell the From and >From lines at the head of the + * message to work who sent it, the path it took to get + * here and when it was sent. Some or all of this info may + * be ignore depending on the 822 header info given. + */ + /* Zero fromwhom to stop channel crashing later on if no + * From or >From + */ + (void) strcpy(fromwhom, ""); + for (;;) { + if (fgets (linebuf, sizeof linebuf, stdin) == NULL) + break; + if (strncmp (linebuf, "From ", 5) + && strncmp (linebuf, ">From ", 6)) + break; + + cp = index (linebuf, ' '); /* start of name */ + fromptr = ++cp; + cp = index (cp, ' '); /* cp at end of name */ + *cp++ = 0; /* term. name, cp at date */ + (void) strcpy (fromwhom, fromptr); + while (isspace (*cp)) + cp++; /* Skip any ws */ + + /* + * The date is the rest of the line ending at \0 or + * remote + */ + d = rm_date; + while (*cp && strncmp (cp, " remote from ", 13)) + *d++ = *cp++; + *d = '\0'; + + for (;;) { + cp = index (cp + 1, 'r'); + if (cp == NULL) { + cp = rindex (fromwhom, '!'); + if (cp != NULL) { + char *p; + + *cp = '\0'; + p = rindex (fromwhom, '!'); + if (p != NULL) + (void) strcpy (origsys, p + 1); + else + (void) strcpy (origsys, fromwhom); + (void) strcat (rm_from, fromwhom); + (void) strcat (rm_from, "!"); + (void) strcpy (fromwhom, cp + 1); + goto out; + } + + /* + * Nothing coherent found - so look + * in environment for ACCTSYS + */ + if ((cp = getenv ("ACCTSYS")) && *cp) { + (void) strcpy (origsys, cp); + (void) strcat (rm_from, cp); + (void) strcat (rm_from, "!"); + goto out; + } + (void) strcpy(cp = sys, "remote from somewhere"); + } + if (strncmp (cp, "remote from ", 12) == 0) + break; + } + + (void) sscanf (cp, "remote from %s", sys); + (void) strcat (rm_from, sys); + (void) strcpy (origsys, sys); /* Save for quick ref. */ + (void) strcat (rm_from, "!"); +out: ; + } + if (fromwhom[0] == '\0')/* No from line, illegal */ + bomb ("%s", "No 'from' lines in message\n"); + + ungetline (linebuf); + + /* Complete the from field */ + (void) strcat (rm_from, fromwhom); + + /* + * A uk special - see if the first two components of the + * constructed bang address are in fact the same site. + * If so replace by their official name */ + domain_cross (rm_from); + + /* + * Save a copy of the path to the original site. This is + * all the the path we were given - the user name after the + * last !. NOTE: We keep the trailing !, hence the +1. + */ + (void) strcpy (origpath, rm_from); + *(rindex (origpath, '!') + 1) = '\0'; + + /* Savepath is given a copy of the immediate neighbour */ + if ((d = index (rm_from, '!')) != NULL) { + *d = '\0'; + (void) strcpy (nextdoor, rm_from); + *d = '!'; + } + else + (void) strcpy (nextdoor, rm_from); + + /* find the channel depending in the nextdoor site */ + set_channel (nextdoor); + + /* Convert the from to Arpa format and leave it in from */ + fromcvt (rm_from, fromwhom); + (void) strcpy (rm_from, fromwhom); + + if (debug) + printf ("from=%s, origpath=%s, date=%s\n", + rm_from, origpath, rm_date); + + msgfix (rm_from, rm_date); + + exit (xsubmit (rm_from, argv, argc)); + /* NOTREACHED */ +} + +/* + * Munge the message header. + * All header lines with addresses in are munged into 822 format. + * If no "From:" line is given supply one based on the UUCP Froms, do the + * same if no "Date:". + */ +typedef struct { + char *hname; + int hfound; +} Hdrselect; + +Hdrselect hdrselect[] = { + "date", 0, /* this is a little naughty - we + * need */ + /* to register that we have had this */ + /* but not address munge it */ + /* so it has token 0 */ + "from", 0, + "to", 0, + "cc", 0, + "bcc", 0, + "sender", 0, + "reply-to", 0, + "resent-from", 0, + "resent-sender", 0, + "resent-to", 0, + 0, 0 + +#define HDATE 0 +#define HFROM 1 +#define HTO 2 +#define HCC 3 +#define HBCC 4 +#define HSENDER 5 +#define HREPLY 6 +#define HRFROM 7 +#define HRSENDER 8 +#define HRTO 9 +}; + +/* Is this header in the list of those to have their addresses munged? */ +/* return header value offset value */ +/* notice that it returns 0 for the date header */ +shouldmunge (name) +char *name; +{ + register Hdrselect *h; + + if (debug > 1) + printf ("in shouldmunge with %s\n", name); + + for (h = hdrselect; h->hname != NULL; h++) + if (!lexequ (h->hname, name)) { + h->hfound++; + return (h - hdrselect); + } + return (0); +} + +/* If this is a header line then grab the name of the header and stuff it + * into name then return a pointer to the actually body of the line. + * Otherwise return NULL. + * NOTE: A header is a line that begins with a word formed of alphanums and + * dashes (-) then possibly some whitespace then a colon (:). + */ +char * + grabheader (s, name) +register char *s, *name; +{ + char *sanitise(); + char tmpbuf[LINESIZE]; + + /* Copy the name into name */ + while (isalpha (*s) || isdigit (*s) || *s == '-') + *name++ = *s++; + *name = '\0'; + + /* Skip any whitespace */ + while (isspace (*s)) + s++; + + /* This is a header if the next char is colon */ + if (*s == ':') { + s++; + + /* + * This is probably illegal but we fail horribly if + * it happens - so we will guard against it + */ + if (*s != ' ' && *s != '\t' && *s != '\0') { /* we need to add a + * space */ + (void) strcpy (tmpbuf, s); + (void) sprintf (s, " %s", tmpbuf); + } + return (sanitise(s)); /* Return a pointer to the rest of + * the line */ + } + else + return (NULL); +} + +msgfix (from, date) +char *from, *date; +{ + register char *s; + char *rest; + char *lkp; + char name[LINESIZE]; + char tmpbuf[LINESIZE]; + int haveheader = 0; /* Do I have a header? */ + int headertoken; + char *grabline (); + + /* Loop through all the headers */ + while (1) { + if (debug > 1) + printf ("in msgfix about to grabline\n"); + + s = grabline (); + + if (debug > 2) + printf ("got %s", s); + + /* Is this the end of the header? */ + if (*s == '\0' || *s == '\n' || feof (stdin)) + break; + + + /* Is this a continuation line? */ + if (haveheader && isspace (*s)) { + + /* + * Note: Address munged headers handled + * specially + */ + fputs (s, rm_msgf); + } + else { + + /* Grab the header name from the line */ + if ((rest = grabheader (s, name)) == NULL) + + /* + * Not a header therefore all + * headers done + */ + break; + + haveheader = 1; + + /* Should I address munge this? */ + if (headertoken = shouldmunge (name)) { + char *finalstr; + + finalstr = "\n"; + fprintf (rm_msgf, "%s: ", name); + + /* + * deal specially with From lines + * the parser loses comments so we + * retain them specially here + */ + if (headertoken == HFROM + || headertoken == HRFROM) { + if (lkp = index (rest, '<')) { + *lkp = '\0'; + if (*rest == ' ') + fprintf (rm_msgf, "%s<", rest + 1); + else + fprintf (rm_msgf, "%s<", rest); + *lkp = '<'; + finalstr = ">\n"; + (void) strcpy (tmpbuf, lkp); + + /* + * notice that we + * copy from the < + * to start with + * a space + */ + tmpbuf[0] = ' '; + rest = tmpbuf; + lkp = rindex (rest, '>'); + if (lkp) + *lkp = '\0'; + + } + if (lkp = index (rest, '(')) { + *lkp = '\0'; + (void) sprintf (tmpbuf, " (%s", lkp + 1); + finalstr = tmpbuf; + } + } + hadr_munge (rest); + fputs (finalstr, rm_msgf); + } + else + fputs (s, rm_msgf); + } + } + + /* No From: line was given, create one based on the From's */ + if (hdrselect[HFROM].hfound == 0) { + fprintf (rm_msgf, "From: %s\n", from); + } + + /* No Date: line was given, create one based on the From's */ + if (hdrselect[HDATE].hfound == 0) { + datecvt (date, tmpbuf); /* Convert from uucp -> + * Arpa */ + fprintf (rm_msgf, "Date: %s\n", tmpbuf); + } + + /* Copy the rest of the file, if there is any more */ + if (!feof (stdin)) { + + /* + * If the first line of the message isn't blank + * output the blank separator line. + */ + if (*s && *s != '\n') + (void) putc ('\n', rm_msgf); + do { + (void) fputs (s, rm_msgf); + s = grabline (); + } while (!feof (stdin)); + } +} + +char * + grabline () +{ + if (debug > 2) + printf ("in grabline "); + + /* + * Grab the next line. Remembering this might be the + * tmpline + */ + if (usetmp) { + if (debug > 2) + printf ("using tmpline "); + (void) strcpy (linebuf, tmpline); + usetmp = 0; + } + else + fgets (linebuf, sizeof linebuf, stdin); + + /* Anything wrong? */ + if (ferror (stdin)) + fputs ("\n *** Problem during receipt from UUCP ***\n", rm_msgf); + + if (debug > 2) + printf ("returning %s\n ", linebuf); + + return (linebuf); + +} + +char *next = NULL; /* Where nextchar gets the next + * char from */ +char adrs[LINESIZE]; /* Partly munged addresses go here */ + +nextchar () +{ + register char *s; /* scratch pointer. */ + + if (next != NULL && *next != '\0') { + if (debug > 5) + printf ("<%c>", *next); + return (*next++); + } + + /* The last buffer is now empty, fill 'er up */ + next = grabline (); + + if (feof (stdin) || !isspace (*next) || + *next == '\n' || *next == '\0') { + + /* + * Yipee! We've reached the end of the address + * list. + */ + ungetline (next); + next = NULL; /* Force it to read buffer */ + return (-1); + } + + /* Zap excess whitespace */ + (void) compress (next, adrs); + + /* + * This may be a slightly duff list generated by some of + * the UNIX mailers eg: "x y z" rather than "x,y,z" If it + * is in this ^^^^^^^ convert to ^^^^^^^ NOTE: This won't + * handle list: "x y" conversions! + */ + if (index (adrs, ' ') != NULL && + index (adrs, ',') == NULL && + index (adrs, '<') == NULL && + index (adrs, '(') == NULL && + index (adrs, '"') == NULL) { + for (s = adrs; *s; s++) + if (*s == ' ') + *s = ','; + } + next = adrs; + + /* + * This a continuation line so return in a seperator just + * in case + */ + return (','); +} + + +/* Munge and address list thats part of a header line. + * Try and get the ap_* (MMDF) routines to do as much as possible for + * us. + */ +hadr_munge (list) +char *list; +{ + AP_ptr the_addr; /* ---> THE ADDRESS <--- */ + int adrsout = 0; /* How many address have been + * output */ + + ungetline (list); + + while (1) { + AP_ptr ap_pinit (); + + the_addr = ap_pinit (nextchar); + + if (the_addr == (AP_ptr) NOTOK) + bomb ("%s", "cannot initialise address parser!"); + + ap_clear (); + + switch (ap_1adr ()) { + case NOTOK: + /* Something went wrong!! */ + ap_sqdelete (the_addr, (AP_ptr) 0); + ap_free (the_addr); + + /* + * Emergency action in case of parser break + * down: print out the rest of the line (I + * hope). + */ + fprintf (rm_msgf, "%s", tmpline); + continue; + case OK: + /* I've got an address to output! */ + + /* + * output a comma seperator between the + * addresses and a newline every once in a + * while to make sure the lines aren't too + * long + */ + if (adrsout++) + fprintf (rm_msgf, ",%s ", adrsout % MAXADRS ? "" : "\n"); + + /* Munge will do all the work to output it */ + munge (the_addr); + + /* Reclaim the space */ + ap_sqdelete (the_addr, (AP_ptr) 0); + ap_free (the_addr); + + if (debug > 4) + printf ("munged and space freed\n"); + break; + case DONE: + if (debug > 2) + printf ("hadr_munge all done\n"); + + /* Reclaim the space */ + ap_sqdelete (the_addr, (AP_ptr) 0); + ap_free (the_addr); + + return; + + } + } +} + +/* We now have a single address in the_addr to output. + */ +munge (the_addr) +AP_ptr the_addr; +{ + char adr[LINESIZE]; + char *s, *frees; + AP_ptr local, domain, route; + + if (debug > 1) + printf ("in munge with: "); + + /* Find where the important bits begin in the tree */ + ap_t2p (the_addr, (AP_ptr *) 0, (AP_ptr *) 0, + &local, &domain, &route); + + /* Convert from the tree back into a string */ + frees = s = ap_p2s_nc ((AP_ptr) 0, (AP_ptr) 0, local, domain, route); + + if (debug > 1) + printf ("%s\n", s); + + /* Is it a uucp style address? */ + if (domain == (AP_ptr) 0 && index (s, '!') != (char *) 0) { + char adr2[LINESIZE]; + + (void) strcpy (adr, s); + + /* + * Stick the path it took to get here at the start. + * But try to avoid any duplicates by overlapping + * the matching parts of the address. Eg: adr = + * 'x!y!z' path = 'a!b!x!y!' adr2 = 'a!b!x!y!z' + */ + for (s = origpath; *s; s++) { + /* Does it match? */ + if (strncmp (adr, s, strlen (s)) == 0) { + char c = *s; + + *s = '\0'; + (void) strcpy (adr2, origpath); + (void) strcat (adr2, adr); + *s = c; + break; + } + } + + /* + * Did I just scan the whole path without finding a + * match! + */ + if (*s == '\0') { + /* Append the adr to the path */ + (void) strcpy (adr2, origpath); + (void) strcat (adr2, adr); + } + + /* + * Munge the address into its shortest form and + * print it + */ + fromcvt (adr2, adr); + fprintf (rm_msgf, "%s", adr); + + if (debug > 1) + printf ("uucp munge gives %s\n", adr); + } + else { + char *p; + char *at; + char *official = NULL; + char *fmt; + char *brace; + AP_ptr norm; + extern int ap_outtype; + + /* Normalise the address */ + ap_outtype = AP_PARSE_733; /* Hmm. Maybe should be + * from channel */ + norm = ap_normalize (the_addr, CH_USA_PREF); + + /* Convert it back in to a string and output it */ + ap_t2s (norm, &p); + if (debug > 1) + printf ("Normalised address: %s\n", p); + + /* + * Look for the last address component and re-write + * to the + */ + + /* + * official form. There are probably better ways of + * doing this + */ + at = rindex (p, '@'); + fmt = "%s"; + if (at) { + brace = index (at + 1, '>'); + if (brace) + *brace = '\0'; + official = canon_name (at + 1); + if (official) { + *at = '\0'; + fmt = brace ? "%s@%s>" : "%s@%s"; + } + else if (brace) + *brace = '>'; + } + fprintf (rm_msgf, fmt, p, official); + + if (debug > 1) { + printf ("arpa munge gives "); + printf (fmt, p, official); + printf ("\n"); + } + if (official) free (official); + free (p); + } + free (frees); +} + + + +/* + * datecvt() -- convert UNIX ctime() style date to ARPA style + * (change done in place) + */ +datecvt (date, newdate) +char *date; +char *newdate; +{ + + /* + * LMCL: Changed the default timezone, when none given. + */ + + if (isdigit (date[0]) || date[3] == ',' || isdigit (date[5])) + (void) strcpy (newdate, date); /* Probably already ARPA */ + else if (isdigit (date[20])) + (void) sprintf (newdate, + "%.3s, %.2s %.3s %.2s %.2s:%.2s:%.2s GMT", + date, date + 8, date + 4, date + 22, + date + 11, date + 14, date + 17); + else if (isalpha (date[17])) /* LMCL. Bum Unix format */ + (void) sprintf (newdate, + "%.3s, %.2s %.3s %.2s %.2s:%.2s:00 GMT", + date, date + 8, date + 4, date + 23, + date + 11, date + 14); + else + (void) sprintf (newdate, + "%.3s, %.2s %.3s %.2s %.2s:%.2s:%.2s %.3s", + date, date + 8, date + 4, date + 26, + date + 11, date + 14, date + 17, date + 20); +} + + +msg_failure (addr, rp, reason) +char *addr; +RP_Buf *rp; +char *reason; +{ + extern char *getpostmaster(); + char buf[BUFSIZ]; + + if (rp) + (void) sprintf (buf, "%s: %s [%s]", + reason, rp->rp_line, + rp_valstr ((int)rp->rp_val)); + else + (void) sprintf (buf, "%s", reason); + + PP_LOG (LLOG_EXCEPTIONS, ("Message failure: %s", buf)); + + return msg_return (getpostmaster(AD_822_TYPE), addr, buf); +} + + +msg_return (addr, dest, reason) +char *addr, *dest, *reason; +{ + RP_Buf rp; + + io_end (NOTOK); + + if (rp_isbad (pps_1adr ("UUCP (rmail) Failed Message", addr, &rp))) + bomb ("pps_1adr failed [%s]", rp.rp_line); + if (rp_isbad (pps_txt ("Your message was not delivered to:\n ", &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + if (rp_isbad (pps_txt (dest, &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + if (rp_isbad (pps_txt ("\nFor the following reason:\n ", &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + if (rp_isbad (pps_txt (reason, &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + if (rp_isbad (pps_txt ("\n\n--------------- Returned Mail ---------------\n\n", &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + rewind (rm_msgf); + if (rp_isbad (pps_file (rm_msgf, &rp))) + bomb ("pps_file failed [%s]", rp.rp_line); + + if (rp_isbad (pps_txt ("--------------- End of Returned Mail -------------\n", &rp))) + bomb ("pps_txt failed [%s]", rp.rp_line); + if (rp_isbad (pps_end (OK, &rp))) + bomb ("pps_end failed [%s]", rp.rp_line); + return 0; +} + +/* */ + +static char * +pling2norm(to, from) +char *to; +char *from; +{ + char temp[1024]; + char *pling; + char *c; + int quote_it; + + (void) strcpy(temp, from); + *to = '\0'; + + /* copy over all (?) the hosts on the path */ + while (pling = rindex(temp, '!')) + { + quote_it = 0; + *(pling++) = '\0'; + if (*to) + (void) strcat(to, "%"); + else if (*pling != '"') + for ( c = NEED_QUOTE; *c; c++) + if (index(pling, *c)) { + quote_it = 1; + break; + } + if (quote_it) + (void) strcat (to, "\""); + (void) strcat(to, pling); + if (quote_it) + (void) strcat (to, "\""); + } + + quote_it = 0; + if (*to) + (void) strcat(to, "%"); + else if (*temp != '"') + for ( c = NEED_QUOTE; *c; c++) + if (index(temp, *c)) { + quote_it = 1; + break; + } + if (quote_it) + (void) strcat (to, "\""); + (void) strcat(to, temp); + if (quote_it) + (void) strcat (to, "\""); + if (pling = rindex(to, '%')) *pling = '@'; + if (debug > 1) printf("%s -> %s\n", from, to); + return to; +} +/* */ + +xsubmit (from, argv, argc) +char *from; +char **argv; +int argc; +{ + char buf[LINESIZE]; + RP_Buf rp; + struct prm_vars prm; + LIST_BPT *new; + ADDR *orig = NULL; + Q_struct que; + char *name = NULL; + int i; + int first_bp = TRUE; + + PP_NOTICE((">>> UUCP incoming message from %s", from)); + prm_init (&prm); + q_init (&que); + /* inbound channel, inbound host, contenttype */ + + prm.prm_opts = PRM_ACCEPTALL; + que.msgtype = MT_UMPDU; + que.encodedinfo.eit_types = NULLIST_BPT; + new = list_bpt_new (hdr_822_bp); + list_bpt_add (&que.encodedinfo.eit_types, new); + new = list_bpt_new (ia5_bp); + list_bpt_add (&que.encodedinfo.eit_types, new); + + que.inbound = list_rchan_new (origsys, chanptr->ch_name); + + rewind (rm_msgf); + + if (debug > 0) { + char buff[1024]; + + printf("From %s, ", from); + for (argv++; --argc > 0; argv++) + printf ("arg = %s (%s)\n", + pling2norm(buff, *argv), *argv); + while (fgets (buf, LINESIZE - 1, rm_msgf) != NULL) + printf ("T=%s", buf); + if (ferror (rm_msgf)) + bomb ("%s", "Error reading messge file"); + + exit (0); + } + + if (rp_isbad (io_init (&rp))) + return msg_failure (from, &rp, "io_init failed"); + + if (rp_isbad (io_wprm (&prm, &rp))) + return msg_failure (from, &rp, "io_wprm failed"); + if (rp_isbad (io_wrq (&que, &rp))) + return msg_failure (from, &rp, "io_wrq failed"); + + orig = adr_new (from, AD_822_TYPE, 0); + if (rp_isbad (io_wadr (orig, AD_ORIGINATOR, &rp))) + return msg_failure (from, &rp, + "Sender address unacceptable"); + + adr_free (orig); + + for (i = 1; i < argc; i++) { + ADDR *adr; + char buff[1024]; + + name = pling2norm(buff, argv[i]); + adr = adr_new (name, AD_822_TYPE, i); + if (rp_isbad (io_wadr (adr, AD_RECIPIENT, &rp))) + return msg_failure (name, &rp, + "Recipient address bad"); + PP_NOTICE(("valid recipient %s", argv[i])); + adr_free (adr); + } + + if (rp_isbad (io_adend (&rp))) + return msg_failure (name, &rp, "Address end failed"); + + if (rp_isbad (io_tinit (&rp))) + return msg_failure (name, &rp, "body initialisation failed"); + if (rp_isbad (io_tpart (hdr_822_bp, FALSE, &rp))) + return msg_failure (name, &rp, + "822 header initialisation failed"); + + rewind (rm_msgf); + first_bp = TRUE; + while (fgets (buf, LINESIZE - 1, rm_msgf) != NULL) { + if (first_bp == TRUE + && buf[0] == '\n') { + first_bp = FALSE; + if (rp_isbad (io_tdend (&rp))) + return msg_failure (name, &rp, + "header end failed"); + if (rp_isbad (io_tpart ("1.ia5", FALSE, &rp))) + return msg_failure (name, &rp, + "body initialisation failed"); + } + + if (rp_isbad (io_tdata (buf, strlen (buf)))) + return msg_failure (name, (RP_Buf *)0, + "data copied failed"); + } + if (ferror (rm_msgf)) + return msg_failure (name, (RP_Buf *)0, "Data copy failed"); + + if (rp_isbad (io_tdend (&rp))) + return msg_failure (name, &rp, "Text termination problem"); + + if (rp_isbad (io_tend (&rp))) + return msg_failure (name, &rp, "Termination problem"); + (void) io_end (OK); + PP_NOTICE(("Message successfully submitted")); + return 0; +} + + +/*VARARGS1*/ +#ifdef lint +bomb (fmt) +char *fmt; +{ + bomb (fmt); +} + +#else +bomb (va_alist) +va_dcl +{ + va_list ap; + char buf[BUFSIZ]; + + va_start (ap); + + _asprintf (buf, NULLCP, ap); + PP_LOG (LLOG_EXCEPTIONS, ("uucp bombing: %s", buf)); + va_end (ap); + + exit (99); +} +#endif + +/* + * fromcvt() -- trys to convert the UUCP style path into + * an ARPA style name. + */ +fromcvt (from, newfrom) +char *from, *newfrom; +{ + register char *cp; + register char *sp; + register char *off; + char *at; + char *atoff; + char buf[LINESIZE]; + + if (debug > 1) + printf ("fromcvt on %s\n", from); + + (void) strcpy (buf, from); + cp = rindex (buf, '!'); + if (cp == 0) { + (void) strcpy (newfrom, from); + return; + } + + /* + * look for @site at the end of the name + */ + atoff = NULL; + if ((at = index (cp, '@')) != NULL) { + /* got one - is it followed by a ! ? */ + if (index (at + 1, '!') != NULL) + at = NULL; + else { + /* look up the official name of the at site */ + atoff = canon_name (at + 1); + } + } + *cp = 0; + while (sp = rindex (buf, '!')) { + + /* + * scan the path backwards looking for hosts that + * we know about + */ + if (off = canon_name (sp + 1)) { + if (atoff && !lexequ (atoff, off)) + (void) strcpy (newfrom, cp + 1); + else + (void) sprintf (newfrom, "%s@%s", cp + 1, off); + if (atoff) free (atoff); + return; + } + else if (at && !lexequ (at + 1, sp + 1)) { + (void) strcpy (newfrom, cp + 1); + if (atoff) free(atoff); + return; + } + *cp = '!'; + cp = sp; + *cp = 0; + } + if (atoff) free(atoff); + if (off = canon_name (buf)) { + (void) sprintf (newfrom, "%s@%s", cp + 1, off); + free (off); + } + else + (void) sprintf (newfrom, "%s@%s", cp + 1, buf); +} + +/* + * This piece added by Peter Collinson (UKC) + * rather than just making rmail submit into the uucp channel which + * is hard coded. First look up in a table 'rmail.chans' for entries + * of the form + * nextdoor:channel + * If the name exists then use that channel otherwise just default to + * the uucp channel. This is for authorisation purposes really + * + * It seems to me to be much less confusing if we use the canonical + * name of the site in the channel lookup. This means that aliasing + * at the uucp level should map onto the correct site without + * having to install redundant names into the rmail table + * + * If we do this, then there's a good chance that canon_name will + * be called twice with the same key. So add a modicum of caching into + * canon_name() + */ +extern char *uucpin_chan; + +set_channel (nxt) +char *nxt; +{ + char *canon; + char *uucpc; + + uucpc = uucpin_chan; + + canon = canon_name(nxt); + if (canon == NULL) + canon = nxt; + if ((chanptr = ch_mta2struct (uucpc, canon)) == NULLCHAN) + bomb ("Cannot look up channel '%s'\n", uucpc); +} + +/* + * Check if the from machine which we have constructed actually + * contains two references to the same machine of the form + * site.uucp!site.??.uk!something + * if so replace by the single official name + */ +domain_cross (route) +char *route; +{ + char *second; + char *endsecond; + char *official; + char *host_equal (); + + second = index (route, '!'); + if (second == (char *) 0) + return; + second++; + endsecond = index (second, '!'); + if (endsecond == (char *) 0) + return; + second[-1] = '\0'; + *endsecond = '\0'; + if (official = host_equal (route, second)) { + char buf[LINESIZE]; + + /* Construct things in a seperate buffer to avoid problems + * caused by the overlap of route and endsecond. + * i.e. if len(official) > len(route!second) + */ + (void) strcpy (buf, official); + free (official); + *endsecond = '!'; + (void) strcat (buf, endsecond); + (void) strcpy(route, buf); + } + else { + second[-1] = '!'; + *endsecond = '!'; + } +} + +/* + * host_equal + * a routine to see whether the strings which are input + * are in fact the same host + * Returns the official name if they are and a null pointer if not + */ +char * +host_equal(n1, n2) + char *n1, *n2; +{ + char *o1, *o2; + char *canon_name(); + + if ((o1 = canon_name(n1)) == NULLCP) + return NULLCP; + if ((o2 = canon_name(n2)) == NULLCP) { + free (o1); + return(NULLCP); + } + if (lexequ (o1, o2) == 0) { + free (o2); + return o1; + } + free (o1); + free (o2); + return NULLCP; +} + +/* This procedure takes a string and converts all control characters + * to spaces. This is necessary to protect against the depradations + * of various out of spec mailers (HP-UX for example) which allow + * spurious control characters in headers. + */ +char * +sanitise(s) + char *s; +{ + char *t; + + /* Scan along string and convert all control characters except + * white space into space. + */ + for (t = s; *t; t++) + *t = (iscntrl(*t) && !isspace(*t)) ? ' ' : *t; + return (s); +} + +/* UUCP MUST work on USA order but we will be charitable */ +static int dmnorder = CH_USA_PREF; + +static char * +canon_name(host) + char *host; +{ + static char official[LINESIZE]; + static char lasthost[LINESIZE]; + char *ptr; + + if (lasthost[0]) + { if (lexequ(host, lasthost) == 0) + { if (debug > 0) + printf("canon_name cache hit: %s -> %s\n", + host, official); + return strdup(official); + } + } + if (rp_isbad(tb_getdomain(host, (char *)0, official, dmnorder, &ptr))) { + official[0] = lasthost[0] = '\0'; + /* must clear the cache, as official is now "(ERROR)" */ + return (char *) 0; + } + (void) strcpy(lasthost, host); + return strdup(official); +} diff --git a/Chans/uucp/t-rfc8222uu.c b/Chans/uucp/t-rfc8222uu.c new file mode 100644 index 0000000..e142308 --- /dev/null +++ b/Chans/uucp/t-rfc8222uu.c @@ -0,0 +1,44 @@ +/* t-rfc8222uu.c: test the rfc8222uu routine */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/uucp/RCS/t-rfc8222uu.c,v 6.0 1991/12/18 20:13:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/uucp/RCS/t-rfc8222uu.c,v 6.0 1991/12/18 20:13:06 jpo Rel $ + * + * $Log: t-rfc8222uu.c,v $ + * Revision 6.0 1991/12/18 20:13:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" + +CHAN *mychan; + +main(argc, argv) +int argc; +char **argv; +{ + char *into; + + if (argc != 3) { + printf("usage: %s host adr",argv[0]); + exit(1); + } + sys_init(argv[0]); + if ((mychan = ch_nm2struct("uucp-out")) == NULLCHAN) { + printf("unable to find uucp-out channel\n"); + exit(1); + } + if (rfc8222uu(argv[1], argv[2], &into) != OK) + printf ("failed to convert '%s' at %s\n",argv[2],argv[1]); + else { + printf("%s at %s\n\t-> %s\n",argv[2],argv[1],into); + free(into); + } +} diff --git a/Chans/uucp/uucp_out.c b/Chans/uucp/uucp_out.c new file mode 100644 index 0000000..606da12 --- /dev/null +++ b/Chans/uucp/uucp_out.c @@ -0,0 +1,630 @@ +/* uucp_out.c: uucp outbound channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/uucp/RCS/uucp_out.c,v 6.0 1991/12/18 20:13:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/uucp/RCS/uucp_out.c,v 6.0 1991/12/18 20:13:06 jpo Rel $ + * + * $Log: uucp_out.c,v $ + * Revision 6.0 1991/12/18 20:13:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "dr.h" +#include "prm.h" +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#define VOLATILE volatile +#else +#define VOLATILE +#endif + +#ifndef WCOREDUMP +#define WCOREDUMP(x) (((union wait *)&(x))->w_coredump) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif +#ifndef WTERMSIG +#define WTERMSIG(x) (((union wait *)&(x)) -> w_termsig) +#endif + +extern char *quedfldir, + *chndfldir, + *logdfldir, + *hdr_822_bp; + +extern CHAN *ch_nm2struct(); +extern char *loc_dom_mta; +extern int rfc8222uu(); +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; +char *myhostname; +char *uuxstr; +int first_successDR; + +static struct type_Qmgr_DeliveryStatus *process(); +static void set_success(); +static void dirinit(); +static ADDR *getnthrecip(); +static jmp_buf toplevel; +static int pipe_signaled; +static int data_bytes; +static int initialise(); + +static int processMsg(), doProcess(), send_to_child(); +/* ARGSUSED */ +static SFD sig_pipe(sig) +int sig; +{ + pipe_signaled = TRUE; + longjmp (toplevel, DONE); +} + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); + dirinit(); +#ifdef PP_DEBUG + if (argc>1 && (strcmp (argv[1],"debug") == 0)) + debug_channel_control (argc,argv,initialise,process, NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ + +static CMD_TABLE uucptbl[] = { +#define TBL_UUXCMD 1 + "uux", TBL_UUXCMD, +#define TBL_HOST 2 + "host", TBL_HOST, + 0, -1 + }; + +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name, *p; + char *argv[20]; + int i, argc; + char buffer[BUFSIZ]; + + if (uuxstr) free (uuxstr); + uuxstr = NULLCP; + if (myhostname) free (myhostname); + myhostname = NULLCP; + + name = qb2str (arg); + + if ((mychan = ch_nm2struct (name)) == NULLCHAN) { + PP_OPER (NULLCP, ("Chan/uucp_out : Channel '%s' not known",name)); + if (name != NULL) free (name); + return NOTOK; + } + + if (mychan -> ch_out_info == NULLCP) { + PP_OPER (NULLCP, ("%s channel (%s) has no info parameter", + mychan -> ch_name, mychan -> ch_show)); + return NOTOK; + } + (void) strcpy (buffer, mychan -> ch_out_info); + if ((argc = sstr2arg (buffer, 20, argv, ",")) <= 0) { + PP_LOG (LLOG_EXCEPTIONS, ("Info string unparseable")); + return NOTOK; + } + + for (i = 0; i < argc; i++) { + if ((p = index (argv[i], '=')) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Info string for %s not in key=val format", + mychan -> ch_name)); + return NOTOK; + } + *p++ = '\0'; + switch (cmd_srch (argv[i], uucptbl)) { + case TBL_UUXCMD: + uuxstr = strdup (p); + break; + + case TBL_HOST: + myhostname = strdup (p); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown key in chan info for %s '%s'", + mychan -> ch_name, + argv[i])); + return NOTOK; + } + } + if (uuxstr == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("uux not set in info")); + return NOTOK; + } + if (myhostname == NULLCP) + myhostname = strdup (loc_dom_mta); + + (void) signal (SIGCHLD, SIG_DFL); + if (name != NULL) free (name); + return OK; +} + +/* */ +/* routine to check if allowed to filter this message through this channel */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp (msg_chan,mychan->ch_name) != 0)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Chans/shell channel err: '%s'",msg_chan)); + result = FALSE; + } + + /* free all storage used */ + if (msg_file != NULL) free (msg_file); + if (msg_chan != NULL) free (msg_chan); + return result; +} + +/* */ +/* routine called to do uucp */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *realfrom = NULL; + bzero ((char *) &que,sizeof (que)); + bzero ((char *) &prm,sizeof (prm)); + + delivery_init (arg->users); + delivery_setall (int_Qmgr_status_messageFailure); + first_successDR = TRUE; + + if (security_check (arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free (this_msg); + if (this_chan != NULL) free (this_chan); + + this_msg = qb2str (arg->qid); + this_chan = qb2str (arg->channel); + + PP_LOG (LLOG_NOTICE, + ("%s processing msg '%s'",mychan->ch_name,this_msg)); + + if (rp_isbad (rd_msg (this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s rd_msg err: '%s'",mychan->ch_name,this_msg)); + rd_end(); + return deliverystate; + } + + + if (getrealfrom (sender, &realfrom) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s unable to construct real sender message for orig of message '%s'",mychan->ch_name,this_msg)); + rd_end(); + return deliverystate; + } + + if (arg->users == NULL) + PP_LOG (LLOG_NOTICE, + ("%s : passed a NULL user list for message '%s'", + mychan->ch_name, + this_msg)); + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip (&que,(int)ix->RecipientId->parm)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s : failed to find recipient %d of msg '%s'",mychan->ch_name,ix->RecipientId->parm, this_msg)); + delivery_set ((int)ix->RecipientId->parm, int_Qmgr_status_messageFailure); + continue; + } + + switch (chan_acheck (adr, mychan, 1, NULLVP)) { + case OK: + if (processMsg (this_msg,adr, realfrom) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s : failed to process msg '%s' for recip '%d' on channel '%s'",mychan->ch_name,this_msg, adr->ad_no, this_chan)); + delivery_set (adr->ad_no, int_Qmgr_status_messageFailure); + } else { + PP_LOG (LLOG_NOTICE, + ("%s : processed '%s' for recipient %d",mychan->ch_name,this_msg,adr->ad_no)); + set_success (adr, &que, this_msg); + } + break; + default: + break; + } + } + + if (rp_isbad (retval = wr_q2dr (&que, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs (int_Qmgr_status_messageFailure); + } + + rd_end(); + if (realfrom != NULL) free (realfrom); + return deliverystate; +} + +static void set_success (recip, que, msg) +ADDR *recip; +Q_struct *que; +char *msg; +{ + if (recip->ad_usrreq == AD_USR_CONFIRM || + recip->ad_mtarreq == AD_MTA_CONFIRM || + recip->ad_mtarreq == AD_MTA_AUDIT_CONFIRM) { + set_1dr (que, recip->ad_no, this_msg, + DRR_NO_REASON, -1, NULLCP); + delivery_set (recip->ad_no, + (first_successDR == TRUE) ? int_Qmgr_status_positiveDR : int_Qmgr_status_successSharedDR); + } else { + (void) wr_ad_status (recip, AD_STAT_DONE); + (void) wr_stat (recip, que, this_msg, data_bytes); + delivery_set (recip->ad_no, int_Qmgr_status_success); + } +} + +/* */ +static int processMsg (msg,recip, realfrom) +/* returns OK if managed to process msg for recip on mychan */ +char *msg; +ADDR *recip; +char *realfrom; +{ + char *origdir = NULL, + *cmdline = NULL; + int result = OK; + + if (qid2dir (msg, recip, TRUE, &origdir) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s original directory not found for recipient %d of message '%s'",mychan->ch_name,recip->ad_no, msg)); + result = NOTOK; + } + + if (result == OK && + mychan->ch_out_info == NULL) { + PP_OPER (NULLCP, + ("%s uux pathname not given in info string",mychan->ch_name)); + result = NOTOK; + } + + if (result == OK && + rfc8222uu (recip->ad_outchan->li_mta,recip->ad_r822adr, &cmdline) != OK) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s unable to convert to uucp format address of recip %d of message '%s'",mychan->ch_name,recip->ad_no, msg)); + result = NOTOK; + } + + if ((result == OK) && (doProcess (origdir,msg, cmdline, realfrom) != OK)) + result = NOTOK; + + if (origdir != NULL) free (origdir); + if (cmdline != NULL) free (cmdline); + return result; +} + +/* */ + +static int sigpiped, sigalarmed; +static SFD alarmed(), piped(); +static jmp_buf pipe_alrm_jmp; + +static int doProcess (orig, msg, cmdline, realfrom) +/* processes orig directory contents through mychan */ +char *orig, /* original directory */ + *msg, /* message */ + *cmdline,/* uucp cmdline */ + *realfrom;/* real sender */ +{ + int fd[2], + result = OK, + pid, + pgmresult, + margc; + char *program = NULL, + *margv[20]; + SFP oldalarm, oldpipe; + VOLATILE int killed = 0; + struct stat statbuf; + + if (pipe (fd) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s pipe failed",mychan->ch_name)); + return NOTOK; + } + + if ((margc = sstr2arg (cmdline, 20, margv, " \t")) < 1) + return NOTOK; + + if (margv[0][0] == '/') + /* given full path name */ + program = strdup (margv[0]); + else { + program = (char *) malloc ((unsigned int) (strlen (chndfldir) + 1 + strlen (margv[0]) + 1)); + (void) sprintf (program,"%s/%s",chndfldir,margv[0]); + } + + if (stat (program, &statbuf) != OK) { + PP_OPER (NULLCP, + ("%s : missing uux program '%s'",mychan -> ch_name, program)); + return NOTOK; + } + if ((pid = tryfork()) == 0) { + /* in child so redirect in- and out-put */ + (void) dup2 (fd[0], 0); + (void) close (fd[0]); + (void) close (fd[1]); + (void) setpgrp (0, getpid()); + + (void) execv (program,margv); + _exit (1); + } else if (pid == -1) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s: tryfork failed for msg %s", + mychan->ch_name,this_msg)); + (void) close (fd[1]); + result = NOTOK; + } else { +#ifdef SYS5 + int w; +#else + union wait w; +#endif + + oldalarm = signal (SIGALRM, alarmed); + oldpipe = signal (SIGPIPE, piped); + sigpiped = 0; + sigalarmed = 0; + data_bytes = 0; + + if (setjmp (pipe_alrm_jmp) != DONE) { + if (send_to_child (orig, fd[1], realfrom) == NOTOK) + result = NOTOK; + (void) close (fd[1]); + } else { + if (sigalarmed) + PP_TRACE (("alarm went off")); + if (sigpiped) + PP_TRACE (("pipe went off")); + } + + if (sigpiped) { /* pipe died - reset for timeout */ + sigpiped = 0; + if (setjmp (pipe_alrm_jmp) == DONE) + PP_TRACE (("Timeout")); + } + + if (sigalarmed) { /* alarm went off */ + PP_NOTICE (("Process taking too long ... killing")); + killed = 1; + (void) killpg (pid, SIGTERM); + sleep (2); + (void) killpg (pid, SIGKILL); + } + +#ifdef SYS5 + while ((pgmresult = wait (&w)) != pid && + pgmresult != -1) +#else + while ((pgmresult = wait (&w.w_status)) != pid && + pgmresult != -1) +#endif + PP_TRACE (("process %d returned", pgmresult)); + + PP_TRACE (("pid %d returned term=%d, retcode=%d core = %d killed = %d", + pid, WTERMSIG(w), WEXITSTATUS(w), + WCOREDUMP(w), killed)); + (void) alarm (0); + + (void) signal (SIGPIPE, oldpipe); + (void) signal (SIGALRM, oldalarm); + + if ((pgmresult == pid) && (WEXITSTATUS(w) == 0) && (killed == 0)) + result = OK; + else + result = NOTOK; + } + (void) close (fd[0]); + + return result; +} + +/* ARGSUSED */ +static SFD alarmed(sig) +int sig; +{ + sigalarmed = 1; + longjmp (pipe_alrm_jmp, DONE); +} + +/* ARGSUSED */ +static SFD piped(sig) +int sig; +{ + sigpiped = 1; + longjmp (pipe_alrm_jmp, DONE); +} + +/* */ +static int write_to_child (file, fd_out) +char *file; +int fd_out; +{ + char buf[BUFSIZ]; + int fd_in, + num; + + if ((fd_in = open (file, O_RDONLY, 0666)) == -1) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s input file err '%s'",mychan->ch_name, file)); + return NOTOK; + } + + while ((num = read (fd_in, buf, BUFSIZ)) > 0) { + if (write (fd_out, buf, num) == -1) { + close (fd_out); + return NOTOK; + } + data_bytes += num; + } + close (fd_in); + return OK; +} + +static ADDR *getnthrecip (que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no < num)) + ix = ix->ad_next; + return ix; +} + +static LIST_RCHAN *getnthchannel (chans,num) +LIST_RCHAN *chans; +int num; +{ + LIST_RCHAN *ix = chans; + int icount = 0; + + while ((ix != NULL) && (icount++ < num)) + ix = ix->li_next; + + return ix; +} + +static char *get_adrstr (adr) +ADDR *adr; +{ + char *key; + switch (adr->ad_type) { + case AD_X400_TYPE: + key = adr->ad_r400adr; + break; + case AD_822_TYPE: + key = adr->ad_r822adr; + break; + default: + key = adr->ad_value; + break; + } + return key; +} + +static int is822hdr (file) +char *file; +{ + char *ix = rindex (file, '/'); + + if (ix == NULL + || (strncmp ((ix+1),hdr_822_bp,strlen (hdr_822_bp)) != 0)) + return FALSE; + else + return TRUE; +} + +static int send_to_child (orig, fd, realfrom) +char *orig; +int fd; +char *realfrom; +{ + char file[MAXPATHLENGTH]; + SFP old_sig; + char buf[BUFSIZ]; + time_t timenow; + int len; + + (void) time (&timenow); + + msg_rinit (orig); + + pipe_signaled = FALSE; + + /* set signal handler */ + old_sig = signal (SIGPIPE, sig_pipe); + + /* set long jump */ + setjmp (toplevel); + (void) sprintf (buf, "From %s %.24s remote from %s\n", + realfrom, ctime (&timenow), myhostname); + len = strlen (buf); + if (write (fd, buf, len) != len) + return NOTOK; + data_bytes += len; + + while (pipe_signaled == FALSE + && msg_rfile (file) == RP_OK) { + if (write_to_child (file, fd) == NOTOK) { + msg_rend (); + return NOTOK; + } + if (is822hdr (file) == TRUE) { + if (write (fd, "\n", 1) != 1) + return NOTOK; + data_bytes ++; + } + } + + msg_rend(); + + /* unset signal handler */ + (void) signal (SIGPIPE, old_sig); + return OK; +} diff --git a/Chans/warnings/Makefile b/Chans/warnings/Makefile new file mode 100644 index 0000000..76c4a8c --- /dev/null +++ b/Chans/warnings/Makefile @@ -0,0 +1,134 @@ +# Preliminary comments +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/warnings/RCS/Makefile,v 6.0 1991/12/18 20:13:32 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:13:32 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = warnings.c +OBJS = warnings.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xwarnings + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# warnings channel +# +############################################################ + +xwarnings: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# misc stuff +# +############################################################ + +install: inst-dir inst-warnings + +inst-warnings: $(CHANDIR)/warnings +$(CHANDIR)/warnings: xwarnings + -$(BACKUP) $@ zxwarnings + rm -f $@ + $(INSTALL) xwarnings $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "warnings channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f $(PROGS) core a.out Makefile.old + +lint: l-warnings + +l-warnings: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +warnings.o: warnings.c +warnings.o: ../../h/util.h +warnings.o: ../../h/config.h +warnings.o: ../../h/ll_log.h +warnings.o: ../../h/retcode.h +warnings.o: ../../h/expand.h +warnings.o: ../../h/qmgr.h +warnings.o: ../../h/Qmgr-types.h +warnings.o: ../../h/Qmgr-ops.h +warnings.o: ../../h/q.h +warnings.o: ../../h/adr.h +warnings.o: ../../h/list_rchan.h +warnings.o: ../../h/chan.h +warnings.o: ../../h/table.h +warnings.o: ../../h/list_bpt.h +warnings.o: ../../h/auth.h +warnings.o: ../../h/list_bpt.h +warnings.o: ../../h/extension.h +warnings.o: ../../h/mta.h +warnings.o: ../../h/adr.h +warnings.o: ../../h/list_bpt.h +warnings.o: ../../h/aparse.h +warnings.o: ../../h/ap.h +warnings.o: ../../h/util.h +warnings.o: ../../h/or.h +warnings.o: ../../h/chan.h +warnings.o: ../../h/auth.h +warnings.o: ../../h/list_rchan.h +warnings.o: ../../h/mta.h +warnings.o: ../../h/prm.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/warnings/make b/Chans/warnings/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/warnings/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/warnings/warnings.c b/Chans/warnings/warnings.c new file mode 100644 index 0000000..f834686 --- /dev/null +++ b/Chans/warnings/warnings.c @@ -0,0 +1,628 @@ +/* warnings.c: send warning messages back to originator */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/warnings/RCS/warnings.c,v 6.0 1991/12/18 20:13:32 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/warnings/RCS/warnings.c,v 6.0 1991/12/18 20:13:32 jpo Rel $ + * + * $Log: warnings.c,v $ + * Revision 6.0 1991/12/18 20:13:32 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "retcode.h" +#include "expand.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include + +static int initialise(); +static struct type_Qmgr_DeliveryStatus *process(), *submit_warning(); +static int endfunc(); +static void dirinit(); +static ADDR *getnthrecip(); + +extern char *quedfldir, *loc_dom_site, *loc_dom_mta, + *getpostmaster(), *hdr_822_bp, *ia5_bp; + +int start_submit; +CHAN *mychan; +#ifdef COPYTO_ADDRESS +char *copyAddr = NULLCP; +#endif + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && strcmp(argv[1], "debug") == 0) + debug_channel_control(argc,argv,initialise,process,endfunc); + else +#endif + channel_control(argc,argv,initialise,process,endfunc); +} + +/* */ +/* move to correct place in file system */ + +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* initialise */ + +static void decode_ch_info (info) +char *info; +{ + char *info_copy; + int margc, i; + char *margv[100]; + +#ifdef COPYTO_ADDRESS + copyAddr = NULLCP; +#endif + info_copy = strdup(info); + margc = sstr2arg(info_copy, 100, margv, ",="); + + for (i = 0; i < margc; i++) { + if (!isstr(margv[i])) + continue; +#ifdef COPYTO_ADDRESS + if (lexequ(margv[i], "copy-to") == 0) { + i++; + if (i >= margc) + copyAddr = getpostmaster(mychan->ch_out_ad_type); + else + copyAddr = strdup(margv[i]); + } else +#endif + PP_LOG (LLOG_EXCEPTIONS, + ("Unrecognised ch_out_info element '%s'", + margv[i])); + } +} + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("warnings: Channel '%s' not knpown", + name)); + if (name) free(name); + return NOTOK; + } + + /* check is a warning channel */ + if (mychan->ch_chan_type != CH_WARNING) { + PP_OPER(NULLCP, + ("warnings: Channel '%s' is not specified as type warning", + name)); + if (name) free(name); + } + if (name) free(name); + + if (mychan->ch_out_info) + decode_ch_info(mychan->ch_out_info); + + start_submit = TRUE; + + return OK; +} + +/* */ + +static void stop_io() +{ + if (start_submit == FALSE) + io_end(OK); + start_submit = TRUE; +} + +/* ARGSUSED */ +static int endfunc(arg) +struct type_Qmgr_Channel *arg; +{ + stop_io(); +} + +/* */ +/* routine to check if allowed to filter this message through this channel */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/fcontrol channel err: '%s'",msg_chan)); + result = FALSE; + } + + /* free all storage used */ + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to send warning */ + +static struct type_Qmgr_DeliveryStatus *process(arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULLADDR; + ADDR *recips = NULLADDR; + char *this_msg; + int rcounts; + struct type_Qmgr_DeliveryStatus *retval; + + + prm_init (&prm); + q_init(&que); + + sender = recips = NULLADDR; + + delivery_init (arg->users); + delivery_setall (int_Qmgr_status_success); /* always lie! */ + + if (security_check(arg) != TRUE) + return deliverystate; + + /* ok - send a warning */ + this_msg = qb2str (arg->qid); + + + if (rp_isbad(rd_msg(this_msg, &prm, &que, + &sender, &recips, &rcounts))) { + PP_LOG(LLOG_EXCEPTIONS, + ("warnings: rd_msg error '%s'", this_msg)); + rd_end(); + if (this_msg) free(this_msg); + q_free(&que); + + return deliverystate; + } + + if (que.nwarns == NOTOK) /* old message */ + return delivery_setall(int_Qmgr_status_success); /* lie */ + fillin_expansions(&que, arg->users, this_msg); + + PP_NOTICE(("sending warning for msg %s", this_msg)); + if ((retval = submit_warning(&que)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + rd_end(); + return retval; + } + + inc_warnings(&que); + + rd_end(); + + if (this_msg) free(this_msg); + q_free(&que); + prm_free(&prm); + + return delivery_setall (int_Qmgr_status_success); +} + +/* */ + +inc_warnings(q) +Q_struct *q; +{ + q->nwarns++; + wr_q_nwarns(q); +} + +/* */ +/* fillin the various things that can be expanded in the warning message */ + +Expand expand_macros[] = { + "sender", NULLCP, /* 0 */ + "822sender", NULLCP, /* 1 */ + "400sender", NULLCP, /* 2 */ + "qid", NULLCP, /* 3 */ + "ua-id", NULLCP, /* 4 */ + "p1-id", NULLCP, /* 5 */ + "recips", NULLCP, /* 6 */ + "822recips", NULLCP, /* 7 */ + "400recips", NULLCP, /* 8 */ + "locmta", NULLCP, /* 9 */ + "locsite", NULLCP, /* 10 */ + "hours-left", NULLCP, /* 11 */ + NULLCP, NULLCP}; + +static char *add_string(porig, add) +char **porig; +char *add; +{ + char *new; + + if (*porig == NULLCP) + new = strdup(add); + else { + new = malloc (strlen (*porig) + + strlen ("\n") + + strlen (add) + + 1); + (void) sprintf(new, "%s\n%s", + *porig, + add); + free(*porig); + } + return new; +} + +fillin_expansions(q, users, this_msg) +Q_struct *q; +struct type_Qmgr_UserList *users; +char *this_msg; +{ + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *recips, *recips822, *recips400; + char hbuf[64]; + time_t now; + + recips = recips822 = recips400 = NULLCP; + + expand_macros[0].expansion = q->Oaddress->ad_value; + expand_macros[1].expansion = q->Oaddress->ad_r822adr; + expand_macros[2].expansion = q->Oaddress->ad_r400adr; + expand_macros[3].expansion = this_msg; + expand_macros[4].expansion = q->ua_id; + expand_macros[5].expansion = q->msgid.mpduid_string; + + for (adr = q -> Raddress; adr; adr = adr -> ad_next) { + if (adr -> ad_status == AD_STAT_PEND) { + recips = add_string(&recips, adr->ad_value); + recips822 = add_string(&recips822, adr->ad_r822adr); + recips400 = add_string(&recips400, adr->ad_r400adr); + } + } + if (expand_macros[6].expansion) + free(expand_macros[6].expansion); + expand_macros[6].expansion = recips; + + if (expand_macros[7].expansion) + free(expand_macros[7].expansion); + expand_macros[7].expansion = recips822; + + if (expand_macros[8].expansion) + free(expand_macros[8].expansion); + expand_macros[8].expansion = recips400; + expand_macros[9].expansion = loc_dom_mta; + expand_macros[10].expansion = loc_dom_site; + (void) time (&now); + (void) sprintf (hbuf, "%d", + q -> retinterval - + ((now - utc2time_t(q -> queuetime)) / 3600)); + expand_macros[11].expansion = strdup(hbuf); +} + +/* */ +/* submit warning message */ + +static char *expand_line(line) +char *line; +{ + char *margv[100], *ret, *cp; + int margc, len, i; + + cp = strdup(line); + compress(cp, cp); + if (*cp == '\0') { + free(cp); + return strdup(line); + } + if (index (line, '$')) + ret = expand_dyn (line, expand_macros); + else + ret = strdup (line); + return ret; +} + +/* for now */ +extern char *wrndfldir, *wrnfile; + +static char *q2warnfile(q) +Q_struct *q; +{ + static char filename[MAXPATHLENGTH]; + struct stat statbuf; + + (void) sprintf(filename, + "%s/%s.%d", + wrndfldir, + wrnfile, + q->nwarns + 1); + + if (stat(filename, &statbuf) == OK) + return filename; + + /* try for default warning */ + (void) sprintf(filename, + "%s/%s", + wrndfldir, + wrnfile); + if (stat(filename, &statbuf) == OK) + return filename; + return NULLCP; +} + +static void submit_error(proc, rp) +char *proc; +RP_Buf *rp; +{ + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/warnings %s failure [%s]", + proc, rp->rp_line)); + start_submit = TRUE; + io_end(NOTOK); +} + +#define fold_and_submit_line submit_line + +static struct type_Qmgr_DeliveryStatus *submit_line(line, rp) +char *line; +RP_Buf *rp; +{ + if (rp_isbad(io_tdata (line, strlen(line)))) { + submit_error ("io_tdata", rp); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_tdata failed"); + } + return (struct type_Qmgr_DeliveryStatus *) OK; +} + +static struct type_Qmgr_DeliveryStatus *submit_warning(q) +Q_struct *q; +{ + struct prm_vars prm; + Q_struct qs; + char *warningfile; + RP_Buf reply; + char buffer[BUFSIZ], timestr[BUFSIZ], *expanded; + struct type_Qmgr_DeliveryStatus *retval; + FILE *fp; + UTC now, start_time, utclocalise (); + + + now = utcnow (); + start_time = utclocalise (now); + free ((char *)now); + + prm_init(&prm); + q_init(&qs); + + qs.inbound = list_rchan_new (loc_dom_site, + mychan->ch_name); + qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp); + list_bpt_add(&qs.encodedinfo.eit_types, + list_bpt_new (ia5_bp)); + qs.Oaddress = adr_new (getpostmaster(AD_822_TYPE), AD_822_TYPE, 0); + qs.Raddress = adr_new (q->Oaddress->ad_r822adr, AD_822_TYPE, 1); +#ifdef COPYTO_ADDRESS + if (copyAddr != NULLCP) + qs.Raddress->ad_next = adr_new(copyAddr, + mychan->ch_out_ad_type, 1); +#endif + + /* select which template warning message to use */ + if ((warningfile = q2warnfile(q)) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("unable to find warnings template warning")); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "unable to find warnings template file"); + } + + /* check submission started */ + if (start_submit == TRUE + && rp_isbad (io_init (&reply))) { + submit_error ("io_init", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "unable to start submit"); + } + + if (rp_isbad (io_wprm(&prm, &reply))) { + submit_error ("io_wprm", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_wprm failed"); + } + + if (rp_isbad (io_wrq(&qs, &reply))) { + submit_error ("io_wrq", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_wrq failed"); + } + + /* from postmaster@loc_dom_site */ + if (rp_isbad(io_wadr (qs.Oaddress, AD_ORIGINATOR, &reply))) { + submit_error ("io_wadr(postmaster)", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_wadr(postamster) failed"); + } + + /* to originator of message */ + + if (rp_isbad(io_wadr (qs.Raddress, AD_RECIPIENT, &reply))) { + submit_error ("io_wadr(recipient)", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_wadr(recipient) failed"); + } + +#ifdef COPYTO_ADDRESS + if (copyAddr != NULLCP && + qs.Raddress->ad_next != NULLADDR) { + if (rp_isbad(io_wadr (qs.Raddress->ad_next, AD_RECIPIENT, &reply))) { + submit_error ("io_wadr(recipient)", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_wadr(recipient) failed"); + } + } +#endif + + if (rp_isbad (io_adend (&reply))) { + submit_error ("io_adend", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_adend failed"); + } + + if (rp_isbad (io_tinit(&reply))) { + submit_error ("io_tinit", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_tinit failed"); + } + + /* submit header */ + + if (rp_isbad (io_tpart (hdr_822_bp, FALSE, &reply))) { + submit_error ("io_tpart", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_tpart failed"); + } + + (void) sprintf(buffer, "From: %s\n", qs.Oaddress->ad_value); + + if ((retval = submit_line(buffer, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + return retval; + } + + (void) sprintf(buffer, "To: %s\n", qs.Raddress->ad_value); + + if ((retval = submit_line(buffer, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + return retval; + } + +#ifdef COPYTO_ADDRESS + if (copyAddr != NULLCP) { + (void) sprintf(buffer, "Cc: %s\n", + copyAddr); + if ((retval = submit_line(buffer, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + return retval; + } + } +#endif + (void) UTC2rfc (start_time, timestr); + free ((char *)start_time); + start_time = NULLUTC; + + (void) sprintf(buffer, + "Date: %s\n", + timestr); + + if ((retval = submit_line(buffer, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + return retval; + } + + + (void) sprintf(buffer, + "Subject: WARNING: message delayed at \"%s\"\n", + loc_dom_site); + + if ((retval = submit_line(buffer, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + return retval; + } + + if (rp_isbad(io_tdend (&reply))) { + submit_error("io_tdend", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_tdend failed"); + } + + (void) sprintf(buffer, "1.%s", ia5_bp); + if (rp_isbad(io_tpart(buffer, FALSE, &reply))) { + submit_error ("io_tpart", &reply); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "io_tpart failed"); + } + + /* submit text of message */ + + if ((fp = fopen (warningfile, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, + warningfile, + ("Can't open file")); + stop_io(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "failed to open warnings file"); + } + + while (fgets (buffer, sizeof buffer, fp) != NULL) { + /* expand macros in that line */ + + if ((expanded = expand_line(buffer)) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to expand line in warning file '%s'", + warningfile)); + fclose(fp); + stop_io(); + return delivery_setallstate + (int_Qmgr_status_messageFailure, + "expansion of line failed"); + } + + if ((retval = fold_and_submit_line(expanded, &reply)) != + (struct type_Qmgr_DeliveryStatus *) OK) { + fclose (fp); + return retval; + } + + free(expanded); + + } + + fclose(fp); + if (rp_isbad(io_tdend (&reply)) + || rp_isbad(io_tend (&reply))) { + submit_error("io_tend failed", &reply); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "io_tend failed"); + } + + return (struct type_Qmgr_DeliveryStatus *) OK; +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} diff --git a/Chans/x40084/Makefile b/Chans/x40084/Makefile new file mode 100644 index 0000000..6225212 --- /dev/null +++ b/Chans/x40084/Makefile @@ -0,0 +1,377 @@ +# X400 inbound & outbound channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/Makefile,v 6.0 1991/12/18 20:13:50 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:13:50 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = P1_in.c P1_out.c P1_print.c Rts84-print.c Rts84-types.c \ + ut_logs.c \ + ut_misc.c ut_rts.c x400in84.c x400out84.c x400topp.c +OBJS = P1_in.o P1_out.o P1_print.o Rts84-print.o Rts84-types.o \ + ut_logs.o \ + ut_misc.o ut_rts.o x400in84.o x400out84.o x400topp.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) + +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xx400in84 xx400out84 + + +############################################################ +# +# Suffix rules +# +############################################################ + + +.SUFFIXES: .py + +.py.c: + $(PEPY) $(PYFLAGS) -a PY_advise $< + +.py.o: + $(PEPY) $(PYFLAGS) -a PY_advise $< + $(CC) $(CFLAGS) -c $*.c + rm $*.c + + +############################################################ +# +# Building Rules +# +############################################################ + + +default: $(PROGS) + + +lint: l-x400out84 l-x400in84 + +install: inst-dir inst-x400out84 inst-x400in84 + + +############################################################ +# +# X400out84 +# +############################################################ + +OUTSRCS = x400out84.c P1_out.c +OUTOBJS = x400out84.o P1_out.o + +x400out84: xx400out84 +xx400out84: $(OUTOBJS) libx400.a $(LIBPP) + $(CC) $(LDFLAGS) -o xx400out84 $(OUTOBJS) libx400.a \ + $(LIBPP) $(LIBSYS) + +saber_x400out: $(OUTSRCS) $(LIBSRC) + #load -C $(CFLAGS) $(OUTSRCS) $(LIBSRC) $(LIBPP) $(LIBSYS) + +l-x400out84: $(OUTSRCS) + $(LINT) $(LLFLAGS) $(OUTSRCS) $(LINTLIBS) + +inst-x400out84: $(CHANDIR)/x400out84 +$(CHANDIR)/x400out84: xx400out84 + -$(BACKUP) $@ zxx400out84 + rm -f $@ + $(INSTALL) xx400out84 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X400out84 channel installed normally"; echo "" + + +inst-dir: $(CHANDIR) $(TOOLDIR) + +############################################################ +# +# X400in84 +# +############################################################ + +INSRCS = x400in84.c P1_in.c x400topp.c +INOBJS = x400in84.o P1_in.o x400topp.o + +x400in84: xx400in84 +xx400in84: $(INOBJS) libx400.a $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(INOBJS) libx400.a $(LIBPP) $(LIBSYS) + + +inst-x400in84: $(CHANDIR)/x400in84 +$(CHANDIR)/x400in84: xx400in84 + -$(BACKUP) $@ zxx400in84 + rm -f $@ + $(INSTALL) xx400in84 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X400in84 channel installed normally"; echo "" + + +lint: l-x400in84 +l-x400in84: $(INSRCS) + $(LINT) $(LLFLAGS) $(INSRCS) $(LINTLIBS) + + +############################################################ +# +# X400 library +# +############################################################ + +LIBSRC = Rts84-print.c Rts84-types.c ut_logs.c ut_rts.c ut_misc.c P1_print.c +LIBOBJS = Rts84-print.o Rts84-types.o ut_logs.o ut_rts.o ut_misc.o P1_print.o + +libx400.a: $(LIBOBJS) + $(AR) r$(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + touch $@ + +Rts84-print.c: Rts_posy.py + $(PEPY) -a PY_advise -S PRINT -o $@ Rts_posy.py + +Rts84-types.h Rts84-types.c: Rts84-types.py + $(PEPY) -a PY_advise Rts84-types.py +# -cmp -s Rts84-types.h $(HEADERS)/Rts84-types.h || \ +# cp Rts84-types.h $(HEADERS)/Rts84-types.h + +Rts84-types.py: + $(POSY) $(POFLAGS) -f -h -o Rts84-types.py Rts_posy.py + +############################################################ +# +# Other things +# +############################################################ + +clean: tidy + rm -f $(OBJS) $(OUTOBJS) libx400.a + rm -f P1_out.c P1_in.c P1_print.c Rts84-* acsold.c Rts84-types.h + +tidy: + rm -f $(PROGS) core a.out *.ph *old *.BAK zxx* zxrts* + +depend: $(SRCS) + $(DEPEND) $(INCLUDE) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +P1_in.o: P1_in.c +P1_in.o: ../../h/head.h +P1_in.o: ../../h/util.h +P1_in.o: ../../h/config.h +P1_in.o: ../../h/ll_log.h +P1_in.o: ../../h/retcode.h +P1_in.o: ../../h/prm.h +P1_in.o: ../../h/q.h +P1_in.o: ../../h/adr.h +P1_in.o: ../../h/list_rchan.h +P1_in.o: ../../h/chan.h +P1_in.o: ../../h/table.h +P1_in.o: ../../h/list_bpt.h +P1_in.o: ../../h/auth.h +P1_in.o: ../../h/list_bpt.h +P1_in.o: ../../h/extension.h +P1_in.o: ../../h/mta.h +P1_in.o: ../../h/adr.h +P1_in.o: ../../h/list_bpt.h +P1_in.o: ../../h/aparse.h +P1_in.o: ../../h/ap.h +P1_in.o: ../../h/util.h +P1_in.o: ../../h/or.h +P1_in.o: ../../h/chan.h +P1_in.o: ../../h/auth.h +P1_in.o: ../../h/list_rchan.h +P1_in.o: ../../h/mta.h +P1_in.o: ../../h/or.h +P1_in.o: ../../h/dr.h +P1_in.o: ../../h/extension.h +P1_in.o: ../../h/mta.h +P1_out.o: P1_out.c +P1_out.o: ../../h/head.h +P1_out.o: ../../h/util.h +P1_out.o: ../../h/config.h +P1_out.o: ../../h/ll_log.h +P1_out.o: ../../h/retcode.h +P1_out.o: ../../h/q.h +P1_out.o: ../../h/adr.h +P1_out.o: ../../h/list_rchan.h +P1_out.o: ../../h/chan.h +P1_out.o: ../../h/table.h +P1_out.o: ../../h/list_bpt.h +P1_out.o: ../../h/auth.h +P1_out.o: ../../h/list_bpt.h +P1_out.o: ../../h/extension.h +P1_out.o: ../../h/mta.h +P1_out.o: ../../h/adr.h +P1_out.o: ../../h/list_bpt.h +P1_out.o: ../../h/aparse.h +P1_out.o: ../../h/ap.h +P1_out.o: ../../h/util.h +P1_out.o: ../../h/or.h +P1_out.o: ../../h/chan.h +P1_out.o: ../../h/auth.h +P1_out.o: ../../h/list_rchan.h +P1_out.o: ../../h/mta.h +P1_out.o: ../../h/or.h +P1_out.o: ../../h/dr.h +P1_out.o: ../../h/extension.h +P1_out.o: ../../h/mta.h +P1_out.o: ../../h/rtsparams.h +P1_print.o: P1_print.c +Rts84-print.o: Rts84-print.c +Rts84-types.o: Rts84-types.c +Rts84-types.o: Rts84-types.h +ut_logs.o: ut_logs.c +ut_logs.o: ../../h/util.h +ut_logs.o: ../../h/config.h +ut_logs.o: ../../h/ll_log.h +ut_misc.o: ut_misc.c +ut_misc.o: ../../h/util.h +ut_misc.o: ../../h/config.h +ut_misc.o: ../../h/ll_log.h +ut_misc.o: ../../h/tb_bpt84.h +ut_misc.o: ../../h/list_bpt.h +ut_rts.o: ut_rts.c +ut_rts.o: ../../h/util.h +ut_rts.o: ../../h/config.h +ut_rts.o: ../../h/ll_log.h +ut_rts.o: ../../h/rtsparams.h +ut_rts.o: ../../h/chan.h +ut_rts.o: ../../h/table.h +ut_rts.o: ../../h/list_bpt.h +ut_rts.o: Rts84-types.h +x400in84.o: x400in84.c +x400in84.o: ../../h/head.h +x400in84.o: ../../h/util.h +x400in84.o: ../../h/config.h +x400in84.o: ../../h/ll_log.h +x400in84.o: ../../h/retcode.h +x400in84.o: ../../h/prm.h +x400in84.o: ../../h/dr.h +x400in84.o: ../../h/extension.h +x400in84.o: ../../h/mta.h +x400in84.o: ../../h/adr.h +x400in84.o: ../../h/list_rchan.h +x400in84.o: ../../h/chan.h +x400in84.o: ../../h/table.h +x400in84.o: ../../h/list_bpt.h +x400in84.o: ../../h/auth.h +x400in84.o: ../../h/list_bpt.h +x400in84.o: ../../h/extension.h +x400in84.o: ../../h/mta.h +x400in84.o: ../../h/aparse.h +x400in84.o: ../../h/ap.h +x400in84.o: ../../h/util.h +x400in84.o: ../../h/or.h +x400in84.o: ../../h/chan.h +x400in84.o: ../../h/auth.h +x400in84.o: ../../h/list_rchan.h +x400in84.o: ../../h/list_bpt.h +x400in84.o: ../../h/q.h +x400in84.o: ../../h/adr.h +x400in84.o: ../../h/mta.h +x400in84.o: Rts84-types.h +x400out84.o: x400out84.c +x400out84.o: ../../h/head.h +x400out84.o: ../../h/util.h +x400out84.o: ../../h/config.h +x400out84.o: ../../h/ll_log.h +x400out84.o: ../../h/retcode.h +x400out84.o: ../../h/sys.file.h +x400out84.o: ../../h/prm.h +x400out84.o: ../../h/q.h +x400out84.o: ../../h/adr.h +x400out84.o: ../../h/list_rchan.h +x400out84.o: ../../h/chan.h +x400out84.o: ../../h/table.h +x400out84.o: ../../h/list_bpt.h +x400out84.o: ../../h/auth.h +x400out84.o: ../../h/list_bpt.h +x400out84.o: ../../h/extension.h +x400out84.o: ../../h/mta.h +x400out84.o: ../../h/adr.h +x400out84.o: ../../h/list_bpt.h +x400out84.o: ../../h/aparse.h +x400out84.o: ../../h/ap.h +x400out84.o: ../../h/util.h +x400out84.o: ../../h/or.h +x400out84.o: ../../h/chan.h +x400out84.o: ../../h/auth.h +x400out84.o: ../../h/list_rchan.h +x400out84.o: ../../h/mta.h +x400out84.o: ../../h/qmgr.h +x400out84.o: ../../h/Qmgr-types.h +x400out84.o: ../../h/Qmgr-ops.h +x400out84.o: ../../h/dr.h +x400out84.o: ../../h/extension.h +x400out84.o: ../../h/mta.h +x400out84.o: Rts84-types.h +x400out84.o: ../../h/rtsparams.h +x400topp.o: x400topp.c +x400topp.o: ../../h/util.h +x400topp.o: ../../h/config.h +x400topp.o: ../../h/ll_log.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/table.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/q.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/list_rchan.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/auth.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/extension.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/aparse.h +x400topp.o: ../../h/ap.h +x400topp.o: ../../h/util.h +x400topp.o: ../../h/or.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/auth.h +x400topp.o: ../../h/list_rchan.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/or.h +x400topp.o: ../../h/prm.h +x400topp.o: ../../h/dr.h +x400topp.o: ../../h/extension.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/retcode.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/x40084/P1_in.py b/Chans/x40084/P1_in.py new file mode 100644 index 0000000..b1e2d4e --- /dev/null +++ b/Chans/x40084/P1_in.py @@ -0,0 +1,929 @@ +-- P1: P1 MHS definitions + + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/P1_in.py,v 6.0 1991/12/18 20:13:50 jpo Rel $ +-- +-- $Log: P1_in.py,v $ +-- Revision 6.0 1991/12/18 20:13:50 jpo +-- Release 6.0 +-- +-- +-- + + + +P1 DEFINITIONS ::= + +%{ +#ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/P1_in.py,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +#endif lint + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "or.h" +#include "dr.h" +#include + +#define PPSTRUCT "/usr/pp/pp/logs/x400in84.pdus" + +extern char *loc_dom_site; +extern char *pp_myname; +extern char *remote_site; +extern char *undefined_bodyparts; +extern char *cont_p2; + + +static DRmpdu DRstruct; +DRmpdu *DRptr = &DRstruct; +static OR_ptr orptr; +static Q_struct Qstruct; +Q_struct *PPQuePtr = &Qstruct; +static int ad_no; + + +ADDR *adr_new(); +char *pe2str(); +char *body_string; +int body_len; + + +#ifdef DEBUG +int testdebug (pe, s) +register PE pe; +register char *s; +{ + register PS ps; + static int debug = OK; + static FILE *fptrace; + + switch (debug) { + case NOTOK: + return; + + case OK: + debug = 1; + fflush (stdout); + if (access (PPSTRUCT, 02) == NOTOK) { + debug = NOTOK; + break; + } + fptrace = fopen (PPSTRUCT, "a"); + if (fptrace == NULL) { + debug = NOTOK; + break; + } + fprintf (fptrace, "testdebug made with %s\n", pepyid); + /* and fall... */ + + default: + fflush (stdout); + fprintf (fptrace, "%s\n", s); + + if ((ps = ps_alloc (std_open)) == NULLPS) + break; + if (std_setup (ps, fptrace) != NOTOK) + (void) pe2pl (ps, pe); + fprintf (fptrace, "--------\n"); + (void) fflush (fptrace); + ps_free (ps); + break; + } +} + +#endif /* DEBUG */ +%} + +BEGIN + +DECODER do + + +-- P1 makes use of types defined in the following module: +-- Sa: Recommendation S.a[14] +-- T73: T.73, Section 5 + +MPDU ::= + %{ + q_init (PPQuePtr); /* initialise Q struct */ + dr_init (&DRstruct); /* initialise DR struct */ + PPQuePtr->inbound = + list_rchan_new (remote_site, pp_myname); + ad_no = 1; + %} + + CHOICE { + [0] + IMPLICIT UserMPDU [[p PPQuePtr]], + + -- service mpdus are sent as ordinary messages + + ServiceMPDU [[p PPQuePtr]] + } + + + +ServiceMPDU [[P Q_struct *]] ::= + CHOICE { + [1] + IMPLICIT DeliveryReportMPDU [[p PPQuePtr]] + %{ + PPQuePtr->msgtype = MT_DMPDU; + %}, + + [2] + IMPLICIT ProbeMPDU [[p PPQuePtr]] + %{ + PPQuePtr->msgtype = MT_PMPDU; + %} + } + + +UserMPDU [[P Q_struct *]] ::= + SEQUENCE { + envelope + %{ + PPQuePtr->msgtype = MT_UMPDU; + ad_no = 1; + %} + UMPDUEnvelope [[p PPQuePtr]], + + content + UMPDUContent + %{ + body_string = prim2str ($$, &body_len); + PPQuePtr->msgsize = body_len; + %} + } + +UMPDUEnvelope [[P Q_struct *]] %{ + ADDR *ad_link; + char *sp; + int n; + %} ::= + SET { + mpduID + MPDUIdentifier [[p &parm->msgid]], + + originator + ORName [[p &sp]] + %{ + parm->Oaddress = adr_new (sp, AD_X400_TYPE, 0); + %}, + + original + EncodedInformationTypes + [[p &parm->orig_encodedinfo]] OPTIONAL, + + ContentType [[i n]] + %{ if (n != 2) { + PP_OPER (NULLCP, ("Bad content type %d aborting",n)); + exit (2); + } + parm->cont_type = strdup (cont_p2); + %}, + + UAContentId [[s parm->ua_id]] OPTIONAL, + + Priority [[i parm->priority]] DEFAULT normal, + + PerMessageFlag [[p parm]] DEFAULT {}, + + deferredDelivery[0] + IMPLICIT Time + [[p &parm->defertime]] OPTIONAL, + + [1] + IMPLICIT SEQUENCE OF + PerDomainBilateralInfo + OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF RecipientInfo [[p &ad_link]] + %{ + register ADDR **ap; + for (ap = &(parm->Raddress); + *ap; ap = &(*ap)->ad_next); + *ap = ad_link; + %}, + + TraceInformation [[p &parm->trace]], + + -- this one's for EAN + [UNIVERSAL 17] + IMPLICIT ANY OPTIONAL + } + + +UMPDUContent ::= + OCTETSTRING + + +-- time + +Time [[P UTC *]] ::= + UniversalTime + %{ + char *p = pe2str ($$); + UTC ut; + + ut = str2utct (p, strlen(p)); + if (ut) { + *parm = (UTC) smalloc (sizeof *ut); + **parm = *ut; + } else + return NOTOK; + free (p); + %} + + +-- various envelope information + +MPDUIdentifier [[P MPDUid *]] ::= + [APPLICATION 4] IMPLICIT SEQUENCE { + GlobalDomainIdentifier + [[p &parm->mpduid_DomId]], + + IA5String [[s parm->mpduid_string]] + } + + +ContentType ::= + [APPLICATION 6] + IMPLICIT INTEGER { + p2 (2) + } + + +UAContentId ::= + [APPLICATION 10] + IMPLICIT PrintableString + + +Priority ::= + [APPLICATION 7] + IMPLICIT INTEGER { + normal (0), + + nonUrgent (1), + + urgent (2) + } + + +PerMessageFlag [[P Q_struct *]] ::= + [APPLICATION 8] + IMPLICIT BITSTRING { + discloseRecipients (0), + conversionProhibited (1), + alternateRecipientAllowed (2), + contentReturnRequest (3) + } + %{ + if (bit_test ($$, 0)) + parm -> disclose_recips = TRUE; + else parm -> disclose_recips = FALSE; + + if (bit_test ($$, 1)) + parm -> implicit_conversion_prohibited = TRUE; + else parm -> implicit_conversion_prohibited = FALSE; + + if (bit_test ($$, 2)) + parm -> alternate_recip_allowed = TRUE; + else parm -> alternate_recip_allowed = FALSE; + + if (bit_test ($$, 3)) + parm -> content_return_request = TRUE; + else parm -> content_return_request = FALSE; + %} + + + +-- per-domain bilateral information +-- IGNORED! + +PerDomainBilateralInfo ::= + SEQUENCE { + country + CountryName, + + AdministrationDomainName, + + BilateralInfo + } + +BilateralInfo ::= + ANY + + +-- recipient information + +RecipientInfo [[P ADDR **]] + %{ + char *sp; + int anint; + %} ::= + SET { + recipient + ORName [[p &sp]] + %{ + *parm = adr_new (sp, AD_X400_TYPE, ad_no); + ++ad_no; + %}, + + [0] + IMPLICIT ExtensionIdentifier [[i (*parm)->ad_extension]], + + [1] + IMPLICIT PerRecipientFlag [[p &anint]] + %{ + prf2mem (anint, &(*parm)->ad_resp, + &(*parm)->ad_mtarreq, + &(*parm)->ad_usrreq); + %}, + + [2] + IMPLICIT ExplicitConversion [[i anint]] + %{ + (*parm)->ad_explicitconversion = anint; + %} + DEFAULT {} + + -- this one's for EAN --, + [UNIVERSAL 2] + IMPLICIT INTEGER OPTIONAL + } + +ExtensionIdentifier ::= + INTEGER + +PerRecipientFlag [[P int *]] ::= + BITSTRING -- See Figure 23/X.411 + %{ + *parm = pe2bits ($$); + %} + +ExplicitConversion ::= + INTEGER { + iA5TextTeletex (0), + + teletexTelex (1) + } + + + +-- trace information + +TraceInformation [[P Trace **]] %{ + Trace *newtrace; + %} ::= + [APPLICATION 9] + IMPLICIT SEQUENCE OF SEQUENCE { + domainid + %{ + Trace **tp; + + newtrace = (Trace *) smalloc (sizeof (*newtrace)); + bzero ((char *) newtrace, sizeof (*newtrace)); + for (tp = parm; *tp; tp = &(*tp)->trace_next); + *tp = newtrace; + newtrace->trace_next = (Trace *) NULL; + %} + GlobalDomainIdentifier + [[p &newtrace->trace_DomId]], + + domaininfo + DomainSuppliedInfo + [[p &newtrace->trace_DomSinfo]] + } + + + +DomainSuppliedInfo [[P DomSupInfo *]] ::= + SET { + arrival[0] + IMPLICIT Time [[p &parm->dsi_time]], + + deferred[1] + IMPLICIT Time [[p &parm->dsi_deferred]] + OPTIONAL, + + action[2] + IMPLICIT INTEGER [[i parm->dsi_action]] { + relayed (0), + + rerouted (1) + }, + + converted + EncodedInformationTypes + [[p &parm->dsi_converted]] OPTIONAL, + + previous + GlobalDomainIdentifier + [[p &parm->dsi_attempted_md]] OPTIONAL + } + + + +-- global domain identifier + +GlobalDomainIdentifier [[P GlobalDomId *]] ::= + [APPLICATION 3] + IMPLICIT SEQUENCE { + CountryName [[p &parm->global_Country]], + AdministrationDomainName + [[p &parm->global_Admin]], + PrivateDomainIdentifier + [[p &parm->global_Private]] OPTIONAL + } + + +CountryName [[P char **]] ::= + [APPLICATION 1] + CHOICE { + NumericString [[s *parm]], + + PrintableString [[s *parm]] + } + + +AdministrationDomainName [[P char **]] ::= + [APPLICATION 2] + CHOICE { + NumericString [[s *parm]], + PrintableString [[s *parm]] + } + + +PrivateDomainIdentifier [[P char **]] ::= + CHOICE { + NumericString [[s *parm]], + + PrintableString [[s *parm]] + } + + + +-- O/R name + +ORName [[P char **]] + %{ + PE pe_standard = NULLPE; + PE pe_domain = NULLPE; + char buf[1024]; + %} ::= + [APPLICATION 0] + IMPLICIT SEQUENCE { + standard + ANY + [[a pe_standard]], + + domaindefined + ANY + [[a pe_domain]] + OPTIONAL + } + %{ + *parm = NULLCP; + if (decode_OR_StandardAttributeList + (pe_standard, 1, NULLIP, NULLVP, &orptr) == NOTOK) { + (void) sprintf (buf, "problem decoding standard attributes: %s", PY_pepy); + advise (NULLCP, "%s", buf); + or_free (orptr); + return NOTOK; + } + + if (pe_domain && decode_OR_DomainDefinedAttributeList + (pe_domain, 1, NULLIP, NULLVP, &orptr) == NOTOK) { + (void) sprintf (buf, "problem decoding DD: %s", + PY_pepy); + advise (NULLCP, "%s", buf); + or_free (orptr); + return NOTOK; + } + or_or2std (orptr, buf, FALSE); + *parm = strdup (buf); + or_free (orptr); + orptr = NULLOR; + %} + + + +-- encoded information types + +EncodedInformationTypes [[P EncodedIT *]] ::= + [APPLICATION 5] IMPLICIT SET { + [0] + IMPLICIT BITSTRING { + undefined (0), + tLX (1), + iA5Text (2), + g3Fax (3), + tIF0 (4), + tTX (5), + videotex (6), + voice (7), + sFD (8), + tIF1 (9) + } + %{ + enctypes2mem (pe2bits ($$), + undefined_bodyparts, &parm->eit_types); + %} + -- this OPTIONAL is for EAN -- OPTIONAL, + + [1] + IMPLICIT G3NonBasicParams [[p &parm->eit_g3parms]] + OPTIONAL, + + [2] + IMPLICIT TeletexNonBasicParams OPTIONAL, + + [3] + IMPLICIT PresentationCapabilities OPTIONAL + + -- other non-basic parameters are for further study + + -- but this one's for EAN --, + [UNIVERSAL 3] + IMPLICIT BITSTRING { + undefined (0), + tLX (1), + iA5Text (2), + g3Fax (3), + tIF0 (4), + tTX (5), + videotex (6), + voice (7), + sFD (8), + tIF1 (9) + } + %{ + enctypes2mem (pe2bits ($$), + undefined_bodyparts, &parm->eit_types); + %} OPTIONAL + } + +G3NonBasicParams [[P long *]] ::= + BITSTRING { + twoDimensional (8), + fineResolution (9), + unlimitedLength (20), + b4Length (21), + a3Width (22), + b4Width (23), + uncompressed (30) + } + %{ *parm = pe2bits ($$); %} + +TeletexNonBasicParams ::= + SET { + graphicCharacterSets[0] + IMPLICIT T61String OPTIONAL, + + controlCharacterSets[1] + IMPLICIT T61String OPTIONAL, + + pageFormats[2] + IMPLICIT OCTETSTRING OPTIONAL, + + miscTerminalCapabilities[3] + IMPLICIT T61String OPTIONAL, + + privateUse[4] + IMPLICIT OCTETSTRING OPTIONAL + } + +PresentationCapabilities ::= + T73PresentationCapabilities + + +T73PresentationCapabilities ::= + SET { --unimportant-- } + + +-- Delivery Report MPDU + +DeliveryReportMPDU [[P Q_struct *]]::= + %{ dr_init (&DRstruct); %} + SEQUENCE { + envelope + DeliveryReportEnvelope [[p parm]], + + content + DeliveryReportContent [[p parm]] + } + + +DeliveryReportEnvelope [[P Q_struct *]] %{ char *sp; %} ::= + SET { + report %{ + DRptr -> dr_mpduid = (MPDUid *) + smalloc (sizeof (MPDUid)); + bzero ((char *)DRptr -> dr_mpduid, sizeof (MPDUid)); + %} + MPDUIdentifier [[p DRptr->dr_mpduid]], + + originator + ORName [[p &sp]] + %{ + parm->Oaddress = adr_new (sp, AD_X400_TYPE, 0); + parm->Oaddress->ad_resp = YES; + %}, + + TraceInformation [[p &DRptr->dr_trace]] + } + + +DeliveryReportContent [[P Q_struct *]] ::= + SET { + original + MPDUIdentifier [[p &parm->msgid]], + + intermediate + TraceInformation [[p &DRptr -> dr_subject_intermediate_trace]] + OPTIONAL, + + UAContentId [[s parm->ua_id]] OPTIONAL, + + [0] + IMPLICIT SEQUENCE OF ReportedRecipientInfo + [[p parm]], + + returned[1] + IMPLICIT UMPDUContent + %{ + body_string = prim2str ($$, &body_len); + PPQuePtr->msgsize = body_len; + %} OPTIONAL, + + billingInformation[2] + ANY OPTIONAL + } + + +ReportedRecipientInfo [[P Q_struct *]] + %{ + int anint; + Rrinfo *rr; + ADDR *ap; + %} ::= + SET %{ + Rrinfo **rp; + + rr = (Rrinfo *) smalloc (sizeof (*rr)); + bzero ((char *) rr, sizeof (*rr)); + for (rp = &DRptr -> dr_recip_list; + *rp; rp = &(*rp)->rr_next); + *rp = rr; + %} + { + recipient[0] + %{ + if (orptr != NULLOR) { + or_free (orptr); + orptr = NULLOR; + } + ap = adr_new (NULLCP, AD_X400_TYPE, ad_no); + rr -> rr_recip = ad_no ++; + ap->ad_status = AD_STAT_DRWRITTEN; + adr_add (&parm -> Raddress, ap); + %} + IMPLICIT ORName + [[p &ap -> ad_value]], + + [1] + IMPLICIT ExtensionIdentifier [[i ap->ad_extension]], + + [2] + IMPLICIT PerRecipientFlag [[p &anint]] + %{ + prf2mem (anint, &ap->ad_resp, + &ap->ad_mtarreq, + &ap->ad_usrreq); + %}, + + [3] + IMPLICIT LastTraceInformation + [[p rr]], + + intendedRecipient[4] + %{ + rr -> rr_originally_intended_recip = + (FullName *) smalloc(sizeof(FullName)); + bzero ((char *) rr -> rr_originally_intended_recip, + sizeof(FullName)); + %} + IMPLICIT ORName + [[p &rr->rr_originally_intended_recip -> fn_addr]] + OPTIONAL, + + [5] + IMPLICIT SupplementaryInformation + [[s rr->rr_supplementary]] OPTIONAL + } + + + +-- last trace information + +LastTraceInformation [[P Rrinfo *]] ::= + SET { + arrival[0] + IMPLICIT Time [[p &parm->rr_arrival]], + + converted + %{ + parm->rr_converted = (EncodedIT *) + smalloc (sizeof (*parm->rr_converted)); + bzero ((char *) parm->rr_converted, + sizeof (*parm->rr_converted)); + %} + + EncodedInformationTypes [[p parm->rr_converted]] OPTIONAL, + + [1] + Report [[p &parm->rr_report]] + } + + +Report [[P Report *]] ::= + CHOICE { + [0] + IMPLICIT DeliveredInfo + [[p &parm->rep.rep_dinfo]] + %{ + parm->rep_type = DR_REP_SUCCESS; + %}, + + [1] + IMPLICIT NonDeliveredInfo + [[p &parm->rep.rep_ndinfo]] + %{ + parm->rep_type = DR_REP_FAILURE; + %} + } + + +DeliveredInfo [[P Delinfo *]] ::= + SET { + delivery[0] + IMPLICIT Time [[p &parm->del_time]], + + typeOfUA[1] + %{ + parm->del_type = 0; + %} + IMPLICIT INTEGER [[i parm->del_type]] { + public (0), + + private (1) + } DEFAULT public + } + + +NonDeliveredInfo [[P NonDelinfo *]] ::= + SET { + [0] + IMPLICIT ReasonCode [[i parm->nd_rcode]], + + [1] + IMPLICIT DiagnosticCode [[i parm->nd_dcode]] OPTIONAL + } + + +-- No ReasonCodes specifed because 84 should be able to accept 88 codes +ReasonCode ::= + INTEGER + + +-- No DiagnosticCodes specifed because 84 should be able to accept 88 codes +DiagnosticCode ::= + INTEGER + + +-- supplementary information + +SupplementaryInformation ::= + PrintableString -- length limited and for further study + + +-- Probe MPDU + +ProbeMPDU [[P Q_struct *]]::= + ProbeEnvelope [[p parm]] + +ProbeEnvelope [[P Q_struct *]] %{ + char *sp; + ADDR *ad_link; + int n; + %} ::= + SET { + probe + MPDUIdentifier [[p &parm->msgid]], + + originator + ORName [[p &sp]] + %{ + parm->Oaddress = adr_new (sp, AD_X400_TYPE, 0); + %}, + + ContentType [[i n]] + %{ if (n != 2) { + PP_OPER (NULLCP, ("Bad content type %d aborting", n)); + exit (2); + } + parm->cont_type = strdup (cont_p2); + %}, + + UAContentId [[s parm->ua_id]] OPTIONAL, + + original + EncodedInformationTypes + [[p &parm->orig_encodedinfo]] OPTIONAL, + + TraceInformation [[p &parm->trace]], + + PerMessageFlag [[p parm]] + DEFAULT {}, + + contentLength[0] + IMPLICIT INTEGER [[i parm->msgsize]] OPTIONAL, + + [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo + OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF + RecipientInfo [[p &ad_link]] + %{ + register ADDR **ap; + for (ap = &(parm->Raddress); + *ap; ap = &(*ap)->ad_next); + *ap = ad_link; + %} +} + +END + + +%{ +int pe2bits (pe) +register PE pe; +{ + int i, + j, + k; + + j = 0; + for (k = 1 << (i = 0); i < sizeof (j) * 8; i++, k <<= 1) { + switch (bit_test (pe, i)) { + case NOTOK: + break; + + default: + j |= k; /* fall */ + case OK: + continue; + } + + break; + } + + return (j); +} + +char *pe2str (pe) +PE pe; +{ + int len; + + return prim2str (pe, &len); +} + + +dump_struct () +{ + FILE *fp; + + if ((fp = fopen (PPSTRUCT, "a")) == NULL) + { + advise (NULLCP, "Can't open %s", PPSTRUCT); + return; + } + if (rp_isbad (wr_q (PPQuePtr, fp)) ) + advise (NULLCP, "Can't write Qstruct"); + if (PPQuePtr->Oaddress != NULL) + if (rp_isbad (wr_adr (PPQuePtr->Oaddress, fp, AD_ORIGINATOR))) + advise (NULLCP, "Can't write Oaddress"); + if (PPQuePtr->Raddress != NULL) + if (rp_isbad (wr_adr (PPQuePtr->Raddress, fp, AD_RECIPIENT))) + advise (NULLCP, "Can't write Raddress"); + fputs ("-------------------------\n", fp); + (void) fclose (fp); +} + +%} diff --git a/Chans/x40084/P1_out.py b/Chans/x40084/P1_out.py new file mode 100644 index 0000000..cce543f --- /dev/null +++ b/Chans/x40084/P1_out.py @@ -0,0 +1,1112 @@ +-- P1: P1 MHS definitions + + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/P1_out.py,v 6.0 1991/12/18 20:13:50 jpo Rel $ +-- +-- $Log: P1_out.py,v $ +-- Revision 6.0 1991/12/18 20:13:50 jpo +-- Release 6.0 +-- +-- +-- + + +P1 DEFINITIONS ::= + +%{ +#ifndef lint +static char Rcsid [] = "@(#)$Header"; +#endif lint + +#include "head.h" +#include "q.h" +#include "or.h" +#include "dr.h" +#include "rtsparams.h" +#include + + +#define PPSTRUCT "/usr/pp/pp/logs/x400out84.pdus" + + +extern char *body_string; +extern char *cont_p2; +extern int trace_type; +extern int body_len; +extern Q_struct *PPQuePtr; +extern DRmpdu *DRptr; +extern ADDR *ad_list; + + +static int aninteger; +struct botheit { + EncodedIT *eit; + LIST_BPT *bp; +}; + + + +/* -- local routines -- */ +int testdebug(); +static int get_content_type(); +static int or_print_struct(); +static int pmf2int(); +static int same_trace(); +static void compress_trace(); +static void compress_trace_admd_style(); +static void compress_trace_localinternal_style(); +static void convert2printablestring(); + + + + +/* ---------------------- Begin Routines ----------------------------------- */ + + + + + +#ifdef DEBUG +int testdebug (pe, s) +register PE pe; +register char *s; +{ + register PS ps; + static int debug = OK; + static FILE *fptrace; + + switch (debug) { + case NOTOK: + return; + + case OK: + if ((pp_log_norm -> ll_events & LLOG_PDUS) == 0) { + debug = NOTOK; + break; + } + debug = 1; + fflush (stdout); + if (access (PPSTRUCT, 02) == NOTOK) { + debug = NOTOK; + break; + } + + fptrace = fopen (PPSTRUCT, "a"); + if (fptrace == NULL) { + debug = NOTOK; + break; + } + fprintf (fptrace, "testdebug made with %s\n", pepyid); + /* and fall... */ + + default: + fflush (stdout); + fprintf (fptrace, "%s\n", s); + + if ((ps = ps_alloc (std_open)) == NULLPS) + break; + if (std_setup (ps, fptrace) != NOTOK) + (void) pe2pl (ps, pe); + fprintf (fptrace, "--------\n"); + (void) fflush (fptrace); + ps_free (ps); + break; + } +} + +#endif /* DEBUG */ + +%} + + + + +BEGIN + +ENCODER build + + +-- P1 makes use of types defined in the following module: +-- Sa: Recommendation S.a [14] +-- T73: T.73, Section 5 + +MPDU ::= + CHOICE << PPQuePtr->msgtype == MT_UMPDU ? 1 : 2 >> { + [0] + IMPLICIT UserMPDU [[p PPQuePtr]], + + -- service mpdus are sent as ordinary messages + + ServiceMPDU [[p PPQuePtr]] + } + + + +ServiceMPDU [[P Q_struct *]] ::= + CHOICE << parm->msgtype == MT_DMPDU ? 1 : 2 >> { + [1] + IMPLICIT DeliveryReportMPDU [[p parm]], + + [2] + IMPLICIT ProbeMPDU [[p parm]] + } + + + +UserMPDU [[P Q_struct *]] ::= + SEQUENCE { + envelope + UMPDUEnvelope [[p parm]], + + content + UMPDUContent [[o body_string $ body_len]] + } + + + + +UMPDUEnvelope [[P Q_struct *]] + %{ + char *cp; + ADDR *ap; + struct botheit b; + %} ::= + SET { + mpduID + MPDUIdentifier [[p &parm->msgid]], + + originator %{ + cp = parm->Oaddress->ad_r400adr; + if (cp == NULLCP) + cp = parm->Oaddress->ad_value; + %} + ORName [[p cp]], + + + original %{ + b.eit = &parm->orig_encodedinfo; + b.bp = ad_list -> ad_eit; + %} EncodedInformationTypes [[p &b]], + + + ContentType [[i get_content_type (ad_list, parm)]], + + UAContentId [[p parm->ua_id]] OPTIONAL + <ua_id != NULLCP >>, + + Priority [[i parm->priority]] DEFAULT normal + <priority != 0 >>, + + PerMessageFlag [[p parm]] + DEFAULT {} < disclose_recips || + parm -> implicit_conversion_prohibited || + parm -> alternate_recip_allowed || + parm -> content_return_request >>, + + deferredDelivery [0] + IMPLICIT Time + [[p parm->defertime]] OPTIONAL + <defertime != NULLUTC>>, + + [1] + IMPLICIT SEQUENCE OF + PerDomainBilateralInfo OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF + <Raddress; ap!=NULLADDR; ap=ap->ad_next>> + RecipientInfo [[p ap]], + + TraceInformation [[p &parm->trace]] + + } + + + +UMPDUContent ::= + OCTETSTRING [[o body_string $ body_len]] + + + +-- time + +Time [[P UTC]] + %{ + char *str; + %} ::= + %{ str= utct2str (parm); %} + UniversalTime [[s str]] + + + +-- various envelope information + +MPDUIdentifier [[P MPDUid *]] + %{ + char tbuf[LINESIZE]; + %} ::= + [APPLICATION 4] IMPLICIT SEQUENCE { + GlobalDomainIdentifier + [[p &parm->mpduid_DomId]], + + dummy %{ + bzero (tbuf, LINESIZE); + strncpy (tbuf, parm -> mpduid_string, 32); + %} + IA5String [[s tbuf]] + } + + + +ContentType ::= + [APPLICATION 6] + IMPLICIT INTEGER { + p2 (2) + } + + + +UAContentId [[P char *]] + %{ + char tbuf[LINESIZE]; + %} ::= + %{ + bzero (tbuf, LINESIZE); + strncpy (tbuf, parm, 16); + %} + [APPLICATION 10] + IMPLICIT PrintableString [[s tbuf]] + + +Priority ::= + [APPLICATION 7] + IMPLICIT INTEGER { + normal (0), + nonUrgent (1), + urgent (2) + } + + + +PerMessageFlag [[P Q_struct *]] ::= + [APPLICATION 8] + IMPLICIT BITSTRING [[x int2strb(pmf2int(parm),4) $ 4 ]] { + discloseRecipients (0), + conversionProhibited (1), + alternateRecipientAllowed (2), + contentReturnRequest (3) + } + + + +-- per-domain bilateral information + +PerDomainBilateralInfo ::= + SEQUENCE { + country + CountryName, + AdministrationDomainName, + BilateralInfo + } + + + +BilateralInfo ::= + ANY + + + +-- recipient information + +RecipientInfo [[P ADDR *]] + %{ + char *cp; + %} ::= + SET { + recipient %{ + cp = parm->ad_r400adr; + if (cp == NULLCP) + cp = parm->ad_value; + %} + ORName [[p cp]], + + [0] + IMPLICIT ExtensionIdentifier [[i parm->ad_extension]], + + [1] + %{ + int resp; + ADDR *ap; + for (ap = ad_list; ap; ap = ap -> ad_next) + if (ap -> ad_no == parm -> ad_no) + break; + if (ap == NULLADDR) + resp = FALSE; + else resp = parm -> ad_resp; + aninteger = mem2prf (resp, parm->ad_mtarreq, + parm->ad_usrreq); + %} + IMPLICIT PerRecipientFlag [[x int2strb (aninteger, 8) $ 8 ]], + + [2] + IMPLICIT ExplicitConversion + [[i parm->ad_explicitconversion]] DEFAULT {} + } + + + +ExtensionIdentifier ::= + INTEGER + + +PerRecipientFlag ::= + BITSTRING -- See Figure 23/X.411 + + +ExplicitConversion ::= + INTEGER { + iA5TextTeletex (0), + teletexTelex (1) + } + + + +-- trace information + +TraceInformation [[P Trace **]] + %{ + Trace *tp; + %} ::= + + + %{ + compress_trace (parm); + %} + + + [APPLICATION 9] + IMPLICIT SEQUENCE OF + <trace_next>> + SEQUENCE { + domainid + GlobalDomainIdentifier + [[p &tp->trace_DomId]], + domaininfo + DomainSuppliedInfo + [[p &tp->trace_DomSinfo]] + } + + + +DomainSuppliedInfo [[P DomSupInfo *]] + %{ + struct botheit b; + %} ::= + SET { + arrival [0] %{ + if (parm -> dsi_time == NULL) + parm->dsi_time = utcnow (); + %} + IMPLICIT Time [[p parm->dsi_time]], + + deferred [1] + IMPLICIT Time [[p parm->dsi_deferred]] OPTIONAL + <dsi_deferred != NULLUTC>>, + + action [2] + IMPLICIT INTEGER [[i parm->dsi_action]] { + relayed (0), + rerouted (1) + }, + + converted %{ + b.eit = &parm->dsi_converted; + b.bp = NULL; + %} EncodedInformationTypes + [[p &b]] OPTIONAL + <dsi_converted.eit_types != 0>>, + + previous + GlobalDomainIdentifier + [[p &parm->dsi_attempted_md]] OPTIONAL + <dsi_attempted_md.global_Country != NULLCP>> + } + + + +-- global domain identifier + +GlobalDomainIdentifier [[P GlobalDomId *]] ::= + [APPLICATION 3] + IMPLICIT SEQUENCE { + CountryName [[p parm->global_Country]], + AdministrationDomainName [[p parm->global_Admin]], + PrivateDomainIdentifier [[p parm->global_Private]] OPTIONAL + <global_Private != NULLCP>> + } + + +CountryName [[P char *]] ::= + [APPLICATION 1] + CHOICE << (parm && or_str_isns(parm)) ? 1 : 2 >> { + NumericString [[s parm ? parm : "" ]], + PrintableString [[s parm ? parm : "" ]] + } + + + +AdministrationDomainName [[P char *]] ::= + [APPLICATION 2] + CHOICE << (parm && or_str_isns(parm)) ? 1 : 2 >> { + NumericString [[s parm ? parm : ""]], + PrintableString [[s parm ? parm : ""]] + } + + + +PrivateDomainIdentifier [[P char *]] ::= + CHOICE << (parm && or_str_isns(parm)) ? 1 : 2 >> { + NumericString [[s parm ? parm : ""]], + PrintableString [[s parm ? parm : ""]] + } + + + + +-- O/R name + +ORName [[P char *]] + %{ + OR_ptr or; + PE peptr = NULLPE; + + or = or_std2or (parm); + if (or == NULLOR) { + advise (NULLCP, "x400out84: Bad ORName %s", parm); + return NOTOK; + } + or_downgrade(&or); + or_print_struct (or, 0); + + if (build_OR_ORName (&peptr, 1, 0, NULLCP, or) == NOTOK) + if (peptr) { + pe_free (peptr); + peptr= NULLPE; + } + or_free (or); + { + %} ::= + ANY [[a peptr]] + %{ + } + %} + + + +-- encoded information types + +EncodedInformationTypes [[P struct botheit *]] ::= + %{ + if (parm->bp) + aninteger = mem2enctypes (parm->bp); + else + aninteger = mem2enctypes (parm->eit->eit_types); + %} + + [APPLICATION 5] IMPLICIT SET { + [0] + IMPLICIT BITSTRING [[x int2strb (aninteger, 10) $ 10]] + { + undefined(0), + tLX(1), + iA5Text(2), + g3Fax(3), + tIF0(4), + tTX(5), + videotex(6), + voice(7), + sFD(8), + tIF1(9) + }, + + + [1] + IMPLICIT G3NonBasicParams + [[x int2strb (parm->eit->eit_g3parms, 30) $ 30]] OPTIONAL + <eit->eit_types, + "P2.g3fax")>>, + [2] + IMPLICIT TeletexNonBasicParams OPTIONAL, + + [3] + IMPLICIT PresentationCapabilities OPTIONAL + + -- other non-basic parameters are for further study + + } + + + +G3NonBasicParams ::= + BITSTRING { + twoDimensional(8), + fineResolution(9), + unlimitedLength(20), + b4Length(21), + a3Width(22), + b4Width(23), + uncompressed(30) + } + + + +TeletexNonBasicParams ::= + SET { + graphicCharacterSets [0] + IMPLICIT T61String OPTIONAL, + + controlCharacterSets [1] + IMPLICIT T61String OPTIONAL, + + pageFormats [2] + IMPLICIT OCTETSTRING OPTIONAL, + + miscTerminalCapabilities [3] + IMPLICIT T61String OPTIONAL, + + privateUse [4] + IMPLICIT OCTETSTRING OPTIONAL + } + + + +PresentationCapabilities ::= + T73PresentationCapabilities + + + +T73PresentationCapabilities ::= + SET { --unimportant-- } + + + + +-- Delivery Report MPDU + +DeliveryReportMPDU [[P Q_struct *]]::= + SEQUENCE { + envelope + DeliveryReportEnvelope [[p parm]], + + content + DeliveryReportContent [[p parm]] + } + + + + +DeliveryReportEnvelope [[P Q_struct *]] ::= + SET { + report + MPDUIdentifier [[p DRptr-> dr_mpduid]], + + originator + ORName [[p parm->Oaddress->ad_r400adr]], + + TraceInformation [[p &DRptr->dr_trace]] + } + + + +DeliveryReportContent [[P Q_struct *]] + %{ + Rrinfo *rq; + %} ::= + SET { + original + MPDUIdentifier [[p &parm->msgid]], + + intermediate + TraceInformation [[p &DRptr-> dr_subject_intermediate_trace]] + OPTIONAL << DRptr -> dr_subject_intermediate_trace>>, + + UAContentId [[p parm->ua_id]] OPTIONAL + <ua_id != NULLCP>>, + + [0] + IMPLICIT SEQUENCE OF + <dr_recip_list; rq; + rq = rq->rr_next>> + ReportedRecipientInfo [[p rq]], + + returned [1] + IMPLICIT UMPDUContent [[o body_string $ body_len ]] OPTIONAL <>, + + billingInformation [2] + ANY OPTIONAL + } + + + +ReportedRecipientInfo [[P Rrinfo *]] + %{ + ADDR *ap; + %} ::= %{ + for (ap = PPQuePtr -> Raddress; ap; ap = ap -> ad_next) + if (ap -> ad_no == parm -> rr_recip) + break; + if (ap == NULLADDR) { + PP_OPER (NULLCP, ("NO match for recip %d terminating", + parm -> rr_recip)); + exit (3); + } + %} + SET + { + recipient [0] + IMPLICIT ORName [[p ap->ad_r400adr]] %{ + $$ -> pe_class = PE_CLASS_CONT; + $$ -> pe_id = 0; + %}, + + [1] + IMPLICIT ExtensionIdentifier [[i ap->ad_extension]], + + [2] + %{ + aninteger = mem2prf (ap->ad_resp, + ap->ad_mtarreq, + ap->ad_usrreq); + %} + IMPLICIT PerRecipientFlag [[x int2strb (aninteger, 8) $ 8 ]], + + [3] IMPLICIT LastTraceInformation [[p parm]], + + intendedRecipient [4] + IMPLICIT + ORName [[p parm->rr_originally_intended_recip->fn_addr]] + %{ + $$ -> pe_class = PE_CLASS_CONT; + $$ -> pe_id = 4; + %} OPTIONAL + <rr_originally_intended_recip && + parm->rr_originally_intended_recip->fn_addr>> , + + [5] + %{ + convert2printablestring (parm -> rr_supplementary); + %} + IMPLICIT SupplementaryInformation + [[o parm -> rr_supplementary $ + min ((int)strlen(parm->rr_supplementary), 64)]] + OPTIONAL + <rr_supplementary != NULLCP>> + } + + + +-- last trace information + +LastTraceInformation [[P Rrinfo *]] + %{ + struct botheit b; + %} ::= + SET { + arrival [0] + IMPLICIT Time [[p parm->rr_arrival]], + + converted %{ + b.eit = parm->rr_converted; + b.bp = NULL; + %} EncodedInformationTypes [[p &b]] OPTIONAL + <rr_converted != 0>>, + + [1] + Report [[p &parm->rr_report]] + } + + + +Report [[P Report *]] ::= + CHOICE <rep_type == DR_REP_SUCCESS ? 1 : 2 >> { + [0] + IMPLICIT DeliveredInfo [[p &parm->rep.rep_dinfo]], + + [1] + IMPLICIT NonDeliveredInfo [[p &parm->rep.rep_ndinfo]] + } + + + +DeliveredInfo [[P Delinfo *]] ::= + SET { + delivery [0] + IMPLICIT Time [[p parm->del_time]], + + typeOfUA [1] + IMPLICIT INTEGER [[i parm->del_type]] { + public (0), + private (1) + } DEFAULT public <del_type != 0>> + } + + + +NonDeliveredInfo [[P NonDelinfo *]] ::= + SET { + [0] + %{ + if (parm->nd_rcode > 2) + parm->nd_rcode = 0; + %} + IMPLICIT ReasonCode [[i parm->nd_rcode]], + + [1] + %{ + if (parm->nd_dcode > 11) + parm->nd_dcode = 11; + %} + IMPLICIT DiagnosticCode [[i parm->nd_dcode]] OPTIONAL + <nd_dcode >= 0>> + } + + + +ReasonCode ::= + INTEGER { + transferFailure (0), + + unableToTransfer (1), + + conversionNotPerformed (2) + + } + + + +DiagnosticCode ::= + INTEGER { + unrecognizedORName (0), + + ambiguousORName (1), + + mtaCongestion (2), + + loopDetected (3), + + uaUnavailable (4), + + maximumTimeExpired (5), + + encodedInformationTypesUnsupported (6), + + contentTooLong (7), + + conversionImpractical (8), + + conversionProhibited (9), + + implicitConversionNotResgistered (10), + + invalidParameters (11) + } + + + +-- supplementary information + +SupplementaryInformation ::= + PrintableString -- length limited and for further study + + + + +-- Probe MPDU + +ProbeMPDU [[P Q_struct *]]::= + ProbeEnvelope [[p parm]] + + + +ProbeEnvelope [[P Q_struct *]] + %{ + char *cp; + ADDR *ap; + struct botheit b; + %} ::= + + SET { + probe + MPDUIdentifier [[p &parm->msgid]], + + + originator %{ + cp = parm->Oaddress->ad_r400adr; + if (cp == NULLCP) + cp = parm->Oaddress->ad_value; + %} + ORName [[p cp]], + + + ContentType [[i get_content_type (ad_list, parm)]], + + UAContentId [[p parm->ua_id]] OPTIONAL + <ua_id != NULLCP>>, + + original %{ + b.eit = &parm->orig_encodedinfo; + b.bp = NULL; + %} EncodedInformationTypes + [[p &b]] OPTIONAL + <orig_encodedinfo.eit_types != 0>>, + + TraceInformation [[p &parm->trace]], + + PerMessageFlag [[p parm]] + DEFAULT {} << parm -> implicit_conversion_prohibited || + parm -> alternate_recip_allowed >>, + + contentLength [0] + IMPLICIT INTEGER [[i parm->msgsize]] OPTIONAL + <msgsize > 0>>, + + [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo + OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF + << ap = parm -> disclose_recips ? parm->Raddress : ad_list; + ap != NULLADDR; ap=ap->ad_next>> + RecipientInfo [[p ap]] +} + +END + + + + +%{ + + +static int get_content_type (ad, qp) +ADDR *ad; +Q_struct *qp; +{ + char *p; + + if (isstr(ad -> ad_content)) + p = ad -> ad_content; + else p = qp -> cont_type; + + if (lexequ (p, cont_p2) != 0) + adios (NULLCP, "Bad content type %s", p); + + return 2; +} + + + +static int pmf2int (parm) /* --- PerMessageFlag Params -> integer --- */ +Q_struct *parm; +{ + + aninteger = 0; + + switch (parm -> msgtype) { + case MT_PMPDU: + /* --- *** --- + only the conversionProhibited and alternateRecipientAllowed + flags affect the deliverability of the message as tested by + Probe. - See X.411 page 164. + --- *** --- */ + + if (parm -> implicit_conversion_prohibited) + aninteger |= (1 << 1); + if (parm -> alternate_recip_allowed) + aninteger |= (1 << 2); + break; + + default: + if (parm -> disclose_recips) + aninteger |= (1 << 0); + if (parm -> implicit_conversion_prohibited) + aninteger |= (1 << 1); + if (parm -> alternate_recip_allowed) + aninteger |= (1 << 2); + if (parm -> content_return_request) + aninteger |= (1 << 3); + break; + } + + return aninteger; +} + + + +/* --- *** --- +This routine is necessary because sometimes the supplementary +information field has return characeters which is not valid X.409 +--- *** --- */ + +static void convert2printablestring (ptr) +char *ptr; +{ + char *cp; + + for (cp = ptr; isstr(cp); cp++) + switch (*cp) { + case '\n': + case '\t': + *cp = ' '; + break; + default: + break; + } +} + + + + +static void compress_trace (tpp) +Trace **tpp; +{ + + switch (trace_type) { + case RTSP_TRACE_ADMD: + compress_trace_admd_style (tpp); + break; + case RTSP_TRACE_LOCALINT: + compress_trace_localinternal_style (tpp); + break; + } + + return; +} + + + + +static void compress_trace_admd_style (tpp) +Trace **tpp; +{ + Trace *tlast, + *tlast_butone = (Trace *)0, + *tp = *tpp; + + + /* --- *** --- + Keep the first and last. Get rid of intermediate. If the ADMD is + the same in the first and last trace, then keep only the first. + --- *** --- */ + + for (tlast = tp; tlast && tlast -> trace_next; + tlast = tlast -> trace_next) { + tlast_butone = tlast; + continue; + } + + if (tlast != tp && same_trace (tlast, tp)) { + /* -- keep only the first trace -- */ + trace_free (tp -> trace_next); + tp -> trace_next = (Trace *)0; + } + else if (tlast != tp) { + /* -- keep first and last, remove intermediates -- */ + tlast_butone -> trace_next = (Trace *)0; + trace_free (tp -> trace_next); + tp -> trace_next = tlast; + } + + *tpp = tp; + return; +} + + + + +static void compress_trace_localinternal_style (tpp) +Trace **tpp; +{ + Trace *tnew, + *tprev = (Trace *)0, + *tptr, + *tp = *tpp; + + /* -- *** -- + Throw away ALL trace that is not of the local PRMD + -- *** -- */ + + tnew = trace_new(); + + for (tptr = tp; tptr; tptr = tptr -> trace_next) { + if (!same_trace (tnew, tptr)) + break; + tprev = tptr; + } + + if (tprev) + tprev -> trace_next = (Trace *)0; + + trace_free (tptr); + trace_free (tnew); + + *tpp = tp; + + return; +} + + + + +static int same_trace (tp1, tp2) +Trace *tp1; +Trace *tp2; +{ + GlobalDomId *d1 = &tp1 -> trace_DomId; + GlobalDomId *d2 = &tp2 -> trace_DomId; + + + if (d1 -> global_Country && d2 -> global_Country && + lexequ (d1 -> global_Country, d2 -> global_Country) == 0 && + d1 -> global_Admin && d2 -> global_Admin && + lexequ (d1 -> global_Admin, d2 -> global_Admin) == 0) { + + if (d1 -> global_Private == NULL && + d2 -> global_Private == NULL) + return TRUE; + + if (d1 -> global_Private && d2 -> global_Private && + lexequ (d1 -> global_Private, + d2 -> global_Private) == 0) + return TRUE; + } + + return FALSE; +} + + + + +static int or_print_struct (or, indent) +OR_ptr or; +int indent; +{ + char buf[BUFSIZ]; + int i; + +#ifdef DEBUG + if (or == NULLOR) return; + + for (i = 0; i < indent; i++) + buf[i] = ' '; + buf[i] = '\0'; + + PP_TRACE (("%s%s = %s", buf, or_type2name(or->or_type), or->or_value)); + + or_print_struct (or -> or_next, indent + 3); +#endif DEBUG +} + + +%} diff --git a/Chans/x40084/P1_print.py b/Chans/x40084/P1_print.py new file mode 100644 index 0000000..a42ea19 --- /dev/null +++ b/Chans/x40084/P1_print.py @@ -0,0 +1,599 @@ +-- P1: P1 MHS definitions + + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/P1_print.py,v 6.0 1991/12/18 20:13:50 jpo Rel $ +-- +-- $Log: P1_print.py,v $ +-- Revision 6.0 1991/12/18 20:13:50 jpo +-- Release 6.0 +-- +-- +-- + + +P1 DEFINITIONS ::= + +%{ +#ifndef lint +static char Rcsid [] = "@(#)$Header"; +#endif lint + +%} + + +BEGIN + +PRINTER print + + +-- P1 makes use of types defined in the following module: +-- Sa: Recommendation S.a [14] +-- T73: T.73, Section 5 + + +MPDU ::= + CHOICE { + [0] IMPLICIT UserMPDU, + + ServiceMPDU + } + +ServiceMPDU ::= + CHOICE { + [1] + IMPLICIT DeliveryReportMPDU, + + [2] + IMPLICIT ProbeMPDU + } + + +UserMPDU ::= + SEQUENCE { + envelope + UMPDUEnvelope, + content + UMPDUContent + } + +UMPDUEnvelope ::= + SET { + mpduID + MPDUIdentifier, + + originator + ORName, + + original + EncodedInformationTypes OPTIONAL, + + ContentType, + + UAContentId OPTIONAL, + + Priority DEFAULT normal, + + PerMessageFlag DEFAULT {}, + + deferredDelivery [0] IMPLICIT Time OPTIONAL, + + [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF RecipientInfo, + + TraceInformation + } + + +UMPDUContent ::= + OCTETSTRING +-- time + + +Time ::= + UniversalTime + + +-- various envelope information + +MPDUIdentifier ::= + [APPLICATION 4] IMPLICIT SEQUENCE { + GlobalDomainIdentifier, + IA5String + } + + +ContentType ::= + [APPLICATION 6] + IMPLICIT INTEGER { + p2(2) + } + + +UAContentId ::= + [APPLICATION 10] + IMPLICIT PrintableString + +Priority ::= + [APPLICATION 7] + IMPLICIT INTEGER { + normal(0), + + nonUrgent(1), + + urgent(2) + } + +PerMessageFlag ::= + [APPLICATION 8] + IMPLICIT BITSTRING { + discloseRecipients(0), + conversionProhibited(1), + alternateRecipientAllowed(2), + contentReturnRequest(3) + } + +-- per-domain bilateral information + +PerDomainBilateralInfo ::= + SEQUENCE { + country + CountryName, + + AdministrationDomainName, + + BilateralInfo + } + +BilateralInfo ::= + ANY + +-- recipient information + +RecipientInfo ::= + SET { + recipient ORName, + + [0] + IMPLICIT ExtensionIdentifier, + + [1] + IMPLICIT PerRecipientFlag, + + [2] + IMPLICIT ExplicitConversion DEFAULT {} + } + +ExtensionIdentifier ::= + INTEGER + +PerRecipientFlag ::= + BITSTRING -- See Figure 23/X.411 + +ExplicitConversion ::= + INTEGER { + iA5TextTeletex(0), + + teletexTelex(1) + } + +-- trace information + +TraceInformation ::= + [APPLICATION 9] + IMPLICIT SEQUENCE OF + SEQUENCE { + domainid + GlobalDomainIdentifier, + + domaininfo + DomainSuppliedInfo + } + +DomainSuppliedInfo ::= + SET { + arrival [0] + IMPLICIT Time, + + deferred [1] + IMPLICIT Time OPTIONAL, + + action [2] + IMPLICIT INTEGER { + relayed(0), + rerouted(1) + }, + + converted + EncodedInformationTypes OPTIONAL, + + previous + GlobalDomainIdentifier OPTIONAL + } + + +-- global domain identifier + +GlobalDomainIdentifier ::= + [APPLICATION 3] + IMPLICIT SEQUENCE { + CountryName, + + AdministrationDomainName, + + PrivateDomainIdentifier OPTIONAL + } + +CountryName ::= + [APPLICATION 1] + CHOICE { + NumericString, + PrintableString + } + +AdministrationDomainName ::= + [APPLICATION 2] + CHOICE { + NumericString, + PrintableString + } + +PrivateDomainIdentifier ::= + CHOICE { + NumericString, + PrintableString + } + + + +-- O/R name + +ORName ::= + [APPLICATION 0] + IMPLICIT SEQUENCE { + standard + StandardAttributeList, + + domaindefined + DomainDefinedAttributeList + OPTIONAL + } + + + +StandardAttributeList ::= + SEQUENCE { + country CountryName OPTIONAL, + + admd AdministrationDomainName OPTIONAL, + + x121 [0] + IMPLICIT X121Address + OPTIONAL, + + terminalId [1] + IMPLICIT TerminalID + OPTIONAL, + + prmd [2] + PrivateDomainName + OPTIONAL, + + organization [3] + IMPLICIT OrganizationName + OPTIONAL, + + uaId [4] + IMPLICIT UniqueUAIdentifier + OPTIONAL, + + personalname [5] + IMPLICIT PersonalName + OPTIONAL, + + orgunit [6] + IMPLICIT SEQUENCE OF + OrganizationalUnit + OPTIONAL + } + +DomainDefinedAttributeList ::= + SEQUENCE OF + DomainDefinedAttribute + +DomainDefinedAttribute ::= + SEQUENCE { + type + PrintableString, + + value + PrintableString + } + + +X121Address ::= + NumericString + +TerminalID ::= + PrintableString + +OrganizationName ::= + PrintableString + +UniqueUAIdentifier ::= + NumericString + +PersonalName ::= + SET { + surName [0] + IMPLICIT PrintableString, + + givenName [1] + IMPLICIT PrintableString OPTIONAL, + + initials [2] + IMPLICIT PrintableString + OPTIONAL, + + generalQualifier [3] + IMPLICIT PrintableString OPTIONAL + } + +OrganizationalUnit ::= + PrintableString + +PrivateDomainName ::= + CHOICE { + NumericString, + PrintableString + } + + +-- encoded information types + +EncodedInformationTypes ::= + [APPLICATION 5] IMPLICIT SET { + [0] + IMPLICIT BITSTRING + { + undefined(0), + tLX(1), + iA5Text(2), + g3Fax(3), + tIF0(4), + tTX(5), + videotex(6), + voice(7), + sFD(8), + tIF1(9) + }, + + [1] + IMPLICIT G3NonBasicParams + OPTIONAL, + + [2] + IMPLICIT TeletexNonBasicParams + OPTIONAL, + + [3] + IMPLICIT PresentationCapabilities + OPTIONAL + + -- other non-basic parameters are for further study + } + + + +G3NonBasicParams ::= + BITSTRING { + twoDimensional(8), + fineResolution(9), + unlimitedLength(20), + b4Length(21), + a3Width(22), + b4Width(23), + uncompressed(30) + } + + +TeletexNonBasicParams ::= + SET { + graphicCharacterSets [0] + IMPLICIT T61String OPTIONAL, + + controlCharacterSets [1] + IMPLICIT T61String OPTIONAL, + + pageFormats [2] + IMPLICIT OCTETSTRING OPTIONAL, + + miscTerminalCapabilities [3] + IMPLICIT T61String OPTIONAL, + + privateUse [4] + IMPLICIT OCTETSTRING OPTIONAL + } + +PresentationCapabilities ::= + T73PresentationCapabilities + + +T73PresentationCapabilities ::= + SET { --unimportant-- } + + +-- Delivery Report MPDU + +DeliveryReportMPDU ::= + SEQUENCE { + envelope + DeliveryReportEnvelope, + + content + DeliveryReportContent + } + +DeliveryReportEnvelope ::= + SET { + report + MPDUIdentifier, + + originator + ORName, + + TraceInformation + } + +DeliveryReportContent ::= + SET { + original + MPDUIdentifier, + + intermediate + TraceInformation + OPTIONAL, + + UAContentId + OPTIONAL, + + [0] + IMPLICIT SEQUENCE OF ReportedRecipientInfo, + + returned [1] + IMPLICIT UMPDUContent OPTIONAL, + + billingInformation [2] + ANY OPTIONAL + } + +ReportedRecipientInfo ::= + SET + { + recipient [0] + IMPLICIT ORName, + + [1] + IMPLICIT ExtensionIdentifier, + + [2] + IMPLICIT PerRecipientFlag, + + [3] + IMPLICIT LastTraceInformation, + + intendedRecipient [4] + IMPLICIT ORName + OPTIONAL, + + [5] + IMPLICIT SupplementaryInformation OPTIONAL + } + + +-- last trace information + +LastTraceInformation ::= + SET { + arrival [0] + IMPLICIT Time, + + converted + EncodedInformationTypes + OPTIONAL, + + [1] + Report + } + +Report ::= + CHOICE { + [0] + IMPLICIT DeliveredInfo, + + [1] + IMPLICIT NonDeliveredInfo + } + +DeliveredInfo ::= + SET { + delivery [0] + IMPLICIT Time, + + typeOfUA [1] + IMPLICIT INTEGER { + public(0), + + private(1) + } DEFAULT public + } + + +NonDeliveredInfo::= + SET { + [0] + IMPLICIT ReasonCode, + + [1] + IMPLICIT DiagnosticCode OPTIONAL + } + + +ReasonCode ::= + INTEGER + + +DiagnosticCode ::= + INTEGER + + +-- supplementary information + +SupplementaryInformation ::= + PrintableString -- length limited and for further study + + +-- Probe MPDU + +ProbeMPDU ::= + ProbeEnvelope + +ProbeEnvelope ::= + SET { + probe + MPDUIdentifier, + + originator + ORName, + + ContentType, + + UAContentId OPTIONAL, + + original + EncodedInformationTypes + OPTIONAL, + + TraceInformation, + + PerMessageFlag DEFAULT {}, + + contentLength [0] + IMPLICIT INTEGER + OPTIONAL, + + [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo + OPTIONAL, + + [2] + -- should be just IMPLICIT SEQUENCE OF RecipientInfo + IMPLICIT SEQUENCE OF CHOICE { + [UNIVERSAL 17] + IMPLICIT RecipientInfo + } +} + +END diff --git a/Chans/x40084/Rts_posy.py b/Chans/x40084/Rts_posy.py new file mode 100644 index 0000000..103a9b6 --- /dev/null +++ b/Chans/x40084/Rts_posy.py @@ -0,0 +1,30 @@ +-- Rts_posy.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/Rts_posy.py,v 6.0 1991/12/18 20:13:50 jpo Rel $ +-- +-- $Log: Rts_posy.py,v $ +-- Revision 6.0 1991/12/18 20:13:50 jpo +-- Release 6.0 +-- +-- +-- + + +Rts84 DEFINITIONS ::= + +BEGIN + +Request ::= + CHOICE { + NULL, + + [1] IMPLICIT SET { + mTAName[0] + IMPLICIT IA5String, + password[1] + ANY + } + } + +END diff --git a/Chans/x40084/make b/Chans/x40084/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/x40084/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/x40084/ut_logs.c b/Chans/x40084/ut_logs.c new file mode 100644 index 0000000..d6a5269 --- /dev/null +++ b/Chans/x40084/ut_logs.c @@ -0,0 +1,231 @@ +/* ut_logs.c - X400 logging and error routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_logs.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_logs.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: ut_logs.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include + + +#define RC_BASE 0x80 + + + +/* -- externals -- */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +/* -- globals -- */ +char reason[BUFSIZ]; + + +/* -- static -- */ +static char *reason_err0[] = { + "no specific reason stated", + "user receiving ability jeopardized", + "reserved(1)", + "user sequence error", + "reserved(2)", + "local SS-user error", + "unreceoverable procedural error" + }; +static int reason_err0_cnt = sizeof reason_err0 / sizeof reason_err0[0]; + + +static char *reason_err8[] = { + "demand data token" + }; +static int reason_err8_cnt = sizeof reason_err8 / sizeof reason_err8[0]; + + + +/* -- local routines -- */ +char *SReportString(); +void adios(); +void advise(); +void rts_adios(); +void rts_advise(); +void rts_exceptions(); +void do_reason(); + + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +char *SReportString (code) +int code; +{ + register int fcode; + static char buffer[BUFSIZ]; + + if (code == SP_PROTOCOL) + return "SS-provider protocol error"; + + code &= 0xff; + if (code & RC_BASE) + if ((fcode = code & ~RC_BASE) < reason_err8_cnt) + return reason_err8[fcode]; + else + if (code < reason_err0_cnt) + return reason_err0[code]; + + (void) sprintf (buffer, "unknown reason code 0x%x", code); + return buffer; +} + + + + +/* --------------------- Logging Routines ------------------------------- */ + + + +#ifdef lint +/*VARARGS2*/ +void do_reason (str) +char *str; +{ + do_reason (str); +} + +#else +void do_reason (va_alist) +va_dcl +{ + va_list ap; + + bzero (reason, BUFSIZ); + va_start (ap); + _asprintf (reason, NULLCP, ap); + va_end (ap); + PP_OPER (NULLCP, ("%s", reason)); +} +#endif + + + + + +/*ERRORS*/ + +void rts_adios (rta, event) +register struct RtSAPabort *rta; +char *event; +{ + rts_advise (rta, event); + _exit (1); +} + + + + +void rts_advise (rta, event) /* -- updates x40084 logs + OPER log -- */ +register struct RtSAPabort *rta; +char *event; +{ + char buffer[BUFSIZ]; + + if (rta->rta_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RtErrString (rta->rta_reason), + rta->rta_cc, rta->rta_cc, rta->rta_data); + else + (void) sprintf (buffer, "[%s]", + RtErrString (rta->rta_reason)); + + do_reason ("%s: %s", event, buffer); +} + + + +void rts_exceptions (rta, message) /* -- only updates x400 logs -- */ +register struct RtSAPabort *rta; +char *message; +{ + char buffer[BUFSIZ]; + + if (rta->rta_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RtErrString (rta->rta_reason), + rta->rta_cc, rta->rta_cc, rta->rta_data); + else + (void) sprintf (buffer, "[%s]", + RtErrString (rta->rta_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s, %s", message, buffer)); +} + + + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_oper, LLOG_FATAL, ap); + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Chans/x40084/ut_misc.c b/Chans/x40084/ut_misc.c new file mode 100644 index 0000000..c005bc2 --- /dev/null +++ b/Chans/x40084/ut_misc.c @@ -0,0 +1,90 @@ +/* ut_misc.c - Other miscellaneous routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_misc.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_misc.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: ut_misc.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include +#include "tb_bpt84.h" +#include "list_bpt.h" + + +extern CMD_TABLE bptbl_body_parts84 [/* body part types */]; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int mem2enctypes (lptr) /* Memory -> EncodedInformationTypesBitString */ +LIST_BPT *lptr; +{ + int i, + field = 0; + LIST_BPT *list; + + + PP_TRACE (("x40084/mem2enctypes ()")); + + for (list = lptr; list; list = list->li_next) { + + PP_TRACE (("x40084/mem2enctypes (%s)", list->li_name)); + + if (strncmp (list->li_name, "hdr.", 4) == 0) + continue; + + switch (cmd_srch (list->li_name, bptbl_body_parts84)) { + default: + case BPT_UNDEFINED: + /* --- if not found then set to undefined -- */ + i = 0; + break; + case BPT_TLX: + i = 1; + break; + case BPT_IA5: + i = 2; + break; + case BPT_G3FAX: + i = 3; + break; + case BPT_TIF0: + i = 4; + break; + case BPT_TTX: + i = 5; + break; + case BPT_VIDEOTEX: + i = 6; + break; + case BPT_VOICE: + i = 7; + break; + case BPT_SFD: + i = 8; + break; + case BPT_TIF1: + i = 9; + break; + } + + field |= (1 << i); + } + + + PP_TRACE (("x40084/mem2enctypes (%d)", field)); + + return (field); +} diff --git a/Chans/x40084/ut_rts.c b/Chans/x40084/ut_rts.c new file mode 100644 index 0000000..b57f90a --- /dev/null +++ b/Chans/x40084/ut_rts.c @@ -0,0 +1,399 @@ +/* ut_rts.c - X400 rts utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_rts.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/ut_rts.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: ut_rts.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + + +#include +#include "util.h" +#include "rtsparams.h" +#include "chan.h" +#include "Rts84-types.h" + +static char *build_inkey(); +static char *pretty_key = NULLCP; /* -- for logging only -- */ +static void print_remote_info(); + +char *remote_site = NULLCP; +char *undefined_bodyparts = NULLCP; + +static int remote_info_not_found(); + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rts_encode_request (ppe, request, mta, pass) +PE *ppe; +struct type_Rts84_Request **request; +char *mta, *pass; +{ + struct type_Rts84_Request *req; + struct member_Rts84_0 *rq; + + PP_TRACE (("rts_encode_request (%s %s)", mta, pass)); + + req = (struct type_Rts84_Request *) calloc (1, sizeof (*req)); + if (req == NULL) { + do_reason ("rts_encode_request/Unable to calloc"); + return NOTOK; + } + + rq = req->un.choice_Rts84_1 = + (struct member_Rts84_0 *) calloc (1, sizeof (*rq)); + if (rq == NULL) { + do_reason ("rts_encode_request/Unable to calloc"); + return NOTOK; + } + + if (mta == NULLCP) + req -> offset = type_Rts84_Request_1; + else { + req->offset = type_Rts84_Request_2; + rq->mTAName = str2qb (mta, strlen (mta), 1); + rq->password = ia5s2prim (pass, strlen (pass)); + } + + *request = req; + + if (encode_Rts84_Request (ppe, 1, 0, NULLCP, req) == NOTOK) { + do_reason ("rts_encode_request/Rejected: '%s'", PY_pepy); + return NOTOK; + } + + PP_TRACE (("x400out84/encode_Rts84_Request successful!")); + return OK; +} + + + + +int parameter_checks (pe, mta, pass, key, checks) +PE pe; +char *mta; +char *pass; +char *key; +int checks; +{ + struct type_Rts84_Request *req = NULL; + struct member_Rts84_0 *rq; + char *remotesite = NULLCP; + char *password = NULLCP; + int retval = NOTOK; + + PP_TRACE (("parameter_checks('%s', '%s', '%s', '%s')", + key ? key : "null", + mta ? mta : "null", + pass ? pass : "null", + checks ? "true" : "false")); + + if (decode_Rts84_Request (pe, 0, NULLIP, NULLVP, &req) == NOTOK) { + do_reason ("parameter_checks/Rejected: '%s'", PY_pepy); + goto parameter_checks_free; + } + + print_remote_info (key, req); + + if (checks == FALSE) { + retval = OK; + goto parameter_checks_free; + } + + if (req->offset == type_Rts84_Request_1) { + PP_NOTICE (("x400out84/parameter_checks() are not required")); + retval = OK; + goto parameter_checks_free; + } + + rq = req->un.choice_Rts84_1; + + remotesite = qb2str (rq->mTAName); + + if (rq->password->pe_form != PE_FORM_PRIM) { + do_reason ("parameter_checks/Password has a bad format"); + goto parameter_checks_free; + } + else { + int len; + password = prim2str (rq->password, &len); + } + + PP_TRACE (("parameter_checks MTA=%s, P=%s", remotesite, password)); + + if (mta && lexequ (remotesite, mta) != 0) { + do_reason ("parameter_checks/MTAName mismatch: specified='%s' received='%s'", mta, remotesite); + goto parameter_checks_free; + } + + + if (lexequ (pass, "dflt") == 0) { + retval = OK; + goto parameter_checks_free; + } + + + if (pass && lexequ ((char *)password, pass) != 0) { + do_reason ("parameter_checks/Password mismatch: specified='%s' received='%s'", pass, (char *)password); + goto parameter_checks_free; + } + + retval = OK; + +parameter_checks_free: ; + if (req) free_Rts84_Request (req); + if (remotesite) free (remotesite); + if (password) free ((char *)password); + + return retval; +} + + + + +/* -- Checks P1 User-data: mTAName and password -- */ + +rts_decode_request (rts, ppe, prq, chan) +struct RtSAPstart *rts; +PE *ppe; +struct type_Rts84_Request **prq; +CHAN *chan; +{ + char *key; + RtsParams *rp; + int checkit = TRUE; + + key = build_inkey (rts); + + PP_TRACE (("x400in84/rts_decode_request (%s)", key)); + + + if ((rp = tb_rtsparams (chan->ch_in_table, key)) == NULL) + return (remote_info_not_found (rts, ppe, prq, key, chan)); + + + /* -- Check that the right info is in the tables -- */ + if (rp->their_internal_ppname == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No rname specified in the entry '%s'", key)); + return RTS_VALIDATE; + } + + if (rp->their_name == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No rmta specified in the entry '%s'", key)); + return RTS_VALIDATE; + } + + if (lexequ (chan -> ch_in_info, "sloppy") == 0 + || lexequ (rp -> info_mode, "sloppy") == 0) + checkit = FALSE; + + if (parameter_checks (rts -> rts_data, rp -> their_name, + rp -> their_passwd, key, checkit) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Parameter check failed")); + return RTS_VALIDATE; + } + + + /* -- encode new Connect Accept Data -- */ + rts_encode_request (ppe, prq, rp -> our_name, rp -> our_passwd); + + + /* -- set the remote site value -- */ + if (remote_site) + free (remote_site); + if (rp -> their_internal_ppname == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("No internal name for %s", key)); + remote_site = strdup (key); + } + else remote_site = strdup (rp -> their_internal_ppname); + + + /* --- *** --- + if "undefined" set in eit - replace with rp->info_undefined + --- *** --- */ + + if (undefined_bodyparts) { + free (undefined_bodyparts); + undefined_bodyparts = NULLCP; + } + if (rp -> info_undefined) + undefined_bodyparts = strdup (rp -> info_undefined); + + RPfree (rp); + return OK; +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + + + +static int remote_info_not_found (rts, ppe, prq, key, chan) +struct RtSAPstart *rts; +PE *ppe; +struct type_Rts84_Request **prq; +char *key; +CHAN *chan; +{ + RtsParams *rp; /* --- contains default values --- */ + + + PP_TRACE (("remote_info_not_found()")); + + parameter_checks (rts -> rts_data, NULLCP, NULLCP, key, FALSE); + + if (lexequ (chan -> ch_in_info, "sloppy") != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("No information found in the X.400 incoming tables")); + return RTS_VALIDATE; + } + + if ((rp = tb_rtsparams (chan -> ch_in_table, "default")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("No 'default' found in the X.400 incoming tables")); + return RTS_VALIDATE; + } + + + /* -- encode new Connect Accept Data -- */ + rts_encode_request (ppe, prq, rp -> our_name, rp -> our_passwd); + RPfree (rp); + + if (remote_site) free (remote_site); + remote_site = strdup (key); + + PP_LOG (LLOG_EXCEPTIONS, + ("No information found in the X.400 incoming tables - BUT have accepted the connection")); + + return OK; +} + + + + +static void print_remote_info (key, req) +char *key; +struct type_Rts84_Request *req; +{ + static char databuf[BUFSIZ]; + char buf[BUFSIZ]; + PE pe; + char *cp; + + + bzero (databuf, BUFSIZ); + + (void) sprintf (databuf, "key='%s' ", key); + + if (pretty_key) { + (void) sprintf (buf, "key-pretty='%s' ", pretty_key); + (void) strcat (databuf, buf); + } + + if (req->offset == type_Rts84_Request_1) { + (void) strcat (databuf, "(no more connection data info)"); + goto print_remote_info_end; + } + + + if ((cp = qb2str (req->un.choice_Rts84_1->mTAName)) != NULLCP) { + (void) sprintf (buf, "mta='%s' ", cp); + (void) strcat (databuf, buf); + free (cp); + } + + pe = req->un.choice_Rts84_1->password; + + if (pe->pe_form == PE_FORM_PRIM) + if (pe -> pe_prim != 0) { + int len; + cp = prim2str (pe, &len); + (void) sprintf (buf, "password='%s' ", cp); + (void) strcat (databuf, buf); + free (cp); + } + + +print_remote_info_end: ; + PP_NOTICE (("Connection from %s", databuf)); + return; +} + + + + +static char *build_inkey (rts) +struct RtSAPstart *rts; +{ + struct PSAPaddr pas; + struct NSAPaddr *na; + int nna; + char *cp; + + PP_TRACE (("build_inkey()")); + + bzero ((char *)&pas, sizeof pas); + pas.pa_addr = rts -> rts_initiator.rta_addr; + for (na = pas.pa_addr.sa_addr.ta_addrs, + nna = pas.pa_addr.sa_addr.ta_naddr; + nna > 0; nna --, na ++) { + if (na -> na_type == NA_TCP) { + PP_TRACE (("Address is TCP, port set to 0 from %d", + na -> na_port)); + na -> na_port = 0; + /* bug in isode 6.6 */ + if ((cp = index(na -> na_domain, '+')) != NULL) + *cp = '\0'; + } + } + + if (pretty_key) free (pretty_key); + pretty_key = strdup(paddr2str (&pas, NULLPA)); + + return _paddr2str (&pas, NULLPA, -1); +} + +dump_pdu (qb, str) +struct qbuf *qb; +char *str; +{ + struct qbuf *q; + char buf[512]; + char *cp; + int len, n; + + PP_LOG (LLOG_PDUS, ("PDU dump: %s", str)); + if ((pp_log_norm -> ll_events & LLOG_PDUS) == 0) + return; + + for (q = qb -> qb_forw; q != qb; q = q -> qb_forw) { + for (cp = q -> qb_data, len = q -> qb_len; + len > 0;) { + n = min (sizeof (buf) / 2 - 1, len); + buf[explode (buf, (u_char *)cp, n)] = 0; + ll_printf (pp_log_norm, "%s", buf); + + len -= n; + cp += n; + } + } + ll_printf (pp_log_norm, "\n-----------\n"); +} diff --git a/Chans/x40084/x400in84.c b/Chans/x40084/x400in84.c new file mode 100644 index 0000000..ef1e2c8 --- /dev/null +++ b/Chans/x40084/x400in84.c @@ -0,0 +1,622 @@ +/* x400in84.c: receives the incomming x400 messages */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400in84.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400in84.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: x400in84.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "dr.h" +#include "q.h" +#include "Rts84-types.h" +#include +#include +#include +#include +#include +#include + + + +/* -- defines -- */ + /* --- hex dump of msg --- */ +#define qb2postie(qb) (send2postie (NULLPE, qb, 0)) + /* --- splat of msg --- */ +#define pe2postie1(pe) (send2postie (pe, (struct qbuf *)0, 1)) + /* --- pretty print of msg --- */ +#define pe2postie(pe) (send2postie (pe, (struct qbuf *)0, 2)) + + + +#define RTS_MAX_NO_OF_TURNS 5 +#define RTS_SENT_TURN 'S' +#define SUBMIT_NOT_CALLED 1 + + +/* -- externals -- */ +extern int errno, + body_len; +extern char *isodesetailor(), + *hdr_p2_bp, + *cont_p2, + *loc_dom_site, + *quedfldir, + *body_string, + *rcmd_srch(), + *remote_site; +extern int hdrproc(), + bodyproc(), + msgfinished(); +extern void isodetailor(); +extern ADDR *adr_new(); +extern Q_struct *PPQuePtr; +extern DRmpdu *DRptr; +extern CMD_TABLE qtbl_mt_type[]; +extern IFP asn_procfnx; + + +/* -- statics -- */ +static struct timeval data_timer; +static int data_bytes=0, + initial_mode, + initial_turn, + nturns=0, + rts_uptrans(); +int submit_running = 0; + +static char turn_status=' '; +CHAN *mychan; + + +/* -- globals -- */ +char *pp_myname = "x400in84"; + +#ifdef PP_DEBUG +static int do_debug_transfer(); +#endif + + +/* -- local routines -- */ +void set_msg_adrs(); +static int qblen(); +static int rts_uptrans(); +static int rts_do_turn(); +static void rts_get_request(); +static void rts_abort(); +static void rts_close(); +static void rts_get_request(); +static void rts_indication(); + + + +/* --------------------- Main Routine ---------------------------------- */ + + +/*ARGSUSED)*/ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + int sd; + struct RtSAPstart rtss; + register struct RtSAPstart *rts = &rtss; + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + struct SSAPaddr *sai = &rts -> rts_initiator.rta_addr; + struct TSAPaddr *tai = &sai -> sa_addr; + struct NSAPaddr *nai = tai -> ta_addrs; + PE accept_pe = NULLPE; + struct type_Rts84_Request *request = 0; + int retval; + RP_Buf rps, *rp = &rps; + int opt; + extern char *optarg; + extern int optind; + + + + /* -- Reading of the tailor file info -- */ + + if (pp_myname = rindex (argv[0], '/')) + pp_myname++; + + if (pp_myname == NULL || *pp_myname == NULL) + pp_myname = argv[0]; + + while ((opt = getopt (argc, argv, "c:")) != EOF) { + switch (opt) { + case 'c': + pp_myname = optarg; + break; + default: + adios (NULLCP, "Unknown argument -%c", opt); + } + } + + chan_init (pp_myname); + + if ((mychan = ch_nm2struct (pp_myname)) == NULLCHAN) + adios (NULLCP, "No such channel %s", pp_myname); + + pp_setuserid(); + + (void) chdir (quedfldir); + + or_myinit(); + + PP_NOTICE (("Starting %s (%s)", mychan->ch_name, mychan->ch_show)); + + + /* --- *** --- + Since isode/isoservices calls x400in84, the RTS connection needs + to be terminated, if an error occurs, otherwise the connection + hangs ... the remote initiator waits for a response and none + is forthcoming ... + --- *** --- */ + +#if PP_DEBUG + if (argv[optind] && strcmp (argv[optind], "debug") == 0) { + do_debug_transfer(); + exit (0); + } +#endif + if (RtBInit (argc, argv, rts, rti) == NOTOK) { + rts_exceptions (rta, "RtBInit"); + exit (NOTOK); + } + + + /* --- And lots & lots of tracing! --- */ + + PP_TRACE (("RT-BEGIN.INDICATION: <%d, %s, %s, %d, 0x%x>", + rts->rts_sd, + rts->rts_mode == RTS_TWA ? "twa" : "mon", + rts->rts_turn == RTS_RESPONDER ? "responder" : "initiator", + ntohs (rts->rts_port), + rts->rts_data)); + + PP_TRACE (("Calling addresses: <<%s, %s>, %s>", + na2str (nai), + sel2str (tai->ta_selector, tai->ta_selectlen, 1), + sel2str (sai->sa_selector, sai->sa_selectlen, 1))); + + PP_TRACE (("more .... <<%s, '%s' '%d'>, '%s' '%d'>", + na2str (nai), + &tai->ta_selector[0], tai->ta_selectlen, + &sai->sa_selector[0], sai->sa_selectlen)); + + + /* -- Important in determining the logic of the RTS turns -- */ + + initial_mode = rts->rts_mode; + initial_turn = rts->rts_turn; + + + sd = rts -> rts_sd; + + + /* -- x400in84 never transmits information -- */ + + if (initial_turn == RTS_RESPONDER && initial_mode == RTS_MONOLOGUE) { + do_reason ("main/turn=responder && mode=monologue"); + RtBeginResponse (sd, RTS_REJECT, NULLPE, rti); + exit (NOTOK); + } + + + if (rts->rts_data == NULLPE) { + do_reason ("main/Rejected -- no user data parameter"); + RtBeginResponse (sd, RTS_REJECT, NULLPE, rti); + exit (NOTOK); + } + + + PP_PDU (print_Rts84_Request, rts -> rts_data, + "RTS84.Request", PDU_READ); + + if ((retval = rts_decode_request (rts, &accept_pe, + &request, mychan)) != OK) { + RtBeginResponse (sd, retval, NULLPE, rti); + exit (NOTOK); + } + + PP_PDU (print_Rts84_Request, accept_pe, "RTS84.Response", PDU_WRITE); + + + if (RtBeginResponse (sd, RTS_ACCEPT, accept_pe, rti) == NOTOK) { + rts_advise (rta, "RT-BEGIN.RESPONSE Accept"); + RtBeginResponse (sd, RTS_REMOTE, NULLPE, rti); + exit (NOTOK); + } + + + if (accept_pe) + pe_free (accept_pe); + if (request) + free_Rts84_Request (request); + + + + /* --- *** --- + Initialise submit as late as possible so if error occurs earlier on + x400in and submit are not both running. + --- *** --- */ + + if (rp_isbad (io_init(rp))) + adios (NULLCP, "io_init error: %s", rp -> rp_line); + submit_running = 1; + + + /* -- Returns the turn. x400in84 never transmits info -- */ + + if (initial_turn == RTS_RESPONDER) { + if (RtGTurnRequest (sd, rti) == NOTOK) + rts_adios (rta, "RT-TURN-GIVE.REQUEST"); + turn_status = RTS_SENT_TURN; + nturns++; + } + + + RTSFREE (rts); + + + /* -- Sets up the RTS to receive incomming data -- */ + + if (RtSetUpTrans (sd, rts_uptrans, rti) == NOTOK) + rts_adios (rta, "RtSetUpTrans upcall"); + + + rts_get_request (sd); + + do_reason ("main/Impossible to arrive here!"); + + exit (NOTOK); +} + + + + +void set_msg_adrs() +{ + ADDR *ap; + + for (ap = PPQuePtr->Raddress; ap; ap = ap->ad_next) + if (ap->ad_resp == NO) + ap->ad_status = AD_STAT_DONE; +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void rts_get_request (sd) +int sd; +{ + struct RtSAPindication rti; + int loop_forever = TRUE, + result; + + + while (loop_forever) { + switch (result = RtWaitRequest (sd, NOTOK, &rti)) { + case NOTOK: + case OK: + case DONE: + PP_TRACE (("rts_get_request (%d)", result)); + rts_indication (sd, &rti); + break; + default: + do_reason ("rts_get_request/result='%d'", result); + } + } +} + + + + +static void rts_indication (sd, rti) +int sd; +struct RtSAPindication *rti; +{ + switch (rti->rti_type) { + case RTI_TURN: + PP_TRACE (("RTI_TURN")); + if (rts_do_turn (sd, &rti->rti_turn) == NOTOK) + rts_abort (sd, &rti->rti_abort); + break; + case RTI_TRANSFER: + PP_TRACE (("RTI_TRANSFER")); + /* -- rts_uptrans() does all the work -- */ + timer_end (&data_timer, data_bytes, "Transfer Completed"); + break; + case RTI_ABORT: + PP_TRACE (("RTI_ABORT")); + rts_abort (sd, &rti->rti_abort); + break; + case RTI_CLOSE: + PP_TRACE (("RTI_CLOSE")); + rts_close (sd, &rti->rti_close); + break; + default: + do_reason ("rts_indication/'%d' unknown", rti->rti_type); + rts_abort (sd, &rti->rti_abort); + break; + } +} + + + + +static int rts_do_turn (sd, rtu) +int sd; +struct RtSAPturn *rtu; +{ + struct RtSAPindication rti; + + + PP_TRACE (("rts_do_turn %s %s %d %s", + initial_mode == RTS_TWA ? "twa" : "mon", + initial_turn == RTS_RESPONDER ? "responder" : "initiator", + nturns, + turn_status == RTS_SENT_TURN ? "send" : "received")); + + + /* -- Remote site is requesting the turn which x400in84 -- */ + /* -- already possesses -- */ + + + if (rtu->rtu_please) + if (turn_status == RTS_SENT_TURN) { + do_reason ("rts_do_turn/Already sent turn!"); + return NOTOK; + } + else { + /* -- should never have turn! but left for now -- */ + do_reason ("rts_do_turn/Should not have turn!"); + return NOTOK; + } + + + /* -- Remote site is transferring the turn to x400in84 -- */ + + if (initial_turn == RTS_INITIATOR && initial_mode == RTS_MONOLOGUE) { + do_reason ("rts_do_turn/Should not give turn in Monologue!"); + return NOTOK; + } + + if (nturns > RTS_MAX_NO_OF_TURNS) { + do_reason ("rts_do_turn/Too many turns occurred!"); + return NOTOK; + } + + + /* -- Returns turn but keeps count to prevent turn looping -- */ + + if (RtGTurnRequest (sd, &rti) == NOTOK) { + do_reason ("rts_do_turn/RT-TURN-GIVE.REQUEST failed"); + return NOTOK; + } + + turn_status = RTS_SENT_TURN; + nturns++; + return OK; +} + + + + +/*ARGSUSED*/ +static void rts_abort (sd, rta) +int sd; +register struct RtSAPabort *rta; +{ + + if (submit_running) + io_end (NOTOK); + + if (rta->rta_peer) + rts_adios (rta, "RT-U-ABORT.INDICATION"); + + if (RTS_FATAL (rta->rta_reason)) + rts_adios (rta, "RT-P-ABORT.INDICATION"); + + rts_adios (rta, "RT-P-ABORT.INDICATION (error)"); +} + + + + +/* ARGSUSED */ +static void rts_close (sd, rtc) +int sd; +struct RtSAPclose *rtc; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti->rti_abort; + + PP_TRACE (("RT-END.INDICATION %d", sd)); + + if (RtEndResponse (sd, rti) == NOTOK) + rts_adios (rta, "RT-END-RESPONSE.REQUEST error"); + + if (submit_running) + io_end (OK); + + PP_NOTICE (("Connection successfully terminated")); + + exit (0); + +} + + + + +static struct qbuf *fullqb = NULL; + + +/*ARGSUSED)*/ +static int rts_uptrans (sd, type, addr, rti) +int sd; +int type; +caddr_t addr; +struct RtSAPindication *rti; +{ + register struct SSAPactivity *sv = (struct SSAPactivity *) addr; + register struct SSAPsync *sn = (struct SSAPsync *) addr; + register struct SSAPreport *sp = (struct SSAPreport *) addr; + register struct qbuf *qbp = (struct qbuf *) addr; + PE pe = NULLPE; + int len; + + + PP_TRACE (("rts_uptrans()")); + + switch (type) { + case SI_DATA: + PP_TRACE (("SI_DATA")); + + dump_pdu (qbp, "Incoming X.400 data"); + len = qblen (qbp); + data_bytes += len; + PP_TRACE (("Data %d bytes (%d so far)", len, data_bytes)); + + switch ((*asn_procfnx)(qbp)) { + case NOTOK: + default: + io_end (NOTOK); + submit_running = 0; + return rtsaplose (rti, RTS_TRANSFER, NULLCP, + "process data failed"); + case OK: + case DONE: + break; + } + break; + + case SI_SYNC: + PP_TRACE (("S-MINOR-SYNC.INDICATION: %ld", sn->sn_ssn)); + break; + + case SI_ACTIVITY: + switch (sv->sv_type) { + case SV_START: + PP_TRACE (("S-ACTIVITY-START.INDICATION")); + data_bytes = 0; + timer_start (&data_timer); + asn_init (hdrproc, bodyproc, 0); + break; + + case SV_INTRIND: + case SV_DISCIND: + PP_LOG (LLOG_EXCEPTIONS, + ("activity %s: %s", + sv->sv_type == SV_INTRIND ? + "interrupted" : "discarded", + SReportString (sv->sv_reason))); + break; + + case SV_ENDIND: + PP_TRACE (("S-ACTIVITY-END.INDICATION")); + PP_TRACE (("Accumulated '%d'", data_bytes)); + if (msgfinished() == NOTOK) + return rtsaplose (rti, RTS_TRANSFER, + NULLCP, + "data termination failed"); + break; + + default: + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unexpected activity indication=0x%x", + sv->sv_type)); + } + break; + + + case SI_REPORT: + if (!sp->sp_peer) + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unexpected provider-initiated SI_REPORT")); + do_reason ("rts_uptrans/Exception Report: '%s'", + SReportString (sp->sp_reason)); + if (pe) + pe_free (pe); + break; + + default: + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unknown rts_uptrans type=0x%x", type)); + } + + return OK; +} + + + + +static int qblen (qbstart) +struct qbuf *qbstart; +{ + int len; + register struct qbuf *qb; + + for (len = 0, qb = qbstart->qb_forw; qb != qbstart; qb = qb->qb_forw) + len += qb -> qb_len; + + return len; +} + + + + +/* --------------------- Postmaster Routines ---------------------------- */ + + + + +#if PP_DEBUG +static int do_debug_transfer() +{ + char buf[BUFSIZ]; + int n; + int result = NOTOK; + struct qbuf *qb; + struct SSAPactivity ssa; + struct RtSAPindication rti; + extern char *loc_dom_mta; + + bzero ((char *)&ssa, sizeof ssa); + bzero ((char *)&rti, sizeof rti); + ssa.sv_type = SV_START; + remote_site = loc_dom_mta; + + rts_uptrans (0, SI_ACTIVITY, (caddr_t)&ssa, &rti); + while ((n = fread (buf, 1, sizeof buf, stdin)) > 0) { + qb = str2qb (buf, n, 1); + rts_uptrans (0, SI_DATA, (caddr_t)qb, &rti); + qb_free (qb); + } + ssa.sv_type = SV_ENDIND; + rts_uptrans (0, SI_ACTIVITY, (caddr_t)&ssa, &rti); + if (result != DONE) + advise (NULLCP, "Read message - not parsed"); +} +#endif diff --git a/Chans/x40084/x400out84.c b/Chans/x40084/x400out84.c new file mode 100644 index 0000000..a25a47f --- /dev/null +++ b/Chans/x40084/x400out84.c @@ -0,0 +1,1211 @@ +/* x400out84.c: transmit x400 messages out across RTS */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400out84.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400out84.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: x400out84.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include +#include "sys.file.h" +#include "prm.h" +#include "q.h" +#include "qmgr.h" +#include "dr.h" +#include "Rts84-types.h" +#include "rtsparams.h" +#include +#include +#include +#include + + +#define MAXTRIES 10 + + +/* -- externals -- */ +extern char *loc_dom_site; +extern char *quedfldir; +extern char *rcmd_srch(); +extern char reason[]; +extern CMD_TABLE qtbl_mt_type[]; + + +/* -- queue variables -- */ +static Q_struct Qstruct; +static DRmpdu DRstruct; +static struct prm_vars PRMstruct; +Q_struct *PPQuePtr = &Qstruct; +DRmpdu *DRptr = &DRstruct; + + +/* -- globals -- */ +char *body_string = NULLCP; +char *pp_myname; +char *fix_orig; +int body_len = 0; +int trace_type = RTSP_TRACE_ALL; +ADDR *ad_list; + + +/* -- statics -- */ +static int RTS_PING_84 = FALSE; +static CHAN *mychan; +static char *this_msgid = NULLCP, + *dumpp1 = NULLCP, + *chan_name = NULLCP, + *current_mta = NULLCP, + *connected_to_site = NULLCP, + *p1_string = NULLCP, + *p1_ptr; +static struct timeval data_timer; +static int data_bytes=0, + p1_length = 0, + rts_sd = NOTOK; +static enum { st_init, st_hdr, st_bodyinit, st_body, st_end } trans_state; + + +/* -- local routines -- */ +static char *pe_flatten(); +static int attempt_connect(); +static void close_body(); +static int construct_dr(); +static int construct_msg(); +static int construct_probe(); +static int deliver(); +static void dirinit(); +static void dump2file(); +static int endproc(); +static int get_more_message(); +static int initproc(); +static void open_body(); +static int read_body(); +static int rts_connect(); +static int rts_downtrans_all(); +static int rts_downtrans_inc(); +static int rts_end(); +static int rts_start(); +static int rts_transfer_request(); +static int rtsping84(); +static void wr_sender2log(); +static struct type_Qmgr_DeliveryStatus *process(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + + +main (argc, argv) +int argc; +char **argv; +{ + if (pp_myname = rindex (argv[0], '/')) + pp_myname++; + if (pp_myname == NULL || *pp_myname == NULL) + pp_myname = argv[0]; + + + /* -- read pp tailor file -- */ + chan_init (pp_myname); + + + /* -- rts84 ping required ? -- */ + if (argc > 1 && strcmp(argv[1], "ping") == 0) + rtsping84 (argc - 1, argv + 1); + + + /* -- get ready to transmit x400out84 messages -- */ + pp_setuserid(); + or_myinit(); + dirinit(); + + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) { + if (argc > 2) + dumpp1 = argv[2]; + debug_channel_control (argc, argv, initproc, process, endproc); + } else +#endif + (void) channel_control (argc, argv, initproc, process, endproc); + + exit (0); + /* NOTREACHED */ +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void dirinit() /* -- Change into pp queue space -- */ +{ + PP_TRACE (("dirinit()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change to dir '%s'", quedfldir); +} + + + + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + + if (!RTS_PING_84) chan_name = qb2str (arg); + + PP_TRACE (("initproc (%s)", chan_name)); + + if ((mychan = ch_nm2struct (chan_name)) == NULLCHAN) + err_abrt (RP_PARM, "Channel '%s' not known", chan_name); + + rename_log (chan_name); + free (chan_name); + chan_name = NULLCP; + + PP_NOTICE (("Starting %s (%s)", mychan -> ch_name, mychan -> ch_show)); + + if (RTS_PING_84) return OK; + + prm_init (&PRMstruct); + q_init (PPQuePtr); + dr_init (&DRstruct); + if (current_mta) + free (current_mta); + current_mta = NULLCP; + return OK; +} + + + + +static int endproc() +{ + switch (rts_end()) { + case RP_OK: + PP_NOTICE (("Connection successfully terminated")); + break; + case RP_BAD: + PP_NOTICE (("Connection badly terminated")); + break; + default: + PP_NOTICE (("Connection not made")); + break; + } + return OK; +} + + + + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + ADDR *ad_sender = NULLADDR, + *ad_recip = NULLADDR, + *rp, + *sp, + *lp = NULL; + int naddrs = 0, + ad_count, + retval; + + if (this_msgid) free (this_msgid); + this_msgid = qb2str (arg -> qid); + + PP_NOTICE (("Reading message '%s'", this_msgid)); + + q_free (PPQuePtr); + dr_free (&DRstruct); + prm_free (&PRMstruct); + + delivery_init (arg -> users); + + retval = rd_msg (this_msgid, &PRMstruct, PPQuePtr, + &ad_sender, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Read message failed for '%s'", this_msgid)); + reason[0] = 0; + goto process_error; + } + + if (ad_sender -> ad_r400adr == NULLCP) { + do_reason ("x400 address not set in sender field of '%s'", + this_msgid); + goto process_error; + } + + + for (sp = ad_sender, rp = ad_recip; rp; rp = rp -> ad_next) { + + for (up = arg -> users; up; up = up -> next) { + + PP_TRACE (("'%s' '%s' ad_no=%d up_no=%d", + this_msgid, rp -> ad_value, rp -> ad_no, + up -> RecipientId -> parm)); + + if (up -> RecipientId -> parm != rp -> ad_no) + continue; + + if (dchan_acheck (rp, sp, mychan, naddrs == 0, + ¤t_mta)) + continue; + naddrs ++; + break; + + } /* -- end of for -- */ + + + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = lp = (ADDR *)calloc(1, sizeof *lp); + else { + lp -> ad_next = (ADDR *)calloc(1, sizeof *lp); + lp = lp -> ad_next; + } + + *lp = *rp; /* struct copy */ + lp -> ad_next = NULLADDR; + + } /* -- end of for -- */ + + + if (naddrs == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("No recips to be processed in '%s'", this_msgid)); + rd_end (); + return deliverystate; /* delivery state is set correct */ + } + + + deliver (ad_list); /* deliverystate set in deliver */ + + for (lp = ad_list; lp; lp = rp) { + rp = lp -> ad_next; + free ((char *)lp); + } + + ad_list = NULLADDR; + rd_end(); + return deliverystate; + + +process_error: ; + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, reason); +} + + + + +static void wr_sender2log (sender) +ADDR *sender; +{ + switch (PPQuePtr -> msgtype) { + case MT_PMPDU: + PP_NOTICE (("Sender (of probe) '%s'", sender -> ad_r400adr)); + break; + + default: + if (ad_list -> ad_status == AD_STAT_PEND) + PP_NOTICE (("Sender '%s'", sender -> ad_r400adr)); + else + PP_NOTICE (("Sender (of delivery report '%s'", + sender -> ad_r400adr)); + break; + } + + return; +} + + + + +static int deliver (recip) +ADDR *recip; +{ + int value = int_Qmgr_status_messageFailure; + ADDR *ap; + int msgtype; + int retval; + + + switch (recip -> ad_status) { + case AD_STAT_PEND: + case AD_STAT_DRWRITTEN: + break; + case AD_STAT_DONE: + delivery_setallstate (int_Qmgr_status_success, "All delivered"); + return NOTOK; + default: + do_reason ("bad state"); + delivery_setallstate (int_Qmgr_status_messageFailure, reason); + return NOTOK; + } + + + if (attempt_connect() != OK) + return NOTOK; + + msgtype = Qstruct.msgtype; + if (fix_orig) + x400_fixorig (Qstruct.Oaddress, fix_orig); + if (recip -> ad_status == AD_STAT_DRWRITTEN || + Qstruct.msgtype == MT_DMPDU) { + retval = construct_dr ( &Qstruct, recip); + msgtype = MT_DMPDU; + } + else if (Qstruct.msgtype == MT_PMPDU) + retval = construct_probe (&Qstruct, recip); + else + retval = construct_msg (&Qstruct, recip); + + + if (retval == NOTOK) + return NOTOK; + + + wr_sender2log (Qstruct.Oaddress); + + for (ap = recip; ap; ap = ap -> ad_next) + PP_NOTICE (("Recipient Address '%s'", ap -> ad_r400adr)); + + switch (rts_transfer_request(msgtype)) { + case OK: + value = int_Qmgr_status_success; + break; + default: + if (rts_sd == NOTOK) + value = int_Qmgr_status_mtaAndMessageFailure; + else + value = int_Qmgr_status_messageFailure; + break; + } + + + for (ap = recip; ap; ap = ap -> ad_next) + if (ap -> ad_resp) { + switch (value) { + case int_Qmgr_status_success: + delivery_set (ap -> ad_no, value); + wr_ad_status (ap, AD_STAT_DONE); + wr_stat (ap, &Qstruct, this_msgid, data_bytes); + break; + default: + delivery_setstate (ap -> ad_no, value, reason); + break; + } + } + + + if (p1_string) free (p1_string); + p1_string = NULLCP; + data_bytes = 0; + p1_length = 0; + + return OK; +} + + +static void get_dr_content (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + char *dir = NULLCP; + char filename[MAXPATHLENGTH]; + char buf[MAXPATHLENGTH]; + int fd; + struct stat st; + + if (qid2dir (this_msgid, qp->Oaddress, TRUE, &dir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("qid2dir can't find DR content")); + return; + } + if (msg_rinit (dir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit failed")); + return; + } + if (msg_rfile (filename) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_file failed")); + return; + } + if (msg_rfile(buf) != RP_DONE) { + PP_LOG (LLOG_EXCEPTIONS, + ("Extra message component - expecting only one")); + return; + } + msg_rend (); + if ((fd = open (filename, O_RDONLY, 0)) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, filename, ("Cant open")); + return; + } + if (fstat (fd, &st) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, filename, ("Can't fstat")); + (void) close (fd); + return; + } + body_string = smalloc (body_len = st.st_size); + if (read (fd, body_string, st.st_size) != st.st_size) { + PP_SLOG (LLOG_EXCEPTIONS, "read", ("failed")); + (void) close (fd); + return; + } + (void) close(fd); +} + +static int construct_dr (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + PE pe; + + if (rp_isbad (get_dr (recip -> ad_no, this_msgid, &DRstruct))) { + do_reason ("Can't read delivery report '%s' recip '%d'", + this_msgid, recip -> ad_no); + delivery_setallstate (int_Qmgr_status_messageFailure, reason); + return NOTOK; + } + + qp -> msgtype = MT_DMPDU; + if (qp -> content_return_request == TRUE) + get_dr_content(qp, recip); + + if (build_P1_MPDU (&pe, 1, NULLINT, NULLCP, NULL) == NOTOK) { + do_reason ("Can't build DR ASN.1: %s", PY_pepy); + delivery_setallstate (int_Qmgr_status_messageFailure, reason); + return NOTOK; + } + + PP_PDU (print_P1_MPDU, pe, "P1.MPDU", PDU_WRITE); + + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + pe_free (pe); + dr_free (&DRstruct); + if (body_string) { + free (body_string); + body_string = NULLCP; + body_len = 0; + } + return OK; +} + + + +static int construct_probe (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + PE pe; + + if (build_P1_MPDU (&pe, 1, NULLINT, NULLCP, NULL) == NOTOK) { + do_reason ("Can't build Probe ASN.1: %s", PY_pepy); + return NOTOK; + } + + PP_PDU (print_P1_MPDU, pe, "P1.MPDU", PDU_WRITE); + + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + pe_free (pe); + return OK; +} + + + +static int construct_msg (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + PE pe; + + if (build_P1_UMPDUEnvelope (&pe, 1, NULLINT, NULLCP, qp) == NOTOK) { + do_reason ("Can't build MSG ASN.1: %s", PY_pepy); + return NOTOK; + } + PP_PDU (print_P1_UMPDUEnvelope, pe, "P1.UMPDUEnvelope", PDU_WRITE); + + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + pe_free (pe); + return OK; +} + + + + +static int attempt_connect() +{ + if (connected_to_site == NULLCP || rts_sd == NOTOK) + goto attempt_rts_start; + + if (lexequ (connected_to_site, current_mta) == 0) + return OK; + + (void) rts_end(); + goto attempt_rts_start; + +attempt_rts_start: ; + if (connected_to_site) free (connected_to_site); + connected_to_site = NULLCP; + + + if (rts_start() != OK) { + delivery_setallstate (int_Qmgr_status_mtaFailure, reason); + return NOTOK; + } + + connected_to_site = strdup (current_mta); + return OK; +} + + + + +static int rts_start() +{ + RtsParams *rp; + int count, retcode = NOTOK; + + PP_TRACE (("rts_start site %s", current_mta)); + + for (count = 0; count < MAXTRIES; count++) { + + if ((rp = tb_rtsparams (mychan -> ch_table, + current_mta)) == NULL) { + do_reason ("Unable to locate '%s'", current_mta); + return NOTOK; + } + + if (rp -> type != RTSP_1984) { + do_reason ("Not 1984 connection type %s", current_mta); + break; + } + + retcode = rts_connect (rp); + + switch (retcode) { + case OK: + break; + default: + if (rp -> try_next) { + free (current_mta); + current_mta = strdup (rp -> try_next); + RPfree (rp); + continue; + } + break; + } + + break; + } + + + trace_type = rp -> trace_type; + if (fix_orig) + free (fix_orig); + if (rp -> fix_orig) + fix_orig = strdup (rp -> fix_orig); + else fix_orig = NULLCP; + RPfree (rp); + return retcode; +} + + + + +static int rts_connect (rp) +RtsParams *rp; +{ + struct RtSAPaddr rtsapaddr; + register struct RtSAPaddr *rtsap = &rtsapaddr; + struct RtSAPaddr rts_calling; + struct RtSAPaddr *rt_c; + struct SSAPaddr *sa; + struct RtSAPconnect rtcs; + register struct RtSAPconnect *rtc = &rtcs; + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + struct type_Rts84_Request *req = NULL; + int retval = NOTOK; + PE pe = NULLPE; + + PP_TRACE (("rts_connect(%d)", rp -> rts_mode)); + + if (rts_encode_request (&pe, &req, rp -> our_name, + rp -> our_passwd) == NOTOK) + goto rts_connect_free; + + PP_PDU (print_Rts84_Request, pe, "RTS84.Request", PDU_WRITE); + + /* -- clears the relavant structures -- */ + bzero ((char *)rtsap, sizeof (*rtsap)); + bzero ((char *)rtc, sizeof (*rtc)); + bzero ((char *)rti, sizeof (*rti)); + bzero ((char *)rta, sizeof (*rta)); + + rtsap -> rta_port = htons(1); /* P1 id */ + + if (rp -> their_address == NULLCP) { + do_reason ("Null called address for %s", rp -> their_name); + goto rts_connect_free; + } + + if ((sa = str2saddr (rp -> their_address)) == NULLSA) { + do_reason ("Bad called address for %s", rp -> their_address); + goto rts_connect_free; + } + + rtsap -> rta_addr = *sa; /* struct copy */ + + if(rp -> our_address == NULLCP || + (sa = str2saddr (rp -> our_address)) == NULLSA) + rt_c = NULLRtA; + else { + rt_c = &rts_calling; + bzero ((char *)rtc, sizeof *rt_c); + rt_c -> rta_addr = *sa; /* struct copy */ + } + + PP_NOTICE (("Connecting to site %s", current_mta)); + + if (RtBeginRequest2 (rtsap, rt_c, rp -> rts_mode, RTS_INITIATOR, + pe, rtc, rti) == NOTOK) { + rts_advise (rta, "RT-BEGIN.REQUEST"); + goto rts_connect_free; + } + + rts_sd = rtc -> rtc_sd; + + if (rtc -> rtc_result != RTS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to connect to site %s (reason %s)", + current_mta, RtErrString (rtc -> rtc_result))); + goto rts_connect_free; + } + + + PP_PDU (print_Rts84_Request, rtc -> rtc_data, "RTS84.Response", + PDU_READ); + + if (parameter_checks (rtc -> rtc_data, rp -> their_name, + rp -> their_passwd, current_mta, TRUE) == OK) + retval = OK; + +rts_connect_free: ; + RTCFREE(rtc); + RTAFREE(rta); + if (pe) + pe_free (pe); + if (req) + free_Rts84_Request (req); + return retval; +} + + + + +static int rts_transfer_request(type) +int type; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + PP_TRACE (("rts_transfer_request()")); + + trans_state = st_init; + + switch (type) { + case MT_PMPDU: + case MT_DMPDU: + if (RtSetDownTrans (rts_sd, rts_downtrans_all, rti) == NOTOK) { + rts_advise (rta, "set DownTrans upcall"); + return NOTOK; + } + break; + + case MT_UMPDU: + default: + if (RtSetDownTrans (rts_sd, rts_downtrans_inc, rti) == NOTOK) { + rts_advise (rta, "set DownTrans upcall"); + return NOTOK; + } + break; + } + + data_bytes = 0; + timer_start (&data_timer); + if (RtTransferRequest (rts_sd, NULLPE, NOTOK, rti) == NOTOK) { + rts_advise (rta, "RT-TRANSFER.REQUEST"); + if (RTS_FATAL(rta->rta_reason)) + rts_sd = NOTOK; + return NOTOK; + } + + + if (data_bytes > 0) + timer_end (&data_timer, data_bytes, "Transfer Completed"); + + PP_NOTICE((">>> %s %s transfered to %s", + rcmd_srch(Qstruct.msgtype, qtbl_mt_type), + this_msgid, current_mta)); + + return OK; +} + + + + +/* ARGSUSED */ + +static int rts_downtrans_all (sd, base, len, size, ssn, ack, rti) +int sd; +char **base; +int *len, + size; +long ssn, + ack; +struct RtSAPindication *rti; +{ + register int n; + static char *bp; + static int bsize; + + + PP_TRACE (("rts_downtrans()")); + + if (base == NULLVP) { + PP_TRACE (("RT-PLEASE.INDICATION: %d", size)); + return OK; + } + + if (bp == NULLCP) { + + if (size == 0) /* no checkpointing... */ + n = p1_length; + else + n = size; + + if ((bp = malloc ((unsigned) n)) == NULL) + return (rtsaplose (rti, RTS_CONGEST, + NULLCP, "out of memory")); + + PP_TRACE (("Selecting block size of %d", n)); + bsize = n; + } + if (size > 0 && size < bsize) { + PP_LOG (LLOG_EXCEPTIONS, + ("rts_downtrans/downtrans size decreased..")); + bsize = size; + } + + n = MIN(bsize, p1_length); + + if (n == 0) { + *base = NULLCP; + *len = 0; + return OK; + } + + *base = p1_ptr; + *len = n; + + data_bytes += n; + p1_ptr += n; + p1_length -= n; + + if (dumpp1) + dump2file (*base, *len, dumpp1); + + return OK; +} + + +/* ARGSUSED */ +static int rts_downtrans_inc (sd, base, len, size, ssn, ack, rti) +int sd; +char **base; +int *len, + size; +long ssn, + ack; +struct RtSAPindication *rti; +{ + int cc, count; + int n; + char *ptr, *p; + static char *trans_buf; + static int bsize; + static int resetbuf = 0; + int dynamic = 0; + + PP_TRACE (("rts_downtrans_inc (%d, base, len, %d, %ld, %ld, rti)", + sd, size, ssn, ack)); + + if (base == NULLVP) { + PP_TRACE (("RT-PLEASE.INDICATION: %d", size)); + return OK; + } + + if (resetbuf) { + resetbuf = 0; + free (trans_buf); + trans_buf = NULLCP; + bsize = 0; + } + + if (trans_buf == NULLCP) { + + if (size == 0) { /* no checkpointing... */ + n = BUFSIZ * 10; + dynamic = 1; + } + else + n = size; + + if ((trans_buf = malloc ((unsigned) n)) == NULL) + return (rtsaplose (rti, RTS_CONGEST, + NULLCP, "out of memory")); + + PP_TRACE (("Selecting block size of %d", n)); + + bsize = n; + } + + if (size > 0 && size < bsize) { + PP_LOG (LLOG_EXCEPTIONS, ("downtrans size decreased...")); + bsize = size; + } + + if (dynamic) { + for (n = bsize, p = trans_buf, count = 0; ;) { + if ((cc = get_more_message (&ptr, n)) == 0) + break; + bcopy (ptr, p, cc); + p += cc; + n -= cc; + count += cc; + + if (n < 1000) { + bsize += BUFSIZ * 10; + n += BUFSIZ * 10; + trans_buf = realloc (trans_buf, bsize); + p = trans_buf + count; + } + } + + } else { + for (n = bsize, p = trans_buf, count = 0; n > 0;) { + if ((cc = get_more_message (&ptr, n)) == 0) + break; + bcopy (ptr, p, cc); + p += cc; + n -= cc; + count += cc; + } + } + if (dumpp1) + dump2file (trans_buf, count, dumpp1); + if (count == 0) { + *base = NULLCP; + *len = 0; + free (trans_buf); + trans_buf = NULLCP; + dynamic = 0; + return OK; + } + *base = trans_buf; + *len = count; + data_bytes += count; + if (dynamic) resetbuf = 1; + PP_TRACE (("rts_downtrans_inc read %d bytes (%d checkpoint)", + count, bsize)); + + return OK; +} + +static int get_more_message (dptr, n) +char **dptr; +int n; +{ + static char eoc[3]; + static char *ptr; + static int len = 0, inited = 0; + static char buffer[BUFSIZ*8]; + PE pe; + + PP_TRACE (("get_more_message (%d)", n)); + if (!inited) { + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_UNIV_EOC); + inited = 3; + (void) pe_flatten (pe, eoc, 1, &inited); + pe_free (pe); + } + + if (len <= 0) { + switch (trans_state) { + case st_init: + pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0); + pe -> pe_len = PE_LEN_INDF; + len = sizeof buffer; + (void) pe_flatten (pe, buffer, -1, &len); + pe_free (pe); + trans_state = st_hdr; + ptr = buffer; + break; + + case st_hdr: + len = p1_length; + ptr = p1_string; + trans_state = st_bodyinit; + break; + + case st_bodyinit: + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_PRIM_OCTS); + pe -> pe_len = PE_LEN_INDF; + len = sizeof buffer; + (void) pe_flatten (pe, buffer, -1, &len); + pe_free (pe); + ptr = buffer; + open_body (); + trans_state = st_body; + break; + + case st_body: + len = n; + if ((len = read_body (buffer, sizeof buffer)) != 0) { + ptr = buffer; + break; + } + close_body (); + bcopy (eoc, buffer, 2); /* end of octet string (contents) */ + bcopy (eoc, buffer + 2, 2); /* end of hdr sequence */ + len = 4; + ptr = buffer; + trans_state = st_end; + break; + + case st_end: + return 0; + } + } + *dptr = ptr; + n = MIN (n, len); + len -= n; + ptr += n; + PP_TRACE (("get_more_message returning %d bytes", n)); + return n; + +} + +static char *pe_flatten (pe, buffer, flag, ccp) +PE pe; +char *buffer; +int *ccp; +int flag; +{ + PS ps; + char *cp; + + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "ps_alloc failed"); + if (str_setup (ps, buffer, *ccp, buffer == NULLCP ? 0 : 1) == NOTOK) + adios (NULLCP, "str_setup failed", ps_error (ps -> ps_errno)); + + if (pe2ps_aux (ps, pe, flag) == NOTOK) + adios (NULLCP, "pe2ps failed [%s]", ps_error (ps -> ps_errno)); + *ccp = ps -> ps_ptr - ps -> ps_base; + cp = ps -> ps_base; + ps -> ps_base = NULLCP; + ps_free (ps); + return cp; +} + + +static int rts_end() +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + PP_TRACE (("rts_end (%d)", rts_sd)); + + if (rts_sd != NOTOK) + if (RtEndRequest (rts_sd, rti) == NOTOK) { + rts_advise (rta, "RT-END.REQUEST"); + rts_sd = NOTOK; + return RP_BAD; + } + else { + rts_sd = NOTOK; + return RP_OK; + } + + return RP_NOOP; +} + +#ifdef PP_DEBUG +static void dump2file (str, n, file) +char *str; +int n; +char *file; +{ + FILE *fp; + static int once_only = 0; + + if ((fp = fopen (file, once_only ? "a": "w")) == NULL) { + advise (LLOG_NOTICE, NULLCP, file, "Can't open file"); + return; + } + once_only ++; + + fwrite (str, 1, n, fp); + (void) fclose (fp); +} +#endif + +static FILE *body_fp; + +static void open_body() +{ + char filename[MAXPATHLENGTH], + *msgdir = NULLCP; + + if (body_fp) + close_body(); + + if (qid2dir (this_msgid, ad_list, TRUE, &msgdir) == NOTOK) + adios (NULLCP, "Can't find message %s", this_msgid); + + if (rp_isbad (msg_rinit (msgdir))) + adios (NULLCP, "Can't initialise directory %s", msgdir); + + if (rp_isbad (msg_rfile (filename))) + adios (NULLCP, "Can't read file-name"); + + (void) msg_rend(); + + if ((body_fp = fopen (filename, "r")) == NULL) + adios (filename, "Can't open file"); + +} + + +static int read_body (buf, size) +char *buf; +int size; +{ + int len, i; + static PE pe = NULLPE; + PE pe2; + char tbuf[BUFSIZ*8]; + + PP_TRACE (("read_body (%d)", size)); + if (pe == NULLPE) + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_OCTS); + + pe -> pe_len = size; + pe -> pe_len -= ps_get_abs (pe) - size; + for (i = 0; i < 10; i++) { + if (ps_get_abs(pe) <= size) + break; + pe -> pe_len -= 2; + } + + if ( i >= 10) + adios (NULLCP, "Can't sort out asn1 length after 10 attempts"); + + + bzero (tbuf, BUFSIZ); + if ((len = fread (tbuf, 1, pe -> pe_len, body_fp)) <= 0) { + if (ferror (body_fp)) + adios ("fread", "error on file"); + else if (feof (body_fp)) + return 0; + } + + pe2 = oct2prim (tbuf, len); + (void) pe_flatten (pe2, buf, 1, &size); + PP_TRACE (("octet string of length %d returned (%d)", + pe2 -> pe_len, size)); + pe_free (pe2); + return size; +} + + + +static void close_body() +{ + if (body_fp) + fclose (body_fp); + body_fp = NULL; +} + + + + +/* --------------------- Rtsping84 Routine ------------------------------- */ + + + + +static int rtsping84 (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + + PP_NOTICE (("Doing rtsping84")); + + while ((opt = getopt (argc, argv, "c:m:")) != EOF) { + switch (opt) { + case 'c': + chan_name = strdup (optarg); + break; + + case 'm': + current_mta = strdup (optarg); + break; + default: + adios (NULLCP, "Illegal option for rts pinging %s", + argv[optind-1]); + } + } + + RTS_PING_84 = TRUE; + initproc (NULL); + if (attempt_connect() != OK) + PP_NOTICE (("Connection badly terminated")); + else + endproc(); + + exit(0); +} diff --git a/Chans/x40084/x400topp.c b/Chans/x40084/x400topp.c new file mode 100644 index 0000000..f8ed601 --- /dev/null +++ b/Chans/x40084/x400topp.c @@ -0,0 +1,579 @@ +/* x400topp.c: X400(1984) protocol to submit format - inbound */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400topp.c,v 6.0 1991/12/18 20:13:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40084/RCS/x400topp.c,v 6.0 1991/12/18 20:13:50 jpo Rel $ + * + * $Log: x400topp.c,v $ + * Revision 6.0 1991/12/18 20:13:50 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "q.h" +#include "adr.h" +#include "or.h" +#include "prm.h" +#include "dr.h" +#include "retcode.h" +#include +#include + +extern char *remote_site; +extern char *postmaster; +extern int submit_running; +extern CHAN *mychan; +extern Q_struct *PPQuePtr; +extern DRmpdu *DRptr; +extern char *pp_myname; +extern char *cont_p2; +int log_msgtype = 0; /* -- logging of msgtypes -- */ + +enum errstate { + st_normal, st_dr, st_probe, st_err_asn, st_err_submit, st_err_junk +}; +static enum errstate state = st_normal; +static int do_extra_encodedtypes (); + + + +/* -- local routines -- */ +int bodyproc(); +int hdrproc(); +int msgfinished(); +static int do_extra_encodedtypes(); +static int splatfnx(); +static int rebuild_eits(), rebuild_dreits(); +static void resetforpostie(); + + + + +/* ------------------- Begin Routines ------------------------------------ */ + + + + +int hdrproc (pe, type) +PE pe; +int type; +{ + extern char *body_string; + extern int body_len; + ADDR *ap; + struct prm_vars prm; + RP_Buf rps, *rp = &rps; + + + PP_TRACE (("hdrproc (type = '%d')", type)); + + if (type == NOTOK) { + PP_OPER (NULLCP, ("Bad message")); + resetforpostie (st_err_junk, pe, type, "Transfer is not ASN.1"); + return OK; + } + + + state = st_normal; + + if (submit_running == 0) { + if (rp_isbad (io_init (rp))) + adios (NULLCP, "Can't initialise submit: %s", + rp -> rp_line); + submit_running = 1; + } + + + + prm_init (&prm); + prm.prm_opts = PRM_ACCEPTALL | PRM_NOTRACE; + + if (rp_isbad (io_wprm (&prm, rp))) + adios (NULLCP, "io_wpm failed %s", rp -> rp_line); + + + q_init (PPQuePtr); + dr_init (DRptr); + PPQuePtr -> msgtype = log_msgtype = type; + + + switch (type) { + case MT_UMPDU: + PP_PDU (print_P1_UMPDUEnvelope, pe, + "P1.UMPDUEnvelope", PDU_READ); + + PPQuePtr -> inbound = list_rchan_new (remote_site, + NULL); + PPQuePtr -> inbound -> li_chan = ch_mta2struct (pp_myname, + remote_site); + + if (do_P1_UMPDUEnvelope (pe, 1, NULLIP, NULLVP, PPQuePtr) + == NOTOK) { + char buf[BUFSIZ]; + (void) sprintf (buf, "Parse of P1 failed [%s]", PY_pepy); + PP_OPER (NULLCP, ("%s", buf)); + resetforpostie (st_err_asn, pe, type, + buf); + return OK; + } + + (void) rebuild_eits (&PPQuePtr -> encodedinfo, + &PPQuePtr -> orig_encodedinfo, + PPQuePtr -> trace); + + do_extra_encodedtypes (&PPQuePtr -> encodedinfo); + break; + + + case MT_PMPDU: + PP_PDU (print_P1_MPDU, pe, + "P1.MPDU(Probe)", PDU_READ); + + if (do_P1_MPDU (pe, 1, NULLIP, NULLVP, NULL) + == NOTOK) { + char buf[BUFSIZ]; + (void) sprintf (buf, "Parse of P1 probe failed [%s]", PY_pepy); + PP_OPER (NULLCP, ("%s", buf)); + resetforpostie (st_err_asn, pe, type, + buf); + return OK; + } + + state = st_probe; + (void) rebuild_eits (&PPQuePtr -> encodedinfo, + &PPQuePtr -> orig_encodedinfo, + PPQuePtr -> trace); + do_extra_encodedtypes (&PPQuePtr -> encodedinfo); + break; + + + case MT_DMPDU: + PP_PDU (print_P1_MPDU, pe, + "P1.MPDU(DR)", PDU_READ); + + body_string = NULL; + if (do_P1_MPDU (pe, 1, NULLIP, NULLVP, NULL) + == NOTOK) { + char buf[BUFSIZ]; + (void) sprintf (buf, "Parse of P1 DR failed [%s]", PY_pepy); + PP_OPER (NULLCP, ("%s", buf)); + resetforpostie (st_err_asn, pe, type, + buf); + return OK; + } + + state = st_dr; + (void) rebuild_dreits (&PPQuePtr -> encodedinfo, DRptr); + if (body_string != NULLCP) { + do_extra_encodedtypes (&PPQuePtr -> encodedinfo); + PPQuePtr -> content_return_request = TRUE; + } + else { + list_bpt_free (PPQuePtr -> encodedinfo.eit_types); + PPQuePtr -> encodedinfo.eit_types = NULL; + } + PPQuePtr -> cont_type = strdup (cont_p2); + break; + + + default: + adios (NULLCP, "Unknown type of structure %d", type); + } + + + + set_msg_adrs(); + + if (rp_isbad (io_wrq (PPQuePtr, rp))) + adios (NULLCP, "io_wrq %s", rp -> rp_line); + + + PP_NOTICE (("Originator %s", PPQuePtr -> Oaddress -> ad_value)); + + + if (rp_isbad (io_wadr (PPQuePtr -> Oaddress, AD_ORIGINATOR, rp))) { + char ebuf[BUFSIZ]; + do_reason ("io_wadr %s", rp -> rp_line); + + if (rp_gbval(rp -> rp_val) == RP_BNO) { + (void) sprintf (ebuf, "Bad originator address %s: %s", + PPQuePtr -> Oaddress -> ad_value, + rp -> rp_line); + resetforpostie (st_err_submit, pe, type, ebuf); + return OK; + } + + exit (NOTOK); + } + + + + for (ap = PPQuePtr -> Raddress; ap; ap = ap -> ad_next) { + + if (ap -> ad_resp) + PP_NOTICE (("Recipient Address %s", ap -> ad_value)); + else + PP_NOTICE (("Recipient (no responsibility) %s", + ap -> ad_value)); + + if (rp_isbad (io_wadr (ap, AD_RECIPIENT, rp))) { + PP_LOG(LLOG_EXCEPTIONS, ("io_wadr %s", rp -> rp_line)); + return NOTOK; + } + } + + if (rp_isbad (io_adend (rp))) + adios (NULLCP, "io_adend %s", rp -> rp_line); + + + switch (PPQuePtr -> msgtype) { + case MT_UMPDU: + if (rp_isbad (io_tinit (rp))) + adios (NULLCP, "io_tinit %s", rp -> rp_line); + + if (rp_isbad (io_tpart (PPQuePtr -> cont_type, FALSE, rp))) + adios (NULLCP, "io_tpart %s %s", + PPQuePtr -> cont_type, rp -> rp_line); + break; + + case MT_DMPDU: + if (rp_isbad (io_wdr (DRptr, rp))) + adios (NULLCP, "io_wdr %s", rp -> rp_line); + if (rp_isbad (io_tinit (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tinit %s", rp -> rp_line); + return NOTOK; + } + if (body_string) { + if (rp_isbad (io_tpart (PPQuePtr -> cont_type, + FALSE, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tpart %s %s", + PPQuePtr -> cont_type, rp -> rp_line); + return NOTOK; + } + if (rp_isbad (io_tdata (body_string, body_len))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tdata failed"); + return NOTOK; + } + if (rp_isbad (io_tdend (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tdend %s", rp -> rp_line); + return NOTOK; + } + } + + if (rp_isbad (io_tend (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tend %s", rp -> rp_line); + return NOTOK; + } + break; + + case MT_PMPDU: + break; + } + return OK; +} + + + + +int bodyproc (str, len) +char *str; +int len; +{ + char hexbuf[82]; + int i; + RP_Buf rps, *rp = &rps; + + PP_TRACE (("Copy %d bytes", len)); + switch (state) { + case st_normal: + if (rp_isbad (io_tdata (str, len))) { + PP_LOG (LLOG_EXCEPTIONS, ("data write failed")); + return NOTOK; + } + break; + case st_probe: + case st_dr: + PP_LOG (LLOG_EXCEPTIONS, ("Illegal state in bodyproc")); + break; + + case st_err_submit: + case st_err_asn: + case st_err_junk: + for (i = 0; i <= len; i += 40) { + int n = min (40, len - i); + n = explode (hexbuf, str + i, n); + hexbuf[n++] = '\n'; + hexbuf[n] = 0; + if (pps_txt (hexbuf, rp) == NOTOK) + adios (NULLCP, "Error writing to submit: %s", + rp -> rp_line); + } + break; + } + return OK; +} + + + + +int msgfinished () +{ + RP_Buf rps, *rp = &rps; + + switch (state) { + case st_normal: + if (rp_isbad (io_tdend (rp)) || + rp_isbad (io_tend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Data termination failed: %s", + rp -> rp_line)); + return NOTOK; + } + PP_NOTICE (("<<< Message received from %s", + remote_site)); + break; + case st_probe: + PP_NOTICE (("<<< Probe received from %s", + remote_site)); + break; + case st_dr: + PP_NOTICE (("<<< DR received from %s", + remote_site)); + break; + + case st_err_asn: + case st_err_submit: + case st_err_junk: + PP_NOTICE (("<<< Invalid message received from %s", + remote_site)); + if (pps_end (OK, rp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("final handshake failed: %s", + rp -> rp_line)); + return NOTOK; + } + break; + } + return OK; +} + + + + +/* ------------------- Static Routines ------------------------------------ */ + + + + +static int splatfnx (va_alist) +va_dcl +{ + char buffer[BUFSIZ]; + caddr_t junk; + RP_Buf rps; + + va_list ap; + + va_start (ap); + + junk = va_arg (ap, caddr_t); + + _asprintf (buffer, NULLCP, ap); + + PP_TRACE (("splatfnx '%s'", buffer)); + + if (pps_txt (buffer, &rps) == NOTOK) + adios (NULLCP, "Write fails: %s", rps.rp_line); + va_end (ap); +} + + + + +static int rebuild_dreits (eits, dr) +EncodedIT *eits; +DRmpdu *dr; +{ + Trace *tp; + Rrinfo *rr; + LIST_BPT *ep; + + for (rr = dr -> dr_recip_list; rr; rr = rr-> rr_next) { + if (rr -> rr_report.rep_type == DR_REP_FAILURE && + rr -> rr_converted) + for (ep = rr -> rr_converted->eit_types; ep; + ep = ep->li_next) + if (list_bpt_find(eits -> eit_types, ep -> li_name) == NULL) + list_bpt_add (&eits -> eit_types, + list_bpt_new (ep->li_name)); + } + return OK; +} + +static int rebuild_eits (eits, orig, trace) +EncodedIT *eits, *orig; +Trace *trace; +{ + Trace *tp; + LIST_BPT *lasteit = NULL; + + for (tp = trace; tp; tp = tp -> trace_next) + if (tp -> trace_DomSinfo.dsi_converted.eit_types) + lasteit = tp -> trace_DomSinfo.dsi_converted.eit_types; + if (lasteit) + list_bpt_add (&eits -> eit_types, list_bpt_dup (lasteit)); + else + list_bpt_add (&eits -> eit_types, + list_bpt_dup (orig -> eit_types)); + return OK; +} + + + + +static void resetforpostie (st, pe, type, str) +enum errstate st; +PE pe; +int type; +char *str; +{ + static char line[] = "\n\n----------------------------------------\n\n"; + char *msg = ""; + RP_Buf rps, *rp = &rps; + PS ps; + + PP_NOTICE (("Resending the %s to Postmaster", + type == MT_DMPDU ? "Delivery Report" : + type == MT_PMPDU ? "Probe" : "Message")); + + if (submit_running) { + io_end (NOTOK); + submit_running = 0; + } + + switch (state = st) { + case st_err_submit: + msg = "Submission Error"; + break; + case st_err_asn: + msg = "ASN.1 Parsing error"; + break; + case st_err_junk: + msg = "Invalid ASN.1"; + break; + default: + adios (NULLCP, "Bad state in resetforpostie %d", st); + } + + if (pps_1adr (msg, postmaster, rp) == NOTOK) + adios (NULLCP, "Can't initialize submit for error report: %s", + rp -> rp_line); + + if (pps_txt ("X.400 inbound error detected\n\t", rp) == NOTOK || + pps_txt (str, rp) == NOTOK || + pps_txt ("\nThe message was received from ", rp) == NOTOK || + pps_txt (remote_site ? remote_site : "", rp) == NOTOK) + adios (NULLCP, "Error writing data to submit: %s", + rp -> rp_line); + + switch (st) { + case st_err_asn: + msg = "\n\nA dump of the ASN.1 follows:\n\n"; + break; + case st_err_junk: + msg = "\n\nA hex dump of the incoming message follows:\n\n"; + break; + case st_err_submit: + msg = "\n\nA trace of the P1 envelope follows:\n\n"; + break; + } + if (pps_txt (msg, rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Error writing to submit: %s", rp -> rp_line); + + if (st == st_err_junk) + return; + + switch (type) { + case MT_DMPDU: + vpushpp (stdout, splatfnx, pe, "DR MPDU", PDU_WRITE); + break; + case MT_PMPDU: + vpushpp (stdout, splatfnx, pe, "Probe MPDU", PDU_WRITE); + break; + case MT_UMPDU: + vpushpp (stdout, splatfnx, pe, "User MPDU", PDU_WRITE); + break; + } + switch (st) { + case st_err_asn: + vunknown (pe); + break; + + case st_err_submit: + switch (type) { + case MT_DMPDU: + case MT_PMPDU: + print_P1_MPDU(pe, 1, NULLIP, NULLVP, NULLCP); + break; + case MT_UMPDU: + print_P1_UMPDUEnvelope (pe, 1, NULLIP, + NULLVP, NULLCP); + break; + } + } + vpopp (); + if (pps_txt ("\n\nHEX dump of this data now follows", rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Can't write to submit: %s", rp -> rp_line); + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "Can't allocate PS stream"); + if (str_setup (ps, NULLCP, 0, 0) == NOTOK) + adios (NULLCP, "Can't setup PS stream"); + if (pe2ps (ps, pe) == NOTOK) + adios (NULLCP, "pe2ps failed: %s", ps_error (ps -> ps_errno)); + bodyproc (ps -> ps_base, ps -> ps_ptr - ps -> ps_base); + ps_free (ps); + + if (type == MT_UMPDU) { + if (pps_txt ("\n\nP2 hex dump follows", rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Can't write to submit: %s", + rp -> rp_line); + } +} + + + + +static int do_extra_encodedtypes (ep) +EncodedIT *ep; +{ + extern char *hdr_p2_bp; + LIST_BPT *base = NULLIST_BPT, + *new; + + + if ((new = list_bpt_new (hdr_p2_bp)) == NULLIST_BPT) + return NOTOK; + list_bpt_add (&base, new); + + if (ep ->eit_types) + list_bpt_add (&base, ep->eit_types); + + ep->eit_types = base; + + return OK; +} diff --git a/Chans/x40088/Makefile b/Chans/x40088/Makefile new file mode 100644 index 0000000..fd682b1 --- /dev/null +++ b/Chans/x40088/Makefile @@ -0,0 +1,373 @@ +# PP X400 1988 modules +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/Makefile,v 6.0 1991/12/18 20:14:27 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:14:27 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = util.c x400in88.c x400out88.c x400topp.c x400inmsg.c \ + ut_rts.c ut_misc.c pptox400.c +OBJS = + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +#LIBSYS = -lm + +LIBX400 = ../x40084/libx400.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xx400out88 xx400in88 + +lint: l-x400out88 l-x400in88 + +############################################################ +# +# x400out 1988 protocol +# +############################################################ + +X400OUTSRCS = x400out88.c pptox400.c util.c ut_rts.c ut_misc.c +X400OUTOBJS = x400out88.o pptox400.o util.o ut_rts.o ut_misc.o + +x400out88: xx400out88 + +xx400out88: $(X400OUTOBJS) $(LIBX400) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(X400OUTOBJS) \ + $(LIBX400) $(LIBPP) $(LIBSYS) + + +saber_x400out88: $(X400OUTSRCS) + #load -C $(CFLAGS) $(X400OUTSRCS) $(LIBX400) $(LIBPP) $(LIBSYS) + +inst-x400out88: $(CHANDIR)/x400out88 +$(CHANDIR)/x400out88: xx400out88 + -$(BACKUP) $@ zxx400out88 + rm -f $@ + $(INSTALL) xx400out88 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X400out88 channel installed normally"; echo "" + +l-x400out88: $(SRCS) + $(LINT) $(LLFLAGS) $(X400OUTSRCS) $(LINTLIBS) + + + +############################################################ +# +# x400in 1988 protocol +# +############################################################ + +X400INSRCS = x400in88.c x400topp.c x400inmsg.c \ + ut_rts.c ut_misc.c +X400INOBJS = x400in88.o x400topp.o x400inmsg.o \ + ut_rts.o ut_misc.o + +x400in88: xx400in88 + +xx400in88: $(X400INOBJS) $(LIBX400) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(X400INOBJS) \ + $(LIBX400) $(LIBPP) $(LIBSYS) + +saber_x400in88: $(X400INSRCS) + #load -C $(CFLAGS) $(X400INSRCS) $(LIBX400) $(LIBPP) $(LIBSYS) + +inst-x400in88: $(CHANDIR)/x400in88 +$(CHANDIR)/x400in88: xx400in88 + -$(BACKUP) $@ zxx400in88 + rm -f $@ + $(INSTALL) xx400in88 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X400in88 channel installed normally"; echo "" + +l-x400in88: $(SRCS) + $(LINT) $(LLFLAGS) $(X400INSRCS) $(LINTLIBS) + + +############################################################ +# +# p88 +# +############################################################ + +p88: xp88 + +xp88: p88.o + $(CC) $(LDFLAGS) -o $@ p88.o $(LIBPP) $(LIBSYS) + +l-p88: p88.c + $(LINT) $(LLFLAGS) p88.c $(LINTLIBS) +############################################################ +# +# Other stuff +# +############################################################ + +tasn: xtasn + +xtasn: tasn.o ps2pe.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ tasn.o ps2pe.o \ + $(LIBPP) $(LIBSYS) + +l-tasn: tasn.c ps2pe.c + $(LINT) $(LLFLAGS) tasn.c ps2pe.c $(LINTLIBS) + +install: inst-dir inst-x400out88 inst-x400in88 +inst-dir: $(CHANDIR) + + +clean: tidy + rm -f $(OBJS) *.o *.ph + +tidy: + rm -f core a.out *.old MTA* xx400in88 xx400out88 xp88 xtasn + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +util.o: util.c +util.o: ../../h/util.h +util.o: ../../h/config.h +util.o: ../../h/ll_log.h +x400in88.o: x400in88.c +x400in88.o: ../../h/Trans-types.h +x400in88.o: ../../h/MTA-types.h +x400in88.o: ../../h/Toks-types.h +x400in88.o: ../../h/Auth-types.h +x400in88.o: ../../h/util.h +x400in88.o: ../../h/config.h +x400in88.o: ../../h/ll_log.h +x400in88.o: ../../h/chan.h +x400in88.o: ../../h/table.h +x400in88.o: ../../h/list_bpt.h +x400in88.o: ../../h/q.h +x400in88.o: ../../h/adr.h +x400in88.o: ../../h/list_rchan.h +x400in88.o: ../../h/chan.h +x400in88.o: ../../h/auth.h +x400in88.o: ../../h/list_bpt.h +x400in88.o: ../../h/extension.h +x400in88.o: ../../h/mta.h +x400in88.o: ../../h/adr.h +x400in88.o: ../../h/list_bpt.h +x400in88.o: ../../h/aparse.h +x400in88.o: ../../h/ap.h +x400in88.o: ../../h/util.h +x400in88.o: ../../h/or.h +x400in88.o: ../../h/chan.h +x400in88.o: ../../h/auth.h +x400in88.o: ../../h/list_rchan.h +x400in88.o: ../../h/mta.h +x400in88.o: ../../h/adr.h +x400in88.o: ../../h/or.h +x400in88.o: ../../h/retcode.h +x400in88.o: ../../h/RTS84-types.h +x400out88.o: x400out88.c +x400out88.o: ../../h/Trans-types.h +x400out88.o: ../../h/MTA-types.h +x400out88.o: ../../h/Toks-types.h +x400out88.o: ../../h/Auth-types.h +x400out88.o: ../../h/head.h +x400out88.o: ../../h/util.h +x400out88.o: ../../h/config.h +x400out88.o: ../../h/ll_log.h +x400out88.o: ../../h/retcode.h +x400out88.o: ../../h/prm.h +x400out88.o: ../../h/q.h +x400out88.o: ../../h/adr.h +x400out88.o: ../../h/list_rchan.h +x400out88.o: ../../h/chan.h +x400out88.o: ../../h/table.h +x400out88.o: ../../h/list_bpt.h +x400out88.o: ../../h/auth.h +x400out88.o: ../../h/list_bpt.h +x400out88.o: ../../h/extension.h +x400out88.o: ../../h/mta.h +x400out88.o: ../../h/adr.h +x400out88.o: ../../h/list_bpt.h +x400out88.o: ../../h/aparse.h +x400out88.o: ../../h/ap.h +x400out88.o: ../../h/util.h +x400out88.o: ../../h/or.h +x400out88.o: ../../h/chan.h +x400out88.o: ../../h/auth.h +x400out88.o: ../../h/list_rchan.h +x400out88.o: ../../h/mta.h +x400out88.o: ../../h/qmgr.h +x400out88.o: ../../h/Qmgr-types.h +x400out88.o: ../../h/Qmgr-ops.h +x400out88.o: ../../h/dr.h +x400out88.o: ../../h/extension.h +x400out88.o: ../../h/mta.h +x400out88.o: ../../h/rtsparams.h +x400out88.o: ../../h/sys.file.h +x400topp.o: x400topp.c +x400topp.o: ../../h/Trans-types.h +x400topp.o: ../../h/MTA-types.h +x400topp.o: ../../h/Toks-types.h +x400topp.o: ../../h/Auth-types.h +x400topp.o: ../../h/Ext-types.h +x400topp.o: ../../h/MTA-types.h +x400topp.o: ../../h/Toks-types.h +x400topp.o: ../../h/Auth-types.h +x400topp.o: ../../h/util.h +x400topp.o: ../../h/config.h +x400topp.o: ../../h/ll_log.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/table.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/q.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/list_rchan.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/auth.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/extension.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/list_bpt.h +x400topp.o: ../../h/aparse.h +x400topp.o: ../../h/ap.h +x400topp.o: ../../h/util.h +x400topp.o: ../../h/or.h +x400topp.o: ../../h/chan.h +x400topp.o: ../../h/auth.h +x400topp.o: ../../h/list_rchan.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/adr.h +x400topp.o: ../../h/or.h +x400topp.o: ../../h/prm.h +x400topp.o: ../../h/dr.h +x400topp.o: ../../h/extension.h +x400topp.o: ../../h/mta.h +x400topp.o: ../../h/retcode.h +x400inmsg.o: x400inmsg.c +x400inmsg.o: ../../h/Trans-types.h +x400inmsg.o: ../../h/MTA-types.h +x400inmsg.o: ../../h/Toks-types.h +x400inmsg.o: ../../h/Auth-types.h +x400inmsg.o: ../../h/util.h +x400inmsg.o: ../../h/config.h +x400inmsg.o: ../../h/ll_log.h +x400inmsg.o: ../../h/chan.h +x400inmsg.o: ../../h/table.h +x400inmsg.o: ../../h/list_bpt.h +x400inmsg.o: ../../h/q.h +x400inmsg.o: ../../h/adr.h +x400inmsg.o: ../../h/list_rchan.h +x400inmsg.o: ../../h/chan.h +x400inmsg.o: ../../h/auth.h +x400inmsg.o: ../../h/list_bpt.h +x400inmsg.o: ../../h/extension.h +x400inmsg.o: ../../h/mta.h +x400inmsg.o: ../../h/adr.h +x400inmsg.o: ../../h/list_bpt.h +x400inmsg.o: ../../h/aparse.h +x400inmsg.o: ../../h/ap.h +x400inmsg.o: ../../h/util.h +x400inmsg.o: ../../h/or.h +x400inmsg.o: ../../h/chan.h +x400inmsg.o: ../../h/auth.h +x400inmsg.o: ../../h/list_rchan.h +x400inmsg.o: ../../h/mta.h +x400inmsg.o: ../../h/adr.h +x400inmsg.o: ../../h/or.h +x400inmsg.o: ../../h/prm.h +x400inmsg.o: ../../h/dr.h +x400inmsg.o: ../../h/extension.h +x400inmsg.o: ../../h/mta.h +x400inmsg.o: ../../h/retcode.h +ut_rts.o: ut_rts.c +ut_rts.o: ../../h/util.h +ut_rts.o: ../../h/config.h +ut_rts.o: ../../h/ll_log.h +ut_rts.o: ../../h/rtsparams.h +ut_rts.o: ../../h/chan.h +ut_rts.o: ../../h/table.h +ut_rts.o: ../../h/list_bpt.h +ut_rts.o: ../../h/Trans-types.h +ut_rts.o: ../../h/MTA-types.h +ut_rts.o: ../../h/Toks-types.h +ut_rts.o: ../../h/Auth-types.h +ut_misc.o: ut_misc.c +ut_misc.o: ../../h/util.h +ut_misc.o: ../../h/config.h +ut_misc.o: ../../h/ll_log.h +ut_misc.o: ../../h/tb_bpt88.h +ut_misc.o: ../../h/list_bpt.h +pptox400.o: pptox400.c +pptox400.o: ../../h/Trans-types.h +pptox400.o: ../../h/MTA-types.h +pptox400.o: ../../h/Toks-types.h +pptox400.o: ../../h/Auth-types.h +pptox400.o: ../../h/Ext-types.h +pptox400.o: ../../h/MTA-types.h +pptox400.o: ../../h/Toks-types.h +pptox400.o: ../../h/Auth-types.h +pptox400.o: ../../h/util.h +pptox400.o: ../../h/config.h +pptox400.o: ../../h/ll_log.h +pptox400.o: ../../h/q.h +pptox400.o: ../../h/adr.h +pptox400.o: ../../h/list_rchan.h +pptox400.o: ../../h/chan.h +pptox400.o: ../../h/table.h +pptox400.o: ../../h/list_bpt.h +pptox400.o: ../../h/auth.h +pptox400.o: ../../h/list_bpt.h +pptox400.o: ../../h/extension.h +pptox400.o: ../../h/mta.h +pptox400.o: ../../h/adr.h +pptox400.o: ../../h/list_bpt.h +pptox400.o: ../../h/aparse.h +pptox400.o: ../../h/ap.h +pptox400.o: ../../h/util.h +pptox400.o: ../../h/or.h +pptox400.o: ../../h/chan.h +pptox400.o: ../../h/auth.h +pptox400.o: ../../h/list_rchan.h +pptox400.o: ../../h/mta.h +pptox400.o: ../../h/adr.h +pptox400.o: ../../h/dr.h +pptox400.o: ../../h/extension.h +pptox400.o: ../../h/mta.h +pptox400.o: ../../h/or.h +pptox400.o: ../../h/rtsparams.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Chans/x40088/make b/Chans/x40088/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Chans/x40088/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Chans/x40088/p88.c b/Chans/x40088/p88.c new file mode 100644 index 0000000..5743818 --- /dev/null +++ b/Chans/x40088/p88.c @@ -0,0 +1,153 @@ +/* p88 : pretty print an X.400 1988 message */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/p88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/p88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: p88.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + +#include "Trans-types.h" +#include "util.h" +#include + +char *myname; +void adios (), advise (); + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + while((opt = getopt(argc, argv, "")) != EOF) + switch (opt) { + default: + fprintf (stderr, "Usage: %s\n", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc > 0) { + while (argc -- > 0) { + FILE *fp; + + if ((fp = fopen (*argv, "r")) == NULL) + adios (*argv, "Can't open file"); + process (fp); + (void) fclose (fp); + argv ++; + } + } + else + process (stdin); + exit (0); +} + +process (fp) +FILE *fp; +{ + PS ps; + PE pe; + + if ((ps = ps_alloc (std_open)) == NULLPS) + adios (NULLCP, "Can't allocate PS stream"); + + if (std_setup (ps, fp) == NOTOK) + adios (NULLCP, "Can't setup stream"); + + if ((pe = ps2pe(ps)) == NULLPE) + adios (NULLCP, "Error reading stream [%s]", + ps_error (ps -> ps_errno)); + + PY_pepy[0] = NULL; + print_Trans_MtsAPDU (pe, 1, 0, NULLCP, NULL); + if (PY_pepy[0]) + advise (NULLCP, "Error : %s", PY_pepy); + + ps_free (ps); + pe_free (pe); +} + +#include + + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +static void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Chans/x40088/pptox400.c b/Chans/x40088/pptox400.c new file mode 100644 index 0000000..eb272e5 --- /dev/null +++ b/Chans/x40088/pptox400.c @@ -0,0 +1,2760 @@ +/* pptox400.c: convert PP structures to X.400 88 structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/pptox400.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/pptox400.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: pptox400.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "Trans-types.h" +#include "Ext-types.h" +#include "util.h" +#include "q.h" +#include "adr.h" +#include "dr.h" +#include "or.h" +#include +#include "rtsparams.h" +#include "x400_ub.h" + +#define STR2QB(s) str2qb(s, strlen(s), 1) + +static int build_envelope (); +static int build_msgid (); +int build_addr (); +static int build_addrdn (); +static int build_eits (); +static int build_content (); +static int build_pmf (); +static int build_time (); +static int build_recips (); +static int build_p3_recips (); +static int build_ri (); +static int build_p3_ri (); +static int build_trace (); +static int build_gdi (); +static int build_pm_extensions (); +static int build_prf_ext (); +static int build_drenvelope (); +static int build_drcontent (); +static int build_drc_pr_fields (); +static int build_lasttrace (); +static int build_report (); +static int build_fullname (); +static int add_eeit (); +static int setuberror (); +struct type_IOB_ORName *orn2orname(); + +static int trace_type; + +static int build_probe_envelope(), build_dehl(), build_drc_extensions(), + build_drc_pr_extensions(), build_dre_extensions(); + +char ub_error_string[BUFSIZ]; +int ub_error_set; + +int build_p1 (qp, adl, p1, tt) +Q_struct *qp; +ADDR *adl; +struct type_Trans_MtsAPDU **p1; +int tt; +{ + ub_error_set = NOTOK; + trace_type = tt; + *p1 = (struct type_Trans_MtsAPDU *) smalloc (sizeof **p1); + bzero ((char *)*p1, sizeof **p1); + + (*p1) -> offset = type_Trans_MtsAPDU_message; + (*p1) -> un.message = (struct type_Trans_MessageAPDU *) + smalloc (sizeof *(*p1) -> un.message); + (*p1) -> un.message -> content = NULL; + if (build_envelope (qp, adl, &(*p1) -> un.message -> envelope) == OK) + return OK; + + free_Trans_MtsAPDU (p1); + if (ub_error_set != NOTOK) + return DONE; + return NOTOK; +} + +int build_dr (qp, recip, dr, qb, p1dr, tt) +Q_struct *qp; +ADDR *recip; +DRmpdu *dr; +struct type_MTA_Content *qb; +struct type_Trans_MtsAPDU **p1dr; +int tt; +{ + + ub_error_set = NOTOK; + trace_type = tt; + *p1dr = (struct type_Trans_MtsAPDU *) smalloc (sizeof **p1dr); + bzero ((char *)*p1dr, sizeof **p1dr); + + (*p1dr) -> offset = type_Trans_MtsAPDU_report; + (*p1dr) -> un.report = (struct type_Trans_ReportAPDU *) + smalloc (sizeof *(*p1dr) -> un.report); + if (build_drenvelope (qp, dr, + &(*p1dr) -> un.report -> envelope) == OK && + build_drcontent (qp, recip, dr, qb, + &(*p1dr) -> un.report -> content) == OK) + return OK; + free_Trans_MtsAPDU (p1dr); + if (ub_error_set != NOTOK) + return DONE; + return NULL; +} + + +int build_probe (qp, recip, p1, tt) +Q_struct *qp; +ADDR *recip; +struct type_Trans_MtsAPDU **p1; +int tt; +{ + ub_error_set = NOTOK; + trace_type = tt; + *p1 = (struct type_Trans_MtsAPDU *) smalloc (sizeof **p1); + bzero ((char *)*p1, sizeof **p1); + + (*p1) -> offset = type_Trans_MtsAPDU_probe; + if (build_probe_envelope (qp, recip, &(*p1) -> un.probe) == OK) + return OK; + + free_Trans_MtsAPDU (*p1); + if (ub_error_set != NOTOK) + return DONE; + return NOTOK; +} + +static int build_envelope (qp, adl, envp) +Q_struct *qp; +ADDR *adl; +struct type_MTA_MessageTransferEnvelope **envp; +{ + struct type_MTA_MessageTransferEnvelope *env; + + *envp = env = (struct type_MTA_MessageTransferEnvelope *) + smalloc (sizeof *env); + bzero ((char *)env, sizeof *env); + + if (build_msgid (&qp->msgid, &env -> message__identifier) == NOTOK) + return NOTOK; + + if (build_addrdn (qp -> Oaddress -> ad_r400adr, + qp -> Oaddress -> ad_dn, + &env -> originator__name) == NOTOK) + return NOTOK; + + + if (build_eits (&qp -> encodedinfo, + &env -> original__encoded__information__types) == NOTOK) + return NOTOK; + + if (build_content (adl -> ad_content ? + adl -> ad_content : + qp -> cont_type, + &env -> member_MTA_13) == NOTOK) + return NOTOK; + + + if (qp -> ua_id) { + if ((int) strlen(qp -> ua_id) > UB_CONTENT_ID_LENGTH) + return setuberror ("Content Id", strlen(qp -> ua_id), + UB_CONTENT_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if ((env -> content__identifier = + STR2QB (qp -> ua_id)) == NULL) + return NOTOK; + } + + env -> priority = (struct type_MTA_Priority *) + smalloc (sizeof *env -> priority); + env -> priority -> parm = qp -> priority; + + if (build_pmf (qp, + &env -> per__message__indicators) == NOTOK) + return NOTOK; + + if (qp -> defertime && + build_time (qp -> defertime, + &env -> deferred__delivery__time) == NOTOK) + return NOTOK; + + env -> per__domain__bilateral__information = NULL; + + if (build_pm_extensions (qp,1,1, + &env -> extensions) == NOTOK) + return NOTOK; + + if (build_trace (qp->trace, + &env -> trace__information) == NOTOK) + return NOTOK; + + if (build_recips (qp -> disclose_recips ? + qp -> Raddress : adl, adl, + qp->disclose_recips, + &env -> per__recipient__fields) == NOTOK) + return NOTOK; + + return OK; +} + + + + +int build_p3_envelope (qp, envp, tt) +Q_struct *qp; +struct type_MTA_MessageSubmissionEnvelope **envp; +int tt; +{ + struct type_MTA_MessageSubmissionEnvelope *env; + + trace_type = tt; + *envp = env = (struct type_MTA_MessageSubmissionEnvelope *) + smalloc (sizeof *env); + bzero ((char *)env, sizeof *env); + + + if (build_addrdn (qp -> Oaddress -> ad_r400adr, + qp -> Oaddress -> ad_dn, + &env -> originator__name) == NOTOK) + return NOTOK; + + + if (build_eits (&qp -> orig_encodedinfo, + &env -> original__eits) == NOTOK) + return NOTOK; + + if (build_content (qp -> cont_type, + &env -> member_MTA_6) == NOTOK) + return NOTOK; + + if (qp -> ua_id) { + if ((int) strlen(qp -> ua_id) > UB_CONTENT_ID_LENGTH) + return setuberror ("Content Id", strlen(qp -> ua_id), + UB_CONTENT_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if ((env -> content__identifier = + STR2QB (qp -> ua_id)) == NULL) + return NOTOK; + } + env -> priority = (struct type_MTA_Priority *) + smalloc (sizeof *env -> priority); + + env -> priority -> parm = + qp -> priority ? qp -> priority : PRIO_NORMAL; + + if (build_pmf (qp, + &env -> per__message__indicators) == NOTOK) + return NOTOK; + + if (qp -> defertime && + build_time (qp -> defertime, + &env -> deferred__delivery__time) == NOTOK) + return NOTOK; + + if (build_pm_extensions (qp,0,1, + &env -> extensions) == NOTOK) + return NOTOK; + + if (build_p3_recips (qp -> Raddress, + &env -> per__recipient__fields) == NOTOK) + return NOTOK; + + return OK; +} + + +static int build_msgid (mid, p1mp) +MPDUid *mid; +struct type_MTA_MTSIdentifier **p1mp; +{ + struct type_MTA_MTSIdentifier *p1msgid; + + *p1mp = p1msgid = (struct type_MTA_MTSIdentifier *) + smalloc (sizeof *p1msgid); + bzero ((char *)p1msgid, sizeof *p1msgid); + + if (mid -> mpduid_string) { + if ((int) strlen(mid -> mpduid_string) > UB_LOCAL_ID_LENGTH) + return setuberror ("LocalId", + strlen(mid -> mpduid_string), + UB_LOCAL_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if ((p1msgid -> local__identifier = + STR2QB (mid -> mpduid_string)) == NULL) + return NOTOK; + } + if (build_gdi (&mid -> mpduid_DomId, + &p1msgid -> global__domain__identifier) == NOTOK) + return NOTOK; + return OK; +} + +static int build_addrdn (cp, dn, ornp) +char *cp; +char *dn; +struct type_MTA_ORName **ornp; +{ + OR_ptr or; + ORName *orn; + struct type_IOB_ORName *orname; + + orn = (ORName *) calloc (1, sizeof *orn); + if ((or = or_std2or (cp)) == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't convert %s", cp)); + ORName_free (orn); + return NOTOK; + } + orn -> on_or = or; + if (dn) + orn -> on_dn = str2dn (dn); + orname = orn2orname (orn); + ORName_free (orn); + *ornp = (struct type_MTA_ORName *)orname; + return OK; +} + +int build_addr (cp, orap) +char *cp; +struct type_MTA_ORAddress **orap; +{ + OR_ptr or; + extern struct type_MTA_ORAddress *ora2oradr(); + + if ((or = or_std2or (cp)) == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't convert %s", cp)); + or_free (or); + return NOTOK; + } + *orap = ora2oradr (or); + or_free (or); + return OK; +} + + +static int build_eits (eit, p1eitp) +EncodedIT *eit; +struct type_MTA_EncodedInformationTypes **p1eitp; +{ + struct type_MTA_EncodedInformationTypes *p1eit; + LIST_BPT *ep; + int n; + PE pe; + + + if (eit == NULL) return NULL; + + if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_BITS)) + == NULLPE) + return NOTOK; + + *p1eitp = p1eit = (struct type_MTA_EncodedInformationTypes *) + smalloc (sizeof *p1eit); + bzero ((char *)p1eit, sizeof *p1eit); + p1eit -> built__in__encoded__information__types = NULL; + p1eit -> external__encoded__information__types = NULL; + + + for (ep = eit -> eit_types; ep; ep = ep -> li_next) { + switch (n = bodypart2value (ep -> li_name)) { + case NOTOK: + /* -- unrecognised -- */ + break; + case 10: + /* -- object id -- */ + if (add_eeit (&p1eit->external__encoded__information__types, + (ep -> li_name + strlen("oid."))) == NOTOK) + return NOTOK; + break; + default: + if (n > UB_BUILT_IN_ENCODED_INFORMATION_TYPES) + return setuberror ("BuiltInEit", + n, UB_BUILT_IN_ENCODED_INFORMATION_TYPES, + DRD_SIZE_CONSTRAINT_VIOLATION); + /* -- recognised eit -- */ + if (bit_on(pe,n) == NOTOK) + return NOTOK; + break; + } + } + + p1eit -> built__in__encoded__information__types = pe; + + return OK; +} + + + +static int add_eeit (eep, oidn) +struct type_MTA_ExternalEncodedInformationTypes **eep; +char *oidn; +{ + int n; + if (*eep == NULL) { + *eep = (struct type_MTA_ExternalEncodedInformationTypes *) + calloc (1, sizeof **eep); + (*eep) -> ExternalEncodedInformationType = str2oid (oidn); + } + else { + struct type_MTA_ExternalEncodedInformationTypes *ep; + + for (n = 0, ep = *eep; ep -> next; ep = ep -> next, n++) + continue; + if (n > UB_ENCODED_INFORMATION_TYPES) + return setuberror ("EncodedInfoTypes", + n, UB_ENCODED_INFORMATION_TYPES, + DRD_SIZE_CONSTRAINT_VIOLATION); + ep -> next = (struct type_MTA_ExternalEncodedInformationTypes *) + calloc (1, sizeof *ep); + ep -> next -> ExternalEncodedInformationType = + str2oid (oidn); + } + return OK; +} + +static int build_content (str, bictp) +char *str; +struct type_MTA_ContentType **bictp; +{ + struct type_MTA_ContentType *bict; + + *bictp = bict = (struct type_MTA_ContentType *) + smalloc (sizeof *bict); + + bzero ((char *)bict, sizeof *bict); + if (lexnequ (str, "oid.", 4) == 0) { + bict -> offset = type_MTA_ContentType_external; + bict -> un.external = str2oid(str+4); + return OK; + } + bict -> offset = type_MTA_ContentType_built__in; + bict -> un.built__in = (struct type_MTA_BuiltInContentType *) + smalloc (sizeof *bict->un.built__in); + if (lexequ (str, "p2") == 0) + bict -> un.built__in -> parm = + int_MTA_BuiltInContentType_interpersonal__messaging__1984; + else if (lexequ (str, "p22") == 0) + bict -> un.built__in -> parm = + int_MTA_BuiltInContentType_interpersonal__messaging__1988; + else if (lexequ (str, "external") == 0) + bict -> un.built__in -> parm = + int_MTA_BuiltInContentType_external; + else + bict -> un.built__in -> parm = + int_MTA_BuiltInContentType_unidentified; + + return OK; +} + +static int build_pmf (qp, pep) +Q_struct *qp; +PE *pep; +{ + PE pe; + + if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_BITS)) + == NULLPE) + return NOTOK; + *pep = pe; + + if (qp -> disclose_recips && + bit_on(pe, bit_MTA_PerMessageIndicators_disclosure__of__recipients) + == NOTOK) + return NOTOK; + if (qp -> implicit_conversion_prohibited && + bit_on(pe, bit_MTA_PerMessageIndicators_implicit__conversion__prohibited) + == NOTOK) + return NOTOK; + if (qp -> alternate_recip_allowed && + bit_on(pe, bit_MTA_PerMessageIndicators_alternate__recipient__allowed) + == NOTOK) + return NOTOK; + if (qp -> content_return_request && + bit_on(pe, bit_MTA_PerMessageIndicators_content__return__request) + == NOTOK) + return NOTOK; + + return OK; +} + +static int build_time (utc, utp) +UTC utc; +struct type_UNIV_UTCTime **utp; +{ + char *str; + + str = utct2str (utc); + + if((*utp = STR2QB (str)) == NULL) + return NOTOK; + return OK; +} + +static int build_recips (ad, adl, disclose, rlp) +ADDR *ad; +ADDR *adl; +int disclose; +struct element_MTA_4 **rlp; +{ + struct element_MTA_4 *rl = NULL; + struct type_MTA_PerRecipientMessageTransferFields *prmtf; + ADDR *ap, *ap2; + int resp; + int naddr = 0; + + *rlp = NULL; + for (ap = ad; ap; ap = ap -> ad_next) { + for (ap2 = adl; ap2; ap2 = ap2 -> ad_next) { + if (ap2 -> ad_no == ap -> ad_no) + break; + } + if (ap2 == NULLADDR) + resp = FALSE; + else + resp = ap2 -> ad_resp; + + + if (*rlp == NULL) + *rlp = rl = (struct element_MTA_4 *) + smalloc (sizeof *rl); + else { + rl -> next = (struct element_MTA_4 *) + smalloc (sizeof *rl); + rl = rl -> next; + } + bzero ((char *)rl, sizeof *rl); + prmtf = rl -> PerRecipientMessageTransferFields = + (struct type_MTA_PerRecipientMessageTransferFields *) + smalloc (sizeof *prmtf); + bzero ((char *)prmtf, sizeof *prmtf); + + if (build_addrdn (ap -> ad_r400adr, + ap -> ad_dn, + &prmtf -> recipient__name) == NOTOK) + return NOTOK; + + prmtf -> originally__specified__recipient__number = + (struct type_MTA_OriginallySpecifiedRecipientNumber *) + smalloc (sizeof *prmtf -> + originally__specified__recipient__number); + prmtf -> originally__specified__recipient__number -> parm = + ap -> ad_extension; + + if (ap -> ad_explicitconversion != AD_EXP_NONE) { + if (ap -> ad_explicitconversion > UB_INTEGER_OPTIONS) + return setuberror("ExplicitConversion", + ap -> ad_explicitconversion, + UB_INTEGER_OPTIONS, + DRD_SIZE_CONSTRAINT_VIOLATION); + prmtf -> explicit__conversion = + + (struct type_MTA_ExplicitConversion *) + smalloc (sizeof *prmtf -> explicit__conversion); + prmtf -> explicit__conversion -> parm = + ap -> ad_explicitconversion; + } + else prmtf -> explicit__conversion = NULL; + + if (build_ri (resp, + ap -> ad_mtarreq, + ap -> ad_usrreq, + &prmtf -> per__recipient__indicators) == NOTOK) + return NOTOK; + + if (build_prf_ext (ap,1,1, + &prmtf -> extensions) == NOTOK) + return NOTOK; + if (naddr++ > UB_RECIPIENTS) + return setuberror("Max number of recipients", naddr, + UB_RECIPIENTS, DRD_TOO_MANY_RECIPIENTS); + } + return OK; +} + + +static int build_p3_recips (ad, rlp) +ADDR *ad; +struct element_MTA_0 **rlp; +{ + struct element_MTA_0 *rl = NULL; + struct type_MTA_PerRecipientMessageSubmissionFields *prmtf; + ADDR *ap; + int naddr = 0; + + *rlp = NULL; + for (ap = ad; ap; ap = ap -> ad_next) { + + if (*rlp == NULL) + *rlp = rl = (struct element_MTA_0 *) + smalloc (sizeof *rl); + else { + rl -> next = (struct element_MTA_0 *) + smalloc (sizeof *rl); + rl = rl -> next; + } + bzero ((char *)rl, sizeof *rl); + prmtf = rl -> PerRecipientMessageSubmissionFields = + (struct type_MTA_PerRecipientMessageSubmissionFields *) + smalloc (sizeof *prmtf); + if (build_addrdn (ap -> ad_r400adr, ap -> ad_dn, + &prmtf -> recipient__name) == NOTOK) + return NOTOK; + + if (ap -> ad_explicitconversion != AD_EXP_NONE) { + prmtf -> explicit__conversion = + (struct type_MTA_ExplicitConversion *) + smalloc (sizeof *prmtf -> explicit__conversion); + prmtf -> explicit__conversion -> parm = + ap -> ad_explicitconversion; + } + else prmtf -> explicit__conversion = NULL; + + if (build_p3_ri (ap -> ad_usrreq, + &prmtf -> originator__report__request) + == NOTOK) + return NOTOK; + if (build_prf_ext (ap,0,1, + &prmtf -> extensions) == NOTOK) + return NOTOK; + if (naddr++ > UB_RECIPIENTS) + return setuberror("Max number of recipients", naddr, + UB_RECIPIENTS, + DRD_TOO_MANY_RECIPIENTS); + } + return OK; +} + +static int build_ri (resp, mta, usr, pep) +int resp, mta, usr; +PE *pep; +{ + PE pe; + + if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_BITS)) + == NULLPE) + return NOTOK; + *pep = pe; + if (resp && bit_on(pe, + bit_MTA_PerRecipientIndicators_responsibility) == NOTOK) + return NOTOK; + + switch (mta) { + case AD_MTA_NONE: + break; + case AD_MTA_BASIC: + if (bit_on(pe, + bit_MTA_PerRecipientIndicators_originating__MTA__non__delivery__report) == NOTOK) + return NOTOK; + break; + case AD_MTA_CONFIRM: + if (bit_on(pe, + bit_MTA_PerRecipientIndicators_originating__MTA__report) == NOTOK) + return NOTOK; + break; + case AD_MTA_AUDIT_CONFIRM: + if (bit_on(pe, + bit_MTA_PerRecipientIndicators_originating__MTA__non__delivery__report) == NOTOK || + bit_on(pe, + bit_MTA_PerRecipientIndicators_originating__MTA__report) == NOTOK) + return NOTOK; + break; + } + + switch (usr) { + case AD_USR_NOREPORT: + break; + case AD_USR_BASIC: + if (bit_on(pe, + bit_MTA_PerRecipientIndicators_originator__non__delivery__report) == NOTOK) + return NOTOK; + break; + case AD_USR_CONFIRM: + if (bit_on(pe, + bit_MTA_PerRecipientIndicators_originator__report) == NOTOK) + return NOTOK; + break; + } + if (bit_test (pe, 8) == NOTOK) + (void) bit_off (pe, 8); + return OK; +} + + +static int build_p3_ri (usr, pep) +int usr; +PE *pep; +{ + PE pe; + + if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_BITS)) + == NULLPE) + return NOTOK; + *pep = pe; + + switch (usr) { + case AD_USR_NOREPORT: + case AD_USR_BASIC: + if (bit_on(pe, + bit_MTA_OriginatorReportRequest_non__delivery__report) == NOTOK) + return NOTOK; + break; + case AD_USR_CONFIRM: + if (bit_on(pe,bit_MTA_OriginatorReportRequest_report) + == NOTOK) + return NOTOK; + break; + } + return OK; +} + +static int build_traceelement (tp, tiep) +Trace *tp; +struct type_MTA_TraceInformationElement **tiep; +{ + struct type_MTA_TraceInformationElement *tie; + struct type_MTA_DomainSuppliedInformation *dsi; + DomSupInfo *dsp; + + *tiep = tie = (struct type_MTA_TraceInformationElement *) + smalloc (sizeof *tie); + bzero ((char *)tie, sizeof *tie); + + if (build_gdi (&tp -> trace_DomId, + &tie -> global__domain__identifier) == NOTOK) + return NOTOK; + + dsp = &tp -> trace_DomSinfo; + dsi = tie -> domain__supplied__information = + (struct type_MTA_DomainSuppliedInformation *) + smalloc (sizeof *tie -> + domain__supplied__information); + bzero ((char *)dsi, sizeof *dsi); + if (dsp -> dsi_time && + build_time (dsp -> dsi_time, + &dsi -> arrival__time) == NOTOK) + return NOTOK; + + dsi -> routing__action = + (struct type_MTA_RoutingAction *) + smalloc (sizeof *dsi -> routing__action); + if (dsp -> dsi_action) + dsi -> routing__action -> parm = dsp -> dsi_action; + else dsi -> routing__action -> parm = + int_MTA_RoutingAction_relayed; + + if (dsp -> dsi_attempted_md.global_Country != NULLCP && + dsp -> dsi_attempted_md.global_Admin != NULLCP) + if (build_gdi (&dsp -> dsi_attempted_md, + &dsi -> attempted__domain) == NOTOK) + return NOTOK; + + if (dsp -> dsi_deferred && + build_time (dsp -> dsi_deferred, + &dsi -> deferred__time) == NOTOK) + return NOTOK; + + if (dsp -> dsi_converted.eit_types && + build_eits (&dsp -> dsi_converted, + &dsi -> converted__encoded__information__types) == NOTOK) + return NOTOK; + + if (dsp -> dsi_other_actions) { + if ((dsi -> other__actions = + pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, + PE_PRIM_BITS)) == NULLPE) + return NOTOK; + if (dsp -> dsi_other_actions & ACTION_REDIRECTED && + bit_on(dsi -> other__actions, + bit_MTA_OtherActions_redirected) == NOTOK) + return NOTOK; + if (dsp -> dsi_other_actions & ACTION_EXPANDED && + bit_on(dsi -> other__actions, + bit_MTA_OtherActions_dl__operation) == NOTOK) + return NOTOK; + } + return OK; +} + +int same_prmd (tp1, tp2) +Trace *tp1, *tp2; +{ + GlobalDomId *d1, *d2; + + d1 = &tp1 -> trace_DomId; + d2 = &tp2 -> trace_DomId; + + if (d1 -> global_Country && d2 -> global_Country && + lexequ (d1 -> global_Country, d2 -> global_Country) == 0 && + d1 -> global_Admin && d2 -> global_Admin && + lexequ (d1 -> global_Admin, d2 -> global_Admin) == 0) { + if (d1 -> global_Private == NULL && + d2 -> global_Private == NULL) + return 1; + if (d1 -> global_Private && d2 -> global_Private && + lexequ (d1 -> global_Private, d2 -> global_Private) == 0) + return 1; + } + return 0; + +} + +static int build_trace (trp, tracep) +Trace *trp; +struct type_MTA_TraceInformation **tracep; +{ + Trace *tp, *tlast; + struct type_MTA_TraceInformation *trace = NULL; + int ntrace = 0; + + *tracep = NULL; + + for (tlast = trp; tlast && tlast -> trace_next; + tlast = tlast -> trace_next) + continue; + + if (trace_type == RTSP_TRACE_ADMD) { + if (tlast != trp && same_prmd (tlast, trp)) + tp = trp; + else tp = tlast; + *tracep = trace = (struct type_MTA_TraceInformation *) + smalloc (sizeof *trace); + trace -> next = NULL; + + if (build_traceelement (tp, + &trace -> TraceInformationElement) + == NOTOK) + return NOTOK; + return OK; + } + + for (tp = trp; tp; tp = tp -> trace_next) { + if (*tracep == NULL) + *tracep = trace = + (struct type_MTA_TraceInformation *) + smalloc (sizeof *trace); + else { + trace -> next = + (struct type_MTA_TraceInformation *) + smalloc (sizeof *trace); + trace = trace -> next; + } + bzero ((char *)trace, sizeof *trace); + + if (build_traceelement(tp, + &trace -> TraceInformationElement) + == NOTOK) + return NOTOK; + if (++ntrace > UB_TRANSFERS) + return setuberror ("Trace", + ntrace, UB_TRANSFERS, + DRD_SIZE_CONSTRAINT_VIOLATION); + } + + return OK; +} + +static int build_gdi (gdi, p1gdip) +GlobalDomId *gdi; +struct type_MTA_GlobalDomainIdentifier **p1gdip; +{ + struct type_MTA_GlobalDomainIdentifier *p1gdi; + struct type_MTA_AdministrationDomainName *admd; + struct type_MTA_CountryName *co; + struct type_MTA_PrivateDomainIdentifier *prmd; + + *p1gdip = p1gdi = (struct type_MTA_GlobalDomainIdentifier *) + smalloc (sizeof *p1gdi); + bzero ((char *)p1gdi, sizeof *p1gdi); + + if (gdi -> global_Country) { + p1gdi -> country__name = co = + (struct type_MTA_CountryName *) + smalloc (sizeof *co); + if (or_str_isns(gdi -> global_Country)) { + if ((int) strlen(gdi -> global_Country) > + UB_COUNTRY_NAME_NUMERIC_LENGTH) + return setuberror ("NumericCountryLength", + strlen(gdi -> global_Country), + UB_COUNTRY_NAME_NUMERIC_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + co -> offset = type_MTA_CountryName_x121__dcc__code; + if ((co -> un.x121__dcc__code = + STR2QB (gdi -> global_Country)) == NULL) + return NOTOK; + } else { + if ((int) strlen(gdi -> global_Country) > + UB_COUNTRY_NAME_ALPHA_LENGTH) + return setuberror ("Country", + strlen(gdi -> global_Country), + UB_COUNTRY_NAME_ALPHA_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + co -> offset = type_MTA_CountryName_iso__3166__alpha2__code; + if ((co -> un.iso__3166__alpha2__code = + STR2QB (gdi -> global_Country)) == NULL) + return NOTOK; + } + } + else { + PP_LOG (LLOG_EXCEPTIONS, ("Country missing from GDI")); + return NOTOK; + } + + if (gdi -> global_Admin) { + if ((int) strlen(gdi -> global_Admin) > UB_DOMAIN_NAME_LENGTH) + return setuberror ("ADMD", strlen(gdi -> global_Admin), + UB_DOMAIN_NAME_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + p1gdi -> administration__domain__name = admd = + (struct type_MTA_AdministrationDomainName *) + smalloc (sizeof *admd); + + if (or_str_isns (gdi -> global_Admin)) { + admd -> offset = type_MTA_AdministrationDomainName_numeric; + if ((admd -> un.numeric = + STR2QB(gdi -> global_Admin)) == NULL) + return NOTOK; + } else { + admd -> offset = type_MTA_AdministrationDomainName_printable; + if ((admd -> un.printable = STR2QB (gdi -> global_Admin)) + == NULL) + return NOTOK; + } + } + else { + PP_LOG (LLOG_EXCEPTIONS, ("ADMD missing from GDI")); + return NOTOK; + } + + if (gdi -> global_Private) { + if ((int) strlen(gdi -> global_Private) > UB_DOMAIN_NAME_LENGTH) + return setuberror ("PrivateDomainIdentifier", + strlen(gdi -> global_Private), + UB_DOMAIN_NAME_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + p1gdi -> private__domain__identifier = prmd = + (struct type_MTA_PrivateDomainIdentifier *) + smalloc (sizeof *prmd); + if (or_str_isns (gdi -> global_Private)) { + prmd -> offset = type_MTA_PrivateDomainIdentifier_numeric; + if ((prmd -> un.numeric = STR2QB (gdi -> global_Private)) + == NULL) + return NOTOK; + } else { + prmd -> offset = type_MTA_PrivateDomainIdentifier_printable; + if ((prmd -> un.printable = STR2QB (gdi -> global_Private)) + == NULL) + return NOTOK; + } + } + + return OK; +} + + +static int build_drenvelope (qp, dr, envp) +Q_struct *qp; +DRmpdu *dr; +struct type_MTA_ReportTransferEnvelope **envp; +{ + struct type_MTA_ReportTransferEnvelope *env; + + *envp = env = (struct type_MTA_ReportTransferEnvelope *) + smalloc (sizeof *env); + bzero ((char *)env, sizeof *env); + + + if (build_msgid (dr -> dr_mpduid, &env -> report__identifier) == NOTOK) + return NOTOK; + + if (build_addrdn (qp -> Oaddress -> ad_r400adr, + qp -> Oaddress -> ad_dn, + &env -> report__destination__name) == NOTOK) + return NOTOK; + + if (build_trace (dr -> dr_trace, + &env -> trace__information) == NOTOK) + return NOTOK; + + if (build_dre_extensions (dr, &env -> extensions) == NOTOK) + return NOTOK; + + return OK; +} + +static int build_drcontent (qp, recip, dr, qb, drcp) +Q_struct *qp; +ADDR *recip; +DRmpdu *dr; +struct type_MTA_Content *qb; +struct type_MTA_ReportTransferContent **drcp; +{ + struct type_MTA_ReportTransferContent *drc; + + *drcp = drc = (struct type_MTA_ReportTransferContent *) + smalloc (sizeof *drc); + + bzero ((char *)drc, sizeof *drc); + + + if (build_msgid (&qp -> msgid, &drc -> subject__identifier) == NOTOK) + return NOTOK; + + + if (build_trace (dr -> dr_subject_intermediate_trace, + &drc -> subject__intermediate__trace__information) == NOTOK) + return NOTOK; + + if (build_eits (&qp -> encodedinfo, + &drc -> original__encoded__information__types) == NOTOK) + return NOTOK; + + if ((qp -> cont_type || recip -> ad_content) && + build_content (qp -> cont_type, + &drc -> member_MTA_17) == NOTOK) + return NOTOK; + + if (qp -> ua_id) { + if ((int) strlen(qp -> ua_id) > UB_CONTENT_ID_LENGTH) + return setuberror ("Content ID", qp -> msgsize, + UB_CONTENT_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if ((drc -> content__identifier = + STR2QB (qp -> ua_id)) == NULL) + return NOTOK; + } + drc -> returned__content = qb; + + drc -> additional__information = NULLPE; + + if (build_drc_extensions (qp, recip, dr, + &drc -> extensions) == NOTOK) + return NOTOK; + + + if (build_drc_pr_fields (qp, recip, dr -> dr_recip_list, + &drc -> per__recipient__fields) == NOTOK) + return NOTOK; + + return OK; +} + +static int build_drc_pr_fields (qp, recip, rr, prp) +Q_struct *qp; +ADDR *recip; +Rrinfo *rr; +struct element_MTA_9 **prp; +{ + struct element_MTA_9 *prf; + struct type_MTA_PerRecipientReportTransferFields *pr; + ADDR *ap; + + if (rr == NULL) + return NULL; + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) + if (ap -> ad_no == rr -> rr_recip) + break; + if (ap == NULLADDR) + return build_drc_pr_fields (qp, recip, rr -> rr_next, prp); + + *prp = prf = (struct element_MTA_9 *) smalloc (sizeof *prf); + + prf -> next = NULL; + prf -> PerRecipientReportTransferFields = pr = + (struct type_MTA_PerRecipientReportTransferFields *) + smalloc (sizeof *pr); + bzero ((char *)pr, sizeof *pr); + + if (build_addrdn (ap -> ad_r400adr, ap -> ad_dn, + &pr -> actual__recipient__name) == NOTOK) + return NOTOK; + + pr -> originally__specified__recipient__number = + (struct type_MTA_OriginallySpecifiedRecipientNumber *) + smalloc (sizeof *pr -> + originally__specified__recipient__number); + pr -> originally__specified__recipient__number -> parm = + ap -> ad_extension; + + if (build_ri (ap -> ad_resp, + ap -> ad_mtarreq, + ap -> ad_usrreq, + &pr -> per__recipient__indicators) == NOTOK) + return NOTOK; + + if (build_lasttrace (rr, + &pr -> last__trace__information) == NOTOK) + return NOTOK; + + if (rr -> rr_originally_intended_recip && + build_fullname (rr -> rr_originally_intended_recip, + &pr -> originally__intended__recipient__name) == NOTOK) + return NOTOK; + + if (rr -> rr_supplementary) { + if ((int) strlen(rr -> rr_supplementary) > + UB_SUPPLEMENTARY_INFO_LENGTH) + return setuberror ("Supplementary Information", + strlen(rr -> rr_supplementary), + UB_SUPPLEMENTARY_INFO_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + + if ((pr -> supplementary__information = + STR2QB (rr -> rr_supplementary)) == NULL) + return NOTOK; + } + if (build_drc_pr_extensions (qp, rr, &pr -> extensions) == NOTOK) + return NOTOK; + + if (build_drc_pr_fields (qp, recip, rr -> rr_next, + &prf -> next) == NOTOK) + return NOTOK; + + return OK; +} + +static int build_lasttrace (rr, ltip) +Rrinfo *rr; +struct type_MTA_LastTraceInformation **ltip; +{ + struct type_MTA_LastTraceInformation *lti; + + *ltip = lti = (struct type_MTA_LastTraceInformation *) + smalloc (sizeof *lti); + bzero ((char *)lti, sizeof *lti); + + if (build_time (rr -> rr_arrival, + <i -> arrival__time) == NOTOK) + return NOTOK; + + if (rr -> rr_converted && + build_eits (rr -> rr_converted, + <i -> converted__encoded__information__types) == NOTOK) + return NOTOK; + + if (build_report (&rr -> rr_report, + <i -> report) == NOTOK) + return NOTOK; + + return OK; +} + +static int build_report (rp, repp) +Report *rp; +struct type_MTA_Report **repp; +{ + struct type_MTA_Report *rep; + + *repp = rep = (struct type_MTA_Report *) + smalloc (sizeof *rep); + + if (rp -> rep_type == DR_REP_SUCCESS) { + struct type_MTA_DeliveryReport *drp; + + rep -> offset = type_MTA_Report_delivery; + + rep -> un.delivery = drp = + (struct type_MTA_DeliveryReport *) + smalloc (sizeof *drp); + + if (build_time (rp->rep.rep_dinfo.del_time, + &drp -> message__delivery__time) == NOTOK) + return NOTOK; + + if (rp -> rep.rep_dinfo.del_type > UB_MTS_USER_TYPES) + return setuberror ("TypeOfMtsUser", + rp -> rep.rep_dinfo.del_type, + UB_MTS_USER_TYPES, + DRD_SIZE_CONSTRAINT_VIOLATION); + drp -> type__of__MTS__user = + (struct type_MTA_TypeOfMTSUser *) + smalloc (sizeof *drp -> type__of__MTS__user); + drp -> type__of__MTS__user -> parm = + rp -> rep.rep_dinfo.del_type; + } + else if (rp -> rep_type == DR_REP_FAILURE) { + struct type_MTA_NonDeliveryReport *ndr; + + rep -> offset = type_MTA_Report_non__delivery; + + rep -> un.non__delivery = ndr = + (struct type_MTA_NonDeliveryReport *) + smalloc (sizeof *ndr); + if (rp -> rep.rep_ndinfo.nd_rcode > UB_REASON_CODES) + return setuberror ("Reason Code", + rp -> rep.rep_ndinfo.nd_rcode, + UB_REASON_CODES, + DRD_SIZE_CONSTRAINT_VIOLATION); + ndr -> non__delivery__reason__code = + (struct type_MTA_NonDeliveryReasonCode *) + smalloc (sizeof *ndr -> non__delivery__reason__code); + ndr -> non__delivery__reason__code -> parm = + rp -> rep.rep_ndinfo.nd_rcode; + + if (rp -> rep.rep_ndinfo.nd_dcode > UB_DIAGNOSTIC_CODES) + return setuberror ("Diagnostic code", + rp -> rep.rep_ndinfo.nd_dcode, + UB_DIAGNOSTIC_CODES, + DRD_SIZE_CONSTRAINT_VIOLATION); + ndr -> non__delivery__diagnostic__code = + (struct type_MTA_NonDeliveryDiagnosticCode *) + smalloc (sizeof *ndr -> non__delivery__diagnostic__code); + ndr -> non__delivery__diagnostic__code -> parm = + rp -> rep.rep_ndinfo.nd_dcode; + } + else { + PP_LOG (LLOG_EXCEPTIONS, ("Bad delivery report type %d", + rp -> rep_type)); + return NOTOK; + } + + return OK; +} + +static int build_fullname (fn, ornp) +FullName *fn; +struct type_MTA_ORName **ornp; +{ + if (build_addrdn (fn -> fn_addr, fn -> fn_dn, ornp) == NOTOK) + return NOTOK; + return OK; +} + + +static int build_prb_recips (ad, adl, disclose, rlp) +ADDR *ad; +ADDR *adl; +int disclose; +struct element_MTA_7 **rlp; +{ + struct element_MTA_7 *rl = NULL; + struct type_MTA_PerRecipientProbeTransferFields *prmtf; + ADDR *ap, *ap2; + int resp; + int naddr = 0; + + *rlp = NULL; + for (ap = ad; ap; ap = ap -> ad_next) { + for (ap2 = adl; ap2; ap2 = ap2 -> ad_next) { + if (ap2 -> ad_no == ap -> ad_no) + break; + } + if (ap2 == NULLADDR) + resp = FALSE; + else + resp = ap2 -> ad_resp; + + + if (*rlp == NULL) + *rlp = rl = (struct element_MTA_7 *) + smalloc (sizeof *rl); + else { + rl -> next = (struct element_MTA_7 *) + smalloc (sizeof *rl); + rl = rl -> next; + } + bzero ((char *)rl, sizeof *rl); + prmtf = rl -> PerRecipientProbeTransferFields = + (struct type_MTA_PerRecipientProbeTransferFields *) + smalloc (sizeof *prmtf); + + if (build_addrdn (ap -> ad_r400adr, ap -> ad_dn, + &prmtf -> recipient__name) == NOTOK) + return NOTOK; + + prmtf -> originally__specified__recipient__number = + (struct type_MTA_OriginallySpecifiedRecipientNumber *) + smalloc (sizeof *prmtf -> + originally__specified__recipient__number); + prmtf -> originally__specified__recipient__number -> parm = + ap -> ad_extension; + + if (ap -> ad_explicitconversion != AD_EXP_NONE) { + prmtf -> explicit__conversion = + (struct type_MTA_ExplicitConversion *) + smalloc (sizeof *prmtf -> explicit__conversion); + prmtf -> explicit__conversion -> parm = + ap -> ad_explicitconversion; + } + else prmtf -> explicit__conversion = NULL; + + if (build_ri (resp, + ap -> ad_mtarreq, + ap -> ad_usrreq, + &prmtf -> per__recipient__indicators) == NOTOK) + return NOTOK; + if (build_prf_ext (ap,1,0, + &prmtf -> extensions) == NOTOK) + return NOTOK; + if (naddr++ > UB_RECIPIENTS) + return setuberror("Max number of recipients", naddr, + UB_RECIPIENTS, + DRD_TOO_MANY_RECIPIENTS); + } + return OK; +} + +static int build_p3_prb_recips (ad, rlp) +ADDR *ad; +struct element_MTA_1 **rlp; +{ + struct element_MTA_1 *rl = NULL; + struct type_MTA_PerRecipientProbeSubmissionFields *prmtf; + ADDR *ap; + + *rlp = NULL; + for (ap = ad; ap; ap = ap -> ad_next) { + + if (*rlp == NULL) + *rlp = rl = (struct element_MTA_1 *) + smalloc (sizeof *rl); + else { + rl -> next = (struct element_MTA_1 *) + smalloc (sizeof *rl); + rl = rl -> next; + } + bzero ((char *)rl, sizeof *rl); + prmtf = rl -> PerRecipientProbeSubmissionFields = + (struct type_MTA_PerRecipientProbeSubmissionFields *) + smalloc (sizeof *prmtf); + + if (build_addrdn (ap -> ad_r400adr, ap -> ad_dn, + &prmtf -> recipient__name) == NOTOK) + return NOTOK; + + if (ap -> ad_explicitconversion != AD_EXP_NONE) { + prmtf -> explicit__conversion = + (struct type_MTA_ExplicitConversion *) + smalloc (sizeof *prmtf -> explicit__conversion); + prmtf -> explicit__conversion -> parm = + ap -> ad_explicitconversion; + } + else prmtf -> explicit__conversion = NULL; + + if (build_p3_ri (ap -> ad_usrreq, + &prmtf -> originator__report__request) == NOTOK) + return NOTOK; + if (build_prf_ext (ap,0,0, + &prmtf -> extensions) == NOTOK) + return NOTOK; + } + return OK; +} + +static int build_probe_envelope (qp, adl, prbp) +Q_struct *qp; +ADDR *adl; +struct type_MTA_ProbeTransferEnvelope **prbp; +{ + struct type_MTA_ProbeTransferEnvelope *prb; + + *prbp = prb = (struct type_MTA_ProbeTransferEnvelope *) + smalloc (sizeof *prb); + bzero ((char *)prb, sizeof *prb); + + if (build_msgid (&qp -> msgid, &prb -> probe__identifier ) == NOTOK) + return NOTOK; + + + if (build_addrdn (qp -> Oaddress -> ad_r400adr, + qp -> Oaddress -> ad_dn, + &prb -> originator__name) == NOTOK) + return NOTOK; + + if (build_eits (&qp -> encodedinfo, + &prb -> original__encoded__information__types) == NOTOK) + return NOTOK; + + if (build_content (adl -> ad_content ? + adl -> ad_content : + qp -> cont_type, + &prb -> member_MTA_15) == NOTOK) + return NOTOK; + + if (qp -> ua_id) { + if ((int) strlen(qp -> ua_id) > UB_CONTENT_ID_LENGTH) + return setuberror ("Content Id", strlen(qp -> ua_id), + UB_CONTENT_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if ((prb -> content__identifier = + STR2QB (qp -> ua_id)) == NULL) + return NOTOK; + } + prb -> content__length = (struct type_MTA_ContentLength *) + smalloc (sizeof *prb -> content__length); + if (qp -> msgsize > UB_CONTENT_LENGTH) + return setuberror ("MessageSize", qp -> msgsize, + UB_CONTENT_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + + prb -> content__length -> parm = qp -> msgsize; + + if (build_pmf (qp, + &prb -> per__message__indicators) == NOTOK) + return NOTOK; + + prb -> per__domain__bilateral__information = NULL; + + if (build_trace (qp -> trace, + &prb -> trace__information) == NOTOK) + return NOTOK; + + if (build_pm_extensions (qp,1,0, + &prb -> extensions) == NOTOK) + return NOTOK; + + if (build_prb_recips (qp -> disclose_recips ? qp -> Raddress : adl, + adl, qp -> disclose_recips, + &prb -> per__recipient__fields) == NOTOK) + return NOTOK; + + return OK; +} + +int build_p3_probe_envelope (qp, prbp) +Q_struct *qp; +struct type_MTA_ProbeSubmissionEnvelope **prbp; +{ + struct type_MTA_ProbeSubmissionEnvelope *prb; + + *prbp = prb = (struct type_MTA_ProbeSubmissionEnvelope *) + smalloc (sizeof *prb); + bzero ((char *)prb, sizeof *prb); + + + if (build_addrdn (qp -> Oaddress -> ad_r400adr, + qp -> Oaddress -> ad_dn, + &prb -> originator__name) == NOTOK) + return NOTOK; + + if (build_eits (&qp -> orig_encodedinfo, + &prb -> original__eits) == NOTOK) + return NOTOK; + + if (build_content (qp -> cont_type, + &prb -> member_MTA_7) == NOTOK) + return NOTOK; + + if (qp -> ua_id) { + if ((int) strlen(qp -> ua_id) > UB_CONTENT_ID_LENGTH) + return setuberror ("Content Id", strlen(qp -> ua_id), + UB_CONTENT_ID_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + + if ((prb -> content__identifier = + STR2QB (qp -> ua_id)) == NULL) + return NOTOK; + } + prb -> content__length = (struct type_MTA_ContentLength *) + smalloc (sizeof *prb -> content__length); + prb -> content__length -> parm = qp -> msgsize; + + if (build_pmf (qp, + &prb -> per__message__indicators) == NOTOK) + return NOTOK; + + if (build_pm_extensions (qp,0,0, + &prb -> extensions) == NOTOK) + return NOTOK; + + if (build_p3_prb_recips (qp -> Raddress, + &prb -> per__recipient__fields) == NOTOK) + return NOTOK; + + return OK; +} + + +/* EXTENSIONS */ + +#define wrap_up_ext(e, n) \ + (e) = (struct type_MTA_Extensions *) smalloc (sizeof *(e)); \ + (e) -> next = NULL; (e) -> ExtensionField = (n); +#define STR2QB(s) str2qb(s, strlen(s), 1) + + +static int build_ext_type (ext_int, ext_oid, typep) +int ext_int; +OID ext_oid; +struct type_MTA_ExtensionType **typep; +{ + struct type_MTA_ExtensionType *type; + + *typep = type = (struct type_MTA_ExtensionType *) + smalloc (sizeof *type); + + if (ext_int == EXT_OID_FORM) { + type -> offset = type_MTA_ExtensionType_local; + if ((type -> un.local = oid_cpy (ext_oid)) == NULLOID) + return NOTOK; + } else { + type -> offset = type_MTA_ExtensionType_global; + if (ext_int > UB_EXTENSION_TYPES) + return setuberror ("Extension types", + ext_int, UB_EXTENSION_TYPES, + DRD_SIZE_CONSTRAINT_VIOLATION); + + type -> un.global = ext_int; + } + return OK; +} + +static int build_crit (cr, crp) +int cr; +struct type_MTA_Criticality **crp; +{ + char *p; + int nbits = 3; + + if (cr > (1< 7) { + nbits = UB_BIT_OPTIONS; + } + p = int2strb (cr, nbits); + *crp = strb2bitstr (p, nbits, PE_CLASS_UNIV, PE_PRIM_BITS); + if (*crp == NULL) + return NOTOK; + return OK; +} + +static int build_ext_value (qb, pep) +struct qbuf *qb; +PE *pep; +{ + char *cp; + PS ps; + + cp = qb2str(qb); + + if ((ps = ps_alloc (str_open)) == NULLPS) { + PP_LOG (LLOG_EXCEPTIONS, ("PS alloc failed")); + return NOTOK; + } + + if (str_setup (ps, cp, qb -> qb_len, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't setup PS stream")); + return NOTOK; + } + + if ((*pep = ps2pe (ps)) == NULLPE) { + PP_LOG (LLOG_EXCEPTIONS, ("ps2pe failed [%s]", + ps_error (ps -> ps_errno))); + return NOTOK; + } + ps_free (ps); + return OK; +} + +static int build_ext_generic (parm, crit, defcrit, type, oid, mod_idx, + mod, fnx, label, extlp) +caddr_t parm; +int crit; +int type; +int defcrit; +OID oid; +int mod_idx; +modtyp *mod; +IFP fnx; +char *label; +struct type_MTA_Extensions **extlp; +{ + struct type_MTA_ExtensionField *ext; + caddr_t value; + + ext = (struct type_MTA_ExtensionField *) + smalloc (sizeof *ext); + if (build_ext_type (type, oid, &ext -> type) == NOTOK) + return NOTOK; + if (crit != defcrit) { + if (build_crit (crit, &ext -> criticality) == NOTOK) + return NOTOK; + } + else ext -> criticality = NULL; + + if ((*fnx) (&value, parm) == NOTOK) + return NOTOK; + + if (enc_f (mod_idx, mod, &ext -> value, 1, 0, NULLCP, value) + == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode value %s: %s", + label, PY_pepy)); + return NOTOK; + } + +#if PP_DEBUG > 0 + if(pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, mod_idx, mod, + ext -> value, label, PDU_WRITE); +#endif + fre_obj (value, mod->md_dtab[mod_idx], mod, 1); + + *extlp = (struct type_MTA_Extensions *) smalloc (sizeof **extlp); + (*extlp) -> next = NULL; + (*extlp) -> ExtensionField = ext; + return OK; +} + +static int build_ext_int (value, parm) +caddr_t *value; +caddr_t parm; +{ + int *ip = (int *)parm; + struct type_Ext_RecipientReassignmentProhibited **val = + (struct type_Ext_RecipientReassignmentProhibited **) value; + + *val = (struct type_Ext_RecipientReassignmentProhibited *) + smalloc (sizeof **val); + (*val) -> parm = *ip; + return OK; +} + +static int build_ext_char (value, parm) +caddr_t *value; +caddr_t parm; +{ + char *cp = (char *)parm; + struct type_Ext_RecipientReassignmentProhibited **val = + (struct type_Ext_RecipientReassignmentProhibited **) value; + + *val = (struct type_Ext_RecipientReassignmentProhibited *) + smalloc (sizeof **val); + (*val) -> parm = *cp; + return OK; +} + +static int build_ext_time (value, parm) +caddr_t *value; +caddr_t parm; +{ + UTC utc = (UTC)parm; + struct type_UNIV_UTCTime **ut = (struct type_UNIV_UTCTime **)value; + return build_time (utc, ut); +} + +static int build_ext_dlh (value, parm) +caddr_t *value; +caddr_t parm; +{ + DLHistory *dlp = (DLHistory *)parm; + struct type_Ext_DLExpansionHistory **val = + (struct type_Ext_DLExpansionHistory **)value; + return build_dehl (dlp, val); +} + +static int build_aext_oraa (value, parm) +caddr_t *value; +caddr_t parm; +{ + char *ora = (char *)parm; + struct type_MTA_ORName **val = (struct type_MTA_ORName **)value; + + return build_addrdn (ora, NULLCP, val); +} + +static int build_aext_rdm (value, parm) +caddr_t *value; +caddr_t parm; +{ + char *rdm = (char *)parm; + struct type_Ext_RequestedDeliveryMethod **val = + (struct type_Ext_RequestedDeliveryMethod **)value; + int i; + + *val = NULL; + + for (i = 0; i < AD_RDM_MAX && rdm[i] != AD_RDM_NOTUSED; i++) { + *val = (struct type_Ext_RequestedDeliveryMethod *) + smalloc (sizeof **val); + (*val) -> element_Ext_0 = parm[i]; + (*val) -> next = NULL; + val = &(*val) -> next; + } + + return OK; +} +static int build_aext_pra (value, parm) +caddr_t *value; +caddr_t parm; +{ + struct type_Ext_PhysicalRenditionAttributes **val = + (struct type_Ext_PhysicalRenditionAttributes **)value; + OID pra = (OID)parm; + + if ((*val = oid_cpy (pra)) == NULLOID) + return NOTOK; + return OK; +} + +static int build_aext_pdm (value, parm) +caddr_t *value; +caddr_t parm; +{ + int *pdm = (int *)parm; + struct type_Ext_PhysicalDeliveryModes **val = + (struct type_Ext_PhysicalDeliveryModes **)value; + char *p; + + p = int2strb (*pdm, 8); + if ((*val = strb2bitstr (p, 8, PE_CLASS_UNIV, PE_PRIM_BITS)) == NULLPE) + return NOTOK; + return OK; +} + +static int build_aext_rnfa (value, parm) +caddr_t *value; +caddr_t parm; +{ + char *rnfa = (char *)parm; + struct type_Ext_RecipientNumberForAdvice **val = + (struct type_Ext_RecipientNumberForAdvice **)value;; + + if ((int) strlen(rnfa) > UB_RECIPIENT_NUMBER_FOR_ADVICE_LENGTH) + return setuberror ("RecipientNumberForAdvice", + strlen(rnfa), + UB_RECIPIENT_NUMBER_FOR_ADVICE_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + + if ((*val = STR2QB (rnfa)) == NULL) + return NOTOK; + return OK; +} + +static int build_aext_redir (value, parm) +caddr_t *value; +caddr_t parm; +{ + Redirection *redir = (Redirection *)parm; + struct type_Ext_RedirectionHistory **rp = + (struct type_Ext_RedirectionHistory **)value; + struct type_Ext_Redirection *rd; + int nredir = 0; + + *rp = NULL; + for ( ; redir; redir = redir -> rd_next) { + *rp = (struct type_Ext_RedirectionHistory *) + smalloc (sizeof **rp); + (*rp) -> next = NULL; + (*rp) -> Redirection = rd = + (struct type_Ext_Redirection *) + smalloc (sizeof *rd); + rd -> intended__recipient__name = + (struct type_Ext_IntendedRecipientName *) + smalloc (sizeof *rd -> intended__recipient__name); + + if (build_addrdn (redir -> rd_addr, redir -> rd_dn, + &rd -> intended__recipient__name -> address) == NOTOK) + return NOTOK; + + if (build_time (redir -> rd_time, + &rd -> intended__recipient__name -> redirection__time) == NOTOK) + return NOTOK; + + rd -> redirection__reason = + (struct type_Ext_RedirectionReason *) + smalloc (sizeof *rd -> redirection__reason); + rd -> redirection__reason -> parm = redir -> rd_reason; + + if (++nredir > UB_REDIRECTIONS) + return setuberror ("RedirectionHistory", + nredir, UB_REDIRECTIONS, + DRD_SIZE_CONSTRAINT_VIOLATION); + } + return OK; +} + +static int build_ext_ora (value, parm) +caddr_t *value; +caddr_t parm; +{ + struct type_Ext_OriginatorReturnAddress **val = + (struct type_Ext_OriginatorReturnAddress **)value; + char *ora = (char *)parm; + + return build_addr (ora, val); +} + +static int build_ext_fn (value, parm) +caddr_t *value; +caddr_t parm; +{ + FullName *fn = (FullName *)parm; + struct type_MTA_ORName **orn = + (struct type_MTA_ORName **)value; + return build_fullname (fn, orn); +} + +static int build_ext_secure (parm, crit, defcrit, type, oid, + modid, mod, label, extlp) +struct qbuf *parm; +int crit; +int defcrit; +int type; +OID oid; +int modid; +modtyp *mod; +char *label; +struct type_MTA_Extensions **extlp; +{ + struct type_MTA_ExtensionField *ext; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + if (build_ext_type (type, oid, &ext -> type) == NOTOK) + return NOTOK; + + if (crit != defcrit) { + if (build_crit (crit, &ext -> criticality) == NOTOK) + return NOTOK; + } + else + ext -> criticality = NULL; + + + if (build_ext_value (parm, &ext -> value) == NOTOK) + return NOTOK; + +#if PP_DEBUG > 0 + if(pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, modid, mod, + ext -> value, label, PDU_WRITE); +#endif + *extlp = (struct type_MTA_Extensions *) smalloc (sizeof **extlp); + (*extlp) -> next = NULL; + (*extlp) -> ExtensionField = ext; + return OK; +} + + + +static int build_dehl (dlh, dlp) +DLHistory *dlh; +struct type_Ext_DLExpansionHistory **dlp; +{ + struct type_Ext_DLExpansionHistory **dp; + struct type_Ext_DLExpansion *d; + int ndlexp = 0; + + *dlp = NULL; + dp = dlp; + for (;dlh; dlh = dlh -> dlh_next) { + *dp = (struct type_Ext_DLExpansionHistory *) + smalloc (sizeof **dp); + (*dp) -> next = NULL; + d = (*dp) -> DLExpansion = + (struct type_Ext_DLExpansion *) + smalloc (sizeof *d); + + if (build_addrdn (dlh -> dlh_addr, + dlh -> dlh_dn, + &d -> address) == NOTOK) + return NOTOK; + + if (build_time (dlh -> dlh_time, + &d -> dl__expansion__time) == NOTOK) + return NOTOK; + + dp = &(*dp) -> next; + if (++ ndlexp > UB_DL_EXPANSIONS) + return setuberror ("DLexpansionHistory", + ndlexp, UB_DL_EXPANSIONS, + DRD_SIZE_CONSTRAINT_VIOLATION); + } + return OK; +} + + +static int build_msi (dp, msip) +DomSupInfo *dp; +struct type_Ext_MTASuppliedInformation **msip; +{ + struct type_Ext_MTASuppliedInformation *msi; + + *msip = msi = (struct type_Ext_MTASuppliedInformation *) + smalloc(sizeof *msi); + bzero ((char *)msi, sizeof *msi); + + if (dp -> dsi_time) + if (build_time (dp -> dsi_time, + &msi -> arrival__time) == NOTOK) + return NOTOK; + msi -> routing__action = (struct type_MTA_RoutingAction *) + smalloc (sizeof *msi -> routing__action); + msi -> routing__action -> parm = dp -> dsi_action; + + if (dp -> dsi_attempted_mta || + (dp -> dsi_attempted_md.global_Country && + dp -> dsi_attempted_md.global_Admin)) { + msi -> attempted = (struct choice_Ext_1 *) + calloc (1, sizeof *msi -> attempted); + if (dp -> dsi_attempted_mta) { + msi -> attempted -> offset = + choice_Ext_1_mta; + if ((msi -> attempted -> un.mta = + STR2QB (dp -> dsi_attempted_mta)) == NULL) + return NOTOK; + } + else { + msi -> attempted -> offset = + choice_Ext_1_domain; + + if (build_gdi (&dp -> dsi_attempted_md, + &msi -> attempted -> un.domain) == NOTOK) + return NOTOK; + } + } + + if (dp -> dsi_deferred && + build_time (dp -> dsi_deferred, + &msi -> deferred__time) == NOTOK) + return NOTOK; + if (dp -> dsi_other_actions) { + if ((msi -> other__actions = + pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, + PE_PRIM_BITS)) == NULLPE) + return NOTOK; + if ((dp -> dsi_other_actions & ACTION_REDIRECTED) && + bit_on (msi -> other__actions, + bit_MTA_OtherActions_redirected) == NOTOK) + return NOTOK; + if ((dp -> dsi_other_actions & ACTION_EXPANDED) && + bit_on (msi -> other__actions, + bit_MTA_OtherActions_dl__operation) == NOTOK) + return NOTOK; + } + return OK; +} + + +static int build_inttrace (tp, tlp) +Trace *tp; +struct type_Ext_InternalTraceInformation **tlp; +{ + struct type_Ext_InternalTraceInformation **tpp; + struct type_Ext_InternalTraceInformationElement *ti; + Trace *tlast; + + *tlp = NULL; + if (trace_type == RTSP_TRACE_ADMD || + trace_type == RTSP_TRACE_NOINT) + return NULL; + + for (tlast = tp; tlast && tlast -> trace_next; + tlast = tlast -> trace_next) + continue; + + tpp = tlp; + for (; tp; tp = tp -> trace_next) { + if (tp -> trace_mta == NULLCP) + continue; + if (trace_type == RTSP_TRACE_LOCALINT && + !same_prmd (tlast, tp)) + continue; + + *tpp = (struct type_Ext_InternalTraceInformation *) + smalloc (sizeof **tpp); + (*tpp) -> next = NULL; + ti = (*tpp) -> InternalTraceInformationElement = + (struct type_Ext_InternalTraceInformationElement *) + calloc (1, sizeof *ti); + + if (build_gdi (&tp -> trace_DomId, + &ti -> global__domain__identifier) == NOTOK) + return NOTOK; + if ((ti -> mta__name = STR2QB (tp -> trace_mta)) == NULL) + return NOTOK; + + + if (build_msi (&tp -> trace_DomSinfo, + &ti -> mta__supplied__information) == NOTOK) + return NOTOK; + tpp = &(*tpp) -> next; + } + return OK; +} + +static int build_ext_iti (parm, crit, extlp) +Trace *parm; +char crit; +struct type_MTA_Extensions **extlp; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_InternalTraceInformation *value; + + if(build_inttrace (parm, &value) == NOTOK) + return NOTOK; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + if (build_ext_type (EXT_INTERNAL_TRACE_INFORMATION, + NULLOID, + &ext -> type) == NOTOK) + return NOTOK; + + if (crit != EXT_INTERNAL_TRACE_INFORMATION_DC) { + if (build_crit (crit, + &ext -> criticality) == NOTOK) + return NOTOK; + } + else + ext -> criticality = NULL; + + + if (encode_Ext_InternalTraceInformation + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't encode InternalTraceInformation value [%s]", + PY_pepy)); + return NOTOK; + } + + PP_PDUP (Ext_InternalTraceInformation, + ext -> value, "Extensions.InternalTraceInformation", + PDU_WRITE); + + free_Ext_InternalTraceInformation (value); + + wrap_up_ext (*extlp, ext); + return OK; +} + + + + +static int build_extension (ext, epp) +X400_Extension *ext; +struct type_MTA_ExtensionField **epp; +{ + struct type_MTA_ExtensionField *ep; + + *epp = ep = (struct type_MTA_ExtensionField *) smalloc (sizeof *ep); + if (build_ext_type (ext -> ext_int, ext -> ext_oid, + &ep -> type) == NOTOK) + return NOTOK; + if (build_crit (ext -> ext_criticality, &ep -> criticality) == NOTOK) + return NOTOK; + if (build_ext_value (ext -> ext_value, &ep -> value) == NOTOK) + return NOTOK; + return OK; +} + +static int build_gen_extensions (xp, extp) +X400_Extension *xp; +struct type_MTA_Extensions **extp; +{ + for (;xp; xp = xp -> ext_next) { + *extp = (struct type_MTA_Extensions *) + smalloc (sizeof **extp); + (*extp) -> next = NULL; + if (build_extension (xp, + &(*extp) -> ExtensionField) == NOTOK) + return NOTOK; + extp = &(*extp) -> next; + } + return OK; +} + +static int build_pm_extensions (qp,p1,msg, extp) +Q_struct *qp; +int p1,msg; +struct type_MTA_Extensions **extp; +{ + struct type_MTA_Extensions **ep; + + *extp = NULL; + + if (build_gen_extensions (qp -> per_message_extensions, extp) == NOTOK) + return NOTOK; + + for (ep = extp; *ep; ep = &(*ep) -> next) + continue; + + if (qp -> recip_reassign_prohibited) { + if (build_ext_generic (&qp -> recip_reassign_prohibited, + qp -> recip_reassign_crit, + EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC, + EXT_RECIPIENT_REASSIGNMENT_PROHIBITED, + NULLOID, + _ZRecipientReassignmentProhibitedExt, + &_ZExt_mod, + build_ext_char, + "Extension.RecipientReassignmentProhibited", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> dl_expansion_prohibited) { + if (build_ext_generic (&qp -> dl_expansion_prohibited, + qp -> dl_expansion_crit, + EXT_DL_EXPANSION_PROHIBITED_DC, + EXT_DL_EXPANSION_PROHIBITED, + NULLOID, + _ZDLExpansionProhibitedExt, + &_ZExt_mod, + build_ext_char, + "Extension.DLExpansionHistory", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> conversion_with_loss_prohibited) { + if (build_ext_generic (&qp -> conversion_with_loss_prohibited, + qp -> conversion_with_loss_crit, + EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC, + EXT_CONVERSION_WITH_LOSS_PROHIBITED, + NULLOID, + _ZConversionWithLossProhibitedExt, + &_ZExt_mod, + build_ext_char, + "Extension.ConversionWithLossProhibited", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> originator_certificate) { + if (build_ext_secure (qp -> originator_certificate, + qp -> originator_certificate_crit, + EXT_ORIGINATOR_CERTIFICATE_DC, + EXT_ORIGINATOR_CERTIFICATE, + NULLOID, + _ZOriginatorCertificateExt, + &_ZExt_mod, + "Extensions.OriginatorCertificate", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> security_label) { + if (build_ext_secure (qp -> security_label, + qp -> security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + EXT_MESSAGE_SECURITY_LABEL, + NULLOID, + _ZMessageSecurityLabelExt, + &_ZExt_mod, + "Extensions.MessageSecurityLabel", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> general_content_correlator) { + if (build_ext_secure (qp -> general_content_correlator, + qp -> content_correlator_crit, + EXT_CONTENT_CORRELATOR_DC, + EXT_CONTENT_CORRELATOR, + NULLOID, + _ZContentCorrelatorExt, + &_ZExt_mod, + "Extensions.ContentCorrelator", + ep) == NOTOK) + return NOTOK; + if (*ep && + ps_get_abs ((*ep) -> ExtensionField -> value) > + UB_CONTENT_CORRELATOR_LENGTH) + return setuberror ("ContentCorrelator", + ps_get_abs ((*ep) -> ExtensionField -> value), + UB_CONTENT_CORRELATOR_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if (*ep) + ep = &(*ep) -> next; + } + if (msg) { + if (qp -> latest_time) { + if (build_ext_generic ((caddr_t)qp -> latest_time, + qp -> latest_time_crit, + EXT_LATEST_DELIVERY_TIME_DC, + EXT_LATEST_DELIVERY_TIME, + NULLOID, + _ZLatestDeliveryTimeExt, + &_ZExt_mod, + build_ext_time, + "Extensions.LatestDeliveryTime", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> originator_return_address) { + if (build_ext_generic + ((caddr_t)qp -> originator_return_address, + qp -> originator_return_address_crit, + EXT_ORIGINATOR_RETURN_ADDRESS_DC, + EXT_ORIGINATOR_RETURN_ADDRESS, + NULLOID, + _ZOriginatorReturnAddressExt, + &_ZExt_mod, + build_ext_ora, + "Extensions.OriginatorReturnAddress", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> algorithm_identifier) { + if (build_ext_secure + (qp -> algorithm_identifier, + qp -> algorithm_identifier_crit, + EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC, + EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER, + NULLOID, + _ZContentConfidentialityAlgorithmIdentifierExt, + &_ZExt_mod, + "Extensions.ContentConfidentialityAlgorithmIdentifier", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> message_origin_auth_check) { + if (build_ext_secure (qp -> message_origin_auth_check, + qp -> message_origin_auth_check_crit, + EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC, + EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK, + NULLOID, + _ZMessageOriginAuthenticationCheckExt, + &_ZExt_mod, + "Extensions.MessageOriginAuthenticationCheck", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + } + if (!msg) { + if (qp -> message_origin_auth_check) { + if (build_ext_secure + (qp -> message_origin_auth_check, + qp -> message_origin_auth_check_crit, + EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK_DC, + EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK, + NULLOID, + _ZProbeOriginAuthenticationCheckExt, + &_ZExt_mod, + "Extensions.ProbeOriginAuthenticationCheck", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + } + if (p1) { + if (qp -> dl_expansion_history) { + if (build_ext_generic + ((caddr_t)qp -> dl_expansion_history, + qp -> dl_expansion_history_crit, + EXT_DL_EXPANSION_HISTORY_DC, + EXT_DL_EXPANSION_HISTORY, + NULLOID, + _ZDLExpansionHistoryExt, + &_ZExt_mod, + build_ext_dlh, + "Extensions.DLExpansionHistory", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + + if (qp -> trace) { + if (build_ext_iti (qp -> trace, + EXT_INTERNAL_TRACE_INFORMATION_DC, + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + } + if ((!p1) && msg) { + if (qp -> forwarding_request != NOTOK) { + if (build_ext_generic + ((caddr_t)&qp -> forwarding_request, + qp -> forwarding_request_crit, + EXT_FORWARDING_REQUEST_DC, + EXT_FORWARDING_REQUEST, + NULLOID, + _ZSequenceNumberExt, + &_ZExt_mod, + build_ext_int, + "Extensions.ForwardingRequest.SequenceNumber", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> proof_of_submission_request) { + if (build_ext_generic + ((caddr_t)&qp -> proof_of_submission_request, + qp -> proof_of_submission_crit, + EXT_PROOF_OF_SUBMISSION_REQUEST_DC, + EXT_PROOF_OF_SUBMISSION_REQUEST, + NULLOID, + _ZProofOfSubmissionRequestExt, + &_ZExt_mod, + build_ext_int, + "Extensions.ProofOfSubmissionRequest", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + } + return OK; +} + +static int build_drc_extensions (qp, dr, extp) +Q_struct *qp; +DRmpdu *dr; +struct type_MTA_Extensions **extp; +{ + struct type_MTA_Extensions **ep; + + *extp = NULL; + + if (build_gen_extensions (dr -> dr_per_report_extensions, + extp) == NOTOK) + return NOTOK; + + for (ep = extp; *ep; ep = &(*ep) -> next) + continue; + + if (qp -> general_content_correlator) { + if (build_ext_secure (qp -> general_content_correlator, + qp -> content_correlator_crit, + EXT_CONTENT_CORRELATOR_DC, + EXT_CONTENT_CORRELATOR, + NULLOID, + _ZContentCorrelatorExt, + &_ZExt_mod, + "Extensions.ContentCorrelator", + ep) == NOTOK) + return NOTOK; + if (*ep && + ps_get_abs ((*ep) -> ExtensionField -> value) > + UB_CONTENT_CORRELATOR_LENGTH) + return setuberror ("ContentCorrelator", + ps_get_abs ((*ep) -> ExtensionField -> value), + UB_CONTENT_CORRELATOR_LENGTH, + DRD_SIZE_CONSTRAINT_VIOLATION); + if (*ep) + ep = &(*ep) -> next; + } + return OK; +} + + +static int build_drc_pr_extensions (qp, rr, extp) +Q_struct *qp; +Rrinfo *rr; +struct type_MTA_Extensions **extp; +{ + struct type_MTA_Extensions **ep; + + *extp = NULL; + + if (build_gen_extensions (rr -> rr_per_recip_extensions, + extp) == NOTOK) + return NOTOK; + + for (ep = extp; *ep; ep = &(*ep) -> next) + continue; + + if (rr -> rr_redirect_history) { + if (build_ext_generic ((caddr_t)rr -> rr_redirect_history, + rr -> rr_redirect_history_crit, + EXT_REDIRECTION_HISTORY_DC, + EXT_REDIRECTION_HISTORY, + NULLOID, + _ZRedirectionHistoryExt, + &_ZExt_mod, + build_aext_redir, + "Extensions.RedirectionHistory", + ep) == NOTOK) + return NOTOK; + + if (*ep) + ep = &(*ep) -> next; + } + + if (rr -> rr_physical_fwd_addr) { + if (build_ext_generic ((caddr_t) rr -> rr_physical_fwd_addr, + rr -> rr_physical_fwd_addr_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_DC, + EXT_PHYSICAL_FORWARDING_ADDRESS, + NULLOID, + _ZPhysicalForwardingAddressExt, + &_ZExt_mod, + build_ext_fn, + "Extensions.PhysicalForwardingAddress", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + + if (rr -> rr_recip_certificate) { + if (build_ext_secure (rr -> rr_recip_certificate, + rr -> rr_recip_certificate_crit, + EXT_RECIPIENT_CERTIFICATE_DC, + EXT_RECIPIENT_CERTIFICATE, + NULLOID, + _ZRecipientCertificateMTA, + &_ZMTA_mod, + "Extensions.RecipientCertificate", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + + if (rr -> rr_report_origin_authentication_check) { + if (build_ext_secure (rr -> rr_report_origin_authentication_check, + rr -> rr_report_origin_authentication_check_crit, + EXT_PROOF_OF_DELIVERY_DC, + EXT_PROOF_OF_DELIVERY, + NULLOID, + _ZProofOfDeliveryToks, + &_ZToks_mod, + "Extensions.ProofOfDelivery", + ep) == NOTOK) + return NOTOK; + if (*ep) + ep = &(*ep) -> next; + } + + return OK; +} + +static int build_prf_ext (ad,p1,msg, extlp) +ADDR *ad; +int p1,msg; +struct type_MTA_Extensions **extlp; +{ + struct type_MTA_Extensions **ep; + + if (build_gen_extensions (ad -> ad_per_recip_ext_list, extlp) == NOTOK) + return NOTOK; + + for (ep = extlp; *ep; ep = &(*ep) -> next) + continue; +#define bump(x) if (*(x)) (x) = &(*x) -> next + + if (ad -> ad_orig_req_alt) { + if (build_ext_generic + (ad -> ad_orig_req_alt, + ad -> ad_orig_req_alt_crit, + EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT_DC, + EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT, + NULLOID, + _ZOriginatorRequestedAlternateRecipientExt, + &_ZExt_mod, + build_aext_oraa, + "Extensions.OriginatorRequestedAlternateRecipient", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + if (ad -> ad_req_del[0] != AD_RDM_NOTUSED) { + if (build_ext_generic ((caddr_t)ad -> ad_req_del, + ad -> ad_req_del_crit, + EXT_REQUESTED_DELIVERY_METHOD_DC, + EXT_REQUESTED_DELIVERY_METHOD, + NULLOID, + _ZRequestedDeliveryMethodExt, + &_ZExt_mod, + build_aext_rdm, + "Extensions.RequestedDeliveryMethod", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + + if (ad -> ad_phys_rendition_attribs) { + if (build_ext_generic + ((caddr_t)ad -> ad_phys_rendition_attribs, + ad -> ad_phys_rendition_attribs_crit, + EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC, + EXT_PHYSICAL_RENDITION_ATTRIBUTES, + NULLOID, + _ZPhysicalRenditionAttributesExt, + &_ZExt_mod, + build_aext_pra, + "Extensions.PhysicalRenditionAttributes", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + if (msg) { + if (ad -> ad_phys_forward) { + if (build_ext_generic + (&ad -> ad_phys_forward, + ad -> ad_phys_forward_crit, + EXT_PHYSICAL_FORWARDING_PROHIBITED_DC, + EXT_PHYSICAL_FORWARDING_PROHIBITED, + NULLOID, + _ZPhysicalForwardingProhibitedExt, + &_ZExt_mod, + build_ext_char, + "Extensions.PhysicalForwardingProhibited", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + if (ad -> ad_phys_fw_ad_req) { + if (build_ext_generic + (&ad -> ad_phys_fw_ad_req, + ad -> ad_phys_fw_ad_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC, + EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST, + NULLOID, + _ZPhysicalForwardingAddressRequestExt, + &_ZExt_mod, + build_ext_char, + "Extensions.PhysicalForwardingAddressRequest", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + if (ad -> ad_phys_modes) { + if (build_ext_generic + ((caddr_t)&ad -> ad_phys_modes, + ad -> ad_phys_modes_crit, + EXT_PHYSICAL_DELIVERY_MODES_DC, + EXT_PHYSICAL_DELIVERY_MODES, + NULLOID, + _ZPhysicalDeliveryModesExt, + &_ZExt_mod, + build_aext_pdm, + "Extensions.PhysicalDeliveryModes", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + + if (ad -> ad_reg_mail_type) { + if (build_ext_generic + ((caddr_t)&ad -> ad_reg_mail_type, + ad -> ad_reg_mail_type_crit, + EXT_REGISTERED_MAIL_DC, + EXT_REGISTERED_MAIL, + NULLOID, + _ZRegisteredMailTypeExt, + &_ZExt_mod, + build_ext_int, + "Extensions.RegisteredMailType", + ep) == NOTOK) + return NOTOK; + bump (ep); + } + if (ad -> ad_recip_number_for_advice) { + if (build_ext_generic + (ad -> ad_recip_number_for_advice, + ad -> ad_recip_number_for_advice_crit, + EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC, + EXT_RECIPIENT_NUMBER_FOR_ADVICE, + NULLOID, + _ZRecipientNumberForAdviceExt, + &_ZExt_mod, + build_aext_rnfa, + "Extensions.RecipientNumberForAdvice", + ep) == NOTOK) + return NOTOK; + bump (ep); + } + if (ad -> ad_pd_report_request) { + if (build_ext_generic + ((caddr_t)&ad -> ad_pd_report_request, + ad -> ad_pd_report_request_crit, + EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC, + EXT_PHYSICAL_DELIVERY_REPORT_REQUEST, + NULLOID, + _ZPhysicalDeliveryReportRequestExt, + &_ZExt_mod, + build_ext_int, + "Extensions.PhysicalDeliveryReportRequest", + ep) == NOTOK) + return NOTOK; + bump (ep); + } + if (ad -> ad_message_token) { + if (build_ext_secure (ad -> ad_message_token, + ad -> ad_message_token_crit, + EXT_MESSAGE_TOKEN_DC, + EXT_MESSAGE_TOKEN, + NULLOID, + _ZMessageTokenExt, + &_ZExt_mod, + "Extensions.MessageToken", + ep) == NOTOK) + return NOTOK; + bump (ep); + } + if (ad -> ad_content_integrity) { + if (build_ext_secure (ad -> ad_content_integrity, + ad -> ad_content_integrity_crit, + EXT_CONTENT_INTEGRITY_CHECK_DC, + EXT_CONTENT_INTEGRITY_CHECK, + NULLOID, + _ZContentIntegrityCheckExt, + &_ZExt_mod, + "Extensions.ContentIntegrityCheck", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + if (ad -> ad_proof_delivery) { + if (build_ext_generic + ((caddr_t)&ad -> ad_proof_delivery, + ad -> ad_proof_delivery_crit, + EXT_PROOF_OF_DELIVERY_REQUEST_DC, + EXT_PROOF_OF_DELIVERY_REQUEST, + NULLOID, + _ZProofOfDeliveryRequestExt, + &_ZExt_mod, + build_ext_int, + "Extensions.ProofOfDeliveryRequest", + ep) == NOTOK) + return NOTOK; + bump(ep); + } + } + if (p1) { + if (ad -> ad_redirection_history) { + if (build_ext_generic + ((caddr_t)ad -> ad_redirection_history, + ad -> ad_redirection_history_crit, + EXT_REDIRECTION_HISTORY_DC, + EXT_REDIRECTION_HISTORY, + NULLOID, + _ZRedirectionHistoryExt, + &_ZExt_mod, + build_aext_redir, + "Extensions.RedirectionHistory", + ep) == NOTOK) + return NOTOK; + bump (ep); + } + } + return OK; +} + +static int build_dre_extensions (dr, extp) +DRmpdu *dr; +struct type_MTA_Extensions **extp; +{ + struct type_MTA_Extensions **ep; + + if (build_gen_extensions (dr -> dr_per_envelope_extensions, + extp) == NOTOK) + return NOTOK; + + for (ep = extp; *ep; ep = &(*ep) -> next) + continue; + + if (dr -> dr_trace) { + if (build_ext_iti (dr -> dr_trace, + EXT_INTERNAL_TRACE_INFORMATION_DC, ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + if (dr -> dr_security_label) { + if (build_ext_secure (dr -> dr_security_label, + dr -> dr_security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + EXT_MESSAGE_SECURITY_LABEL, + NULLOID, + _ZMessageSecurityLabelExt, + &_ZExt_mod, + "Extensions.MessageSecurityLabel", + ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + if (dr -> dr_report_origin_auth_check) { + if (build_ext_secure + (dr -> dr_report_origin_auth_check, + dr -> dr_report_origin_auth_check_crit, + EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK_DC, + EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK, + NULLOID, + _ZReportOriginAuthenticationCheckExt, + &_ZExt_mod, + "Extensions.MessageOriginAuthenticationCheck", + ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + if (dr -> dr_reporting_mta_certificate) { + if (build_ext_secure + (dr -> dr_reporting_mta_certificate, + dr -> dr_reporting_mta_certificate_crit, + EXT_REPORTING_MTA_CERTIFICATE_DC, + EXT_REPORTING_MTA_CERTIFICATE, + NULLOID, + _ZReportingMTACertificateExt, + &_ZExt_mod, + "Extensions.ReportingMTACertificate", + ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + if (dr -> dr_reporting_dl_name) { + if (build_ext_generic ((caddr_t)dr -> dr_reporting_dl_name, + dr -> dr_reporting_dl_name_crit, + EXT_REPORT_DL_NAME_DC, + EXT_REPORT_DL_NAME, + NULLOID, + _ZReportingDLNameExt, + &_ZExt_mod, + build_ext_fn, + "Extension.ReportingDLName", + ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + if (dr -> dr_dl_history) { + if (build_ext_generic + ((caddr_t)dr -> dr_dl_history, + dr -> dr_dl_history_crit, + EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY_DC, + EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY, + NULLOID, + _ZOriginatorAndDLExpansionHistoryExt, + &_ZExt_mod, + build_ext_dlh, + "Extensions.OriginatorAndDLExpansionHistory", + ep) == NOTOK) + return NOTOK; + if (*ep) ep = &(*ep) -> next; + } + return OK; +} + +static int setuberror(msg, length, constrnt, error_code) +char *msg; +int length; +int constrnt; +{ + (void) sprintf (ub_error_string, + "Upper bound constraint exceeded: %s (%d > %d)", + msg, length, constrnt); + PP_LOG(LLOG_EXCEPTIONS, ("%s", ub_error_string)); + ub_error_set = error_code; + return NOTOK; +} diff --git a/Chans/x40088/tasn.c b/Chans/x40088/tasn.c new file mode 100644 index 0000000..45e03f0 --- /dev/null +++ b/Chans/x40088/tasn.c @@ -0,0 +1,240 @@ +/* tasn.c : test the incremental asn1 reading */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/tasn.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/tasn.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: tasn.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "MTA-types.h" +#include "Trans-types.h" +#include "util.h" +#include "q.h" +#include + +char *myname; +void adios (), advise (); +int numbytes = 40; +extern IFP asn_procfnx; +char *remote_site = "remote-site"; +int log_msgtype = MT_UMPDU; +int ext; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + sys_init (myname); + while((opt = getopt(argc, argv, "Ddxn:")) != EOF) + switch (opt) { + case 'n': + numbytes = atoi (optarg); + break; + case 'x': + ext = 1; + break; + case 'd': + pp_log_norm -> ll_events |= (LLOG_TRACE|LLOG_NOTICE); + break; + case 'D': + pp_log_norm -> ll_events = LLOG_ALL; + break; + default: + fprintf (stderr, "Usage: %s\n", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc > 0) { + while (argc -- > 0) { + FILE *fp; + + if ((fp = fopen (*argv, "r")) == NULL) + adios (*argv, "Can't open file"); + process (fp); + (void) fclose (fp); + argv ++; + } + } + else + process (stdin); + exit (0); +} + +static int hdrprint (pe, type) +PE pe; +int type; +{ + switch (type) { + case MT_UMPDU: + advise (NULLCP, "Message"); + if (print_MTA_MessageTransferEnvelope (pe, 1, NULLINTP, + NULLVP, NULL) + == NOTOK) { + advise (NULLCP, + "print MessageTransferEnvelope failed: [%s]", + PY_pepy); + vunknown (pe); + } + break; + + case MT_PMPDU: + advise (NULLCP, "Probe"); + if (print_MTA_ProbeTransferEnvelope (pe, 1, NULLINTP, + NULLVP, NULL) + == NOTOK) { + advise (NULLCP, + "print MessageTransferEnvelope failed: [%s]", + PY_pepy); + vunknown (pe); + } + break; + + case MT_DMPDU: + advise (NULLCP, "Delivery Report"); + if (print_Transfer_ReportAPDU (pe, 1, NULLINTP, + NULLVP, NULL) + == NOTOK) { + advise (NULLCP, + "print Transfer_ReportAPDU failed: [%s]", + PY_pepy); + vunknown (pe); + } + break; + } + return OK; +} + +static int total_count; + +copycount (str, len) +char *str; +int len; +{ + total_count += len; + return OK; +} + +process (fp) +FILE *fp; +{ + char buf[BUFSIZ]; + int n; + struct qbuf *qb; + int result = NOTOK; + int extra; + + total_count = 0; + asn_init (hdrprint, copycount, ext); + while ((n = fread (buf, 1, numbytes, fp)) > 0) { + qb = str2qb (buf, n, 1); + result = (*asn_procfnx) (qb); + qb_free (qb); + switch (result) { + default: + case NOTOK: + adios (NULLCP, "Error"); + break; + case OK: + case DONE: + break; + } + } + if (result != DONE) + adios (NULLCP, "Read message - not parsed"); + else advise (NULLCP, "Message received, %d bytes of content", + total_count); + extra = 0; + while ((n = fread (buf, 1, numbytes, fp)) > 0) + extra += n; + if (extra) + advise (NULLCP, "Message had %d extra trailing bytes", extra); +} + + +#include + + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Chans/x40088/ut_misc.c b/Chans/x40088/ut_misc.c new file mode 100644 index 0000000..d9111c6 --- /dev/null +++ b/Chans/x40088/ut_misc.c @@ -0,0 +1,67 @@ +/* ut_misc.c - Other miscellaneous routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/ut_misc.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/ut_misc.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: ut_misc.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include +#include "tb_bpt88.h" +#include "list_bpt.h" + + +extern CMD_TABLE bptbl_body_parts88 [/* body part types */]; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int bodypart2value (bodypart) /* bodypart -> value */ +char *bodypart; +{ + + PP_TRACE (("x40088/bodypart2value (%s)", bodypart)); + + if (bodypart == NULLCP) + return NOTOK; + + switch (cmd_srch (bodypart, bptbl_body_parts88)) { + case BPT_UNDEFINED: + return 0; + case BPT_TLX: + return 1; + case BPT_IA5: + return 2; + case BPT_G3FAX: + return 3; + case BPT_TIF0: + return 4; + case BPT_TTX: + return 5; + case BPT_VIDEOTEX: + return 6; + case BPT_VOICE: + return 7; + case BPT_SFD: + return 8; + case BPT_TIF1: + return 9; + default: + if (strncmp (bodypart, "oid.", 4) == 0) + return 10; + } + + return NOTOK; +} diff --git a/Chans/x40088/ut_rts.c b/Chans/x40088/ut_rts.c new file mode 100644 index 0000000..1835611 --- /dev/null +++ b/Chans/x40088/ut_rts.c @@ -0,0 +1,491 @@ +/* ut_rts.c - X400 rts utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/ut_rts.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/ut_rts.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: ut_rts.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include +#include "util.h" +#include "rtsparams.h" +#include "chan.h" +#include "Trans-types.h" + +static char *build_inkey(); +static char *pretty_key = NULLCP; /* -- for logging only -- */ +static void print_remote_info(); +static int remote_info_not_found (); + +char *remote_site = NULLCP; +char *undefined_bodyparts = NULLCP; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rts_encode_request (ppe, request, mta, pass, isacs) +PE *ppe; +struct type_Trans_Bind1988Argument **request; +char *mta, *pass; +{ + struct type_Trans_Bind1988Argument *req; + + PP_TRACE (("rts_encode_request (%s %s)", mta, pass)); + + req = (struct type_Trans_Bind1988Argument *) + calloc (1, sizeof (*req)); + if (req == NULL) return NOTOK; + + + if (mta == NULLCP) + req -> offset = type_MTA_MTABindArgument_no__auth; + else { + req->un.auth = + (struct member_MTA_11 *) + calloc (1, sizeof (*req->un.auth)); + req->offset = type_MTA_MTABindArgument_auth; + req -> un.auth -> initiator__name = + str2qb (mta, strlen (mta), 1); + req -> un.auth -> initiator__credentials = + (struct type_MTA_InitiatorCredentials *) + smalloc (sizeof (struct type_MTA_InitiatorCredentials)); + req -> un.auth -> initiator__credentials -> + offset = type_MTA_InitiatorCredentials_octetstring; + req -> un.auth -> initiator__credentials -> + un.octetstring = str2qb (pass, strlen (pass), 1); + } + *request = req; + + if (isacs) { + if (encode_Trans_Bind1988Result (ppe, 1, 0, + NULLCP, req) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't encode bind request: %s", PY_pepy)); + return NOTOK; + } + } + else { + if (encode_MTA_MTABindArgument (ppe, 1, 0, + NULLCP, req) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't encode bind request: %s", PY_pepy)); + return NOTOK; + } + } + + PP_TRACE (("encode Bind Argument successful!")); + + return OK; +} + +int rts_encode_response (ppe, result, mta, pass, isacs) +PE *ppe; +struct type_Trans_Bind1988Result **result; +char *mta, *pass; +{ + struct type_Trans_Bind1988Result *res; + + PP_TRACE (("rts_encode_result (%s %s)", mta, pass)); + + res = (struct type_Trans_Bind1988Result *) + calloc (1, sizeof (*res)); + if (res == NULL) return NOTOK; + + + if (mta == NULLCP) + res -> offset = type_MTA_MTABindResult_no__auth; + else { + res->un.auth = + (struct member_MTA_12 *) + calloc (1, sizeof (*res->un.auth)); + res->offset = type_MTA_MTABindResult_auth; + res -> un.auth -> responder__name = + str2qb (mta, strlen (mta), 1); + res -> un.auth -> responder__credentials = + (struct type_MTA_ResponderCredentials *) + smalloc (sizeof (struct type_MTA_ResponderCredentials)); + res -> un.auth -> responder__credentials -> + offset = type_MTA_ResponderCredentials_octetstring; + res -> un.auth -> responder__credentials -> + un.octetstring = str2qb (pass, strlen (pass), 1); + } + *result = res; + + if (isacs) { + if (encode_Trans_Bind1988Result (ppe, 1, 0, + NULLCP, res) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't encode bind request: %s", PY_pepy)); + return NOTOK; + } + } + else { + if (encode_MTA_MTABindResult (ppe, 1, 0, + NULLCP, res) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't encode bind request: %s", PY_pepy)); + return NOTOK; + } + } + + PP_TRACE (("encode Bind Argument successful!")); + + return OK; +} + + + + +int parameter_checks (pe, mta, pass, key, checks, isacs) +PE pe; +char *mta; +char *pass; +char *key; +int checks; +int isacs; +{ + struct type_Trans_Bind1988Argument *ba; + struct member_MTA_11 *rq; + char *remotesite = NULLCP; + char *password = NULLCP; + int retval = NOTOK; + + PP_TRACE (("parameter_checks('%s', '%s', '%s', '%s')", + key ? key : "null", + mta ? mta : "null", + pass ? pass : "null", + checks ? "true" : "false")); + + if (isacs) { + if (decode_Trans_Bind1988Argument (pe, 0, NULLIP, + NULLVP, &ba) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't decode request: %s", PY_pepy)); + goto parameter_checks_free; + } + } + else { + if (decode_MTA_MTABindArgument (pe, 0, NULLIP, + NULLVP, &ba) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't decode request: %s", PY_pepy)); + goto parameter_checks_free; + } + } + print_remote_info (key, ba); + + if (checks == FALSE) { + retval = OK; + goto parameter_checks_free; + } + + if (ba->offset == type_MTA_MTABindArgument_no__auth) { + PP_NOTICE (("parameter checks are not required")); + retval = OK; + goto parameter_checks_free; + } + + rq = ba->un.auth; + + remotesite = qb2str (rq->initiator__name); + + switch (rq -> initiator__credentials -> offset) { + case type_MTA_InitiatorCredentials_octetstring: + password = qb2str (rq -> initiator__credentials -> + un.octetstring); + break; + case type_MTA_InitiatorCredentials_ia5string: + password = qb2str (rq -> initiator__credentials -> + un.ia5string); + break; + default: + goto parameter_checks_free; + } + + PP_TRACE (("parameter_checks MTA=%s, P=%s", remotesite, password)); + + if (mta && lexequ (remotesite, mta) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("MTAName mismatch: specified='%s' received='%s'", + mta, remotesite)); + goto parameter_checks_free; + } + + + if (lexequ (pass, "dflt") == 0) { + retval = OK; + goto parameter_checks_free; + } + + + if (pass && lexequ ((char *)password, pass) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Password mismatch: specified='%s' received='%s'", + pass, (char *)password)); + goto parameter_checks_free; + } + + retval = OK; + +parameter_checks_free: ; + if (ba) free_Trans_Bind1988Argument (ba); + if (remotesite) free (remotesite); + if (password) free ((char *)password); + + return retval; +} + + + + +/* -- Checks P1 User-data: mTAName and password -- */ + +rts_decode_request (rts, ppe, prq, chan, isacs) +struct RtSAPstart *rts; +PE *ppe; +struct type_Trans_Bind1988Result **prq; +CHAN *chan; +int isacs; +{ + char *key; + RtsParams *rp; + int checkit = TRUE; + + key = build_inkey (rts, isacs); + + PP_TRACE (("rts_decode_request (%s)", key)); + + if ((rp = tb_rtsparams (chan -> ch_in_table, key)) == NULL) + return (remote_info_not_found (rts, ppe, prq, key, chan, isacs)); + + /* -- Check that the right info is in the tables -- */ + if (rp->their_internal_ppname == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No rname specified in the entry '%s'", key)); + return RTS_VALIDATE; + } + + if (rp->their_name == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No rmta specified in the entry '%s'", key)); + return RTS_VALIDATE; + } + + if (lexequ (chan -> ch_in_info, "sloppy") == 0 + || lexequ (rp -> info_mode, "sloppy") == 0) + checkit = FALSE; + + if (parameter_checks (rts -> rts_data, rp -> their_name, + rp -> their_passwd, key, checkit, isacs) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Parameter check failed")); + return RTS_VALIDATE; + } + + /* -- encode new Connect Accept Data -- */ + rts_encode_response (ppe, prq, rp -> our_name, rp -> our_passwd, isacs); + + + /* -- set the remote site value -- */ + if (remote_site) + free (remote_site); + if (rp -> their_internal_ppname == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("No internal name for %s", key)); + remote_site = strdup (key); + } + else remote_site = strdup (rp -> their_internal_ppname); + + + /* --- *** --- + if "undefined" set in eit - replace with rp->info_undefined + --- *** --- */ + + if (undefined_bodyparts) { + free (undefined_bodyparts); + undefined_bodyparts = NULLCP; + } + if (rp -> info_undefined) + undefined_bodyparts = strdup (rp -> info_undefined); + + RPfree (rp); + return OK; +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + + + +static int remote_info_not_found (rts, ppe, prq, key, chan, isacs) +struct RtSAPstart *rts; +PE *ppe; +struct type_Trans_Bind1988Argument **prq; +char *key; +CHAN *chan; +int isacs; +{ + RtsParams *rp; /* --- contains default values --- */ + + + PP_TRACE (("remote_info_not_found()")); + + parameter_checks (rts -> rts_data, NULLCP, NULLCP, key, FALSE, isacs); + + if (lexequ (chan -> ch_in_info, "sloppy") != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("No information found in the X.400 incoming tables")); + return RTS_VALIDATE; + } + + if ((rp = tb_rtsparams (chan -> ch_in_table, "default")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("No 'default' found in the X.400 incoming tables")); + return RTS_VALIDATE; + } + + + /* -- encode new Connect Accept Data -- */ + rts_encode_request (ppe, prq, rp -> our_name, rp -> our_passwd, isacs); + RPfree (rp); + + if (remote_site) free (remote_site); + remote_site = strdup (key); + + PP_LOG (LLOG_EXCEPTIONS, + ("No information found in the X.400 incoming tables - BUT have accepted the connection")); + + return OK; +} + + + +static void print_remote_info (key, ba) +char *key; +struct type_MTA_MTABindArgument *ba; +{ + static char buffer[BUFSIZ]; + char *cp; + + (void) sprintf (buffer, "key='%s' / '%s'", + key, pretty_key); + + if (ba->offset == type_MTA_MTABindArgument_no__auth) { + PP_NOTICE (("%s (no more connection data info)", + buffer)); + return; + } + + (void) strcat (buffer, " mta='"); + + if ((cp = qb2str (ba->un.auth->initiator__name)) != NULLCP) { + (void) strcat (buffer, cp); + (void) strcat (buffer, "'"); + free (cp); + } + (void) strcat (buffer, " passwd='"); + switch (ba -> un.auth -> initiator__credentials -> offset) { + case type_MTA_InitiatorCredentials_ia5string: + cp = qb2str (ba -> un.auth + -> initiator__credentials -> un.ia5string); + (void) strcat (buffer, cp); + free (cp); + (void) strcat (buffer, "'(IA5)"); + break; + case type_MTA_InitiatorCredentials_octetstring: + cp = qb2str (ba->un.auth -> initiator__credentials + -> un.octetstring); + (void) strcat (buffer, cp); + free (cp); + (void) strcat (buffer, "'(OCTS)"); + break; + default: + (void) strcat (buffer, "'"); + break; + } + + PP_NOTICE (("Connection from %s", buffer)); + return; +} + + + +static char *build_inkey (rts, isacs) +struct RtSAPstart *rts; +{ + struct PSAPaddr pas; + struct PSAPaddr *ps; + struct NSAPaddr *na; + int nna; + char *cp; + + PP_TRACE (("build_inkey()")); + + if (isacs) + ps = &rts -> rts_start.acs_start.ps_calling; + else { + bzero ((char *)&pas, sizeof pas); + pas.pa_addr = rts -> rts_initiator.rta_addr; + ps = &pas; + } + for (na = ps -> pa_addr.sa_addr.ta_addrs, + nna = ps -> pa_addr.sa_addr.ta_naddr; + nna > 0; nna --, na ++) { + if (na -> na_type == NA_TCP) { + PP_TRACE (("Address is TCP, port set to 0 from %d", + na -> na_port)); + na -> na_port = 0; + /* bug in isode 6.6 */ + if ((cp = index(na -> na_domain, '+')) != NULL) + *cp = '\0'; + } + } + + if (pretty_key) + free (pretty_key); + pretty_key = strdup(paddr2str (ps, NULLNA)); + + return _paddr2str (ps, NULLNA, -1); +} + + +dump_pdu (qb, str) +struct qbuf *qb; +char *str; +{ + struct qbuf *q; + char buf[512]; + char *cp; + int len, n; + + if ((pp_log_norm -> ll_events & LLOG_PDUS) == 0) + return; + + PP_LOG (LLOG_PDUS, ("PDU dump: %s", str)); + for (q = qb -> qb_forw; q != qb; q = q -> qb_forw) { + for (cp = q -> qb_data, len = q -> qb_len; + len > 0;) { + n = min (sizeof (buf) / 2 - 1, len); + buf[explode (buf, (u_char *)cp, n)] = 0; + ll_printf (pp_log_norm, "%s", buf); + + len -= n; + cp += n; + } + } + ll_printf (pp_log_norm, "\n-----------\n"); +} diff --git a/Chans/x40088/util.c b/Chans/x40088/util.c new file mode 100644 index 0000000..a388606 --- /dev/null +++ b/Chans/x40088/util.c @@ -0,0 +1,178 @@ +/* util.c - x400 utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/util.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/util.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: util.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include + + +extern char *sys_errlist[]; +extern int sys_nerr; + +void adios(), + advise(), + rts_adios(), + rts_advise(); + + +#define NBBY 8 +#define RC_BASE 0x80 + +static char *reason_err0[] = { + "no specific reason stated", + "user receiving ability jeopardized", + "reserved(1)", + "user sequence error", + "reserved(2)", + "local SS-user error", + "unreceoverable procedural error" + }; + + +static int reason_err0_cnt = sizeof reason_err0 / sizeof reason_err0[0]; + + +static char *reason_err8[] = { + "demand data token" + }; + +static int reason_err8_cnt = sizeof reason_err8 / sizeof reason_err8[0]; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +char *SReportString (code) +int code; +{ + register int fcode; + static char buffer[BUFSIZ]; + + if (code == SP_PROTOCOL) + return "SS-provider protocol error"; + + code &= 0xff; + if (code & RC_BASE) + if ((fcode = code & ~RC_BASE) < reason_err8_cnt) + return reason_err8[fcode]; + else + if (code < reason_err0_cnt) + return reason_err0[code]; + + (void) sprintf (buffer, "unknown reason code 0x%x", code); + return buffer; +} + + +/* --------------------- Logging Routines ------------------------------- */ + + + +/*ERRORS*/ + +void rts_adios (rta, event) +register struct RtSAPabort *rta; +char *event; +{ + rts_advise (rta, event); + _exit (1); +} + + + + +void rts_advise (rta, event) +register struct RtSAPabort *rta; +char *event; +{ + char buffer[BUFSIZ]; + extern int rts_sd; + + if (rta->rta_cc > 0) + (void) sprintf (buffer, "%s[%s] %*.*s", + event, + RtErrString (rta->rta_reason), + rta->rta_cc, rta->rta_cc, rta->rta_data); + else + (void) sprintf (buffer, "%s [%s]", event, + RtErrString (rta->rta_reason)); + if (RTS_FATAL (rta -> rta_reason)) + rts_sd = NOTOK; + PP_LOG (LLOG_EXCEPTIONS, ("%s", buffer)); +} + + + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_oper, LLOG_FATAL, ap); + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else + +/* VARARGS2 */ +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else + +/* VARARGS3 */ +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + + diff --git a/Chans/x40088/x400in88.c b/Chans/x40088/x400in88.c new file mode 100644 index 0000000..f2546fd --- /dev/null +++ b/Chans/x40088/x400in88.c @@ -0,0 +1,718 @@ +/* x400in88.c: X400(1988) protocol machine - inbound */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400in88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400in88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400in88.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "Trans-types.h" +#include "util.h" +#include "chan.h" +#include "q.h" +#include "adr.h" +#include "or.h" +#include "retcode.h" +#include +#include +#include "RTS84-types.h" + +extern char *quedfldir; +extern char *remote_site; + +char *myname; +CHAN *mychan; +int submit_running; +int canabort = 0; + +extern IFP asn_procfnx; +extern int hdrproc (), bodyproc (); + +static struct timeval data_timer; +static int data_bytes = 0; +static enum { x400_1988, x400_1984 } stack = x400_1984; +static int rts_sd; +static void rts_adios (); +static void rts_advise (); +static int rts_close (); +static int rts_indication (); +static int rts_turn (); +static int rts_abort (); +static int rts_finish (); +static int rts_uptrans (); +static char *SReportString (); +void advise (), adios (); +#if PP_DEBUG >= PP_DEBUG_SOME +static int do_debug_transfer (); +static int waittime = 0; +#endif + +main (argc, argv) +int argc; +char **argv; +{ + int sd = -1; + RP_Buf rps, *rp = &rps; + int opt; + extern int optind; + extern char *optarg; + + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + while ((opt = getopt (argc, argv, "c:now:")) != EOF) { + switch (opt) { + case 'n': + stack = x400_1988; + break; + case 'o': + stack = x400_1984; + break; + case 'c': + myname = optarg; + break; + case 'w': +#if PP_DEBUG >= PP_DEBUG_SOME + waittime = atoi(optarg); +#endif + break; + default: + adios (NULLCP, "Unknown argument -%c", opt); + } + } +#if PP_DEBUG >= PP_DEBUG_SOME + if (waittime > 0) + sleep (waittime); +#endif + if (stack == x400_1988) + canabort = 1; + chan_init (myname); + + if ((mychan = ch_nm2struct (myname)) == NULLCHAN) + adios (NULLCP, "No channel %s", myname); + + pp_setuserid(); + + (void) chdir (quedfldir); + + or_myinit(); + + if (rp_isbad (io_init(rp))) + adios (NULLCP, "Initialisation error %s", rp -> rp_line); + submit_running = 1; + + PP_NOTICE (("Starting %s (%s)", mychan->ch_name, mychan->ch_show)); + +#if PP_DEBUG >= 0 + if (argv[optind] && strcmp (argv[optind], "debug") == 0) { + do_debug_transfer (); + exit(0); + } +#endif + switch (stack) { + case x400_1984: + sd = rts_init_1984 (argc, argv); + break; + + case x400_1988: + sd = rts_init_1988 (argc, argv); + break; + + default: + adios (NULLCP, "Illegal stack"); + break; + } + + rts_receive (sd); + + exit (0); +} + +static int rts_uptrans (); + +static int check_contexts (ctxlist) +struct PSAPctxlist *ctxlist; +{ + OID a_ctx, r_ctx, m_ctx; + int a,r,m, i; + struct PSAPcontext *pp; + + a = r = m = 0; +#define aCSE "2.2.1.0.1" +#define rTSE "2.6.0.2.12" +#define mTSE "2.6.0.2.7" + a_ctx = str2oid (aCSE); + r_ctx = str2oid (rTSE); + m_ctx = str2oid (mTSE); + for (i = 0, pp = ctxlist -> pc_ctx; + i < ctxlist -> pc_nctx; pp++, i++) { + if (oid_cmp (pp -> pc_asn, a_ctx) == 0) { + a = 1; + continue; + } + if (oid_cmp (pp -> pc_asn, r_ctx) == 0) { + r = 1; + continue; + } + + if (oid_cmp (pp -> pc_asn, m_ctx) == 0) { + m = 1; + continue; + } + + advise (NULLCP, "Unexpected context %s", + sprintoid (pp -> pc_asn)); + } + if (a != 1) + advise (NULLCP, "context %s not present", aCSE); + if (r != 1) + advise (NULLCP, "context %s not present", rTSE); + if (m != 1) + advise (NULLCP, "context %s not present", mTSE); + oid_free (a_ctx); + oid_free (m_ctx); + oid_free (r_ctx); + return OK; +} + + +rts_init_1988 (argc, argv) +int argc; +char **argv; +{ + struct RtSAPstart rtss; + struct RtSAPstart *rts = &rtss; + struct RtSAPindication rtis; + struct RtSAPindication *rti = &rtis; + struct RtSAPabort *rta = &rti -> rti_abort; + struct AcSAPstart *acs = &rts -> rts_start; + struct PSAPstart *ps = &acs -> acs_start; + struct type_Trans_Bind1988Result *res; + PE accept_pe; + OID r_ctx; + + r_ctx = oid_cpy (str2oid(rTSE)); + PP_TRACE (("rts_init_1988 ()")); + + if (RtInit_Aux (argc, argv, rts, rti, r_ctx) == NOTOK) + rts_adios (rta, "RtInit"); + + advise (LLOG_NOTICE, NULLCP, "RT-OPEN.INDICATION: <%d, %s, %s, 0x%x>", + rts -> rts_sd, + rts -> rts_mode == RTS_TWA ? "twa" : "mono", + rts -> rts_turn == RTS_RESPONDER ? "responder" : "initiator", + rts -> rts_data); + + advise (LLOG_NOTICE, NULLCP, "ACSE: <%d, %s, %s, %s, %d>", + acs -> acs_sd, oid2ode (acs -> acs_context), + sprintaei (&acs -> acs_callingtitle), + sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo); + + advise (LLOG_NOTICE, NULLCP, + "PSAP: <%d, %s, %s, %d, %d, %d>", + ps -> ps_sd, + paddr2str (&ps -> ps_calling, NULLNA), + paddr2str (&ps -> ps_called, NULLNA), + ps -> ps_isn, ps -> ps_ssdusize); + rts_sd = rts -> rts_sd; + + if (check_contexts (&ps -> ps_ctxlist) == NOTOK) { + (void) RtOpenResponse (rts_sd, ACS_PERMANENT, NULLOID, NULLAEI, + &ps -> ps_called, NULLPC, + ps -> ps_defctxresult, + NULLPE, + rti); + adios (NULLCP, "Bad presentation context"); + } + + if (rts -> rts_data == NULLPE) { + (void) RtOpenResponse (rts_sd, ACS_PERMANENT, NULLOID, NULLAEI, + &ps -> ps_called, NULLPC, + ps -> ps_defctxresult, + int2prim (int_MTA_MTABindError_authentication__error), + rti); + adios (NULLCP, "No initial user data"); + } + PP_PDUP (Trans_Bind1988Argument, rts -> rts_data, + "RTS88.BindArgument", PDU_READ); + + if (rts_decode_request (rts, &accept_pe, &res, mychan, 1) != OK) { + PP_OPER (NULLCP, ("rts_decode_request failed")); + (void) RtOpenResponse (rts_sd, ACS_PERMANENT, NULLOID, + NULLAEI, &ps -> ps_called, NULLPC, + ps -> ps_defctxresult, + int2prim (int_MTA_MTABindError_authentication__error), + rti); + adios (NULLCP, "Connection aborted"); + } + + PP_PDUP (Trans_Bind1988Result, accept_pe, + "RTS88.BindResult", PDU_WRITE); + + RTSFREE (rts); + + if (RtOpenResponse (rts_sd, ACS_ACCEPT, NULLOID, NULLAEI, + &ps -> ps_called, NULLPC, ps -> ps_defctxresult, + accept_pe, rti) == NOTOK) + rts_adios (rta, "RT-OPEN.RESPONSE"); + + free_Trans_Bind1988Result (res); + if (RtSetUpTrans (rts_sd, rts_uptrans, rti) == NOTOK) + rts_adios (rta, "RtSetUpTrans"); + + return rts_sd; +} + +rts_init_1984 (argc, argv) +int argc; +char **argv; +{ + struct RtSAPstart rtss; + struct RtSAPstart *rts = &rtss; + struct RtSAPindication rtis; + struct RtSAPindication *rti = &rtis; + struct RtSAPabort *rta = &rti -> rti_abort; + struct type_RTS84_Request *request = 0; /* XXX */ + int retval; + PE accept_pe; + struct SSAPaddr *sai = &rts -> rts_initiator.rta_addr; + struct TSAPaddr *tai = &sai -> sa_addr; + struct NSAPaddr *nai = tai -> ta_addrs; + + if (RtBInit (argc, argv, rts, rti) == NOTOK) + rts_adios (rta, "RtBInit"); + + PP_TRACE (("RT-BEGIN.INDICATION: <%d, %s, %s, %d, 0x%x>", + rts->rts_sd, + rts->rts_mode == RTS_TWA ? "twa" : "mon", + rts->rts_turn == RTS_RESPONDER ? "responder" : "initiator", + ntohs (rts->rts_port), + rts->rts_data)); + + PP_TRACE (("Calling addresses: <<%s, %s>, %s>", + na2str (nai), + sel2str (tai->ta_selector, tai->ta_selectlen, 1), + sel2str (sai->sa_selector, sai->sa_selectlen, 1))); + + PP_DBG (("more .... <<%s, '%s' '%d'>, '%s' '%d'>", + na2str (nai), + &tai->ta_selector[0], tai->ta_selectlen, + &sai->sa_selector[0], sai->sa_selectlen)); + + rts_sd = rts -> rts_sd; + + if (rts -> rts_data == NULLPE) { + (void) RtBeginResponse (rts_sd, RTS_VALIDATE, NULLPE, rti); + adios (NULLCP, "No initial user data"); + } + + PP_PDUP (RTS84_Request, rts -> rts_data, + "RTS84.Request", PDU_READ); + + if ((retval = rts_decode_request (rts, &accept_pe, + &request, mychan, 0)) != OK) { + PP_OPER (NULLCP, ("Can't decode incoming request")); + RtBeginResponse (rts_sd, retval, NULLPE, rti); + adios (NULLCP, "Connection aborted"); + } + + PP_PDUP (RTS84_Request, accept_pe, "RTS84.Response", PDU_WRITE); + + RTSFREE (rts); + + if (RtBeginResponse (rts_sd, RTS_ACCEPT, accept_pe, rti) == NOTOK) + rts_adios (rta, "RT-BEGIN.RESPONSE"); + + if (RtSetUpTrans (rts_sd, rts_uptrans, rti) == NOTOK) + rts_adios (rta, "RtSetUpTrans"); + + return rts_sd; +} + +rts_receive (sd) +int sd; +{ + int result; + struct RtSAPindication rtis; + struct RtSAPindication *rti = &rtis; + + for (;;) { + switch (result = RtWaitRequest (sd, NOTOK, rti)) { + case NOTOK: + case OK: + case DONE: + rts_indication (sd, rti); + break; + + default: + adios (NULLCP, "Unknown return from RoWaitRequest=%d", + result); + } + } +} + +static int rts_indication (sd, rti) +int sd; +register struct RtSAPindication *rti; +{ + switch (rti -> rti_type) { + case RTI_TURN: + rts_turn (sd, &rti -> rti_turn); + break; + + case RTI_TRANSFER: + if (data_bytes) + timer_end (&data_timer, data_bytes, + "Transfer Completed"); + break; + + case RTI_ABORT: + rts_abort (sd, &rti -> rti_abort); + break; + + case RTI_CLOSE: + rts_close (sd, &rti -> rti_close); + break; + + case RTI_FINISH: + rts_finish (sd, &rti -> rti_finish); + break; + + default: + adios (NULLCP, "unknown indication type=%d", rti -> rti_type); + } +} + +static rts_turn (sd, rtu) +int sd; +register struct RtSAPturn *rtu; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + if (rtu -> rtu_please) { + if (RtGTurnRequest (sd, rti) == NOTOK) + rts_adios (rta, "RT-TURN-GIVE.REQUEST"); + } +} + +static int rts_abort (sd, rta) +int sd; +register struct RtSAPabort *rta; +{ + if (rta -> rta_peer) + rts_adios (rta, "RT-U-ABORT.INDICATION"); + + if (RTS_FATAL (rta -> rta_reason)) + rts_adios (rta, "RT-P-ABORT.INDICATION"); + rts_advise (rta, "RT-P-ABORT.INDICATION"); +} + + +static int rts_close (sd, rtc) +int sd; +struct RtSAPclose *rtc; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + advise (LLOG_NOTICE, NULLCP, "RT-END.INDICATION"); + + if (stack == x400_1988) + advise (LLOG_EXCEPTIONS, NULLCP, "rts_close - 1988mode!"); + + if (RtEndResponse (sd, rti) == NOTOK) + rts_adios (rta, "RT-END.RESPONSE"); + PP_NOTICE (("Normal disconnect from %s", remote_site)); + exit (0); +} + +static int rts_finish (sd, acf) +int sd; +register struct AcSAPfinish *acf; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + if (stack == x400_1984) + advise (LLOG_EXCEPTIONS, NULLCP, "rtsfinish - 1984 mode!"); + + if (RtCloseResponse (sd, ACR_NORMAL, NULLPE, rti) == NOTOK) + rts_adios (rta, "RT-CLOSE.RESPONSE"); + ACFFREE (acf); + PP_NOTICE (("Normal disconnect from %s", remote_site)); + exit (0); +} + +static void rts_adios (rta, event) +register struct RtSAPabort *rta; +char *event; +{ + rts_advise (rta, event); + + _exit (1); +} + + +static void rts_advise (rta, event) +register struct RtSAPabort *rta; +char *event; +{ + char buffer[BUFSIZ]; + + if (rta -> rta_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RtErrString (rta -> rta_reason), + rta -> rta_cc, rta -> rta_cc, rta -> rta_data); + else + (void) sprintf (buffer, "[%s]", + RtErrString (rta -> rta_reason)); + + advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); +} + +static int rts_uptrans (sd, type, addr, rti) +int sd; +int type; +caddr_t addr; +struct RtSAPindication *rti; +{ + register struct SSAPactivity *sv = (struct SSAPactivity *) addr; + register struct SSAPsync *sn = (struct SSAPsync *) addr; + register struct SSAPreport *sp = (struct SSAPreport *) addr; + register struct qbuf *qbp = (struct qbuf *) addr; + PE pe = NULLPE; + + PP_TRACE (("rts_uptrans()")); + + switch (type) { + case SI_DATA: + PP_DBG (("SI_DATA")); + + data_bytes += qbp -> qb_len; + dump_pdu (qbp, "Incoming X.400 data"); + PP_TRACE (("Data %d bytes (%d so far)", qbp -> qb_len, + data_bytes)); + switch ((*asn_procfnx) (qbp)) { + case NOTOK: + default: + io_end (NOTOK); + submit_running = 0; + return rtsaplose (rti, RTS_TRANSFER, NULLCP, + "process data failed"); + case OK: + case DONE: + break; + } + break; + + case SI_SYNC: + PP_DBG (("S-MINOR-SYNC.INDICATION: %ld", sn->sn_ssn)); + break; + + case SI_ACTIVITY: + switch (sv->sv_type) { + case SV_START: + PP_DBG (("S-ACTIVITY-START.INDICATION")); + data_bytes = 0; + timer_start (&data_timer); + asn_init (hdrproc, bodyproc, + stack == x400_1988 ? 1 : 0); + break; + + case SV_INTRIND: + case SV_DISCIND: + PP_LOG (LLOG_EXCEPTIONS, + ("activity %s: %s", + sv->sv_type == SV_INTRIND ? + "interrupted" : "discarded", + SReportString (sv->sv_reason))); + break; + + case SV_ENDIND: + PP_DBG (("S-ACTIVITY-END.INDICATION")); + PP_TRACE (("Accumulated '%d'", data_bytes)); + if (msgfinished () == NOTOK) + return rtsaplose (rti, RTS_TRANSFER, NULLCP, + "data termination failed"); + break; + + default: + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unexpected activity indication=0x%x", + sv->sv_type)); + } + break; + + + case SI_REPORT: + if (!sp->sp_peer) + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unexpected provider-initiated SI_REPORT")); + PP_LOG (LLOG_EXCEPTIONS, + ("Exception Report: %s", + SReportString (sp->sp_reason))); + if (pe) + pe_free (pe); + break; + + default: + return (rtsaplose (rti, RTS_TRANSFER, NULLCP, + "unknown rts_uptrans type=0x%x", type)); + } + + return OK; +} + + +#if PP_DEBUG >= PP_DEBUG_SOME +static int do_debug_transfer () +{ + char buf[BUFSIZ]; + int n; + int result = NOTOK; + struct qbuf *qb; + struct SSAPactivity ssa; + struct RtSAPindication rti; + extern char *loc_dom_mta; + + + bzero ((char *)&ssa, sizeof ssa); + bzero ((char *)&rti, sizeof rti); + ssa.sv_type = SV_START; + remote_site = loc_dom_mta; + + rts_uptrans (0, SI_ACTIVITY, (caddr_t)&ssa, &rti); + while ((n = fread (buf, 1, sizeof buf, stdin)) > 0) { + qb = str2qb (buf, n, 1); + rts_uptrans (0, SI_DATA, (caddr_t)qb, &rti); + qb_free (qb); + } + ssa.sv_type = SV_ENDIND; + rts_uptrans (0, SI_ACTIVITY, (caddr_t)&ssa, &rti); + if (result != DONE) + advise (NULLCP, "Read message - not parsed"); +} +#endif + +#include + +#ifndef lint +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_oper, LLOG_FATAL, ap); + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else + +/* VARARGS2 */ +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else + +/* VARARGS3 */ +static void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif +#define RC_BASE 0x80 + + +static char *reason_err0[] = { + "no specific reason stated", + "user receiving ability jeopardized", + "reserved(1)", + "user sequence error", + "reserved(2)", + "local SS-user error", + "unreceoverable procedural error" + }; + + +static int reason_err0_cnt = sizeof reason_err0 / sizeof reason_err0[0]; + +static char *reason_err8[] = { + "demand data token" + }; + +static int reason_err8_cnt = sizeof reason_err8 / sizeof reason_err8[0]; + +static char *SReportString (code) +int code; +{ + register int fcode; + static char buffer[BUFSIZ]; + + if (code == SP_PROTOCOL) + return "SS-provider protocol error"; + + code &= 0xff; + if (code & RC_BASE) + if ((fcode = code & ~RC_BASE) < reason_err8_cnt) + return reason_err8[fcode]; + else + if (code < reason_err0_cnt) + return reason_err0[code]; + + (void) sprintf (buffer, "unknown reason code 0x%x", code); + return buffer; +} + +sendrtsabort () +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + + if(RtUAbortRequest (rts_sd, NULLPE, rti) == NOTOK) + rts_advise (rta, "RT-U-ABORT.Request"); +} diff --git a/Chans/x40088/x400inext.c b/Chans/x40088/x400inext.c new file mode 100644 index 0000000..4f40c3d --- /dev/null +++ b/Chans/x40088/x400inext.c @@ -0,0 +1,1016 @@ +/* x400inext.c: X400(1988) extensions handling - inbound */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400inext.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400inext.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400inext.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "Ext-types.h" +#include "Trans-types.h" +#include "util.h" +#include "chan.h" +#include "q.h" +#include "adr.h" +#include "or.h" +#include "prm.h" +#include "dr.h" +#include "retcode.h" +#include + +static void decode_ext_time (); + +#ifndef PEPSY_VERSION +extern int print_Ext_LatestDeliveryTime (); +extern int decode_Ext_LatestDeliveryTime (); +extern int print_Ext_PhysicalRenditionAttributes (); +extern int decode_Ext_PhysicalRenditionAttributes (); +extern int print_Ext_RecipientNumberForAdvice (); +extern int decode_Ext_RecipientNumberForAdvice (); +extern int print_Ext_RequestedDeliveryMethod (); +extern int decode_Ext_RequestedDeliveryMethod (); +extern int print_Ext_PhysicalDeliveryModes (); +extern int decode_Ext_PhysicalDeliveryModes (); +extern int print_Ext_RecipientReassignmentProhibited(); +extern int decode_Ext_RecipientReassignmentProhibited(); +extern int print_Ext_DLExpansionProhibited(); +extern int decode_Ext_DLExpansionProhibited(); +extern int print_Ext_ConversionWithLossProhibited(); +extern int decode_Ext_ConversionWithLossProhibited(); +extern int print_Ext_SequenceNumber(); +extern int decode_Ext_SequenceNumber(); +extern int print_Ext_ProofOfSubmissionRequest(); +extern int decode_Ext_ProofOfSubmissionRequest(); +extern int print_Ext_ProofOfDeliveryRequest(); +extern int decode_Ext_ProofOfDeliveryRequest(); +extern int print_Ext_PhysicalForwardingProhibited(); +extern int decode_Ext_PhysicalForwardingProhibited(); +extern int print_Ext_PhysicalForwardingAddressRequest(); +extern int decode_Ext_PhysicalForwardingAddressRequest(); +extern int print_Ext_RegisteredMailType(); +extern int decode_Ext_RegisteredMailType(); +extern int print_Ext_PhysicalDeliveryReportRequest(); +extern int decode_Ext_PhysicalDeliveryReportRequest(); +#endif + + +void do_local_extension (); +void do_global_extension (); + +static X400_Extension *flatten_ext (); +static void ext_recip_reassign (); +static void ext_dlxp (); +static void ext_conv (); +static void ext_ora (); +static void ext_dlexph (); +static void ext_inttrace (); + +static int pe2crit (); + +static DLHistory *ext_decode_dlh (); + +#ifdef PEPSY_VERSION + +#define decode_singleint(type, ip, critp, defcrit, magic_num, mod, label, ext) \ + { \ + struct type *genp; \ +\ + if (pp_log_norm -> ll_events & LLOG_PDUS) \ + pvpdu (pp_log_norm, (magic_num), (mod), \ + (ext) -> value, label, PDU_READ); \ + if (dec_f ((magic_num), (mod), (ext) -> value, 1, NULLIP, NULLVP, &genp) == NOTOK) \ + adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy); \ +\ + (ip) = genp -> parm; \ + (critp) = pe2crit ((ext) -> criticality, defcrit); \ + fre_obj ((char *) (genp), (mod)->md_dtab[(magic_num)], (mod)); \ + } + +static void decode_extension (value, crit, defcrit, magic_num, mod, + label, decoder, ext) +caddr_t value; +char *crit; +int defcrit; +int magic_num; +modtyp *mod; +VFP decoder; +char *label; +struct type_MTA_ExtensionField *ext; +{ + caddr_t *genp; + +#if PP_DEBUG > 0 + if (pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, magic_num, mod, + ext -> value, label, PDU_READ); +#endif + if (dec_f(magic_num, mod, ext -> value, 1, NULLIP, NULLVP, &genp) == NOTOK) + adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy); + + (*decoder) (value, genp); + + *crit = pe2crit (ext -> criticality, defcrit); + + fre_obj((char *) genp, mod->md_dtab[magic_num], mod); +} +#else + +#define decode_singleint(type, ip, critp, defcrit, pfnx, dfnx, ffnx, label, ext) \ + { \ + struct type *genp; \ +\ + PP_PDU (pfnx, ext -> value, label, PDU_READ); \ + if (dfnx (ext -> value, 1, NULLIP, NULLVP, &genp) == NOTOK) \ + adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy); \ +\ + (ip) = genp -> parm; \ + (critp) = pe2crit (ext -> criticality, defcrit); \ + ffnx (genp); \ + } + +static void decode_extension (value, crit, defcrit, pfnx, dfnx, ffnx, + label, decoder, ext) +caddr_t value; +char *crit; +int defcrit; +IFP pfnx, dfnx, ffnx; +VFP decoder; +char *label; +struct type_MTA_ExtensionField *ext; +{ + caddr_t *genp; + +#if PP_DEBUG > 0 + if (pfnx && pp_log_norm -> ll_events & LLOG_PDUS) + _vpdu (pp_log_norm, pfnx, ext -> value, label, PDU_READ); +#endif + if ((*dfnx) (ext -> value, 1, NULLIP, NULLVP, &genp) == NOTOK) + adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy); + + (*decoder) (value, genp); + + *crit = pe2crit (ext -> criticality, defcrit); + + (*ffnx) (genp); +} +#endif + +extern OR_ptr do_or_address (); + +#define bit_ison(x,y) (bit_test(x,y) == 1) + +load_pm_extensions (qp, ext,p1,msg) +Q_struct *qp; +struct type_MTA_Extensions *ext; +int p1,msg; +{ + struct type_MTA_Extensions *ep; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + do_local_extension (&qp -> per_message_extensions, + ep -> ExtensionField); + break; + + case type_MTA_ExtensionType_global: + do_global_extension (ep -> ExtensionField -> + type -> un.global, + qp, ep -> ExtensionField,p1,msg); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } +} + + +squash_ext (qbp, value) +struct qbuf **qbp; +PE value; +{ + char *cp; + int len; + PS ps; + + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "Can't allocate PS"); + + len = ps_get_abs (value); + cp = smalloc (len); + + if (str_setup (ps, cp, len, 1) == NOTOK) + adios (NULLCP, "Can't setup stream [%s]", + ps_error (ps -> ps_errno)); + + if (pe2ps (ps, value) == NOTOK) + adios (NULLCP, "pe2ps failed [%s]", ps_error (ps -> ps_errno)); + + ps_free (ps); + + *qbp = str2qb (cp, len, 1); + free (cp); +} + +static X400_Extension *flatten_ext (ext) +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep; + + ep = (X400_Extension *)smalloc (sizeof *ep); + if (ext -> type -> offset == type_MTA_ExtensionType_global) { + ep -> ext_int = ext -> type -> un.global; + ep -> ext_oid = NULLOID; + } + else { + ep -> ext_int = EXT_OID_FORM; + ep -> ext_oid = oid_cpy (ext -> type -> un.local); + } + + squash_ext (&ep -> ext_value, ext -> value); + ep -> ext_criticality = pe2crit (ext -> criticality, + CRITICAL_NONE); + ep -> ext_next = NULL; + return ep; +} + +void do_local_extension (elist, ext) +X400_Extension **elist; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + + PP_LOG (LLOG_EXCEPTIONS, ("Unknown local extension %s", + sprintoid (ext -> type -> un.local))); + + ep = flatten_ext (ext); + for (epp = elist; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; +} + +static void ext_security (qbp, critp, defcrit, ext) +struct qbuf **qbp; +char *critp; +int defcrit; +struct type_MTA_ExtensionField *ext; +{ + squash_ext (qbp, ext -> value); + + *critp = pe2crit (ext -> criticality, defcrit); +} + +static void do_global_extension (n, qp, ext, p1, msg) +int n; +Q_struct *qp; +struct type_MTA_ExtensionField *ext; +int p1,msg; +{ + X400_Extension *ep, **epp; + + switch (n) { + case EXT_RECIPIENT_REASSIGNMENT_PROHIBITED: +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_RecipientReassignmentProhibited, + qp -> recip_reassign_prohibited, + qp -> recip_reassign_crit, + EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC, + _ZRecipientReassignmentProhibitedExt, + &_ZExt_mod, + "Extension.RecipientReassignmentProhibited", + ext); +#else + decode_singleint (type_Ext_RecipientReassignmentProhibited, + qp -> recip_reassign_prohibited, + qp -> recip_reassign_crit, + EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC, + print_Ext_RecipientReassignmentProhibited, + decode_Ext_RecipientReassignmentProhibited, + free_Ext_RecipientReassignmentProhibited, + "Extension.RecipientReassignmentProhibited", + ext); +#endif + break; + + case EXT_DL_EXPANSION_PROHIBITED: +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_DLExpansionProhibited, + qp -> dl_expansion_prohibited, + qp -> dl_expansion_crit, + EXT_DL_EXPANSION_PROHIBITED_DC, + _ZDLExpansionProhibitedExt, + &_ZExt_mod, + "Extension.DLExpansionProhibited", + ext); +#else + decode_singleint (type_Ext_DLExpansionProhibited, + qp -> dl_expansion_prohibited, + qp -> dl_expansion_crit, + EXT_DL_EXPANSION_PROHIBITED_DC, + print_Ext_DLExpansionProhibited, + decode_Ext_DLExpansionProhibited, + free_Ext_DLExpansionProhibited, + "Extension.DLExpansionProhibited", + ext); +#endif + break; + + case EXT_CONVERSION_WITH_LOSS_PROHIBITED: +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_ConversionWithLossProhibited, + qp -> conversion_with_loss_prohibited, + qp -> conversion_with_loss_crit, + EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC, + _ZConversionWithLossProhibitedExt, + &_ZExt_mod, + "Extensions.ConversionWithLossProhibited", + ext); +#else + decode_singleint (type_Ext_ConversionWithLossProhibited, + qp -> conversion_with_loss_prohibited, + qp -> conversion_with_loss_crit, + EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC, + print_Ext_ConversionWithLossProhibited, + decode_Ext_ConversionWithLossProhibited, + free_Ext_ConversionWithLossProhibited, + "Extensions.ConversionWithLossProhibited", + ext); +#endif + break; + + case EXT_ORIGINATOR_CERTIFICATE: + ext_security (&qp -> originator_certificate, + &qp -> originator_certificate_crit, + EXT_ORIGINATOR_CERTIFICATE_DC, + ext); + break; + + case EXT_MESSAGE_SECURITY_LABEL: + ext_security (&qp -> security_label, + &qp -> security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + ext); + break; + case EXT_CONTENT_CORRELATOR: + ext_security (&qp -> general_content_correlator, + &qp -> content_correlator_crit, + EXT_CONTENT_CORRELATOR_DC, + ext); + break; + + case EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK: + if (!msg) + ext_security (&qp -> message_origin_auth_check, + &qp -> message_origin_auth_check_crit, + EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + break; + + case EXT_DL_EXPANSION_HISTORY: + if (p1) + ext_dlexph (qp, ext); + break; + + case EXT_INTERNAL_TRACE_INFORMATION: + if (p1) + ext_inttrace (&qp -> trace, ext); + break; + + case EXT_LATEST_DELIVERY_TIME: + if (msg) + decode_extension (&qp -> latest_time, + &qp -> latest_time_crit, + EXT_LATEST_DELIVERY_TIME_DC, +#ifdef PEPSY_VERSION + _ZLatestDeliveryTimeExt, + &_ZExt_mod, +#else + print_Ext_LatestDeliveryTime, + decode_Ext_LatestDeliveryTime, + free_Ext_LatestDeliveryTime, +#endif + "Extensions.LatestDeliveryTime", + decode_ext_time, + ext); + break; + + case EXT_ORIGINATOR_RETURN_ADDRESS: + if (msg) + ext_ora (qp, ext); + break; + + case EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER: + if (msg) + ext_security (&qp -> algorithm_identifier, + &qp -> algorithm_identifier_crit, + EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC, + ext); + break; + case EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK: + if (msg) + ext_security (&qp -> message_origin_auth_check, + &qp -> message_origin_auth_check_crit, + EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + break; + case EXT_FORWARDING_REQUEST: + if (msg && (!p1)) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_SequenceNumber, + qp -> forwarding_request, + qp -> forwarding_request_crit, + EXT_FORWARDING_REQUEST_DC, + _ZSequenceNumberExt, + &_ZExt_mod, + "Extension.ForwardingRequest.SequenceNumber", + ext); +#else + decode_singleint (type_Ext_SequenceNumber, + qp -> forwarding_request, + qp -> forwarding_request_crit, + EXT_FORWARDING_REQUEST_DC, + print_Ext_SequenceNumber, + decode_Ext_SequenceNumber, + free_Ext_SequenceNumber, + "Extension.ForwardingRequest.SequenceNumber", + ext); +#endif + break; + case EXT_PROOF_OF_SUBMISSION_REQUEST: + if (msg && (!p1)) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_ProofOfSubmissionRequest, + qp -> proof_of_submission_request, + qp -> proof_of_submission_crit, + EXT_PROOF_OF_SUBMISSION_REQUEST_DC, + _ZProofOfSubmissionRequestExt, + &_ZExt_mod, + "Extension.ProofOfSubmissionRequest", + ext); +#else + decode_singleint (type_Ext_ProofOfSubmissionRequest, + qp -> proof_of_submission_request, + qp -> proof_of_submission_crit, + EXT_PROOF_OF_SUBMISSION_REQUEST_DC, + print_Ext_ProofOfSubmissionRequest, + decode_Ext_ProofOfSubmissionRequest, + free_Ext_ProofOfSubmissionRequest, + "Extension.ProofOfSubmissionRequest", + ext); +#endif + break; + default: + PP_NOTICE (("Unknown global extension type %d", n)); + /* fall */ + ep = flatten_ext (ext); + for (epp = &qp -> per_message_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + + } +} + + +static void ext_ora (qp, ext) +Q_struct *qp; +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_OriginatorReturnAddress *ora; + OR_ptr or; + char buf[BUFSIZ]; + + PP_PDU (print_Ext_OriginatorReturnAddress, + ext -> value, "Extensions.OriginatorReturnAddress", + PDU_READ); + + if (decode_Ext_OriginatorReturnAddress (ext -> value, 1, + NULLIP, NULLVP, + &ora) == NOTOK) + adios (NULLCP, "Can't parse originator return address [%s]", + PY_pepy); + + or = do_or_address (ora -> standard__attributes, + ora -> domain__defined__attributes, + ora -> extension__attributes); + or_or2std (or, buf, 0); + or_free (or); + + qp -> originator_return_address = fn_new (buf, NULLCP); + + qp -> originator_return_address_crit = pe2crit (ext -> criticality, + EXT_ORIGINATOR_RETURN_ADDRESS_DC); + free_Ext_OriginatorReturnAddress (ora); +} + +static void ext_dlexph (qp, ext) +Q_struct *qp; +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_DLExpansionHistory *dlh, *dlhp; + DLHistory *dp; + + PP_PDU (print_Ext_DLExpansionHistory, ext -> value, + "Extensions.DLExpansionHistory", PDU_READ); + + if (decode_Ext_DLExpansionHistory (ext -> value, 1, + NULLIP, NULLVP, + &dlh) == NOTOK) + adios (NULLCP, "Can't parse DLExpansionHistory value [%s]", + PY_pepy); + for (dlhp = dlh; dlhp; dlhp = dlhp -> next) { + dp = ext_decode_dlh (dlhp -> DLExpansion); + dlh_add (&qp -> dl_expansion_history, dp); + } + qp -> dl_expansion_history_crit = pe2crit (ext -> criticality, + EXT_DL_EXPANSION_HISTORY_DC); + free_Ext_DLExpansionHistory (dlh); +} + +static DLHistory *ext_decode_dlh (dlp) +struct type_Ext_DLExpansion *dlp; +{ + char buf[BUFSIZ]; + UTC ut; + OR_ptr or; + DLHistory *dp; + + load_time (&ut, dlp -> dl__expansion__time); + or = do_or_address (dlp -> address -> standard__attributes, + dlp -> address -> domain__defined, + dlp -> address -> extension__attributes); + or_or2std (or, buf, 0); + or_free (or); + + dp = dlh_new (buf, NULLCP, ut); + free ((char *)ut); + return dp; +} + +static void decode_ext_time (utc, genp) +UTC *utc; +struct type_UNIV_UTCTime *genp; +{ + load_time (utc, genp); +} + +static void ext_inttrace (trace, ext) +Trace **trace; +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_InternalTraceInformation *intt, *ip; + + PP_PDU (print_Ext_InternalTraceInformation, + ext -> value, "Extension.InternalTraceInformation", + PDU_READ); + + if (decode_Ext_InternalTraceInformation (ext -> value, 1, + NULLIP, NULLVP, + &intt) == NOTOK) + adios (NULLCP, "Can't parse InternalTraceInformation [%s]", + PY_pepy); + + for (ip = intt; ip; ip = ip -> next) { + struct type_Ext_InternalTraceInformationElement *te; + struct type_Ext_MTASuppliedInformation *msi; + Trace *tp; + + te = ip -> InternalTraceInformationElement; + tp = trace_new (); + load_gdi (&tp -> trace_DomId, + te -> global__domain__identifier); + tp -> trace_mta = qb2str (te -> mta__name); + msi = te -> mta__supplied__information; + if (msi -> arrival__time) + load_time (&tp -> trace_DomSinfo.dsi_time, + msi -> arrival__time); + if (msi -> routing__action) + tp -> trace_DomSinfo.dsi_action = + msi -> routing__action -> parm; + if (msi -> deferred__time) + load_time (&tp -> trace_DomSinfo.dsi_deferred, + msi -> deferred__time); + if (msi -> other__actions) { + if (bit_ison (msi -> other__actions, + bit_MTA_OtherActions_redirected)) + tp -> trace_DomSinfo.dsi_other_actions |= + ACTION_REDIRECTED; + if (bit_ison (msi -> other__actions, + bit_MTA_OtherActions_dl__operation)) + tp -> trace_DomSinfo.dsi_other_actions |= + ACTION_EXPANDED; + } + if (msi -> attempted) { + switch (msi -> attempted -> offset) { + case choice_Ext_1_mta: + tp -> trace_DomSinfo.dsi_attempted_mta = + qb2str (msi -> attempted -> un.mta); + break; + case choice_Ext_1_domain: + load_gdi (&tp -> trace_DomSinfo.dsi_attempted_md, + msi -> attempted -> un.domain); + break; + + + default: + break; + } + } + trace_add (trace, tp); + } +} + +static void decode_ext_pdm (value, genp) +int *value; +PE genp; +{ +#define setbit(t,v) \ + (*value) |= (bit_ison(genp, (t)) ? (v) : 0) + + setbit (bit_Ext_PhysicalDeliveryModes_ordinary__mail, + AD_PM_ORD); + setbit (bit_Ext_PhysicalDeliveryModes_special__delivery, + AD_PM_SPEC); + setbit (bit_Ext_PhysicalDeliveryModes_express__mail, + AD_PM_EXPR); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection, + AD_PM_CNT); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telephone__advice, + AD_PM_CNT_PHONE); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telex__advice, + AD_PM_CNT_TLX); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__teletex__advice, + AD_PM_CNT_TTX); + setbit (bit_Ext_PhysicalDeliveryModes_bureau__fax__delivery, + AD_PM_CNT_BUREAU); +#undef setbit +} + +static void decode_ext_pra (value, gen) +OID *value; +OID gen; +{ + *value = oid_cpy (gen); +} +static void decode_ext_rnfa (value, genp) +char **value; +struct qbuf *genp; +{ + *value = qb2str (genp); +} + +static void decode_ext_rdm (value, genp) +int value[AD_RDM_MAX]; +struct type_Ext_RequestedDeliveryMethod *genp; +{ + int i; + + for (i = 0; i < AD_RDM_MAX && genp; + i++, genp = genp -> next) + value[i] = genp -> element_Ext_0; +} + +do_global_ext_prf (n, ad, ext, p1, msg) +int n; +ADDR *ad; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + + switch (n) { + case EXT_MESSAGE_TOKEN: + if (msg) + ext_security (&ad -> ad_message_token, + &ad -> ad_message_token_crit, + EXT_MESSAGE_TOKEN_DC, + ext); + break; + case EXT_CONTENT_INTEGRITY_CHECK: + if (msg) + ext_security (&ad -> ad_content_integrity, + &ad -> ad_content_integrity_crit, + EXT_CONTENT_INTEGRITY_CHECK_DC, + ext); + break; + case EXT_PROOF_OF_DELIVERY_REQUEST: + if (msg) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_ProofOfDeliveryRequest, + ad -> ad_proof_delivery, + ad -> ad_proof_delivery_crit, + EXT_PROOF_OF_DELIVERY_REQUEST_DC, + _ZProofOfDeliveryRequestExt, + &_ZExt_mod, + "Extensions.ProofOfDeliveryRequest", + ext); +#else + decode_singleint (type_Ext_ProofOfDeliveryRequest, + ad -> ad_proof_delivery, + ad -> ad_proof_delivery_crit, + EXT_PROOF_OF_DELIVERY_REQUEST_DC, + print_Ext_ProofOfDeliveryRequest, + decode_Ext_ProofOfDeliveryRequest, + free_Ext_ProofOfDeliveryRequest, + "Extensions.ProofOfDeliveryRequest", + ext); +#endif + break; + case EXT_PHYSICAL_FORWARDING_PROHIBITED: + if (msg) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_PhysicalForwardingProhibited, + ad -> ad_phys_forward, + ad -> ad_phys_forward_crit, + EXT_PHYSICAL_FORWARDING_PROHIBITED_DC, + _ZPhysicalForwardingProhibitedExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingProhibited", + ext); +#else + decode_singleint (type_Ext_PhysicalForwardingProhibited, + ad -> ad_phys_forward, + ad -> ad_phys_forward_crit, + EXT_PHYSICAL_FORWARDING_PROHIBITED_DC, + print_Ext_PhysicalForwardingProhibited, + decode_Ext_PhysicalForwardingProhibited, + free_Ext_PhysicalForwardingProhibited, + "Extensions.PhysicalForwardingProhibited", + ext); +#endif + break; + case EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST: + if (msg) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_PhysicalForwardingAddressRequest, + ad -> ad_phys_fw_ad_req, + ad -> ad_phys_fw_ad_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC, + _ZPhysicalForwardingAddressRequestExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingAddressRequest", + ext); +#else + decode_singleint (type_Ext_PhysicalForwardingAddressRequest, + ad -> ad_phys_fw_ad_req, + ad -> ad_phys_fw_ad_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC, + print_Ext_PhysicalForwardingAddressRequest, + decode_Ext_PhysicalForwardingAddressRequest, + free_Ext_PhysicalForwardingAddressRequest, + "Extensions.PhysicalForwardingAddressRequest", + ext); +#endif + break; + case EXT_REGISTERED_MAIL: + if (msg) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_RegisteredMailType, + ad -> ad_reg_mail_type, + ad -> ad_reg_mail_type_crit, + EXT_REGISTERED_MAIL_DC, + _ZRegisteredMailTypeExt, + &_ZExt_mod, + "Extensions.RegisteredMailType", + ext); +#else + decode_singleint (type_Ext_RegisteredMailType, + ad -> ad_reg_mail_type, + ad -> ad_reg_mail_type_crit, + EXT_REGISTERED_MAIL_DC, + print_Ext_RegisteredMailType, + decode_Ext_RegisteredMailType, + free_Ext_RegisteredMailType, + "Extensions.RegisteredMailType", + ext); +#endif + break; + case EXT_PHYSICAL_DELIVERY_REPORT_REQUEST: + if (msg) +#ifdef PEPSY_VERSION + decode_singleint (type_Ext_PhysicalDeliveryReportRequest, + ad -> ad_pd_report_request, + ad -> ad_pd_report_request_crit, + EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC, + _ZPhysicalDeliveryReportRequestExt, + &_ZExt_mod, + "Extensions.PhysicalDeliveryReportRequest", + ext); +#else + decode_singleint (type_Ext_PhysicalDeliveryReportRequest, + ad -> ad_pd_report_request, + ad -> ad_pd_report_request_crit, + EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC, + print_Ext_PhysicalDeliveryReportRequest, + decode_Ext_PhysicalDeliveryReportRequest, + free_Ext_PhysicalDeliveryReportRequest, + "Extensions.PhysicalDeliveryReportRequest", + ext); +#endif + break; + case EXT_PHYSICAL_RENDITION_ATTRIBUTES: + decode_extension (&ad -> ad_phys_rendition_attribs, + &ad -> ad_phys_rendition_attribs_crit, + EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC, +#ifdef PEPSY_VERSION + _ZPhysicalRenditionAttributesExt, + &_ZExt_mod, +#else + print_Ext_PhysicalRenditionAttributes, + decode_Ext_PhysicalRenditionAttributes, + free_Ext_PhysicalRenditionAttributes, +#endif + "Extensions.PhysicalRenditionAttributes", + decode_ext_pra, + ext); + break; + case EXT_RECIPIENT_NUMBER_FOR_ADVICE: + if (msg) + decode_extension (&ad -> ad_recip_number_for_advice, + &ad -> ad_recip_number_for_advice_crit, + EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC, +#ifdef PEPSY_VERSION + _ZRecipientNumberForAdviceExt, + &_ZExt_mod, +#else + print_Ext_RecipientNumberForAdvice, + decode_Ext_RecipientNumberForAdvice, + free_Ext_RecipientNumberForAdvice, +#endif + "Extensions.RecipientNumberForAdvice", + decode_ext_rnfa, + ext); + break; + case EXT_REQUESTED_DELIVERY_METHOD: + decode_extension (ad -> ad_req_del, + &ad -> ad_req_del_crit, + EXT_REQUESTED_DELIVERY_METHOD_DC, +#ifdef PEPSY_VERSION + _ZRequestedDeliveryMethodExt, + &_ZExt_mod, +#else + print_Ext_RequestedDeliveryMethod, + decode_Ext_RequestedDeliveryMethod, + free_Ext_RequestedDeliveryMethod, +#endif + "Extensions.RequestedDeliveryMethod", + decode_ext_rdm, + ext); + break; + case EXT_PHYSICAL_DELIVERY_MODES: + if (msg) + decode_extension (&ad -> ad_phys_modes, + &ad -> ad_phys_modes_crit, + EXT_PHYSICAL_DELIVERY_MODES_DC, +#ifdef PEPSY_VERSION + _ZPhysicalDeliveryModesExt, + &_ZExt_mod, +#else + print_Ext_PhysicalDeliveryModes, + decode_Ext_PhysicalDeliveryModes, + free_Ext_PhysicalDeliveryModes, +#endif + "Extensions.PhysicalDeliveryModes", + decode_ext_pdm, + ext); + break; + + case EXT_REDIRECTION_HISTORY: + if (p1) { + ep = flatten_ext (ext); + for (epp = &ad -> ad_per_recip_ext_list; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + } + break; + + default: + PP_NOTICE (("Unknown global extension type %d", n)); + /* fall */ + case EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT: + ep = flatten_ext (ext); + for (epp = &ad -> ad_per_recip_ext_list; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } +} + +static int pe2crit (pe, defcrit) +PE pe; +int defcrit; +{ + char *str; + int len, n; + + if (pe == NULLPE) + return defcrit; + str = bitstr2strb (pe, &len); + n = strb2int(str, len); + free (str); + return n; +} + +do_global_repe_prf (n, dr, ext) +int n; +DRmpdu *dr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + + switch (n) { + case EXT_INTERNAL_TRACE_INFORMATION: + ext_inttrace (&dr -> dr_trace, ext); + break; + case EXT_MESSAGE_SECURITY_LABEL: + ext_security (&dr -> dr_security_label, + &dr -> dr_security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + ext); + break; + case EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK: + ext_security (&dr -> dr_report_origin_auth_check, + &dr -> dr_report_origin_auth_check_crit, + EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + break; + case EXT_REPORTING_MTA_CERTIFICATE: + ext_security (&dr -> dr_reporting_mta_certificate, + &dr -> dr_reporting_mta_certificate_crit, + EXT_REPORTING_MTA_CERTIFICATE_DC, + ext); + break; + case EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY: + case EXT_REPORT_DL_NAME: + default: + ep = flatten_ext (ext); + for (epp = &dr -> dr_per_envelope_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } +} + +do_global_cont_prf (n, dr, ext) +int n; +DRmpdu *dr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + + switch (n) { + case EXT_CONTENT_CORRELATOR: + default: + ep = flatten_ext (ext); + for (epp = &dr -> dr_per_envelope_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } +} + +do_global_rr_prf (n, rr, ext) +int n; +Rrinfo *rr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + + switch (n) { + case EXT_RECIPIENT_CERTIFICATE: + ext_security (&rr -> rr_report_origin_authentication_check, + &rr -> rr_report_origin_authentication_check_crit, + EXT_RECIPIENT_CERTIFICATE_DC, + ext); + break; + + case EXT_REDIRECTION_HISTORY: + case EXT_PHYSICAL_FORWARDING_ADDRESS: + case EXT_PROOF_OF_DELIVERY: + default: + ep = flatten_ext (ext); + for (epp = &rr -> rr_per_recip_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } +} diff --git a/Chans/x40088/x400inmsg.c b/Chans/x40088/x400inmsg.c new file mode 100644 index 0000000..fa39817 --- /dev/null +++ b/Chans/x40088/x400inmsg.c @@ -0,0 +1,499 @@ +/* x400inmsg.c: X400(1988) handling of body and envelope */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400inmsg.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400inmsg.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400inmsg.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + +#include "Trans-types.h" +#include "util.h" +#include "chan.h" +#include "q.h" +#include "adr.h" +#include "or.h" +#include "prm.h" +#include "dr.h" +#include "retcode.h" +#include +#include + +#define bit_ison(x,y) (bit_test(x,y) == 1) + +extern char *remote_site; +extern char *undefined_bodyparts; +extern char *postmaster; +extern char *myname; +extern char *cont_p2, hdr_p2_bp; + +enum errstate { st_normal, st_dr, st_probe, st_err_asn, st_err_submit, st_err_junk }; +static enum errstate state = st_normal; + +extern CHAN *mychan; +extern int submit_running; +extern int canabort; +extern int rts_sd; + +static int splatfnx (va_alist) +va_dcl +{ + char buffer[BUFSIZ]; + caddr_t junk; + RP_Buf rps; + + va_list ap; + + va_start (ap); + + junk = va_arg (ap, caddr_t); + + _asprintf (buffer, NULLCP, ap); + + if (pps_txt (buffer, &rps) == NOTOK) + adios (NULLCP, "Write fails: %s", rps.rp_line); + va_end (ap); +} + +int hdrproc (pe, type) +PE pe; +int type; +{ + struct type_Trans_MtsAPDU *parm; + struct type_MTA_MessageTransferEnvelope *envelope; + Q_struct qs, *qp = &qs; + DRmpdu drs, *dr = &drs; + struct prm_vars prm; + RP_Buf rps, *rp = &rps; + ADDR *ap; + struct qbuf *qbret, *qb; + + if (type == NOTOK) { + PP_OPER (NULLCP, ("Bad message")); + resetforpostie (st_err_junk, pe, type, + "Transfer is not ASN.1"); + return OK; + } + state = st_normal; + + if (submit_running == 0) { + if (rp_isbad (io_init (rp))) + adios (NULLCP, "Can't initialise submit: %s", + rp -> rp_line); + submit_running = 1; + } + + prm_init (&prm); + prm.prm_opts = PRM_ACCEPTALL | PRM_NOTRACE; + if (rp_isbad (io_wprm (&prm, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, "io_wpm %s", rp -> rp_line); + return NOTOK; + } + + q_init (qp); + switch (type) { + case MT_UMPDU: + PP_PDUP (MTA_MessageTransferEnvelope, pe, + "MTA.MessageTransferEnvelope", PDU_READ); + if (decode_MTA_MessageTransferEnvelope + (pe, 1, NULLIP, NULLVP, &envelope) + == NOTOK) { + PP_OPER(NULLCP, ("Parse of P1 failed [%s]", PY_pepy)); + resetforpostie (st_err_asn, pe, type, + "ASN.1 is NOT P1"); + return OK; + } + else { + switch (load_qstruct (qp, envelope)) { + case NOTOK: + adios (NULLCP, "Transient problem with ASN"); + case OK: + break; + case DONE: + PP_LOG(LLOG_EXCEPTIONS, + ("Some problem with the P1")); + resetforpostie (st_err_submit, pe, type, + "ASN.1 has a problem"); + return OK; + } + } + break; + + case MT_PMPDU: + PP_PDUP (Trans_MtsAPDU, pe, + "Trans.MtsAPDU", PDU_READ); + if (decode_Trans_MtsAPDU (pe, 1, NULLIP, NULLVP, &parm) + == NOTOK) { + PP_OPER (NULLCP, ("Parse of P1 failed [%s]", PY_pepy)); + resetforpostie (st_err_asn, pe, type, + "ASN.1 is not a Probe"); + return OK; + } + else { + switch (load_probe (qp, parm -> un.probe)) { + case NOTOK: + adios (NULLCP, "Transient problem with ASN"); + case OK: + break; + case DONE: + PP_LOG(LLOG_EXCEPTIONS, + ("Some problem with the P1")); + resetforpostie (st_err_submit, pe, type, + "ASN.1 has a problem"); + return OK; + } + } + state = st_probe; + break; + + case MT_DMPDU: + PP_PDUP (Trans_MtsAPDU, pe, + "Trans.MtsAPDU", PDU_READ); + if (decode_Trans_MtsAPDU (pe, 1, NULLIP, NULLVP, &parm) + == NOTOK) { + PP_OPER (NULLCP, ("Parse of P1 failed [%s]", PY_pepy)); + resetforpostie (st_err_asn, pe, type, + "ASN.1 is not a DR"); + return OK; + } + else { + dr_init (dr); + switch (load_dr (qp, dr, parm -> un.report)) { + case NOTOK: + adios (NULLCP, "Transient problem with ASN"); + case OK: + break; + case DONE: + PP_LOG(LLOG_EXCEPTIONS, + ("Some problem with the P1")); + resetforpostie (st_err_submit, pe, type, + "ASN.1 has a problem"); + return OK; + } + if ( parm -> un.report -> content -> + returned__content) { + if (list_bpt_find (qp -> encodedinfo.eit_types, + hdr_p2_bp) == NULL) + list_bpt_add(&qp -> encodedinfo.eit_types, + list_bpt_new(hdr_p2_bp)); + qp -> content_return_request = TRUE; + } + else { + list_bpt_free (&qp -> encodedinfo.eit_types); + qp -> encodedinfo.eit_types = NULL; + } + if (qp -> cont_type == NULLCP) + qp -> cont_type = strdup(cont_p2); + } + state = st_dr; + break; + default: + PP_OPER (NULLCP, ("Unknown type of structure %d", + type)); + exit (1); + } + qp -> inbound = list_rchan_new (remote_site, NULL); + qp -> inbound -> li_chan = ch_mta2struct (myname, remote_site); + + + if (rp_isbad (io_wrq (qp, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, "io_wrq %s", rp -> rp_line); + return NOTOK; + } + + if (rp_isbad (io_wadr (qp -> Oaddress, AD_ORIGINATOR, rp))) { + char ebuf[BUFSIZ]; + advise (LLOG_EXCEPTIONS, NULLCP, "io_wadr %s", rp -> rp_line); + if (rp_gbval(rp -> rp_val) == RP_BNO) { + (void) sprintf (ebuf, "Can't set sender %s: %s", + qp -> Oaddress -> ad_value, + rp -> rp_line); + resetforpostie (st_err_submit, pe, type, ebuf); + return OK; + } + return NOTOK; + } + PP_NOTICE (("Originator %s", qp -> Oaddress -> ad_value)); + + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) { + if (ap -> ad_resp == NO) ap -> ad_status = AD_STAT_DONE; + + if (rp_isbad (io_wadr (ap, AD_RECIPIENT, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_wadr %s", rp -> rp_line); + return NOTOK; + } + if (ap -> ad_resp) + PP_NOTICE (("Recipient Address %s", ap -> ad_value)); + else + PP_NOTICE (("Recipinet (no responsibility) %s", + ap -> ad_value)); + } + + if (rp_isbad (io_adend (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, "io_adend %s", + rp -> rp_line); + return NOTOK; + } + + switch (qp -> msgtype) { + case MT_UMPDU: + if (rp_isbad (io_tinit (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tinit %s", rp -> rp_line); + return NOTOK; + } + + if (rp_isbad (io_tpart (qp -> cont_type, FALSE, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, "io_tpart %s %s", + qp -> cont_type, rp -> rp_line); + return NOTOK; + } + break; + + case MT_DMPDU: + if (rp_isbad (io_wdr (dr, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_wdr %s", rp -> rp_line); + return NOTOK; + } + if (rp_isbad (io_tinit (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tinit %s", rp -> rp_line); + return NOTOK; + } + if ((qbret = parm -> un.report -> content -> + returned__content) != NULL) { + + if (rp_isbad (io_tpart (qp -> cont_type, FALSE, rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tpart %s %s", + qp -> cont_type, rp -> rp_line); + return NOTOK; + } + for (qb = qbret -> qb_forw; qb != qbret; + qb = qb -> qb_forw) { + if (rp_isbad (io_tdata (qb -> qb_data, + qb -> qb_len))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tdata failed"); + return NOTOK; + } + } + if (rp_isbad (io_tdend (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tdend %s", rp -> rp_line); + return NOTOK; + } + } + if (rp_isbad (io_tend (rp))) { + advise (LLOG_EXCEPTIONS, NULLCP, + "io_tend %s", rp -> rp_line); + return NOTOK; + } + break; + + case MT_PMPDU: + break; + } + return OK; +} + +resetforpostie (st, pe, type, str) +enum errstate st; +PE pe; +int type; +char *str; +{ + static char line[] = "\n\n----------------------------------------\n\n"; + char *msg = ""; + PS ps; + RP_Buf rps, *rp = &rps; + + if (submit_running) { + io_end (NOTOK); + submit_running = 0; + } + + switch (state = st) { + case st_err_submit: + msg = "Submission Error"; + break; + case st_err_asn: + msg = "ASN.1 Parsing error"; + break; + case st_err_junk: + msg = "Invalid ASN.1"; + break; + default: + adios (NULLCP, "Bad state in resetforpostie %d", st); + } + if (canabort) { + sendrtsabort (); + adios (NULLCP, "Aborted submission: inbound error %s - %s", + msg, str); + } + + if (pps_1adr (msg, postmaster, rp) == NOTOK) + adios (NULLCP, "Can't initialize submit for error report: %s", + rp -> rp_line); + + if (pps_txt ("X.400 inbound error detected\n\t", rp) == NOTOK || + pps_txt (str, rp) == NOTOK || + pps_txt ("\nThe message was received from ", rp) == NOTOK || + pps_txt (remote_site ? remote_site : "", rp) == NOTOK) + adios (NULLCP, "Error writing data to submit: %s", + rp -> rp_line); + + switch (st) { + case st_err_asn: + msg = "\n\nA dump of the ASN.1 follows:\n\n"; + break; + case st_err_junk: + msg = "\n\nA hex dump of the incoming message follows:\n\n"; + break; + case st_err_submit: + msg = "\n\nA trace of the P1 envelope follows:\n\n"; + break; + } + if (pps_txt (msg, rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Error writing to submit: %s", rp -> rp_line); + + if (st == st_err_junk) + return; + + switch (type) { + case MT_DMPDU: + vpushpp (stdout, splatfnx, pe, "DR MPDU", PDU_WRITE); + break; + case MT_PMPDU: + vpushpp (stdout, splatfnx, pe, "Probe MPDU", PDU_WRITE); + break; + case MT_UMPDU: + vpushpp (stdout, splatfnx, pe, "User MPDU", PDU_WRITE); + break; + } + switch (st) { + case st_err_asn: + vunknown (pe); + break; + + case st_err_submit: + switch (type) { + case MT_DMPDU: + case MT_PMPDU: + print_Trans_MtsAPDU(pe, 1, NULLIP, NULLVP, NULLCP); + break; + case MT_UMPDU: + print_MTA_MessageTransferEnvelope (pe, 1, NULLIP, + NULLVP, NULLCP); + break; + } + } + vpopp (); + if (pps_txt ("\n\nHEX dump of this data now follows", rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Can't write to submit: %s", rp -> rp_line); + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "Can't allocate PS stream"); + if (str_setup (ps, NULLCP, 0, 0) == NOTOK) + adios (NULLCP, "Can't setup PS stream"); + if (pe2ps (ps, pe) == NOTOK) + adios (NULLCP, "pe2ps failed: %s", ps_error (ps -> ps_errno)); + bodyproc (ps -> ps_base, ps -> ps_ptr - ps -> ps_base); + ps_free (ps); + + if (type == MT_UMPDU) { + if (pps_txt ("\n\nP2 hex dump follows", rp) == NOTOK || + pps_txt (line, rp) == NOTOK) + adios (NULLCP, "Can't write to submit: %s", + rp -> rp_line); + } +} + +bodyproc (str, len) +char *str; +int len; +{ + char hexbuf[82]; + int i; + RP_Buf rps, *rp = &rps; + + PP_TRACE (("Copy %d bytes", len)); + switch (state) { + case st_normal: + if (rp_isbad (io_tdata (str, len))) { + PP_LOG (LLOG_EXCEPTIONS, ("data write failed")); + return NOTOK; + } + break; + case st_probe: + case st_dr: + PP_LOG (LLOG_EXCEPTIONS, ("Illegal state in bodyproc")); + break; + + case st_err_submit: + case st_err_asn: + case st_err_junk: + for (i = 0; i <= len; i += 40) { + int n = min (40, len - i); + n = explode (hexbuf, str + i, n); + hexbuf[n++] = '\n'; + hexbuf[n] = 0; + if (pps_txt (hexbuf, rp) == NOTOK) + adios (NULLCP, "Error writing to submit: %s", + rp -> rp_line); + } + break; + } + return OK; +} + +msgfinished () +{ + RP_Buf rps, *rp = &rps; + + switch (state) { + case st_normal: + if (rp_isbad (io_tdend (rp)) || + rp_isbad (io_tend (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Data termination failed: %s", + rp -> rp_line)); + return NOTOK; + } + PP_NOTICE (("<<< Message received from %s", + remote_site)); + break; + case st_probe: + PP_NOTICE (("<<< Probe received from %s", + remote_site)); + break; + case st_dr: + PP_NOTICE (("<<< DR received from %s", + remote_site)); + break; + + case st_err_asn: + case st_err_submit: + case st_err_junk: + PP_NOTICE (("<<< Invalid message received from %s", + remote_site)); + if (pps_end (OK, rp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("final handshake failed: %s", + rp -> rp_line)); + return NOTOK; + } + break; + } + return OK; +} diff --git a/Chans/x40088/x400out88.c b/Chans/x40088/x400out88.c new file mode 100644 index 0000000..a2e543d --- /dev/null +++ b/Chans/x40088/x400out88.c @@ -0,0 +1,1596 @@ +/* x400out88: x400 out bound channel for 1988 stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400out88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400out88.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400out88.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + +#include "Trans-types.h" +#include "head.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "qmgr.h" +#include "rtsparams.h" +#include +#include "sys.file.h" +#include +#include + + +static enum { st_init, st_hdr, st_bodyinit, st_body, st_end } trans_state; + + +/* -- defines -- */ +#define MAXTRIES 10 +#define STR2QB(s) str2qb (s, strlen (s), 1) + + +/* -- externals -- */ +extern int + build_p1(), + build_dr(), + build_probe (); +extern char + *loc_dom_site, + ub_error_string[], + *quedfldir; +extern int + ub_error_set; + + +/* -- globals -- */ +static ADDR *ad_list; +static CHAN *mychan; +static FILE *body_fp; +static char *chan_name = NULLCP; +static char *connected_to_site = NULLCP; +static char *current_mta = NULLCP; +static char *dumpp1 = NULLCP; +static char *fix_orig; +static char *myname; +static char *p1_ptr; +static char *p1_string; +static char *this_msgid = NULLCP; +static int conn_type = NOTOK; +static int data_bytes; +static int mctx_id; +static int p1_length = 0; +static int trace_type; +static struct timeval data_timer; +int rts_sd = NOTOK; +static int RTS_PING_88 = FALSE; + + +/* -- queue variables -- */ +static Q_struct Qstruct; +Q_struct *PPQuePtr = &Qstruct; +static DRmpdu DRstruct; +DRmpdu *DRptr = &DRstruct; +static struct prm_vars PRMstruct; + + +/* -- local routines -- */ +static char *pe_flatten(); +static int attempt_connect(); +static int check_params(); +static void close_body(); +static int construct_dr(); +static int construct_msg(); +static int construct_probe(); +static int deliver(); +static void dirinit(); +static int dump2file(); +static int endproc(); +static int get_more_message(); +static int initproc(); +static void open_body(); +static int read_body(); +static int rts_downtrans_all(); +static int rts_downtrans_inc(); +static int rts_end(); +static int rts_start(); +static int rts_start84(); +static int rts_start88(); +static int rts_transfer_request(); +static int rtsping88(); +static struct type_MTA_Content *get_dr_content(); +static struct type_MTA_MTABindArgument *convert_prms(); +static struct type_Qmgr_DeliveryStatus *process(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +main (argc, argv) +int argc; +char **argv; +{ + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + + /* -- initialise -- */ + chan_init (myname); + + + /* -- rts88 ping required ? -- */ + if (argc > 1 && strcmp (argv[1], "ping") == 0) + rtsping88 (argc - 1, argv + 1); + + + /* -- get ready to transmit x400out88 messages -- */ + or_myinit(); + dirinit(); + + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) { + if (argc > 2) + dumpp1 = argv[2]; + debug_channel_control (argc, argv, initproc, process, endproc); + } else +#endif + channel_control (argc, argv, initproc, process, endproc); + + exit (0); + /* NOTREACHED */ +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void dirinit() /* -- Change into pp queue space -- */ +{ + PP_TRACE (("dirinit()")); + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change to dir '%s'", quedfldir); +} + + + + +static int initproc (arg) +struct type_Qmgr_Channel *arg; +{ + + if (!RTS_PING_88) chan_name = qb2str (arg); + + PP_TRACE (("initproc (%s)", chan_name)); + + if ((mychan = ch_nm2struct (chan_name)) == NULLCHAN) + adios (NULLCP, "Channel '%s' not known", chan_name); + + rename_log (chan_name); + free (chan_name); + chan_name = NULLCP; + + PP_NOTICE (("Starting %s (%s)", mychan->ch_name, mychan->ch_show)); + + if (RTS_PING_88) return OK; + + prm_init (&PRMstruct); + q_init (PPQuePtr); + dr_init (&DRstruct); + if (current_mta) + free (current_mta); + current_mta = NULLCP; + return OK; +} + + + + +static int endproc() +{ + switch (rts_end()) { + case OK: + PP_NOTICE (("Connection successfully terminated")); + break; + case NOTOK: + PP_NOTICE (("Connection badly terminated")); + break; + case DONE: + PP_NOTICE (("Connection not made")); + break; + } + return OK; +} + + + + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct type_Qmgr_UserList *up; + ADDR *ad_sender = NULLADDR, + *asp, + *ad_recip = NULLADDR, + *alp = NULLADDR, + *ap = NULLADDR; + int naddrs = 0, + ad_count, + retval; + + if (this_msgid) + free (this_msgid); + this_msgid = qb2str (arg->qid); + + PP_NOTICE (("Reading message '%s'", this_msgid)); + + delivery_init (arg->users); + + /* -- queue initialisation - frees memory if called many times -- */ + q_free (PPQuePtr); + dr_free (&DRstruct); + prm_free (&PRMstruct); + + + retval = rd_msg (this_msgid, &PRMstruct, PPQuePtr, + &ad_sender, &ad_recip, &ad_count); + + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg %s", this_msgid)); + (void) rd_end (); + return (delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message")); + } + + + for (asp = ad_sender, ap = ad_recip; ap; ap = ap -> ad_next) { + + for (up = arg->users; up; up = up->next) { + + PP_TRACE (("'%s' '%s' ad_no=%d up_no=%d", + this_msgid, ap->ad_value, ap->ad_no, + up->RecipientId->parm)); + + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + if (dchan_acheck (ap, asp, mychan, naddrs == 0, + ¤t_mta) == NOTOK) { + continue; + } + naddrs ++; + break; + + } + + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = alp = (ADDR *)calloc(1, sizeof *alp); + else { + alp -> ad_next = (ADDR *)calloc(1, sizeof *alp); + alp = alp -> ad_next; + } + + *alp = *ap; /* struct copy */ + alp -> ad_next = NULLADDR; + + } + + if (naddrs == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("No recips to be processed in specified user list")); + rd_end (); + return deliverystate; + } + + + deliver (PPQuePtr, ad_list); /* deliverystate set in deliver */ + + for (alp = ad_list; alp; alp = ap) { + ap = alp -> ad_next; + free ((char *)alp); + } + ad_list = NULLADDR; + + rd_end(); + + return deliverystate; +} + + + + +static int deliver (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + int retval; + int value; + ADDR *ap; + int msgtype; + + switch (recip->ad_status) { + case AD_STAT_PEND: + case AD_STAT_DRWRITTEN: + break; + case AD_STAT_DONE: + delivery_setall (int_Qmgr_status_success); + return NOTOK; + default: + PP_LOG (LLOG_EXCEPTIONS, ("bad state")); + delivery_setallstate (int_Qmgr_status_messageFailure, + "bad state"); + return NOTOK; + } + if (attempt_connect () != OK) + return NOTOK; + + msgtype = Qstruct.msgtype; + if (fix_orig) + x400_fixorig (Qstruct.Oaddress, fix_orig); + + if (recip -> ad_status == AD_STAT_DRWRITTEN || + Qstruct.msgtype == MT_DMPDU) { + retval = construct_dr( &Qstruct, recip); + msgtype = MT_DMPDU; + } + else if (Qstruct.msgtype == MT_PMPDU) + retval = construct_probe (&Qstruct, recip); + else + retval = construct_msg (&Qstruct, recip); + + if (retval != OK) { + delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't build message"); + return NOTOK; + } + + PP_NOTICE (("Sender '%s'", Qstruct.Oaddress->ad_r400adr)); + + for (ap = recip; ap; ap = ap -> ad_next) + PP_NOTICE (("Recipient Address '%s'", ap->ad_r400adr)); + + switch (rts_transfer_request(msgtype)) { + case OK: + value = int_Qmgr_status_success; + break; + case NOTOK: + if (rts_sd == NOTOK) + value = int_Qmgr_status_mtaAndMessageFailure; + else + value = int_Qmgr_status_messageFailure; + break; + case DONE: + value = int_Qmgr_status_negativeDR; + break; + } + + free (p1_string); + + for (ap = recip; ap; ap = ap -> ad_next) { + if (ap -> ad_resp) { + delivery_set (ap -> ad_no, value); + switch (value) { + case int_Qmgr_status_success: + wr_ad_status (ap, AD_STAT_DONE); + wr_stat (ap, qp, this_msgid, data_bytes); + break; + case int_Qmgr_status_negativeDR: + value = int_Qmgr_status_failureSharedDR; + case int_Qmgr_status_failureSharedDR: + set_1dr (qp, ap -> ad_no, this_msgid, + DRR_UNABLE_TO_TRANSFER, + DRD_MTA_CONGESTION, + "Remote site aborted the transfer"); + PP_LOG (LLOG_EXCEPTIONS, + ("Remote site aborted the connection")); + break; + } + } + } + if (rp_isbad(wr_q2dr (qp, this_msgid))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + return OK; + +} + + + + +static int attempt_connect () +{ + if (connected_to_site == NULLCP || rts_sd == NOTOK) { + if (rts_start() != OK) { + delivery_setallstate (int_Qmgr_status_mtaFailure, + "Connection failed"); + return NOTOK; + } + if (connected_to_site) free (connected_to_site); + connected_to_site = strdup (current_mta); + } + else if (lexequ (connected_to_site, current_mta) != 0) { + free (connected_to_site); + connected_to_site = NULLCP; + (void) rts_end(); + if (rts_start() != OK) { + delivery_setallstate (int_Qmgr_status_mtaFailure, + "Connection failed"); + return NOTOK; + } + connected_to_site = strdup (current_mta); + } + return OK; +} + + + + +static int rts_start () +{ + RtsParams *rp; + int retcode, i; + + for (i = 0; i < MAXTRIES; i++) { + if ((rp = tb_rtsparams (mychan -> ch_table, current_mta)) + == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't find connect information for %s", + current_mta)); + return NOTOK; + } + + conn_type = rp -> type; + trace_type = rp -> trace_type; + if (conn_type == RTSP_1984 || conn_type == RTSP_1988_X410MODE) + retcode = rts_start84 (rp); + else + retcode = rts_start88 (rp); + switch (retcode) { + case NOTOK: + if (rp -> try_next) { + free (current_mta); + current_mta = strdup (rp -> try_next); + continue; + } + break; + case OK: + if (fix_orig) + free (fix_orig); + if (rp -> fix_orig) + fix_orig = strdup (rp -> fix_orig); + else fix_orig = NULLCP; + RPfree (rp); + break; + } + break; + } + return retcode; +} + + + + +static int rts_start84 (rp) +RtsParams *rp; +{ + struct type_MTA_MTABindArgument *mtabind; + struct type_MTA_MTABindResult *mtaresult; + PE pe; + struct RtSAPaddr rtsapto, rtsapfrom; + struct RtSAPaddr *rtto = &rtsapto, *rtfrom = &rtsapfrom; + struct RtSAPconnect rtcs, *rtc = &rtcs; + struct RtSAPindication rtis, *rti = &rtis; + struct RtSAPabort *rta = & rti -> rti_abort; + struct SSAPaddr *sa; + + + if ((sa = str2saddr (rp -> their_address)) == NULLSA) { + PP_LOG (LLOG_EXCEPTIONS, ("BAD address in table, %s for %s", + rp -> their_address, current_mta)); + return NOTOK; + } + rtto -> rta_addr = *sa; /* struct copy */ + rtto -> rta_port = rp -> type == RTSP_1984 ? 1 : 12; + + if (rp -> our_address) { + if ((sa = str2saddr (rp -> our_address)) == NULLSA) { + PP_LOG (LLOG_EXCEPTIONS, + ("Bad address in table, %s for us!", + rp -> our_address)); + return NOTOK; + } + rtfrom -> rta_addr = *sa; /* struct copy */ + rtfrom -> rta_port = rtto -> rta_port; + } + else rtfrom = NULL; + + if ((mtabind = convert_prms (rp)) == NULL) + return NOTOK; + + if (encode_MTA_MTABindArgument (&pe, 1, 0, NULLCP, mtabind) == NOTOK) { + free_MTA_MTABindArgument (mtabind); + return NOTOK; + } + + PP_PDUP (MTA_MTABindArgument, pe, "MTA.BindArgument", PDU_WRITE); + + PP_NOTICE (("Connecting (RTS 84 mode) to site %s", current_mta)); + + if (RtBeginRequest2 (rtto, rtfrom, rp->rts_mode, RTS_INITIATOR, + pe, rtc, rti) == NOTOK) { + rts_advise (rta, "RT-BEGIN.REQUEST"); + RTAFREE (rta); + pe_free (pe); + free_MTA_MTABindArgument (mtabind); + return NOTOK; + } + + pe_free (pe); + free_MTA_MTABindArgument (mtabind); + + if (rtc -> rtc_result != RTS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, ("Association rejected: [%s]", + RtErrString (rtc -> rtc_result))); + free_MTA_MTABindResult (mtabind); + RTCFREE (rtc); + return NOTOK; + } + + + PP_PDUP (MTA_MTABindResult, rtc -> rtc_data, + "MTA.BindResult", PDU_READ); + + if (decode_MTA_MTABindResult (rtc -> rtc_data, 1, NULLIP, + NULLVP, &mtaresult) + == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't decode result [%s]", PY_pepy)); + RTCFREE (rtc); + return NOTOK; + } + + + rts_sd = rtc -> rtc_sd; + + RTCFREE (rtc); + + if (check_params (rp, mtaresult) != OK) { + rts_end (); + rts_sd = NOTOK; + return NOTOK; + } + + PP_NOTICE (("Connected sucessfully")); + return OK; +} + + + + +static int rts_start88 (rp) +RtsParams *rp; +{ + struct type_Trans_Bind1988Argument *mtabind; + struct type_Trans_Bind1988Result *bindresult; + PE pe; + struct PSAPaddr pa_tos, pa_froms; + struct PSAPaddr *pa_to, *pa_from; + struct PSAPctxlist pcs; + struct PSAPctxlist *pc = &pcs; + OID a_ctx, r_ctx, m_ctx, t_ctx; + struct RtSAPconnect rtcs, *rtc = &rtcs; + struct RtSAPindication rtis, *rti = &rtis; + struct RtSAPabort *rta = &rti -> rti_abort; + int n; + + if ((mtabind = convert_prms (rp)) == NULL) + return NOTOK; + + if (encode_Trans_Bind1988Argument (&pe, 1, 0, + NULLCP, mtabind) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("encode failed [%s]", PY_pepy)); + free_Trans_Bind1988Argument (mtabind); + return NOTOK; + } + + PP_PDUP (Trans_Bind1988Argument, pe, + "MTA.BindArgument(1988)", PDU_WRITE); + + PP_NOTICE (("Connecting (RTS 88 mode) to site %s", current_mta)); + + if ((pa_to = str2paddr (rp -> their_address)) == NULLPA) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't translate %s", + rp -> their_address)); + free_Trans_Bind1988Argument (mtabind); + pe_free (pe); + return NOTOK; + } + pa_tos = *pa_to; /* struct copy */ + pa_to = &pa_tos; + + if (rp -> our_address) { + if ((pa_from = str2paddr (rp -> our_address)) == NULLPA) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't translate %s", + rp -> our_address)); + free_Trans_Bind1988Argument (mtabind); + pe_free (pe); + return NOTOK; + } + pa_froms = *pa_from; + pa_from = &pa_froms; + } + else + pa_from = NULLPA; + +#define aCSE "2.2.1.0.1" +#define rTSE "2.6.0.2.12" +#define mTSE "2.6.0.2.7" +#define tRANSFER "2.6.0.1.6" + n = 1; + if ((a_ctx = str2oid (aCSE)) == NULLOID) + adios (NULLCP, "No %s object defined", aCSE); + a_ctx = oid_cpy (a_ctx); + pc -> pc_ctx[n-1].pc_id = 2 * n - 1; + pc -> pc_ctx[n-1].pc_asn = oid_cpy (a_ctx); + pc -> pc_ctx[n-1].pc_atn = NULLOID; + n ++; + + if ((r_ctx = str2oid (rTSE)) == NULLOID) + adios (NULLCP, "No %s object defined", rTSE); + r_ctx = oid_cpy (r_ctx); + pc -> pc_ctx[n-1].pc_id = 2 * n - 1; + pc -> pc_ctx[n-1].pc_asn = r_ctx; + pc -> pc_ctx[n-1].pc_atn = NULLOID; + n ++; + + if ((m_ctx = str2oid (mTSE)) == NULLOID) + adios (NULLCP, "No %s object defined", mTSE); + m_ctx = oid_cpy (m_ctx); + pc -> pc_ctx[n-1].pc_id = mctx_id = 2 * n - 1; + pc -> pc_ctx[n-1].pc_asn = m_ctx; + pc -> pc_ctx[n-1].pc_atn = NULLOID; + + pc -> pc_nctx = n; + + if ((t_ctx = str2oid (tRANSFER)) == NULLOID) + adios (NULLCP, "No %s object defined", tRANSFER); + t_ctx = oid_cpy (t_ctx); + + if (RtOpenRequest2 (rp -> rts_mode, RTS_INITIATOR, t_ctx, + NULLAEI, NULLAEI, + pa_from, pa_to, pc, NULLOID, pe, NULLQOS, + oid_cpy (r_ctx), rtc, rti) == NOTOK) { + rts_advise (rta, "RT-OPEN.REQUEST"); + RTAFREE(rta); + return NOTOK; + } + + if (rtc -> rtc_result != RTS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, ("Association rejected: [%s]", + RtErrString (rtc -> rtc_result))); + RTCFREE (rtc); + return NOTOK; + } + rts_sd = rtc -> rtc_sd; + + PP_PDUP (Trans_Bind1988Result, rtc -> rtc_data, + "MTA.BindResult", PDU_READ); + if (decode_Trans_Bind1988Result (rtc -> rtc_data, 1, NULLIP, + NULLVP, &bindresult) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't decode result [%s]", PY_pepy)); + RTCFREE (rtc); + return NOTOK; + } + + if (check_params (rp, bindresult) != OK) { + RTCFREE (rtc); + free_Trans_Bind1988Result (bindresult); + rts_end (); + return NOTOK; + } + RTCFREE (rtc); + free_Trans_Bind1988Result (bindresult); + PP_NOTICE (("Connected Sucessfully")); + return OK; +} + + + + +static struct type_MTA_MTABindArgument *convert_prms (rp) +RtsParams *rp; +{ + struct type_MTA_MTABindArgument *bindarg; + struct member_MTA_11 *mp; + struct type_MTA_InitiatorCredentials *ic; + + bindarg = (struct type_MTA_MTABindArgument *) + smalloc (sizeof *bindarg); + + bindarg -> offset = type_MTA_MTABindArgument_auth; + + bindarg -> un.auth = mp = (struct member_MTA_11 *) + smalloc (sizeof *mp); + + mp -> initiator__name = STR2QB (rp -> our_name); + mp -> initiator__credentials = ic = + (struct type_MTA_InitiatorCredentials *) + smalloc (sizeof *ic); + + ic -> offset = type_MTA_InitiatorCredentials_octetstring; + ic -> un.octetstring = STR2QB (rp -> our_passwd); + + mp -> security__context = NULL; + + return bindarg; +} + + + + +static int check_params (rp, bindresult) +RtsParams *rp; +struct type_MTA_MTABindResult *bindresult; +{ + char *str; + struct member_MTA_12 *mp; + + switch (bindresult -> offset) { + case type_MTA_MTABindResult_auth: + break; + case type_MTA_MTABindResult_no__auth: + default: + PP_LOG (LLOG_EXCEPTIONS, ("Bad result type")); + return NOTOK; + } + + mp = bindresult -> un.auth; + str = qb2str (mp -> responder__name); + if (strcmp (str, rp -> their_name) != 0) { + PP_LOG (LLOG_EXCEPTIONS, ("mta name mismatch %s %s", + str, rp -> their_name)); + free (str); + return NOTOK; + } + + free (str); + switch (mp -> responder__credentials -> offset) { + case type_MTA_ResponderCredentials_ia5string: + str = qb2str (mp -> responder__credentials->un.ia5string); + break; + case type_MTA_ResponderCredentials_octetstring: + str = qb2str (mp -> responder__credentials->un.octetstring); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, ("Not an octet string")); + return NOTOK; + } + + if (isstr (rp -> their_passwd)) { + if (strcmp (str, rp -> their_passwd) != 0) { + PP_LOG (LLOG_EXCEPTIONS, ("passwd mismatch %s %s", + str, rp -> their_passwd)); + free (str); + return NOTOK; + } + } + + free (str); + return OK; +} + + + + +static int rts_transfer_request (type) +int type; +{ + struct RtSAPindication rtis; + register struct RtSAPindication *rti = &rtis; + register struct RtSAPabort *rta = &rti -> rti_abort; + int retval; + + PP_TRACE (("rts_transfer_request()")); + + trans_state = st_init; + + switch (type) { + case MT_PMPDU: + case MT_DMPDU: + if (RtSetDownTrans (rts_sd, rts_downtrans_all, rti) == NOTOK) { + rts_advise (rta, "set DownTrans upcall"); + RTAFREE(rta); + return NOTOK; + } + break; + + default: + case MT_UMPDU: + if (RtSetDownTrans (rts_sd, rts_downtrans_inc, rti) == NOTOK) { + rts_advise (rta, "set DownTrans upcall"); + RTAFREE(rta); + return NOTOK; + } + break; + } + + data_bytes = 0; + timer_start (&data_timer); + if (RtTransferRequest (rts_sd, NULLPE, NOTOK, rti) == NOTOK) { + rts_advise (rta, "RT-TRANSFER.REQUEST"); + if (RTS_FATAL(rta->rta_reason)) + rts_sd = NOTOK; + return retval; + } + + timer_end (&data_timer, data_bytes, "Transfer Completed"); + + PP_NOTICE((">>> Message %s transfered to %s", + this_msgid, current_mta)); + + return OK; +} + + + + +/* ARGSUSED */ +static int rts_downtrans_inc (sd, base, len, size, ssn, ack, rti) +int sd; +char **base; +int *len, + size; +long ssn, + ack; +struct RtSAPindication *rti; +{ + int cc, count; + int n; + char *ptr, *p; + static char *trans_buf; + static int bsize; + static int resetbuf = 0; + int dynamic = 0; + + PP_TRACE (("rts_downtrans_inc (%d, base, len, %d, %ld, %ld, rti)", + sd, size, ssn, ack)); + + if (base == NULLVP) { + PP_DBG (("RT-PLEASE.INDICATION: %d", size)); + return OK; + } + + if (resetbuf) { + resetbuf = 0; + free (trans_buf); + trans_buf = NULLCP; + bsize = 0; + } + + if (trans_buf == NULLCP) { + + if (size == 0) { /* no checkpointing... */ + n = BUFSIZ * 10; + dynamic = 1; + } + else + n = size; + + if ((trans_buf = malloc ((unsigned) n)) == NULL) + return (rtsaplose (rti, RTS_CONGEST, + NULLCP, "out of memory")); + + PP_TRACE (("Selecting block size of %d", n)); + + bsize = n; + } + + if (size > 0 && size < bsize) { + PP_LOG (LLOG_EXCEPTIONS, ("downtrans size decreased...")); + bsize = size; + } + + if (dynamic) { + for (n = bsize, p = trans_buf, count = 0; ;) { + if ((cc = get_more_message (&ptr, n)) == 0) + break; + bcopy (ptr, p, cc); + p += cc; + n -= cc; + count += cc; + + if (n < 1000) { + bsize += BUFSIZ * 10; + n += BUFSIZ * 10; + trans_buf = realloc (trans_buf, + (unsigned)bsize); + p = trans_buf + count; + } + } + + } else { + for (n = bsize, p = trans_buf, count = 0; n > 0;) { + if ((cc = get_more_message (&ptr, n)) == 0) + break; + bcopy (ptr, p, cc); + p += cc; + n -= cc; + count += cc; + } + } + if (dumpp1) + dump2file (trans_buf, count, dumpp1); + if (count == 0) { + *base = NULLCP; + *len = 0; + free (trans_buf); + trans_buf = NULLCP; + dynamic = 0; + return OK; + } + *base = trans_buf; + *len = count; + data_bytes += count; + if (dynamic) resetbuf = 1; + PP_TRACE (("rts_downtrans_inc read %d bytes (%d checkpoint)", + count, bsize)); + + return OK; +} + + + + +static int get_more_message (dptr, dlen) +char **dptr; +int dlen; +{ + static char eoc[3]; + static char *ptr; + static int len = 0, inited = 0; + static char buffer[BUFSIZ * 8]; + char *cp; + int n; + PE pe; + + PP_TRACE (("get_more_message (%d)", dlen)); + if (!inited) { + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_UNIV_EOC); + inited = 3; + (void) pe_flatten (pe, eoc, 1, &inited); + pe_free (pe); + } + + if (len <= 0) { + switch (trans_state) { + case st_init: + cp = buffer; len = 0; + if (conn_type == RTSP_1988_NORMAL) { + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, + PE_CONS_EXTN); + pe -> pe_len = PE_LEN_INDF; + n = sizeof buffer; + (void) pe_flatten (pe, cp, -1, &n); + pe_free (pe); + cp = buffer + n; + len += n; + + pe = int2prim (mctx_id); + n = (sizeof buffer) - len; + (void) pe_flatten (pe, cp, -1, &n); + cp = cp + n; + len += n; + pe_free (pe); + + + pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0); + pe -> pe_len = PE_LEN_INDF; + n = (sizeof buffer) - len; + (void) pe_flatten (pe, cp, -1, &n); + cp = cp + n; + len += n; + pe_free (pe); + } + pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0); + pe -> pe_len = PE_LEN_INDF; + n = (sizeof buffer) - len; + (void) pe_flatten (pe, cp, -1, &n); + len += n; + pe_free (pe); + trans_state = st_hdr; + ptr = buffer; + break; + + case st_hdr: + len = p1_length; + ptr = p1_string; + trans_state = st_bodyinit; + break; + + case st_bodyinit: + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_PRIM_OCTS); + pe -> pe_len = PE_LEN_INDF; + len = sizeof buffer; + (void) pe_flatten (pe, buffer, -1, &len); + pe_free (pe); + ptr = buffer; + open_body (); + trans_state = st_body; + break; + + case st_body: + if ((len = read_body (buffer, sizeof buffer)) != 0) { + ptr = buffer; + break; + } + close_body (); + cp = buffer; + len = 0; + if (conn_type == RTSP_1988_NORMAL) { + bcopy (eoc, cp, 2); + cp += 2; len += 2; + bcopy (eoc, cp, 2); + cp += 2; len += 2; + } + bcopy (eoc, cp, 2); /* end of octet string (contents) */ + cp += 2; len += 2; + bcopy (eoc, cp, 2); /* end of hdr sequence */ + cp += 2; len += 2; + + ptr = buffer; + trans_state = st_end; + break; + + case st_end: + return 0; + } + } + *dptr = ptr; + n = MIN (dlen, len); + len -= n; + ptr += n; + PP_TRACE (("get_more_message returneing %d bytes", n)); + return n; + +} + + + + +static int rts_downtrans_all (sd, base, len, size, ssn, ack, rti) +int sd; +char **base; +int *len, + size; +long ssn, + ack; +struct RtSAPindication *rti; +{ + int n; + static char *trans_buf; + static int bsize; + + PP_TRACE (("rts_downtrans_all (%d, base, len, %d, %ld, %ld, rti)", + sd, size, ssn, ack)); + + if (base == NULLVP) { + PP_DBG (("RT-PLEASE.INDICATION: %d", size)); + return OK; + } + + if (trans_buf == NULLCP) { + + if (size == 0) /* no checkpointing... */ + n = p1_length; + else + n = size; + + if ((trans_buf = malloc ((unsigned) n)) == NULL) + return (rtsaplose (rti, RTS_CONGEST, + NULLCP, "out of memory")); + + PP_TRACE (("Selecting block size of %d", n)); + bsize = n; + } + if (size > 0 && size < bsize) { + PP_LOG (LLOG_EXCEPTIONS, ("downtrans size decreased...")); + bsize = size; + } + + n = MIN(bsize, p1_length); + if (n == 0) { + free(trans_buf); + trans_buf = NULLCP; + *base = NULLCP; + *len = 0; + return OK; + } + *base = p1_ptr; + *len = n; + data_bytes += n; + + p1_ptr += n; + p1_length -= n; + + if (dumpp1) + dump2file (*base, *len, dumpp1); + + return OK; +} + + + + +static char *pe_flatten (pe, buffer, flag, ccp) +PE pe; +char *buffer; +int *ccp; +int flag; +{ + PS ps; + char *cp; + + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "ps_alloc failed"); + if (str_setup (ps, buffer, *ccp, buffer == NULLCP ? 0 : 1) == NOTOK) + adios (NULLCP, "str_setup failed", ps_error (ps -> ps_errno)); + + if (pe2ps_aux (ps, pe, flag) == NOTOK) + adios (NULLCP, "pe2ps failed [%s]", ps_error (ps -> ps_errno)); + *ccp = ps -> ps_ptr - ps -> ps_base; + cp = ps -> ps_base; + ps -> ps_base = NULLCP; + ps_free (ps); + return cp; +} + + + + +static int rts_end () +{ + struct RtSAPindication rtis, *rti = &rtis; + struct RtSAPabort *rta = &rti -> rti_abort; + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + + if (rts_sd == NOTOK) + return DONE; + if (conn_type == RTSP_1988_NORMAL) { + if (RtCloseRequest (rts_sd, ACF_NORMAL, NULLPE, + acr, rti) == NOTOK) { + rts_advise (rta, "RT-CLOSE.REQUEST"); + RTAFREE(rta); + (void) RtUAbortRequest (rts_sd, NULLPE, rti); + return NOTOK; + } + if (!acr -> acr_affirmative) { + (void) RtUAbortRequest (rts_sd, NULLPE, rti); + PP_LOG (LLOG_EXCEPTIONS, + ("release rejected by peer: %d, %d elements", + acr -> acr_reason, acr -> acr_ninfo)); + } + ACRFREE (acr); + } + else { + if (RtEndRequest (rts_sd, rti) == NOTOK) { + rts_advise (rta, "RT-END.REQUEST"); + RTAFREE(rta); + rts_sd = NOTOK; + return NOTOK; + } + } + rts_sd = NOTOK; + return OK; +} + + + + +#ifdef PP_DEBUG +static int dump2file (str, n, file) +char *str; +int n; +char *file; +{ + FILE *fp; + static int once_only = 0; + + if ((fp = fopen (file, once_only ? "a": "w")) == NULL) { + advise (LLOG_NOTICE, NULLCP, file, "Can't open file"); + return; + } + once_only ++; + + fwrite (str, 1, n, fp); + (void) fclose (fp); +} +#endif + + + + +static void open_body () +{ + char filename[MAXPATHLENGTH], + *msgdir = NULLCP; + + if (body_fp) + close_body (); + + if (qid2dir (this_msgid, ad_list, TRUE, &msgdir) == NOTOK) + adios (NULLCP, "Can't find message %s", this_msgid); + + if (rp_isbad (msg_rinit (msgdir))) + adios (NULLCP, "Can't initialise directory %s", msgdir); + + if (rp_isbad (msg_rfile (filename))) + adios (NULLCP, "Can't read file-name"); + + (void) msg_rend (); + + if ((body_fp = fopen (filename, "r")) == NULL) + adios (filename, "Can't open file"); + +} + + + + +static int read_body (buf, size) +char *buf; +int size; +{ + int len, i; + static PE pe = NULLPE; + PE pe2; + char tbuf[BUFSIZ*8]; + + PP_TRACE (("read_body (%d)", size)); + if (pe == NULLPE) + pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_OCTS); + + pe -> pe_len = size; + pe -> pe_len -= ps_get_abs (pe) - size; + for (i = 0; i < 10; i++) { + if (ps_get_abs(pe) <= size) + break; + pe -> pe_len -= 2; + } + if ( i >= 10) + adios (NULLCP, "Can't sort out asn1 length after 10 attempts"); + + if ((len = fread (tbuf, 1, pe -> pe_len, body_fp)) <= 0) { + if (ferror (body_fp)) + adios ("fread", "error on file"); + else if (feof (body_fp)) + return 0; + } + pe2 = oct2prim (tbuf, len); + (void) pe_flatten (pe2, buf, 1, &size); + PP_TRACE (("octet string of length %d returned (%d)", + pe2 -> pe_len, size)); + pe_free (pe2); + return size; +} + + + + +static void close_body () +{ + if (body_fp) + fclose (body_fp); + body_fp = NULL; +} + + + + + +static int construct_msg (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + struct type_Trans_MtsAPDU *p1; + ADDR *ap; + int value; + PE pe; + + switch (build_p1 (qp, recip, &p1, trace_type)) { + case NOTOK: + delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't build P1 information"); + return NOTOK; + case DONE: + for (ap = recip; ap; ap = ap -> ad_next) { + if (!ap -> ad_resp) + continue; + set_1dr (qp, ap -> ad_no, this_msgid, + DRR_UNABLE_TO_TRANSFER, + ub_error_set, + ub_error_string); + } + delivery_setall (int_Qmgr_status_negativeDR); + if (rp_isbad(wr_q2dr (qp, this_msgid))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (encode_MTA_MessageTransferEnvelope (&pe, 1, 0, NULLCP, + p1 -> un.message -> envelope) + == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Error encoding MessageTransferEnvelope [%s]", + PY_pepy)); + pe_free (pe); + free_Trans_MtsAPDU (p1); + return NOTOK; + } + PP_PDUP (MTA_MessageTransferEnvelope, pe, + "MTA.MessageTransferEnvelope", PDU_WRITE); + + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + free_Trans_MtsAPDU (p1); + pe_free (pe); + + return OK; +} + + + + +static int construct_probe (qp, recip) /* XXX */ +Q_struct *qp; +ADDR *recip; +{ + struct type_Trans_MtsAPDU *p1; + ADDR *ap; + PE pe; + + switch (build_probe (qp, recip, &p1, trace_type)) { + case NOTOK: + delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't build P1 information"); + return NOTOK; + case DONE: + for (ap = recip; ap; ap = ap -> ad_next) { + if (!ap -> ad_resp) + continue; + set_1dr (qp, ap -> ad_no, this_msgid, + DRR_UNABLE_TO_TRANSFER, + ub_error_set, + ub_error_string); + } + delivery_setall (int_Qmgr_status_negativeDR); + if (rp_isbad(wr_q2dr (qp, this_msgid))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (encode_Trans_MtsAPDU (&pe, 1, 0, NULLCP, p1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Error encoding MtsAPDU [%s]", PY_pepy)); + if (pe) + pe_free (pe); + free_Trans_MtsAPDU (p1); + return NOTOK; + } + PP_PDUP (Trans_MtsAPDU, pe, "MTA.MtsAPDU", PDU_WRITE); + + if (conn_type == RTSP_1988_NORMAL) { + PE pe_ext, pe2; + if ((pe_ext = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, + PE_CONS_EXTN)) == NULLPE || + (pe2 = int2prim (mctx_id)) == NULLPE || + seq_add (pe_ext, pe2, NOTOK) == NOTOK || + (pe2 = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0)) == NULLPE) + return NOTOK; + pe2 -> pe_cons = pe; + if (seq_add (pe_ext, pe2, NOTOK) == NOTOK) + return NOTOK; + pe = pe_ext; + } + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + + free_Trans_MtsAPDU (p1); + pe_free (pe); + + return OK; +} + + + + +static struct type_MTA_Content *get_dr_content (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + char *dir; + char filename[MAXPATHLENGTH]; + char buf[MAXPATHLENGTH]; + struct type_MTA_Content *qb, *qbh; + int fd; + struct stat st; + + if (qid2dir (this_msgid, qp->Oaddress, TRUE, &dir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("qid2dir can't find DR content")); + return NULL; + } + if (msg_rinit (dir) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_rinit failed")); + return NULL; + } + if (msg_rfile (filename) != RP_OK) { + PP_LOG (LLOG_EXCEPTIONS, ("msg_file failed")); + return NULL; + } + if (msg_rfile(buf) != RP_DONE) { + PP_LOG (LLOG_EXCEPTIONS, ("Extra message component - expecting only one")); + return NULL; + } + msg_rend (); + + if ((fd = open (filename, O_RDONLY, 0)) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, filename, ("Cant open")); + return NULL; + } + if (fstat (fd, &st) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, filename, ("Can't fstat")); + (void) close (fd); + return NULL; + } + qb = (struct type_MTA_Content *) smalloc (st.st_size + sizeof(*qb)); + qb -> qb_data = qb -> qb_base; + if (read (fd, qb->qb_data, st.st_size) != st.st_size) { + PP_SLOG (LLOG_EXCEPTIONS, "read", ("failed")); + (void) close (fd); + return NULL; + } + qb -> qb_len = st.st_size; + (void) close(fd); + qbh = str2qb (NULLCP, 0, 0); + insque(qb, qbh); + return qbh; +} + + + + +static int construct_dr (qp, recip) +Q_struct *qp; +ADDR *recip; +{ + static DRmpdu drs; + DRmpdu *dr = &drs; + struct type_Trans_MtsAPDU *p1dr; + PE pe = NULLPE; + struct type_MTA_Content *qb = NULL; + ADDR *ap; + + dr_free (dr); + if (rp_isbad (get_dr (recip -> ad_no, this_msgid, dr))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't read delivery report for %s/%d", + this_msgid, recip -> ad_no)); + delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read DR"); + return NOTOK; + } + if (qp -> content_return_request == TRUE) + qb = get_dr_content (qp, recip); + + switch (build_dr (qp, recip, dr, qb, &p1dr, trace_type)) { + case NOTOK: + delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't build P1 information"); + return NOTOK; + case DONE: + for (ap = recip; ap; ap = ap -> ad_next) { + if (!ap -> ad_resp) + continue; + set_1dr (qp, ap -> ad_no, this_msgid, + DRR_UNABLE_TO_TRANSFER, + ub_error_set, + ub_error_string); + } + delivery_setall (int_Qmgr_status_negativeDR); + if (rp_isbad(wr_q2dr (qp, this_msgid))) + delivery_resetDRs (int_Qmgr_status_messageFailure); + return NOTOK; + } + if (encode_Trans_MtsAPDU (&pe, 1, 0, NULLCP, + p1dr) + == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Error encoding MtsAPDU [%s]", + PY_pepy)); + if (pe) + pe_free (pe); + free_Trans_MtsAPDU (p1dr); + return NOTOK; + } + PP_PDUP (Trans_MtsAPDU, pe, + "MTA.MtsAPDU", PDU_WRITE); + if (conn_type == RTSP_1988_NORMAL) { + PE pe_ext, pe2; + if ((pe_ext = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, + PE_CONS_EXTN)) == NULLPE || + (pe2 = int2prim (mctx_id)) == NULLPE || + seq_add (pe_ext, pe2, NOTOK) == NOTOK || + (pe2 = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0)) == NULLPE) + return NOTOK; + pe2 -> pe_cons = pe; + if (seq_add (pe_ext, pe2, NOTOK) == NOTOK) + return NOTOK; + pe = pe_ext; + PP_TRACE(("External wrapper in place")); + } + + p1_length = 0; + p1_string = p1_ptr = pe_flatten (pe, NULLCP, 1, &p1_length); + + free_Trans_MtsAPDU (p1dr); + pe_free (pe); + + return OK; +} + + + + +/* --------------------- Rtsping88 Routine ------------------------------- */ + + + + +static int rtsping88 (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + while ((opt = getopt (argc, argv, "c:m:")) != EOF) { + switch (opt) { + case 'c': + chan_name = strdup (optarg); + break; + case 'm': + current_mta = strdup (optarg); + break; + default: + adios (NULLCP, "Illegal option for rts pinging %s", + argv[optind-1]); + } + } + + RTS_PING_88 = TRUE; + + initproc (NULL); + if (attempt_connect() != OK) + PP_NOTICE (("Connection badly terminated")); + else + endproc(); + exit (0); +} diff --git a/Chans/x40088/x400outext.c b/Chans/x40088/x400outext.c new file mode 100644 index 0000000..38262ef --- /dev/null +++ b/Chans/x40088/x400outext.c @@ -0,0 +1,1382 @@ +/* x400outext.c: extension attributes for X400out88 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400outext.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400outext.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400outext.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + + +#include "Trans-types.h" +#include "Ext-types.h" +#include "util.h" +#include "q.h" +#include "adr.h" +#include "dr.h" +#include "or.h" +#include +#include + +struct type_UNIV_UTCTime *build_time (); +struct type_MTA_ORName *build_fullname (); +struct type_MTA_ORName *build_addr (); +struct type_MTA_GlobalDomainIdentifier *build_gdi (); +extern int trace_type; + +#define wrap_up_ext(e, n) \ + (e) = (struct type_MTA_Extensions *) smalloc (sizeof *extl); \ + (e) -> next = NULL; (e) -> ExtensionField = (n); +#define STR2QB(s) str2qb(s, strlen(s), 1) + + +static struct type_MTA_ExtensionType *build_ext_type (ext_int, ext_oid) +int ext_int; +OID ext_oid; +{ + struct type_MTA_ExtensionType *type; + + type = (struct type_MTA_ExtensionType *) smalloc (sizeof *type); + + if (ext_int == EXT_OID_FORM) { + type -> offset = type_MTA_ExtensionType_local; + type -> un.local = oid_cpy (ext_oid); + } else { + type -> offset = type_MTA_ExtensionType_global; + type -> un.global = ext_int; + } + return type; +} + +static struct type_MTA_Criticality *build_crit (cr) +int cr; +{ + char *p; + + p = int2strb (cr, 3); + return strb2bitstr (p, 3, PE_CLASS_UNIV, PE_PRIM_BITS); +} + +static PE build_ext_value (qb) +struct qbuf *qb; +{ + char *cp; + PS ps; + PE pe; + + cp = qb2str(qb); + + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "PS alloc failed"); + + if (str_setup (ps, cp, qb -> qb_len, 1) == NOTOK) + adios (NULLCP, "Can't setup PS stream"); + + if ((pe = ps2pe (ps)) == NULLPE) + adios (NULLCP, "ps2pe failed [%s]", + ps_error (ps -> ps_errno)); + ps_free (ps); + return pe; +} + +static struct type_MTA_Extensions *build_ext_rrp (parm, crit) +int parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_RecipientReassignmentProhibited *value; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_RECIPIENT_REASSIGNMENT_PROHIBITED, + NULLOID); + + if (crit != EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC) + ext -> criticality = build_crit (crit); + else ext -> criticality = NULL; + + value = (struct type_Ext_RecipientReassignmentProhibited *) + smalloc (sizeof *value); + value -> parm = parm; + if (encode_Ext_RecipientReassignmentProhibited + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode RecipientReassignmentProhibited value [%s]", PY_pepy); + + PP_PDUP (Ext_RecipientReassignmentProhibited, + ext -> value, "Extensions.RecipientReassignmentProhibited", + PDU_WRITE); + + free_Ext_RecipientReassignmentProhibited (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_dep (parm, crit) +int parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_DLExpansionProhibited *value; + struct type_MTA_Extensions *extl; + + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_DL_EXPANSION_PROHIBITED, + NULLOID); + + if (crit != EXT_DL_EXPANSION_PROHIBITED_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_DLExpansionProhibited *) + smalloc (sizeof *value); + value -> parm = parm; + if (encode_Ext_DLExpansionProhibited + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode DLExpansionProhibited value [%s]", PY_pepy); + + PP_PDUP (Ext_DLExpansionProhibited, + ext -> value, "Extensions.DLExpansionProhibited", + PDU_WRITE); + + free_Ext_DLExpansionProhibited (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_cwlp (parm, crit) +int parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_ConversionWithLossProhibited *value; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_CONVERSION_WITH_LOSS_PROHIBITED, + NULLOID); + + if (crit != EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_ConversionWithLossProhibited *) + smalloc (sizeof *value); + value -> parm = parm; + if (encode_Ext_ConversionWithLossProhibited + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode ConversionWithLossProhibited value [%s]", PY_pepy); + + PP_PDUP (Ext_ConversionWithLossProhibited, + ext -> value, "Extensions.ConversionWithLossProhibited", + PDU_WRITE); + + free_Ext_ConversionWithLossProhibited (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_lt (parm, crit) +UTC parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_LatestDeliveryTime *value; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_LATEST_DELIVERY_TIME, + NULLOID); + + if (crit != EXT_LATEST_DELIVERY_TIME_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = build_time (parm); + + if (encode_Ext_LatestDeliveryTime + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode LatestDeliveryTime value [%s]", PY_pepy); + + PP_PDUP (Ext_LatestDeliveryTime, + ext -> value, "Extensions.LatestDeliveryTime", + PDU_WRITE); + +/* free_Ext_LatestDeliveryTime (value); too early */ + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_ora (parm, crit) +FullName *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_OriginatorReturnAddress *value; + struct type_MTA_ORName *orn; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_ORIGINATOR_RETURN_ADDRESS, + NULLOID); + + if (crit != EXT_ORIGINATOR_RETURN_ADDRESS_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + orn = build_addr (parm -> fn_addr); + value = (struct type_Ext_OriginatorReturnAddress *) + smalloc (sizeof *value); + value -> standard__attributes = orn -> standard__attributes; + orn -> standard__attributes = NULL; + value -> domain__defined__attributes = orn -> domain__defined; + orn -> domain__defined = NULL; + value -> extension__attributes = orn -> extension__attributes; + orn -> extension__attributes = NULL; + free_MTA_ORName (orn); + + if (encode_Ext_OriginatorReturnAddress + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode OriginatorReturnAddress value [%s]", PY_pepy); + + PP_PDUP (Ext_OriginatorReturnAddress, + ext -> value, "Extensions.OriginatorReturnAddress", + PDU_WRITE); + +/* free_Ext_OriginatorReturnAddress (value); too early */ + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_oc (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_ORIGINATOR_CERTIFICATE, + NULLOID); + + if (crit != EXT_ORIGINATOR_CERTIFICATE_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_OriginatorCertificate, + ext -> value, "Extensions.OriginatorCertificate", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_ai (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER, + NULLOID); + + if (crit != EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_ContentConfidentialityAlgorithmIdentifier, + ext -> value, "Extensions.ContentConfidentialityAlgorithmIdentifier", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_moac (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK, + NULLOID); + + if (crit != EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_MessageOriginAuthenticationCheck, + ext -> value, "Extensions.MessageOriginAuthenticationCheck", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_poac (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK, + NULLOID); + + if (crit != EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_ProbeOriginAuthenticationCheck, + ext -> value, "Extensions.ProbeOriginAuthenticationCheck", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + + +static struct type_MTA_Extensions *build_ext_sl (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_MESSAGE_SECURITY_LABEL, + NULLOID); + + if (crit != EXT_MESSAGE_SECURITY_LABEL_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_MessageSecurityLabel, + ext -> value, "Extensions.MessageSecurityLabel", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_cc (parm, crit) +struct qbuf *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_CONTENT_CORRELATOR, + NULLOID); + + if (crit != EXT_CONTENT_CORRELATOR_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_ContentCorrelator, + ext -> value, "Extensions.ContentCorrelator", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_Ext_DLExpansionHistory * build_dehl (dlh) +DLHistory *dlh; +{ + struct type_Ext_DLExpansionHistory *dlist = NULL, **dp; + struct type_Ext_DLExpansion *d; + + dp = &dlist; + for (;dlh; dlh = dlh -> dlh_next) { + *dp = (struct type_Ext_DLExpansionHistory *) + smalloc (sizeof **dp); + (*dp) -> next = NULL; + d = (*dp) -> DLExpansion = + (struct type_Ext_DLExpansion *) + smalloc (sizeof *d); + d -> address = build_addr (dlh -> dlh_addr); + d -> dl__expansion__time = build_time (dlh -> dlh_time); + dp = &(*dp) -> next; + } + return dlist; +} + +static struct type_MTA_Extensions *build_ext_dl (parm, crit) +DLHistory *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_DLExpansionHistory *value; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_DL_EXPANSION_HISTORY, + NULLOID); + + if (crit != EXT_DL_EXPANSION_HISTORY_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = build_dehl (parm); + + if (encode_Ext_DLExpansionHistory + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode DLExpansionHistory value [%s]", PY_pepy); + + PP_PDUP (Ext_DLExpansionHistory, + ext -> value, "Extensions.DLExpansionHistory", + PDU_WRITE); + + free_Ext_DLExpansionHistory (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_Ext_MTASuppliedInformation * build_msi (dp) +DomSupInfo *dp; +{ + struct type_Ext_MTASuppliedInformation *msi; + + msi = (struct type_Ext_MTASuppliedInformation *) + calloc (1, sizeof *msi); + if (dp -> dsi_time) + msi -> arrival__time = build_time (dp -> dsi_time); + msi -> routing__action = (struct type_MTA_RoutingAction *) + smalloc (sizeof *msi -> routing__action); + msi -> routing__action -> parm = dp -> dsi_action; + + if (dp -> dsi_attempted_mta || + (dp -> dsi_attempted_md.global_Country && + dp -> dsi_attempted_md.global_Admin)) { + msi -> attempted = (struct choice_Ext_1 *) + calloc (1, sizeof *msi -> attempted); + if (dp -> dsi_attempted_mta) { + msi -> attempted -> offset = + choice_Ext_1_mta; + msi -> attempted -> un.mta = + STR2QB (dp -> dsi_attempted_mta); + } + else { + msi -> attempted -> offset = + choice_Ext_1_domain; + msi -> attempted -> un.domain = + build_gdi (&dp -> dsi_attempted_md); + } + } + + if (dp -> dsi_deferred) + msi -> deferred__time = build_time (dp -> dsi_deferred); + if (dp -> dsi_other_actions) { + msi -> other__actions = + pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, + PE_PRIM_BITS); + if (dp -> dsi_other_actions & ACTION_REDIRECTED) + bit_on (msi -> other__actions, + bit_MTA_OtherActions_redirected); + if (dp -> dsi_other_actions & ACTION_EXPANDED) + bit_on (msi -> other__actions, + bit_MTA_OtherActions_dl__operation); + } + return msi; +} + + +static struct type_Ext_InternalTraceInformation *build_inttrace (tp) +Trace *tp; +{ + struct type_Ext_InternalTraceInformation *tlist = NULL, **tpp; + struct type_Ext_InternalTraceInformationElement *ti; + Trace *tlast; + + if (trace_type == RTSP_TRACE_ADMD || + trace_type == RTSP_TRACE_NOINT) + return NULL; + + for (tlast = tp; tlast && tlast -> trace_next; + tlast = tlast -> trace_next) + continue; + + tpp = &tlist; + for (; tp; tp = tp -> trace_next) { + if (tp -> trace_mta == NULLCP) + continue; + if (trace_type == RTSP_TRACE_LOCALINT && + !same_prmd (tlast, tp)) + continue; + *tpp = (struct type_Ext_InternalTraceInformation *) + smalloc (sizeof **tpp); + (*tpp) -> next = NULL; + ti = (*tpp) -> InternalTraceInformationElement = + (struct type_Ext_InternalTraceInformationElement *) + calloc (1, sizeof *ti); + ti -> global__domain__identifier = + build_gdi (&tp -> trace_DomId); + ti -> mta__name = STR2QB (tp -> trace_mta); + + ti -> mta__supplied__information = + build_msi (&tp -> trace_DomSinfo); + tpp = &(*tpp) -> next; + } + return tlist; +} + +static struct type_MTA_Extensions *build_ext_iti (parm, crit) +Trace *parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_Ext_InternalTraceInformation *value; + struct type_MTA_Extensions *extl; + PE pe; + + value = build_inttrace (parm); + if (value == NULL) + return NULL; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_INTERNAL_TRACE_INFORMATION, + NULLOID); + + if (crit != EXT_INTERNAL_TRACE_INFORMATION_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + + if (encode_Ext_InternalTraceInformation + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode InternalTraceInformation value [%s]", PY_pepy); + + PP_PDUP (Ext_InternalTraceInformation, + ext -> value, "Extensions.InternalTraceInformation", + PDU_WRITE); + pe = pe_cpy (ext->value); + pe_free (ext->value); + ext -> value = pe; + + free_Ext_InternalTraceInformation (value); + + wrap_up_ext (extl, ext); + return extl; +} + + +static struct type_MTA_Extensions *build_ext_posr (parm, crit) +int parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_ProofOfSubmissionRequest *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PROOF_OF_SUBMISSION_REQUEST, NULLOID); + + ext -> criticality = build_crit (crit); + + value = (struct type_Ext_ProofOfSubmissionRequest *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_ProofOfSubmissionRequest + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode ProofOfSubmissionRequest value [%s]", + PY_pepy); + PP_PDUP (Ext_ProofOfSubmissionRequest, + ext -> value, "Extensions.ProofOfSubmissionRequest", + PDU_WRITE); + + free_Ext_ProofOfSubmissionRequest (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_ext_forw_req (parm, crit) +int parm; +char crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_SequenceNumber *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_FORWARDING_REQUEST, NULLOID); + + ext -> criticality = build_crit (crit); + + value = (struct type_Ext_SequenceNumber *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_SequenceNumber + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode forwarding request value [%s]", + PY_pepy); + PP_PDUP (Ext_SequenceNumber, + ext -> value, "Extensions.SequenceNumber", + PDU_WRITE); + + free_Ext_SequenceNumber (value); + + wrap_up_ext (extl, ext); + return extl; +} + + +static struct type_MTA_ExtensionField *build_extension (ext) +X400_Extension *ext; +{ + struct type_MTA_ExtensionField *ep; + + ep = (struct type_MTA_ExtensionField *) smalloc (sizeof *ep); + ep -> type = build_ext_type (ext -> ext_int, ext -> ext_oid); + ep -> criticality = build_crit (ext -> ext_criticality); + ep -> value = build_ext_value (ext -> ext_value); + return ep; +} + +struct type_MTA_Extensions *build_pm_extensions (qp,p1,msg) +Q_struct *qp; +int p1,msg; +{ + struct type_MTA_Extensions *ext = NULL, **ep; + X400_Extension *pp_exp; + + ep = &ext; + for (pp_exp = qp -> per_message_extensions; pp_exp; pp_exp = pp_exp -> ext_next) { + *ep = (struct type_MTA_Extensions *) + smalloc (sizeof *ep); + (*ep) -> next = NULL; + (*ep) -> ExtensionField = build_extension (pp_exp); + ep = &(*ep) -> next; + } + if (qp -> recip_reassign_prohibited) { + *ep = build_ext_rrp (qp -> recip_reassign_prohibited, + qp -> recip_reassign_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> dl_expansion_prohibited) { + *ep = build_ext_dep (qp -> dl_expansion_prohibited, + qp -> dl_expansion_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> conversion_with_loss_prohibited) { + *ep = build_ext_cwlp (qp -> conversion_with_loss_prohibited, + qp -> conversion_with_loss_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> originator_certificate) { + *ep = build_ext_oc (qp -> originator_certificate, + qp -> originator_certificate_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> security_label) { + *ep = build_ext_sl (qp -> security_label, + qp -> security_label_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> general_content_correlator) { + *ep = build_ext_cc (qp -> general_content_correlator, + qp -> content_correlator_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (msg) { + if (qp -> latest_time) { + *ep = build_ext_lt (qp -> latest_time, + qp -> latest_time_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> originator_return_address) { + *ep = build_ext_ora (qp -> originator_return_address, + qp -> originator_return_address_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> algorithm_identifier) { + *ep = build_ext_ai (qp -> algorithm_identifier, + qp -> algorithm_identifier_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> message_origin_auth_check) { + *ep = build_ext_moac (qp -> message_origin_auth_check, + qp -> message_origin_auth_check_crit); + if (*ep) + ep = &(*ep) -> next; + } + } + if (!msg) { + if (qp -> message_origin_auth_check) { + *ep = build_ext_poac (qp -> message_origin_auth_check, + qp -> message_origin_auth_check_crit); + if (*ep) + ep = &(*ep) -> next; + } + } + if (p1) { + if (qp -> dl_expansion_history) { + *ep = build_ext_dl (qp -> dl_expansion_history, + qp -> dl_expansion_history_crit); + if (*ep) + ep = &(*ep) -> next; + } + + if (qp -> trace) { + *ep = build_ext_iti (qp -> trace, + EXT_INTERNAL_TRACE_INFORMATION_DC); + if (*ep) + ep = &(*ep) -> next; + } + } + if ((!p1) && msg) { + if (qp -> forwarding_request != NOTOK) { + *ep = build_ext_forw_req(qp -> forwarding_request, + qp -> forwarding_request_crit); + if (*ep) + ep = &(*ep) -> next; + } + if (qp -> proof_of_submission_request) { + *ep = build_ext_posr(qp -> proof_of_submission_request,qp -> proof_of_submission_crit); + if (*ep) + ep = &(*ep) -> next; + } + } + return ext; +} + + + +static struct type_MTA_Extensions *build_aext_oraa (parm, crit) +char *parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_OriginatorRequestedAlternateRecipient *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_ORIGINATOR_RETURN_ADDRESS, NULLOID); + + if (crit != EXT_ORIGINATOR_RETURN_ADDRESS_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = build_addr (parm); + + if (encode_Ext_OriginatorRequestedAlternateRecipient + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode OriginatorRequestedAlternateRecipient value [%s]", + PY_pepy); + PP_PDUP (Ext_OriginatorRequestedAlternateRecipient, + ext -> value, "Extensions.OriginatorRequestedAlternateRecipient", + PDU_WRITE); + + free_Ext_OriginatorRequestedAlternateRecipient (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_rdm (parm, crit) +int parm[AD_RDM_MAX]; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_RequestedDeliveryMethod *value, **vp; + int i; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_REQUESTED_DELIVERY_METHOD, NULLOID); + + if (crit != EXT_REQUESTED_DELIVERY_METHOD_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = NULL; + vp = &value; + + for (i = 0; i < AD_RDM_MAX && parm[i] != AD_RDM_NOTUSED; i++) { + *vp = (struct type_Ext_RequestedDeliveryMethod *) + smalloc (sizeof **vp); + (*vp) -> element_Ext_0 = parm[i]; + (*vp) -> next = NULL; + vp = &(*vp) -> next; + } + + if (encode_Ext_RequestedDeliveryMethod + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode RequestedDeliveryMethod value [%s]", + PY_pepy); + PP_PDUP (Ext_RequestedDeliveryMethod, + ext -> value, "Extensions.RequestedDeliveryMethod", + PDU_WRITE); + + free_Ext_RequestedDeliveryMethod (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_pf (parm, crit) +char parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_PhysicalForwardingProhibited *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PHYSICAL_FORWARDING_PROHIBITED, + NULLOID); + + if (crit != EXT_PHYSICAL_FORWARDING_PROHIBITED_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_PhysicalForwardingProhibited *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_PhysicalForwardingProhibited + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode PhysicalForwardingProhibited value [%s]", + PY_pepy); + PP_PDUP (Ext_PhysicalForwardingProhibited, + ext -> value, "Extend.PhysicalForwardingProhibited", + PDU_WRITE); + + free_Ext_PhysicalForwardingProhibited (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_pfar (parm, crit) +int parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_PhysicalForwardingAddressRequest *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST, NULLOID); + + if (crit != EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_PhysicalForwardingAddressRequest*) + smalloc (sizeof *value); + + value -> parm = parm; + + if (encode_Ext_PhysicalForwardingAddressRequest + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode PhysicalForwardingAddressRequest value [%s]", + PY_pepy); + PP_PDUP (Ext_PhysicalForwardingAddressRequest, + ext -> value, "Extensions.PhysicalForwardingAddressRequest", + PDU_WRITE); + + free_Ext_PhysicalForwardingAddressRequest (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_pdm (parm, crit) +int parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_PhysicalDeliveryModes *value; + char *p; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PHYSICAL_DELIVERY_MODES, NULLOID); + + if (crit != EXT_PHYSICAL_DELIVERY_MODES_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + p = int2strb (parm, 8); + value = strb2bitstr (p, 8, PE_CLASS_UNIV, PE_PRIM_BITS); + + if (encode_Ext_PhysicalDeliveryModes + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode PhysicalDeliveryModes value [%s]", + PY_pepy); + PP_PDUP (Ext_PhysicalDeliveryModes, + ext -> value, "Extensions.PhysicalDeliveryModes", + PDU_WRITE); + + free_Ext_PhysicalDeliveryModes (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_rmt (parm, crit) +int parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_RegisteredMailType *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_REGISTERED_MAIL, NULLOID); + + if (crit != EXT_REGISTERED_MAIL_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_RegisteredMailType *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_RegisteredMailType + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode RegisteredMailType value [%s]", + PY_pepy); + PP_PDUP (Ext_RegisteredMailType, + ext -> value, "Extensions.RegisteredMailType", + PDU_WRITE); + + free_Ext_RegisteredMailType (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_rnfa (parm, crit) +char *parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_RecipientNumberForAdvice *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_RECIPIENT_NUMBER_FOR_ADVICE, NULLOID); + + if (crit != EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = STR2QB (parm); + + if (encode_Ext_RecipientNumberForAdvice + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode RecipientNumberForAdvice value [%s]", + PY_pepy); + PP_PDUP (Ext_RecipientNumberForAdvice, + ext -> value, "Extensions.RecipientNumberForAdvice", + PDU_WRITE); + + free_Ext_RecipientNumberForAdvice (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_pra (parm, crit) +OID parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_PhysicalRenditionAttributes *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PHYSICAL_RENDITION_ATTRIBUTES, + NULLOID); + + if (crit != EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = oid_cpy (parm); + + if (encode_Ext_PhysicalRenditionAttributes + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode PhysicalRenditionAttributes value [%s]", + PY_pepy); + PP_PDUP (Ext_PhysicalRenditionAttributes, + ext -> value, "Extensions.PhysicalRenditionAttributes", + PDU_WRITE); + + free_Ext_PhysicalRenditionAttributes (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_pdrr (parm, crit) +int parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_PhysicalDeliveryReportRequest *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PHYSICAL_DELIVERY_REPORT_REQUEST, NULLOID); + + if (crit != EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_PhysicalDeliveryReportRequest *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_PhysicalDeliveryReportRequest + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode PhysicalDeliveryReportRequest value [%s]", + PY_pepy); + PP_PDUP (Ext_PhysicalDeliveryReportRequest, + ext -> value, "Extensions.PhysicalDeliveryReportRequest", + PDU_WRITE); + + free_Ext_PhysicalDeliveryReportRequest (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_mt (parm, crit) +struct qbuf *parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_MESSAGE_TOKEN, NULLOID); + + if (crit != EXT_MESSAGE_TOKEN_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + ext -> value = build_ext_value (parm); + PP_PDUP (Ext_MessageToken, + ext -> value, "Extensions.MessageToken", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_cic (parm, crit) +struct qbuf *parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_CONTENT_INTEGRITY_CHECK, NULLOID); + + if (crit != EXT_CONTENT_INTEGRITY_CHECK_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + ext -> value = build_ext_value (parm); + + PP_PDUP (Ext_ContentIntegrityCheck, + ext -> value, "Extensions.ContentIntegrityCheck", + PDU_WRITE); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_MTA_Extensions *build_aext_podr (parm, crit) +int parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_ProofOfDeliveryRequest *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_PROOF_OF_DELIVERY_REQUEST, NULLOID); + + if (crit != EXT_PROOF_OF_DELIVERY_REQUEST_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = (struct type_Ext_ProofOfDeliveryRequest *) + smalloc (sizeof *value); + value -> parm = parm; + + if (encode_Ext_ProofOfDeliveryRequest + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode ProofOfDeliveryRequest value [%s]", + PY_pepy); + PP_PDUP (Ext_ProofOfDeliveryRequest, + ext -> value, "Extensions.ProofOfDeliveryRequest", + PDU_WRITE); + + free_Ext_ProofOfDeliveryRequest (value); + + wrap_up_ext (extl, ext); + return extl; +} + +static struct type_Ext_RedirectionHistory *build_redir (redir) +Redirection *redir; +{ + struct type_Ext_RedirectionHistory *rlist, **rp; + struct type_Ext_Redirection *rd; + + rlist = NULL; + rp = &rlist; + for ( ; redir; redir = redir -> rd_next) { + *rp = (struct type_Ext_RedirectionHistory *) + smalloc (sizeof **rp); + (*rp) -> next = NULL; + (*rp) -> Redirection = rd = + (struct type_Ext_Redirection *) + smalloc (sizeof *rd); + rd -> intended__recipient__name = + (struct type_Ext_IntendedRecipientName *) + smalloc (sizeof *rd -> intended__recipient__name); + rd -> intended__recipient__name -> address = + build_addr (redir -> rd_addr); + rd -> intended__recipient__name -> redirection__time = + build_time (redir -> rd_time); + + rd -> redirection__reason = + (struct type_Ext_RedirectionReason *) + smalloc (sizeof *rd -> redirection__reason); + rd -> redirection__reason -> parm = redir -> rd_reason; + + } + return rlist; +} + +static struct type_MTA_Extensions *build_aext_rh (parm, crit) +Redirection *parm; +int crit; +{ + struct type_MTA_ExtensionField *ext; + struct type_MTA_Extensions *extl; + struct type_Ext_RedirectionHistory *value; + + ext = (struct type_MTA_ExtensionField *) smalloc (sizeof *ext); + + ext -> type = build_ext_type (EXT_REDIRECTION_HISTORY, NULLOID); + + if (crit != EXT_REDIRECTION_HISTORY_DC) + ext -> criticality = build_crit (crit); + else + ext -> criticality = NULL; + + value = build_redir (parm); + + if (encode_Ext_RedirectionHistory + (&ext -> value, 1, 0, NULLCP, value) == NOTOK) + adios (NULLCP, "Can't encode RedirectionHistory value [%s]", + PY_pepy); + PP_PDUP (Ext_RedirectionHistory, + ext -> value, "Extensions.RedirectionHistory", + PDU_WRITE); + + free_Ext_RedirectionHistory (value); + + wrap_up_ext (extl, ext); + return extl; +} + +struct type_MTA_Extensions *build_prf_ext (ad,p1,msg) +ADDR *ad; +int p1,msg; +{ + X400_Extension *pp_ext; + struct type_MTA_Extensions *extl, **ep; + +#define bump(x) if (*(x)) (x) = &(*x) -> next + extl = NULL; + ep = &extl; + for (pp_ext = ad -> ad_per_recip_ext_list; pp_ext; + pp_ext = pp_ext -> ext_next) { + *ep = (struct type_MTA_Extensions *) + smalloc (sizeof *ep); + (*ep) -> next = NULL; + (*ep) -> ExtensionField = build_extension (pp_ext); + bump(ep); + } + if (ad -> ad_orig_req_alt) { + *ep = build_aext_oraa (ad -> ad_orig_req_alt, + ad -> ad_orig_req_alt_crit); + bump(ep); + } + if (ad -> ad_req_del[0] != AD_RDM_NOTUSED) { + *ep = build_aext_rdm (ad -> ad_req_del, + ad -> ad_req_del_crit); + bump(ep); + } + if (ad -> ad_phys_rendition_attribs) { + *ep = build_aext_pra (ad -> ad_phys_rendition_attribs, + ad -> ad_phys_rendition_attribs_crit); + bump(ep); + } + if (msg) { + if (ad -> ad_phys_forward) { + *ep = build_aext_pf (ad -> ad_phys_forward, + ad -> ad_phys_forward_crit); + bump(ep); + } + if (ad -> ad_phys_fw_ad_req) { + *ep = build_aext_pfar (ad -> ad_phys_fw_ad_req, + ad -> ad_phys_fw_ad_crit); + bump(ep); + } + if (ad -> ad_phys_modes) { + *ep = build_aext_pdm (ad -> ad_phys_modes, + ad -> ad_phys_modes_crit); + bump(ep); + } + + if (ad -> ad_reg_mail_type) { + *ep = build_aext_rmt (ad -> ad_reg_mail_type, + ad -> ad_reg_mail_type_crit); + bump (ep); + } + if (ad -> ad_recip_number_for_advice) { + *ep = build_aext_rnfa (ad -> ad_recip_number_for_advice, + ad -> ad_recip_number_for_advice_crit); + bump (ep); + } + if (ad -> ad_pd_report_request) { + *ep = build_aext_pdrr (ad -> ad_pd_report_request, + ad -> ad_pd_report_request_crit); + bump (ep); + } + if (ad -> ad_message_token) { + *ep = build_aext_mt (ad -> ad_message_token, + ad -> ad_message_token_crit); + bump (ep); + } + if (ad -> ad_content_integrity) { + *ep = build_aext_cic (ad -> ad_content_integrity, + ad -> ad_content_integrity_crit); + bump(ep); + } + if (ad -> ad_proof_delivery) { + *ep = build_aext_podr (ad -> ad_proof_delivery, + ad -> ad_proof_delivery_crit); + bump(ep); + } + } + if (p1) { + if (ad -> ad_redirection_history) { + *ep = build_aext_rh (ad -> ad_redirection_history, + ad -> ad_redirection_history_crit); + bump (ep); + } + } + return extl; +} diff --git a/Chans/x40088/x400topp.c b/Chans/x40088/x400topp.c new file mode 100644 index 0000000..da755aa --- /dev/null +++ b/Chans/x40088/x400topp.c @@ -0,0 +1,2045 @@ +/* x400topp.c: X400(1988) protocol to submit format - inbound */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400topp.c,v 6.0 1991/12/18 20:14:27 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Chans/x40088/RCS/x400topp.c,v 6.0 1991/12/18 20:14:27 jpo Rel $ + * + * $Log: x400topp.c,v $ + * Revision 6.0 1991/12/18 20:14:27 jpo + * Release 6.0 + * + */ + + +#include "Trans-types.h" +#include "Ext-types.h" +#include "util.h" +#include "chan.h" +#include "q.h" +#include "adr.h" +#include "or.h" +#include "prm.h" +#include "dr.h" +#include "retcode.h" +#include + +#define bit_ison(x,y) (bit_test(x,y) == 1) +extern char *undefined_bodyparts; +extern ORName *orname2orn (); +extern char *dn2str (); + +static int load_msgid(), load_addr(), load_eits(), load_84eit(), + load_content(), load_pmf(), load_time(), load_recips(), + load_p3_recips(), load_prf_ext(), load_trace(), + make_trace(), load_gdi(), load_reportenv(), load_reportcont(), + load_drc_pr_fields(), load_lasttrace(), load_report(), + load_repe_ext(), load_cont_ext(), load_prr_ext(), + load_fullname(), load_pm_extensions(), do_local_extension(), + ext_decode_dlh(), do_global_extension(), ext_ora(), + ext_inttrace(), decode_1redir(), do_global_ext_prf(), + do_global_repe_prf(), do_global_cont_prf(), do_global_rr_prf(); + +static int rebuild_eits (eits, orig, trace) +EncodedIT *eits, *orig; +Trace *trace; +{ + Trace *tp; + LIST_BPT *lasteit = NULL; + + for (tp = trace; tp; tp = tp -> trace_next) + if (tp -> trace_DomSinfo.dsi_converted.eit_types) + lasteit = tp -> trace_DomSinfo.dsi_converted.eit_types; + if (lasteit) + list_bpt_add (&eits -> eit_types, list_bpt_dup (lasteit)); + else + list_bpt_add (&eits -> eit_types, + list_bpt_dup (orig -> eit_types)); + return OK; +} + +static int rebuild_dreits (eits, dr) +EncodedIT *eits; +DRmpdu *dr; +{ + Trace *tp; + Rrinfo *rr; + LIST_BPT *ep; + + for (rr = dr -> dr_recip_list; rr; rr = rr-> rr_next) { + if (rr -> rr_report.rep_type == DR_REP_FAILURE && + rr -> rr_converted) + for (ep = rr -> rr_converted->eit_types; ep; + ep = ep->li_next) + if (list_bpt_find(eits -> eit_types, ep -> li_name) == NULL) + list_bpt_add (&eits -> eit_types, + list_bpt_new (ep->li_name)); + } + return OK; +} + +int load_qstruct (qp, mte) +Q_struct *qp; +struct type_MTA_MessageTransferEnvelope *mte; +{ + int retval; + + if ((retval = load_msgid (&qp->msgid, mte -> message__identifier)) != OK) + return retval; + + if ((retval = load_addr (&qp->Oaddress, mte -> originator__name)) != OK) + return retval; + + if (mte -> original__encoded__information__types && + (retval = load_eits (&qp -> orig_encodedinfo, + mte -> original__encoded__information__types)) != OK) + return retval; + + if ((retval = load_content (qp, mte -> member_MTA_13)) != OK) + return retval; + + if ( mte -> content__identifier && + (qp -> ua_id = qb2str (mte -> content__identifier)) == NULL) + return NOTOK; + + if (mte -> priority) + qp -> priority = mte -> priority -> parm; + + if (mte -> per__message__indicators && + (retval = load_pmf (qp, mte -> per__message__indicators)) != OK) + return retval; + + if (mte -> deferred__delivery__time && + (retval = load_time (&qp -> defertime, mte -> deferred__delivery__time)) != OK) + return retval; + + if (mte -> per__domain__bilateral__information) + PP_LOG (LLOG_EXCEPTIONS, + ("Bilateral Info supplied (ignored)")); + + if ((retval = load_trace (&qp -> trace, mte -> trace__information)) != OK) + return retval; + + + if ((retval = load_recips (&qp -> Raddress, + mte -> per__recipient__fields)) != OK) + return retval; + + if (mte -> extensions && + (retval = load_pm_extensions (qp, mte -> extensions,1,1)) != OK) + return retval; + if ((retval = rebuild_eits (&qp -> encodedinfo, + &qp -> orig_encodedinfo, + qp -> trace)) != OK) + return retval; + + return OK; +} + +int load_probe (qp, probe) +Q_struct *qp; +struct type_Trans_ProbeAPDU *probe; +{ + int retval; + + if ((retval = load_msgid (&qp -> msgid, + probe -> probe__identifier)) != OK || + (retval = load_addr (&qp -> Oaddress, + probe -> originator__name)) != OK) + return retval; + + if (probe -> original__encoded__information__types && + (retval = load_eits (&qp -> orig_encodedinfo, + probe -> original__encoded__information__types)) + != OK) + return retval; + + if ((retval = load_content (qp, probe -> member_MTA_15)) != OK) + return retval; + + if (probe -> content__identifier && + (qp -> ua_id = qb2str (probe -> content__identifier)) == NULL) + return NOTOK; + + if (probe -> content__length) + qp -> msgsize = probe -> content__length -> parm; + + if (probe -> per__message__indicators && + (retval = load_pmf (qp, probe -> per__message__indicators)) != OK) + return retval; + + if (probe -> per__domain__bilateral__information) + PP_LOG (LLOG_EXCEPTIONS, + ("Bilateral Info supplied (ignored)")); + + if ((retval = load_trace (&qp -> trace, + probe -> trace__information)) != OK) + return retval; + + if ((retval = load_recips (&qp -> Raddress, + probe -> per__recipient__fields)) + != OK) + return retval; + + if ((retval = load_pm_extensions (qp, + probe -> extensions,1,0)) != OK || + (retval = rebuild_eits (&qp -> encodedinfo, + &qp -> orig_encodedinfo, + qp -> trace)) != OK) + return retval; + return OK; +} + +int load_dr (qp, dr, report) +Q_struct *qp; +DRmpdu *dr; +struct type_Trans_ReportAPDU *report; +{ + int retval; + + qp -> msgtype = MT_DMPDU; + if ((retval = load_reportenv (qp, dr, report -> envelope)) != OK || + (retval = load_reportcont (qp, dr, report -> content)) != OK || + (rebuild_dreits (&qp -> encodedinfo, dr) != OK)) + return retval; + return OK; +} + +int load_p3_qstruct (qp, mte) +Q_struct *qp; +struct type_MTA_MessageSubmissionEnvelope *mte; +{ + int retval; + + if ((retval = load_addr (&qp->Oaddress, + mte -> originator__name)) != OK) + return retval; + + if (mte -> original__eits) { + if ((retval = load_eits (&qp -> orig_encodedinfo, + mte -> original__eits)) != OK || + (retval = load_eits (&qp -> encodedinfo, + mte -> original__eits)) != OK) + return retval; + } + + if ((retval = load_content (qp, mte -> member_MTA_6)) != OK) + return retval; + + if ( mte -> content__identifier && + (qp -> ua_id = qb2str (mte -> content__identifier)) == NULL) + return NOTOK; + + if (mte -> priority) + qp -> priority = mte -> priority -> parm; + + if (mte -> per__message__indicators && + (retval = load_pmf (qp, mte -> per__message__indicators)) != OK) + return retval; + + if (mte -> deferred__delivery__time && + (retval = load_time (&qp -> defertime, + mte -> deferred__delivery__time)) != OK) + return retval; + + if (mte -> extensions && + (retval = load_pm_extensions (qp, mte -> extensions,0,1)) != OK) + return retval; + + if ((retval = load_p3_recips (&qp -> Raddress, + mte -> per__recipient__fields)) != OK) + return retval; + return OK; +} + +int load_p3_probe (qp, probe) +Q_struct *qp; +struct type_MTA_ProbeSubmissionEnvelope *probe; +{ + int retval; + + if ((retval = load_addr (&qp -> Oaddress, + probe -> originator__name)) != OK) + return retval; + + if (probe -> original__eits) { + if ((retval = load_eits (&qp -> orig_encodedinfo, + probe -> original__eits)) != OK || + (retval = load_eits (&qp -> encodedinfo, /* necessary */ + probe -> original__eits)) != OK) + return retval; + } + + if ((retval = load_content (qp, probe -> member_MTA_7)) != OK) + return retval; + + if (probe -> content__identifier && + (qp -> ua_id = qb2str (probe -> content__identifier)) == NULL) + return NOTOK; + + if (probe -> content__length) + qp -> msgsize = probe -> content__length -> parm; + + if (probe -> per__message__indicators && + (retval = load_pmf (qp, probe -> per__message__indicators)) != OK) + return retval; + + if ((retval = load_p3_recips (&qp -> Raddress, + probe -> per__recipient__fields)) != OK || + (retval = load_prf_ext(&qp, probe -> extensions,0,0)) != OK) + return retval; + return OK; +} + + +static int load_msgid (mid, p1msgid) +MPDUid *mid; +struct type_MTA_MTSIdentifier *p1msgid; +{ + int retval; + + if ((retval = load_gdi (&mid -> mpduid_DomId, + p1msgid -> global__domain__identifier)) != OK) + return retval; + + if((mid -> mpduid_string = + qb2str (p1msgid -> local__identifier)) == NULL) + return NOTOK; + return OK; + +} + +static int decode_ext_orn (value, genp) +char **value; +struct type_MTA_ORName *genp; +{ + ORName *orn; + char buf[BUFSIZ]; + + if ((orn = orname2orn (genp)) == NULL) + return NOTOK; + + or_or2std (orn -> on_or, buf, 0); + *value = strdup(buf); + ORName_free (orn); + return OK; +} + + +static int load_addr (app, orname) +ADDR **app; +struct type_MTA_ORName *orname; +{ + ORName *orn; + char buf[BUFSIZ]; + ADDR *ap; + + if ((orn = orname2orn (orname)) == NULL) + return NOTOK; + + or_or2std (orn -> on_or, buf, 0); + *app = ap = adr_new (buf, AD_X400_TYPE, 1); + ap -> ad_subtype = AD_X400_88; + + if (orn -> on_dn) + ap -> ad_dn = dn2str (orn -> on_dn); + ORName_free (orn); + return OK; +} + +static int load_eits (eit, encinfo) +EncodedIT *eit; +struct type_MTA_EncodedInformationTypes *encinfo; +{ + struct type_MTA_ExternalEncodedInformationTypes *eeit; + LIST_BPT *bpt; + char *str; + int retval; + + if ((retval = load_84eit (eit, + encinfo -> built__in__encoded__information__types)) != OK) + return retval; + + for (eeit = encinfo -> external__encoded__information__types; + eeit; eeit = eeit -> next) { + str = strdup (sprintoid (eeit -> + ExternalEncodedInformationType)); + bpt = list_bpt_new (str); + free (str); + list_bpt_add (&eit->eit_types, bpt); + } + return OK; +} + +static int load_84eit (eit, bieit) /* XXX */ +EncodedIT *eit; +struct type_MTA_BuiltInEncodedInformationTypes *bieit; +{ + char *bs; + int n; + + if (eit == NULL) { + eit = (EncodedIT *) smalloc (sizeof *eit); + bzero ((char *)eit, sizeof *eit); + } + + if ((bs = bitstr2strb (bieit, &n)) == NULLCP) + return NOTOK; + + n = strb2int (bs, n); + free (bs); + enctypes2mem (n, undefined_bodyparts, &eit -> eit_types); + return OK; +} + + +static int load_content (qp, ct) +Q_struct *qp; +struct type_MTA_ContentType *ct; +{ + extern char *cont_p2, *cont_p22, *hdr_p2_bp, *hdr_p22_bp; + struct type_MTA_BuiltInContentType *bict; + LIST_BPT *new; + + if (ct -> offset == type_MTA_ContentType_external) { + qp -> cont_type = strdup(sprintoid (ct -> un.external)); + return OK; + } + + bict = ct -> un.built__in; + + switch (bict -> parm) { + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown content type (%d)")); + /* fall */ + case int_MTA_BuiltInContentType_unidentified: + qp -> cont_type = strdup ("unidentified"); + break; + case int_MTA_BuiltInContentType_external: + qp -> cont_type = strdup ("external"); + break; + case int_MTA_BuiltInContentType_interpersonal__messaging__1984: + qp -> cont_type = strdup (cont_p2); + if ((new = list_bpt_new (hdr_p2_bp)) == NULLIST_BPT) + return NOTOK; + list_bpt_add (&(qp -> encodedinfo.eit_types), new); + break; + case int_MTA_BuiltInContentType_interpersonal__messaging__1988: + qp -> cont_type = strdup (cont_p22); + if ((new = list_bpt_new (hdr_p22_bp)) == NULLIST_BPT) + return NOTOK; + list_bpt_add (&(qp -> encodedinfo.eit_types), new); + break; + } + return OK; +} + +static int load_pmf (qp, pe) +Q_struct *qp; +PE pe; +{ + if (bit_ison (pe, + bit_MTA_PerMessageIndicators_disclosure__of__recipients)) + qp -> disclose_recips = TRUE; + else qp -> disclose_recips = FALSE; + + if (bit_ison (pe, + bit_MTA_PerMessageIndicators_implicit__conversion__prohibited)) + qp -> implicit_conversion_prohibited = TRUE; + else qp -> implicit_conversion_prohibited = FALSE; + + if (bit_ison (pe, bit_MTA_PerMessageIndicators_alternate__recipient__allowed)) + qp -> alternate_recip_allowed = TRUE; + else qp -> alternate_recip_allowed = FALSE; + + if (bit_ison (pe, bit_MTA_PerMessageIndicators_content__return__request)) + qp -> content_return_request = TRUE; + else qp -> content_return_request = FALSE; + + return OK; +} + +static int load_time (utc, utcstr) +UTC *utc; +struct type_UNIV_UTCTime *utcstr; +{ + char *str = qb2str (utcstr); + if (str == NULLCP) + return NOTOK; + *utc = str2utct (str, strlen(str)); + if (*utc == NULLUTC) + return NOTOK; + free (str); + *utc = utcdup (*utc); + return *utc ? OK : NOTOK; +} + +static int load_recips (app, prf) +ADDR **app; +struct element_MTA_4 *prf; +{ + ADDR *ap, *lastap = NULL; + struct type_MTA_PerRecipientMessageTransferFields *prmtf; + int ad_no = 1; + int retval; + + for (; prf; prf = prf -> next) { + prmtf = prf -> PerRecipientMessageTransferFields; + if ((retval = load_addr (&ap, prmtf -> recipient__name)) != OK) + return retval; + if (*app == NULL) + *app = lastap = ap; + else { + lastap -> ad_next = ap; + lastap = ap; + } + ap -> ad_no = ad_no ++; + + ap -> ad_extension = + prmtf -> originally__specified__recipient__number -> + parm; + if (prmtf -> explicit__conversion) + ap -> ad_explicitconversion = + prmtf -> explicit__conversion -> parm; + + if (bit_ison (prmtf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_responsibility)) + ap -> ad_resp = 1; + else ap -> ad_resp = 0; + + ap -> ad_mtarreq = AD_MTA_NONE; + if (bit_ison (prmtf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originating__MTA__report)) + ap -> ad_mtarreq |= AD_MTA_CONFIRM; + + if (bit_ison (prmtf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originating__MTA__non__delivery__report)) + ap -> ad_mtarreq |= AD_MTA_BASIC; + + ap -> ad_usrreq = AD_USR_NOREPORT; + if (bit_ison (prmtf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originator__non__delivery__report)) + ap -> ad_usrreq = AD_USR_BASIC; + + if (bit_ison (prmtf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originator__report)) + ap -> ad_usrreq = AD_USR_CONFIRM; + + + if ((retval = load_prf_ext (ap, prmtf -> extensions,1,1)) != OK) + return retval; + } + return OK; +} + + +static int load_p3_recips (app, prf) +ADDR **app; +struct element_MTA_0 *prf; +{ + ADDR *ap, *lastap = NULL; + struct type_MTA_PerRecipientMessageSubmissionFields *prmtf; + int ad_no = 1; + int retval; + + for (; prf; prf = prf -> next) { + prmtf = prf -> PerRecipientMessageSubmissionFields; + if ((retval = load_addr (&ap, prmtf -> recipient__name)) != OK) + return retval; + if (*app == NULL) + *app = lastap = ap; + else { + lastap -> ad_next = ap; + lastap = ap; + } + ap -> ad_no = ad_no ++; + + if (prmtf -> explicit__conversion) + ap -> ad_explicitconversion = + prmtf -> explicit__conversion -> parm; + + if (bit_ison (prmtf -> originator__report__request, bit_MTA_OriginatorReportRequest_non__delivery__report)) + ap -> ad_usrreq = AD_USR_BASIC; + + if (bit_ison (prmtf -> originator__report__request, bit_MTA_OriginatorReportRequest_report)) + ap -> ad_usrreq = AD_USR_CONFIRM; + + if ((retval = load_prf_ext (ap, prmtf -> extensions,0,1)) != OK) + return retval; + } + return OK; +} + + +static int load_prf_ext (ap, ext,p1,msg) +ADDR *ap; +struct type_MTA_Extensions *ext; +int p1,msg; +{ + struct type_MTA_Extensions *ep; + int retval; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + if ((retval = do_local_extension + (&ap -> ad_per_recip_ext_list, + ep -> ExtensionField)) != OK) + return retval; + break; + case type_MTA_ExtensionType_global: + if ((retval = do_global_ext_prf + (ep -> ExtensionField -> type -> + un.global, ap, + ep -> ExtensionField, + p1,msg)) != OK) + return retval; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } + return OK; +} + + +static int load_trace (tpp, trace) +Trace **tpp; +struct type_MTA_TraceInformation *trace; +{ + Trace *tp; + int retval; + + for ( ; trace; trace = trace -> next) { + if((retval = make_trace (trace -> TraceInformationElement, + &tp)) != OK) + return retval; + if (tp) + trace_add (tpp, tp); + } + return OK; +} + +static int make_trace (ti, tpp) +struct type_MTA_TraceInformationElement *ti; +Trace **tpp; +{ + Trace *tp; + struct type_MTA_GlobalDomainIdentifier *gdi; + struct type_MTA_DomainSuppliedInformation *dsi; + DomSupInfo *dsp; + int retval; + + *tpp = tp = (Trace *) smalloc (sizeof *tp); + bzero ((char *)tp, sizeof *tp); + + if ((gdi = ti -> global__domain__identifier) != NULL && + (retval = load_gdi (&tp -> trace_DomId, gdi)) != OK) + return retval; + + dsp = &tp -> trace_DomSinfo; + if ((dsi = ti -> domain__supplied__information) != NULL) { + if (dsi -> arrival__time && + (retval = load_time (&dsp -> dsi_time, + dsi -> arrival__time)) != OK) + return retval; + + if (dsi -> routing__action) + dsp -> dsi_action = dsi -> routing__action -> parm; + + if (dsi -> attempted__domain && + (retval = load_gdi (&dsp -> dsi_attempted_md, + dsi -> attempted__domain)) != OK) + return retval; + + if (dsi -> deferred__time && + (retval = load_time (&dsp -> dsi_deferred, + dsi -> deferred__time)) != OK) + return retval; + + if (dsi -> converted__encoded__information__types && + (retval = load_eits (&dsp -> dsi_converted, + dsi -> converted__encoded__information__types)) + != OK) + return retval; + + if (dsi -> other__actions) { + if (bit_ison (dsi -> other__actions, + bit_MTA_OtherActions_redirected)) + dsp -> dsi_other_actions |= ACTION_REDIRECTED; + if (bit_ison (dsi -> other__actions, + bit_MTA_OtherActions_dl__operation)) + dsp -> dsi_other_actions |= ACTION_EXPANDED; + } + } + return OK; +} + +static int load_gdi (gdi, gdip1) +GlobalDomId *gdi; +struct type_MTA_GlobalDomainIdentifier *gdip1; +{ + struct type_MTA_AdministrationDomainName *admd; + struct type_MTA_CountryName *co; + struct type_MTA_PrivateDomainIdentifier *prmd; + + if ((co = gdip1 -> country__name) != NULL && + (gdi -> global_Country = + qb2str (co -> offset == + type_MTA_CountryName_x121__dcc__code ? + co -> un.x121__dcc__code : + co -> un.iso__3166__alpha2__code)) == NULL) + return NOTOK; + if ((admd = gdip1 -> administration__domain__name) != NULL && + (gdi -> global_Admin = + qb2str (admd -> offset == + type_MTA_AdministrationDomainName_numeric ? + admd -> un.numeric : admd -> un.printable)) == NULL) + return NOTOK; + if ((prmd = gdip1 -> private__domain__identifier) != NULL && + (gdi -> global_Private = + qb2str (prmd -> offset == + type_MTA_PrivateDomainIdentifier_numeric ? + prmd -> un.numeric : + prmd -> un.printable)) == NULL) + return NOTOK; + return OK; +} + +static int load_reportenv (qp, dr, envelope) +Q_struct *qp; +DRmpdu *dr; +struct type_MTA_ReportTransferEnvelope *envelope; +{ + int retval; + + dr -> dr_mpduid = (MPDUid *) + smalloc (sizeof *dr -> dr_mpduid); + bzero ((char *)dr -> dr_mpduid, sizeof *dr -> dr_mpduid); + + if ((retval = load_msgid (dr -> dr_mpduid, + envelope -> report__identifier)) != OK) + return retval; + + if ((retval = load_addr (&qp -> Oaddress, + envelope -> report__destination__name)) != OK || + (retval = load_trace (&dr -> dr_trace, + envelope -> trace__information)) != OK || + (retval = load_repe_ext (dr, envelope -> extensions)) != OK) + return retval; + return OK; +} + +static int load_reportcont (qp, dr, content) +Q_struct *qp; +DRmpdu *dr; +struct type_MTA_ReportTransferContent *content; +{ + int retval; + + if ((retval = load_msgid (&qp -> msgid, content -> subject__identifier)) != OK) + return retval; + + if (content -> subject__intermediate__trace__information && + (retval = load_trace (&dr -> dr_subject_intermediate_trace, + content -> subject__intermediate__trace__information)) + != OK) + return retval; + + if (content -> original__encoded__information__types && + (retval = load_eits (&qp -> orig_encodedinfo, + content -> original__encoded__information__types)) + != OK) + return retval; + + if (content -> member_MTA_17 && + (retval = load_content (qp, content -> member_MTA_17)) != OK) + return retval; + + if (content -> content__identifier && + (qp -> ua_id = qb2str (content -> content__identifier)) == NULL) + return NOTOK; + + /* content -> returned__contents handled directly. */ + + /* content -> additional__information XXX */ + + if (content -> extensions && + (retval = load_cont_ext (dr, content -> extensions)) != OK) + return retval; + + if ((retval = load_drc_pr_fields (&qp -> Raddress, &dr -> dr_recip_list, + content -> per__recipient__fields, 1)) != OK) + return retval; + return OK; +} + +static int load_drc_pr_fields (app, rrp, prfl, ad_no) +ADDR **app; +Rrinfo **rrp; +struct element_MTA_9 *prfl; +int ad_no; +{ + Rrinfo *rr; + struct type_MTA_PerRecipientReportTransferFields *prf; + int retval; + + if ((prf = prfl -> PerRecipientReportTransferFields) == NULL) + return OK; + + *rrp = rr = (Rrinfo *) smalloc (sizeof *rr); + bzero ((char *)rr, sizeof (*rr)); + + if ((retval = load_addr (app, prf -> actual__recipient__name)) != OK) + return retval; + + rr -> rr_recip = (*app) -> ad_no = ad_no ++; + (*app) -> ad_status = AD_STAT_DRWRITTEN; + + (*app) -> ad_extension = + prf -> originally__specified__recipient__number -> parm; + + if (bit_ison (prf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_responsibility)) + (*app) -> ad_resp = 1; + else (*app) -> ad_resp = 0; + + (*app) -> ad_mtarreq = AD_MTA_NONE; + if (bit_ison (prf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originating__MTA__report)) + (*app) -> ad_mtarreq |= AD_MTA_CONFIRM; + + if (bit_ison (prf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originating__MTA__non__delivery__report)) + (*app) -> ad_mtarreq |= AD_MTA_BASIC; + + (*app) -> ad_usrreq = AD_USR_NOREPORT; + if (bit_ison (prf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originator__non__delivery__report)) + (*app) -> ad_usrreq = AD_USR_BASIC; + + if (bit_ison (prf -> per__recipient__indicators, + bit_MTA_PerRecipientIndicators_originator__report)) + (*app) -> ad_usrreq = AD_USR_CONFIRM; + + + if ((retval = load_lasttrace (rr, prf -> last__trace__information)) != OK) + return retval; + + if (prf -> originally__intended__recipient__name && + (retval = load_fullname (&rr -> rr_originally_intended_recip, + prf -> originally__intended__recipient__name)) + != OK) + return retval; + + if (prf -> supplementary__information && + (rr -> rr_supplementary = + qb2str (prf -> supplementary__information)) == NULL) + return NOTOK; + + if (prf -> extensions && + (retval = load_prr_ext (rr, prf -> extensions)) != OK) + return retval; + + if (prfl -> next) + return load_drc_pr_fields (&(*app) -> ad_next, + &rr -> rr_next, + prfl -> next, ad_no); + return OK; +} + +static int load_lasttrace(rr, lti) +Rrinfo *rr; +struct type_MTA_LastTraceInformation *lti; +{ + int retval; + + if ((retval = load_time (&rr -> rr_arrival, + lti -> arrival__time)) != OK) + return retval; + + if (lti -> converted__encoded__information__types) { + rr -> rr_converted = (EncodedIT *) + calloc (1, sizeof *rr -> rr_converted); + if ((retval = load_eits (rr -> rr_converted, + lti -> converted__encoded__information__types)) + != OK) + return retval; + } + + return load_report (&rr -> rr_report, lti -> report); +} + +static int load_report (rp, report) +Report *rp; +struct type_MTA_Report *report; +{ + int retval; + + if (report -> offset == type_MTA_Report_delivery) { + rp -> rep_type = DR_REP_SUCCESS; + + if ((retval = load_time (&rp -> rep.rep_dinfo.del_time, + report -> un.delivery -> + message__delivery__time)) != OK) + return retval; + + rp -> rep.rep_dinfo.del_type = + report -> un.delivery -> type__of__MTS__user -> parm; + } + else { + rp -> rep_type = DR_REP_FAILURE; + + rp -> rep.rep_ndinfo.nd_rcode = + report -> un.non__delivery -> + non__delivery__reason__code -> parm; + if (report -> un.non__delivery -> + non__delivery__diagnostic__code) + rp -> rep.rep_ndinfo.nd_dcode = + report -> un.non__delivery -> + non__delivery__diagnostic__code -> + parm; + else + rp -> rep.rep_ndinfo.nd_dcode = -1; + } + return OK; +} + + + + + +static int load_repe_ext (dr, ext) +DRmpdu *dr; +struct type_MTA_Extensions *ext; +{ + struct type_MTA_Extensions *ep; + int retval; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + if ((retval = do_local_extension (&dr -> dr_per_envelope_extensions, + ep -> ExtensionField)) != OK) + return retval; + break; + case type_MTA_ExtensionType_global: + if ((retval = do_global_repe_prf (ep -> ExtensionField -> type -> + un.global, dr, + ep -> ExtensionField)) != OK) + return retval; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } + return OK; + +} + +static int load_cont_ext (dr, ext) +DRmpdu *dr; +struct type_MTA_Extensions *ext; +{ + struct type_MTA_Extensions *ep; + int retval; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + if ((retval = do_local_extension (&dr -> dr_per_report_extensions, + ep -> ExtensionField)) != OK) + return retval; + break; + case type_MTA_ExtensionType_global: + if ((retval = do_global_cont_prf (ep -> ExtensionField -> type -> + un.global, dr, + ep -> ExtensionField)) != OK) + return retval; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } + return OK; +} + +static int load_prr_ext (rr, ext) +Rrinfo *rr; +struct type_MTA_Extensions *ext; +{ + struct type_MTA_Extensions *ep; + int retval; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + if ((retval = do_local_extension (&rr -> rr_per_recip_extensions, + ep -> ExtensionField)) != OK) + return retval; + break; + + case type_MTA_ExtensionType_global: + if ((retval = do_global_rr_prf (ep -> ExtensionField -> type -> + un.global, rr, + ep -> ExtensionField)) != OK) + return retval; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } + return OK; +} + +static int load_fullname (fn, orname) +FullName **fn; +struct type_MTA_ORName *orname; +{ + ADDR *ad; + int retval; + + if ((retval = load_addr (&ad, orname)) != OK) + return retval; + + *fn = fn_new (ad -> ad_value, ad -> ad_dn); + adr_free (ad); + return OK; +} + +/* EXTENSIONS */ +static int pe2crit (); + +static int decode_extension (value, crit, defcrit, magic_num, mod, + label, decoder, ext) +caddr_t value; +char *crit; +int defcrit; +int magic_num; +modtyp *mod; +IFP decoder; +char *label; +struct type_MTA_ExtensionField *ext; +{ + caddr_t *genp; + int retval; + +#if PP_DEBUG > 0 + if (pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, magic_num, mod, + ext -> value, label, PDU_READ); +#endif + if (dec_f(magic_num, mod, ext -> value, 1, + NULLIP, NULLVP, &genp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't parse %s value [%s]", label, PY_pepy)); + return DONE; + } + + if ((retval = (*decoder) (value, genp)) != OK) + return retval; + + *crit = pe2crit (ext -> criticality, defcrit); + + fre_obj((char *) genp, mod->md_dtab[magic_num], mod, 1); + return OK; +} + +static int load_pm_extensions (qp, ext,p1,msg) +Q_struct *qp; +struct type_MTA_Extensions *ext; +int p1,msg; +{ + struct type_MTA_Extensions *ep; + int retval; + + for (ep = ext; ep; ep = ep -> next) { + switch (ep -> ExtensionField -> type -> offset) { + case type_MTA_ExtensionType_local: + if ((retval = do_local_extension (&qp -> per_message_extensions, + ep -> ExtensionField)) != OK) + return retval; + break; + + case type_MTA_ExtensionType_global: + if ((retval = do_global_extension (ep -> ExtensionField -> + type -> un.global, + qp, ep -> ExtensionField, + p1,msg)) != OK) + return retval; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown extension type %d", + ep -> ExtensionField -> type -> offset)); + break; + } + } + return OK; +} + + +static int squash_ext (qbp, value) +struct qbuf **qbp; +PE value; +{ + char *cp; + int len; + PS ps; + + if ((ps = ps_alloc (str_open)) == NULLPS) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't allocate PS")); + return NOTOK; + } + + len = ps_get_abs (value); + cp = smalloc (len); + + if (str_setup (ps, cp, len, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't setup stream [%s]", + ps_error (ps -> ps_errno))); + return NOTOK; + } + + if (pe2ps (ps, value) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("pe2ps failed [%s]", ps_error (ps -> ps_errno))); + return NOTOK; + } + + ps_free (ps); + + if ((*qbp = str2qb (cp, len, 1)) == NULL) + return NOTOK; + free (cp); + return OK; +} + +static int flatten_ext (ext, epp) +struct type_MTA_ExtensionField *ext; +X400_Extension **epp; +{ + X400_Extension *ep; + + *epp = ep = (X400_Extension *)smalloc (sizeof *ep); + if (ext -> type -> offset == type_MTA_ExtensionType_global) { + ep -> ext_int = ext -> type -> un.global; + ep -> ext_oid = NULLOID; + } + else { + ep -> ext_int = EXT_OID_FORM; + if ((ep -> ext_oid = oid_cpy (ext -> type -> un.local)) + == NULLOID) + return NOTOK; + } + + if (squash_ext (&ep -> ext_value, ext -> value) == NOTOK) + return NOTOK; + ep -> ext_criticality = pe2crit (ext -> criticality, + CRITICAL_NONE); + ep -> ext_next = NULL; + return OK; +} + +static int do_local_extension (elist, ext) +X400_Extension **elist; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + int retval; + + PP_LOG (LLOG_EXCEPTIONS, ("Unknown local extension %s", + sprintoid (ext -> type -> un.local))); + + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = elist; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + return OK; +} + +static int ext_security (qbp, critp, defcrit, ext) +struct qbuf **qbp; +char *critp; +int defcrit; +struct type_MTA_ExtensionField *ext; +{ + int retval; + + if ((retval = squash_ext (qbp, ext -> value)) != OK) + return retval; + + *critp = pe2crit (ext -> criticality, defcrit); + return OK; +} + +static int decode_ext_time (utc, genp) +UTC *utc; +struct type_UNIV_UTCTime *genp; +{ + return load_time (utc, genp); +} + +static int decode_ext_char (cp, ptr) +char *cp; +struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */ +{ + *cp = ptr -> parm; + return OK; +} + +static int decode_ext_int (ip, ptr) +int *ip; +struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */ +{ + *ip = ptr -> parm; + return OK; +} + +static int ext_decode_dlexph (dpp, genp) +DLHistory **dpp; +struct type_Ext_DLExpansionHistory *genp; +{ + struct type_Ext_DLExpansionHistory *dlhp; + DLHistory *dp; + int retval; + + for (dlhp = genp; dlhp; dlhp = dlhp -> next) { + if ((retval = ext_decode_dlh (dlhp -> DLExpansion, &dp)) != OK) + return retval; + dlh_add (dpp, dp); + } + return OK; +} + +static int ext_decode_dlh (dlp, dpp) +struct type_Ext_DLExpansion *dlp; +DLHistory **dpp; +{ + UTC ut; + ADDR *ad; + int retval; + + if ((retval = load_time (&ut, dlp -> dl__expansion__time)) != OK) + return retval; + if ((retval = load_addr (&ad, dlp -> address)) != OK) + return retval; + + *dpp = dlh_new (ad -> ad_value, ad -> ad_dn , ut); + adr_free (ad); + + free ((char *)ut); + return OK; +} + + +static int do_global_extension (n, qp, ext, p1, msg) +int n; +Q_struct *qp; +struct type_MTA_ExtensionField *ext; +int p1,msg; +{ + X400_Extension *ep, **epp; + int retval; + + switch (n) { + case EXT_RECIPIENT_REASSIGNMENT_PROHIBITED: + return decode_extension + ((caddr_t)&qp -> recip_reassign_prohibited, + &qp -> recip_reassign_crit, + EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC, + _ZRecipientReassignmentProhibitedExt, + &_ZExt_mod, + "Extension.RecipientReassignmentProhibited", + decode_ext_char, + ext); + + case EXT_DL_EXPANSION_PROHIBITED: + return decode_extension + ((caddr_t)&qp -> dl_expansion_prohibited, + &qp -> dl_expansion_crit, + EXT_DL_EXPANSION_PROHIBITED_DC, + _ZDLExpansionProhibitedExt, + &_ZExt_mod, + "Extension.DLExpansionProhibited", + decode_ext_char, + ext); + + case EXT_CONVERSION_WITH_LOSS_PROHIBITED: + return decode_extension + ((caddr_t)&qp -> conversion_with_loss_prohibited, + &qp -> conversion_with_loss_crit, + EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC, + _ZConversionWithLossProhibitedExt, + &_ZExt_mod, + "Extensions.ConversionWithLossProhibited", + decode_ext_char, + ext); + + case EXT_ORIGINATOR_CERTIFICATE: + return ext_security (&qp -> originator_certificate, + &qp -> originator_certificate_crit, + EXT_ORIGINATOR_CERTIFICATE_DC, + ext); + + case EXT_MESSAGE_SECURITY_LABEL: + return ext_security (&qp -> security_label, + &qp -> security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + ext); + + case EXT_CONTENT_CORRELATOR: + return ext_security (&qp -> general_content_correlator, + &qp -> content_correlator_crit, + EXT_CONTENT_CORRELATOR_DC, + ext); + + + case EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK: + if (!msg) + return ext_security + (&qp -> message_origin_auth_check, + &qp -> message_origin_auth_check_crit, + EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + break; + + case EXT_DL_EXPANSION_HISTORY: + if (p1) + return decode_extension + ((caddr_t)&qp -> dl_expansion_history, + &qp -> dl_expansion_crit, + EXT_DL_EXPANSION_HISTORY_DC, + _ZDLExpansionHistoryExt, + &_ZExt_mod, + "Extensions.DLExpansionHistory", + ext_decode_dlexph, + ext); + break; + + case EXT_INTERNAL_TRACE_INFORMATION: + if (p1) + return ext_inttrace (&qp -> trace, ext); + break; + + case EXT_LATEST_DELIVERY_TIME: + if (msg) + return decode_extension + ((caddr_t)&qp -> latest_time, + &qp -> latest_time_crit, + EXT_LATEST_DELIVERY_TIME_DC, + _ZLatestDeliveryTimeExt, + &_ZExt_mod, + "Extensions.LatestDeliveryTime", + decode_ext_time, + ext); + break; + + case EXT_ORIGINATOR_RETURN_ADDRESS: + if (msg) + return ext_ora (qp, ext); + break; + + case EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER: + if (msg) + return ext_security + (&qp -> algorithm_identifier, + &qp -> algorithm_identifier_crit, + EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC, + ext); + break; + case EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK: + if (msg) + return ext_security + (&qp -> message_origin_auth_check, + &qp -> message_origin_auth_check_crit, + EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + break; + case EXT_FORWARDING_REQUEST: + if (msg && (!p1)) + return decode_extension + ((caddr_t)&qp -> forwarding_request, + &qp -> forwarding_request_crit, + EXT_FORWARDING_REQUEST_DC, + _ZSequenceNumberExt, + &_ZExt_mod, + "Extension.ForwardingRequest.SequenceNumber", + decode_ext_int, + ext); + break; + case EXT_PROOF_OF_SUBMISSION_REQUEST: + if (msg && (!p1)) + return decode_extension + ((caddr_t)&qp -> proof_of_submission_request, + &qp -> proof_of_submission_crit, + EXT_PROOF_OF_SUBMISSION_REQUEST_DC, + _ZProofOfSubmissionRequestExt, + &_ZExt_mod, + "Extension.ProofOfSubmissionRequest", + decode_ext_int, + ext); + break; + default: + PP_NOTICE (("Unknown global extension type %d", n)); + /* fall */ + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = &qp -> per_message_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } + return OK; +} + + +static int ext_ora (qp, ext) +Q_struct *qp; +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_OriginatorReturnAddress *ora; + OR_ptr or; + char buf[BUFSIZ]; + + PP_PDU (print_Ext_OriginatorReturnAddress, + ext -> value, "Extensions.OriginatorReturnAddress", + PDU_READ); + + if (decode_Ext_OriginatorReturnAddress (ext -> value, 1, + NULLIP, NULLVP, + &ora) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't parse originator return address [%s]", + PY_pepy)); + return DONE; + } + + or = oradr2ora (ora); + or_or2std (or, buf, 0); + or_free (or); + + qp -> originator_return_address = fn_new (buf, NULLCP); + + qp -> originator_return_address_crit = + pe2crit (ext -> criticality, + EXT_ORIGINATOR_RETURN_ADDRESS_DC); + free_Ext_OriginatorReturnAddress (ora); + return OK; +} + +static int same_gdi (gdi1, gdi2) +GlobalDomId *gdi1, *gdi2; +{ + int vset; + + vset = (gdi1 -> global_Country ? 1 : 0) + + (gdi2 -> global_Country ? 1 : 0); + if (vset == 1 || ( vset == 2 && + lexequ (gdi1 -> global_Country, + gdi2 -> global_Country) != 0)) + return 0; + vset = (gdi1 -> global_Admin ? 1 : 0) + + (gdi2 -> global_Admin ? 1 : 0); + + if (vset == 1 || (vset == 2 && + lexequ (gdi1 -> global_Admin, + gdi2 -> global_Admin) != 0)) + return 0; + + vset = (gdi1 -> global_Private ? 1 : 0) + + (gdi2 -> global_Private ? 1 : 0); + if (vset == 1 || (vset == 2 && + lexequ (gdi1 -> global_Private, + gdi2 -> global_Private) != 0)) + return 0; + return 1; +} + +static int same_dsi (dsi1, dsi2) +DomSupInfo *dsi1, *dsi2; +{ + int vset; + + vset = (dsi1 -> dsi_time ? 1 : 0) + + (dsi2 -> dsi_time ? 1 : 0); + if (vset == 1 || (vset == 2 && + utcequ (dsi1->dsi_time, dsi2 -> dsi_time) != 0)) + return 0; + + vset = (dsi1 -> dsi_deferred ? 1 : 0) + + (dsi2 -> dsi_deferred ? 1 : 0); + if (vset == 1 || (vset == 2 && + utcequ (dsi1 -> dsi_deferred, + dsi2 -> dsi_deferred) != 0)) + return 0; + + if (dsi1 -> dsi_action != dsi2 -> dsi_action) + return 0; + if (dsi1 -> dsi_other_actions != dsi2 -> dsi_other_actions) + return 0; + + if (same_gdi (&dsi1 -> dsi_attempted_md, + &dsi2 -> dsi_attempted_md) == 0) + return 0; + + vset = (dsi1 -> dsi_converted.eit_types ? 1 : 0) + + (dsi2 -> dsi_converted.eit_types ? 1 : 0); + if (vset == 1) /* should check all eit's too. */ + return 0; + + vset = (dsi1 -> dsi_attempted_mta ? 1 : 0) + + (dsi2 -> dsi_attempted_mta ? 1 : 0); + if (vset == 1 || (vset == 2 && + lexequ (dsi1 -> dsi_attempted_mta, + dsi2 -> dsi_attempted_mta) != 0)) + return 0; + return 1; +} + + +static void merge_trace (base, new_tr) +Trace **base, *new_tr; +{ + Trace **tp; + Trace *tmp; + + for (tp = base; *tp; tp = &(*tp) -> trace_next) { + if (same_gdi (&((*tp) -> trace_DomId), + &(new_tr -> trace_DomId)) == 0 || + same_dsi (&((*tp) -> trace_DomSinfo), + &(new_tr -> trace_DomSinfo)) == 0) + continue; + tmp = *tp; + new_tr -> trace_next = (*tp) -> trace_next; + *tp = new_tr; + tmp -> trace_next = NULL; + trace_free (tmp); + return; + } + *tp = new_tr; + new_tr -> trace_next = NULL; +} + +static int ext_inttrace (trace, ext) +Trace **trace; +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_InternalTraceInformation *intt, *ip; + int retval; + + PP_PDU (print_Ext_InternalTraceInformation, + ext -> value, "Extension.InternalTraceInformation", + PDU_READ); + + if (decode_Ext_InternalTraceInformation (ext -> value, 1, + NULLIP, NULLVP, + &intt) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't parse InternalTraceInformation [%s]", + PY_pepy)); + return DONE; + } + + for (ip = intt; ip; ip = ip -> next) { + struct type_Ext_InternalTraceInformationElement *te; + struct type_Ext_MTASuppliedInformation *msi; + Trace *tp; + + te = ip -> InternalTraceInformationElement; + tp = trace_new (); + if ((retval = load_gdi (&tp -> trace_DomId, + te -> global__domain__identifier)) != OK) + return retval; + if ((tp -> trace_mta = qb2str (te -> mta__name)) == NULL) + return NOTOK; + msi = te -> mta__supplied__information; + if (msi -> arrival__time && + (retval = load_time (&tp -> trace_DomSinfo.dsi_time, + msi -> arrival__time)) != OK) + return retval; + if (msi -> routing__action) + tp -> trace_DomSinfo.dsi_action = + msi -> routing__action -> parm; + if (msi -> deferred__time && + (retval = load_time (&tp -> trace_DomSinfo.dsi_deferred, + msi -> deferred__time)) != OK) + return retval; + if (msi -> other__actions) { + if (bit_ison (msi -> other__actions, + bit_MTA_OtherActions_redirected)) + tp -> trace_DomSinfo.dsi_other_actions |= + ACTION_REDIRECTED; + if (bit_ison (msi -> other__actions, + bit_MTA_OtherActions_dl__operation)) + tp -> trace_DomSinfo.dsi_other_actions |= + ACTION_EXPANDED; + } + if (msi -> attempted) { + switch (msi -> attempted -> offset) { + case choice_Ext_1_mta: + if ((tp -> trace_DomSinfo.dsi_attempted_mta = + qb2str (msi -> attempted -> un.mta)) == NULL) + return NOTOK; + break; + case choice_Ext_1_domain: + if ((retval = load_gdi (&tp -> + trace_DomSinfo.dsi_attempted_md, + msi -> attempted -> un.domain)) + != OK) + return retval; + break; + + + default: + break; + } + } + merge_trace (trace, tp); + } + return OK; +} + +static int decode_ext_pdm (value, genp) +int *value; +PE genp; +{ +#define setbit(t,v) \ + (*value) |= (bit_ison(genp, (t)) ? (v) : 0) + + setbit (bit_Ext_PhysicalDeliveryModes_ordinary__mail, + AD_PM_ORD); + setbit (bit_Ext_PhysicalDeliveryModes_special__delivery, + AD_PM_SPEC); + setbit (bit_Ext_PhysicalDeliveryModes_express__mail, + AD_PM_EXPR); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection, + AD_PM_CNT); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telephone__advice, + AD_PM_CNT_PHONE); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telex__advice, + AD_PM_CNT_TLX); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__teletex__advice, + AD_PM_CNT_TTX); + setbit (bit_Ext_PhysicalDeliveryModes_bureau__fax__delivery, + AD_PM_CNT_BUREAU); +#undef setbit + return OK; +} + +static int decode_ext_pra (value, gen) +OID *value; +OID gen; +{ + if ((*value = oid_cpy (gen)) != NULLOID) + return OK; + return NOTOK; +} + +static int decode_ext_rnfa (value, genp) +char **value; +struct qbuf *genp; +{ + if ((*value = qb2str (genp)) == NULL) + return NOTOK; + return OK; +} + +static int decode_ext_rdm (value, genp) +int value[AD_RDM_MAX]; +struct type_Ext_RequestedDeliveryMethod *genp; +{ + int i; + + for (i = 0; i < AD_RDM_MAX && genp; + i++, genp = genp -> next) + value[i] = genp -> element_Ext_0; + return OK; +} + +static int decode_ext_redir (value, genp) +Redirection **value; +struct type_Ext_RedirectionHistory *genp; +{ + int retval; + + while (genp) { + if ((retval = decode_1redir (value, genp->Redirection)) != OK) + return retval; + value = &(*value) -> rd_next; + genp = genp -> next; + } + return OK; +} + +static int decode_1redir (rpp, redir) +Redirection **rpp; +struct type_Ext_Redirection *redir; +{ + ADDR *ad; + int retval; + + *rpp = (Redirection *) smalloc (sizeof **rpp); + if ((retval = + load_addr (&ad, redir -> intended__recipient__name -> address)) + != OK) + return retval; + (*rpp) -> rd_addr = ad -> ad_value; + ad -> ad_value = NULLCP; + (*rpp) -> rd_dn = ad -> ad_dn; + ad -> ad_dn = NULLCP; + adr_free (ad); + + if ((retval = load_time (&(*rpp) -> rd_time, + redir -> intended__recipient__name -> redirection__time)) != OK) + return retval; + (*rpp) -> rd_reason = redir -> redirection__reason -> parm; + return OK; +} + +static int do_global_ext_prf (n, ad, ext, p1, msg) +int n; +ADDR *ad; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + int retval; + + switch (n) { + case EXT_MESSAGE_TOKEN: + if (msg) + return ext_security (&ad -> ad_message_token, + &ad -> ad_message_token_crit, + EXT_MESSAGE_TOKEN_DC, + ext); + break; + case EXT_CONTENT_INTEGRITY_CHECK: + if (msg) + return ext_security (&ad -> ad_content_integrity, + &ad -> ad_content_integrity_crit, + EXT_CONTENT_INTEGRITY_CHECK_DC, + ext); + break; + case EXT_PROOF_OF_DELIVERY_REQUEST: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_proof_delivery, + &ad -> ad_proof_delivery_crit, + EXT_PROOF_OF_DELIVERY_REQUEST_DC, + _ZProofOfDeliveryRequestExt, + &_ZExt_mod, + "Extensions.ProofOfDeliveryRequest", + decode_ext_int, + ext); + break; + case EXT_PHYSICAL_FORWARDING_PROHIBITED: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_phys_forward, + &ad -> ad_phys_forward_crit, + EXT_PHYSICAL_FORWARDING_PROHIBITED_DC, + _ZPhysicalForwardingProhibitedExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingProhibited", + decode_ext_char, + ext); + break; + case EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_phys_fw_ad_req, + &ad -> ad_phys_fw_ad_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC, + _ZPhysicalForwardingAddressRequestExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingAddressRequest", + decode_ext_char, + ext); + break; + case EXT_REGISTERED_MAIL: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_reg_mail_type, + &ad -> ad_reg_mail_type_crit, + EXT_REGISTERED_MAIL_DC, + _ZRegisteredMailTypeExt, + &_ZExt_mod, + "Extensions.RegisteredMailType", + decode_ext_int, + ext); + break; + case EXT_PHYSICAL_DELIVERY_REPORT_REQUEST: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_pd_report_request, + &ad -> ad_pd_report_request_crit, + EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC, + _ZPhysicalDeliveryReportRequestExt, + &_ZExt_mod, + "Extensions.PhysicalDeliveryReportRequest", + decode_ext_int, + ext); + break; + case EXT_PHYSICAL_RENDITION_ATTRIBUTES: + return decode_extension + ((caddr_t)&ad -> ad_phys_rendition_attribs, + &ad -> ad_phys_rendition_attribs_crit, + EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC, + _ZPhysicalRenditionAttributesExt, + &_ZExt_mod, + "Extensions.PhysicalRenditionAttributes", + decode_ext_pra, + ext); + + case EXT_RECIPIENT_NUMBER_FOR_ADVICE: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_recip_number_for_advice, + &ad -> ad_recip_number_for_advice_crit, + EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC, + _ZRecipientNumberForAdviceExt, + &_ZExt_mod, + "Extensions.RecipientNumberForAdvice", + decode_ext_rnfa, + ext); + break; + case EXT_REQUESTED_DELIVERY_METHOD: + return decode_extension + ((caddr_t)ad -> ad_req_del, + &ad -> ad_req_del_crit, + EXT_REQUESTED_DELIVERY_METHOD_DC, + _ZRequestedDeliveryMethodExt, + &_ZExt_mod, + "Extensions.RequestedDeliveryMethod", + decode_ext_rdm, + ext); + + case EXT_PHYSICAL_DELIVERY_MODES: + if (msg) + return decode_extension + ((caddr_t)&ad -> ad_phys_modes, + &ad -> ad_phys_modes_crit, + EXT_PHYSICAL_DELIVERY_MODES_DC, + _ZPhysicalDeliveryModesExt, + &_ZExt_mod, + "Extensions.PhysicalDeliveryModes", + decode_ext_pdm, + ext); + break; + + case EXT_REDIRECTION_HISTORY: + if (p1) + return decode_extension + ((caddr_t)&ad -> ad_redirection_history, + &ad -> ad_redirection_history_crit, + EXT_REDIRECTION_HISTORY_DC, + _ZRedirectionHistoryExt, + &_ZExt_mod, + "Extensions.RedirectionHistory", + decode_ext_redir, + ext); + break; + + case EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT: + return decode_extension + ((caddr_t)&ad -> ad_orig_req_alt, + &ad -> ad_orig_req_alt_crit, + EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT_DC, + _ZOriginatorRequestedAlternateRecipientExt, + &_ZExt_mod, + "Extensions.OriginatorRequestedAlternateRecipient", + decode_ext_orn, + ext); + default: + PP_NOTICE (("Unknown global extension type %d", n)); + /* fall */ + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = &ad -> ad_per_recip_ext_list; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } + return OK; +} + +static int pe2crit (pe, defcrit) +PE pe; +int defcrit; +{ + char *str; + int len, n; + + if (pe == NULLPE) + return defcrit; + str = bitstr2strb (pe, &len); + n = strb2int(str, len); + free (str); + return n; +} + +static int decode_ext_fn (value, genp) +FullName **value; +struct type_MTA_ORName *genp; +{ + return load_fullname (value, genp); +} + +static int do_global_repe_prf (n, dr, ext) +int n; +DRmpdu *dr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + int retval; + + switch (n) { + case EXT_INTERNAL_TRACE_INFORMATION: + return ext_inttrace (&dr -> dr_trace, ext); + case EXT_MESSAGE_SECURITY_LABEL: + return ext_security (&dr -> dr_security_label, + &dr -> dr_security_label_crit, + EXT_MESSAGE_SECURITY_LABEL_DC, + ext); + case EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK: + return ext_security (&dr -> dr_report_origin_auth_check, + &dr -> dr_report_origin_auth_check_crit, + EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK_DC, + ext); + + case EXT_REPORTING_MTA_CERTIFICATE: + return ext_security (&dr -> dr_reporting_mta_certificate, + &dr -> dr_reporting_mta_certificate_crit, + EXT_REPORTING_MTA_CERTIFICATE_DC, + ext); + + case EXT_REPORT_DL_NAME: + return decode_extension + ((caddr_t)&dr -> dr_reporting_dl_name, + &dr -> dr_reporting_dl_name_crit, + EXT_REPORT_DL_NAME_DC, + _ZReportingDLNameExt, + &_ZExt_mod, + "Extension.ReportingDLName", + decode_ext_fn, + ext); + + case EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY: + return decode_extension + ((caddr_t)&dr -> dr_dl_history, + &dr -> dr_dl_history_crit, + EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY_DC, + _ZOriginatorAndDLExpansionHistoryExt, + &_ZExt_mod, + "Extension.OriginatorAndDLExpansion", + ext_decode_dlexph, + ext); + + default: + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = &dr -> dr_per_envelope_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } + return OK; +} + +static int do_global_cont_prf (n, dr, ext) +int n; +DRmpdu *dr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + int retval; + + switch (n) { + case EXT_CONTENT_CORRELATOR: + default: + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = &dr -> dr_per_envelope_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } + return OK; +} + +static int do_global_rr_prf (n, rr, ext) +int n; +Rrinfo *rr; +struct type_MTA_ExtensionField *ext; +{ + X400_Extension *ep, **epp; + int retval; + + switch (n) { + case EXT_RECIPIENT_CERTIFICATE: + return ext_security + (&rr -> rr_recip_certificate, + &rr -> rr_recip_certificate_crit, + EXT_RECIPIENT_CERTIFICATE_DC, + ext); + + case EXT_REDIRECTION_HISTORY: + return decode_extension + ((caddr_t)&rr -> rr_redirect_history, + &rr -> rr_redirect_history_crit, + EXT_REDIRECTION_HISTORY_DC, + _ZRedirectionHistoryExt, + &_ZExt_mod, + "Extensions.RedirectionHistory", + decode_ext_redir, + ext); + + case EXT_PHYSICAL_FORWARDING_ADDRESS: + return decode_extension + ((caddr_t)&rr -> rr_physical_fwd_addr, + &rr -> rr_physical_fwd_addr_crit, + EXT_PHYSICAL_FORWARDING_ADDRESS_DC, + _ZPhysicalForwardingAddressExt, + &_ZExt_mod, + "Extension.PhysicalForwardingAddress", + decode_ext_fn, + ext); + + case EXT_PROOF_OF_DELIVERY: + return ext_security (&rr -> rr_report_origin_authentication_check, + &rr -> rr_report_origin_authentication_check_crit, + EXT_PROOF_OF_DELIVERY_DC, + ext); + + default: + if ((retval = flatten_ext (ext, &ep)) != OK) + return retval; + for (epp = &rr -> rr_per_recip_extensions; *epp; + epp = &(*epp) -> ext_next) + continue; + *epp = ep; + break; + } + return OK; +} diff --git a/Format/Makefile b/Format/Makefile new file mode 100644 index 0000000..77103b1 --- /dev/null +++ b/Format/Makefile @@ -0,0 +1,46 @@ +# Preliminary comments +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/RCS/Makefile,v 6.0 1991/12/18 20:15:10 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:15:10 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = p2explode p2flatten rfc1148 rfc822norm p2norm rfc934 $(OPTIONALFILTERS) + +ALLDIRS = $(SUBDIRS) ascii2fax asn charset + +############################################################ +# +# Building Rules +# +############################################################ + +target: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +install define lint: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +clean tidy depend: + @for i in $(ALLDIRS); \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Format/ascii2fax/Makefile b/Format/ascii2fax/Makefile new file mode 100644 index 0000000..958b83b --- /dev/null +++ b/Format/ascii2fax/Makefile @@ -0,0 +1,192 @@ +# ascii2fax +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/Makefile,v 6.0 1991/12/18 20:15:19 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:15:19 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = bitmap_util.c char_util.c font_util.c str_util.c \ + ia52fax.c hdr2fax.c +OBJS = bitmap_util.o char_util.o font_util.o str_util.o \ + ia52fax.o hdr2fax.o + +PROGS = xia52fax xhdr2fax xfontconv ximageconv + +UTIL = bitmap_util.o char_util.o font_util.o str_util.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) $(FAXPAGESIZE) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# ia52fax converts pages of ia5 to g3fax images +# +############################################################ + +xia52fax: $(UTIL) ia52fax.o image2fax.o $(LIBPP) + $(CC) $(LDFLAGS) $(UTIL) ia52fax.o image2fax.o \ + -o $@ $(LIBPP) $(LIBSYS) + +############################################################ +# +# hdr2fax converts 822 hdr to g3fax image of coverpage +# +############################################################ + +xhdr2fax: $(UTIL) hdr2fax.o image2fax.o $(LIBPP) + $(CC) $(LDFLAGS) $(UTIL) hdr2fax.o image2fax.o \ + -o $@ $(LIBPP) $(LIBSYS) + +############################################################ +# +# font converter: converts X fonts to PP fonts +# +############################################################ + +xfontconv: Xfont2PPfont.o $(UTIL) $(LIBPP) + $(CC) $(LDFLAGS) Xfont2PPfont.o $(UTIL) \ + -o $@ $(LIBPP) $(LIBSYS) -lXt -lX11 + +############################################################ +# +# imageconv converts X images to PP bitmaps +# +############################################################ + +ximageconv: X2PPbitmap.o $(UTIL) + $(CC) $(LDFLAGS) X2PPbitmap.o $(UTIL) \ + -o $@ $(LIBPP) $(LIBSYS) -lXt -lX11 + +############################################################ +# +# Building Rules +# +############################################################ + + +install: inst-dir inst-ia52fax inst-hdr2fax + +inst-dir: $(FORMDIR) + +inst-ia52fax: $(FORMDIR)/ia52fax + +$(FORMDIR)/ia52fax: xia52fax + -$(BACKUP) $@ zxia52fax + rm -f $@ + $(INSTALL) xia52fax $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ia52fax filter installed normally"; echo "" + +inst-hdr2fax: $(FORMDIR)/hdr2fax + +$(FORMDIR)/hdr2fax: xhdr2fax + -$(BACKUP) $@ zxhdr2fax + rm -f $@ + $(INSTALL) xhdr2fax $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "hdr2fax filter installed normally"; echo "" + +clean: tidy + rm -rf $(PROGS) + +tidy: + rm -f $(OBJS) Xfont2PPfont.o X2PPbitmap.o image2fax.o \ + core a.out Makefile.old + +lint: l-targets + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +bitmap_util.o: bitmap_util.c +bitmap_util.o: ./fonts.h +bitmap_util.o: ../../h/util.h +bitmap_util.o: ../../h/config.h +bitmap_util.o: ../../h/ll_log.h +bitmap_util.o: ../../h/sys.file.h +char_util.o: char_util.c +char_util.o: ./fonts.h +char_util.o: ../../h/util.h +char_util.o: ../../h/config.h +char_util.o: ../../h/ll_log.h +char_util.o: ../../h/sys.file.h +font_util.o: font_util.c +font_util.o: ./fonts.h +font_util.o: ../../h/util.h +font_util.o: ../../h/config.h +font_util.o: ../../h/ll_log.h +font_util.o: ../../h/sys.file.h +str_util.o: str_util.c +str_util.o: ./fonts.h +str_util.o: ../../h/util.h +str_util.o: ../../h/config.h +str_util.o: ../../h/ll_log.h +str_util.o: ../../h/sys.file.h +ia52fax.o: ia52fax.c +ia52fax.o: ../../h/util.h +ia52fax.o: ../../h/config.h +ia52fax.o: ../../h/ll_log.h +ia52fax.o: ../../h/IOB-types.h +ia52fax.o: ../../h/MTA-types.h +ia52fax.o: ../../h/Toks-types.h +ia52fax.o: ../../h/Auth-types.h +ia52fax.o: ../../h/table.h +ia52fax.o: ./fonts.h +ia52fax.o: ../../h/util.h +ia52fax.o: ../../h/sys.file.h +ia52fax.o: ./pg_sizes.h +hdr2fax.o: hdr2fax.c +hdr2fax.o: ../../h/util.h +hdr2fax.o: ../../h/config.h +hdr2fax.o: ../../h/ll_log.h +hdr2fax.o: ../../h/or.h +hdr2fax.o: ../../h/IOB-types.h +hdr2fax.o: ../../h/MTA-types.h +hdr2fax.o: ../../h/Toks-types.h +hdr2fax.o: ../../h/Auth-types.h +hdr2fax.o: ../../h/table.h +hdr2fax.o: ./fonts.h +hdr2fax.o: ../../h/util.h +hdr2fax.o: ../../h/sys.file.h +hdr2fax.o: ../../h/ap.h +hdr2fax.o: ../../h/util.h +hdr2fax.o: ./pg_sizes.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/ascii2fax/X2PPbitmap.c b/Format/ascii2fax/X2PPbitmap.c new file mode 100644 index 0000000..f425bfc --- /dev/null +++ b/Format/ascii2fax/X2PPbitmap.c @@ -0,0 +1,146 @@ +/* Ximage2PPbitmap.c: converts as X image to a PP bitmap */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/X2PPbitmap.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/X2PPbitmap.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: X2PPbitmap.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include +#include +#include +#include +#include +#include +#include "fonts.h" +#include + +#define OPT_IN 1 +#define OPT_OUT 2 + +CMD_TABLE tbl_options [] = { + "-in", OPT_IN, + "-out", OPT_OUT, + 0, -1, +}; + +typedef struct _cmdLineResources { + char *in; + char *out; +} CmdLineResources; + +static CmdLineResources cmdLine_resources; +extern BitMap new_bitmap(); + +main(argc, argv) +int argc; +char **argv; +{ + Arg arg[1]; + Display *display; + XtAppContext appContext; + int wid, ht, hot_x, hot_y; + Pixmap pixmap; + XImage *image; + unsigned long black, white; + int row, col, i; + FILE *fp; + BitMap bitmap; + char *ix; + + for (i = 1; i < argc; i++) { + switch (cmd_srch(argv[i], tbl_options)) { + case OPT_IN: + if (++i >= argc) { + printf("No input file given with flag '%s'\n", + argv[i-1]); + exit (1); + } + cmdLine_resources.in = strdup(argv[i]); + break; + case OPT_OUT: + if (++i >= argc) { + printf("No output file given with flag '%s'\n", + argv[i-1]); + exit (1); + } + cmdLine_resources.out = strdup(argv[i]); + break; + default: + printf("Unknown flag '%s'\n", + argv[i]); + exit(1); + } + } + + if (cmdLine_resources.in == NULLCP) { + printf("No input file given\n"); + exit(1); + } + + XtToolkitInitialize(); + + appContext = XtCreateApplicationContext(); + + display = XtOpenDisplay(appContext, + (String) NULL, + (String) argv[0], + (String) "PPCONVERTERS", + NULL, 0, + &argc, + argv); + + if (display == NULL) { + printf("%s\n", "unable to open display"); + exit(1); + } + + black = XBlackPixel(display, XDefaultScreen(display)); + white = XWhitePixel(display, XDefaultScreen(display)); + + if (XReadBitmapFile(display, + XRootWindow(display, XDefaultScreen(display)), + cmdLine_resources.in, &wid, &ht, + &pixmap, &hot_x, &hot_y) != BitmapSuccess) { + printf("Unable to create pixmap from bitmap file '%s'\n", + cmdLine_resources.in); + exit(1); + } + + image = XGetImage (display, + pixmap, + 0, + 0, + wid, ht, + XAllPlanes(), + XYPixmap); + + bitmap = (BitMap) new_bitmap(wid, ht); + + for (row = 0; row < ht; row++) { + for (col = 0; col < wid; col++) { + if (XGetPixel(image, col, row) == white) + BL_CLR(col, bitmap[row]); + else + BL_SET(col, bitmap[row]); + } + } + + if (cmdLine_resources.out == NULL) + fp = stdout; + else if ((fp = fopen(cmdLine_resources.out, "w")) == NULL) { + printf("unable to open output file '%s'\n", + cmdLine_resources.out); + exit(1); + } + bitmap2file (fp, bitmap, wid, ht); + fclose(fp); +} diff --git a/Format/ascii2fax/Xfont2PPfont.c b/Format/ascii2fax/Xfont2PPfont.c new file mode 100644 index 0000000..8d42ed8 --- /dev/null +++ b/Format/ascii2fax/Xfont2PPfont.c @@ -0,0 +1,224 @@ +/* xfont_conv.c:convert an X font to PP nonX format */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/Xfont2PPfont.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/Xfont2PPfont.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: Xfont2PPfont.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ +#include "util.h" +#include +#include +#include +#include +#include +#include +#include "fonts.h" +#include + +#define OPT_FONT 1 +#define OPT_FILE 2 + +CMD_TABLE tbl_options [] = { + "-font", OPT_FONT, + "-file", OPT_FILE, + 0, -1, +}; + +extern PPFontPtr new_font(); +extern CharPtr new_char(); +extern BitMap new_bitmap(); +#define MAXASCII 127 + +typedef struct _cmdLineResources { + char *font; + char *file; +} CmdLineResources; + +static CmdLineResources cmdLine_resources; + +clear_pixmap(display, pixmap, gc,wd,ht) +Display *display; +Pixmap pixmap; +GC gc; +unsigned int wd, ht; +{ + /* clear the pixmap */ + XSetFunction(display, gc, GXclear); + + XFillRectangle(display, + pixmap, + gc, + 0, 0, + wd,ht); + + XSetFunction(display, gc, GXcopy); +} + +main(argc, argv) +int argc; +char **argv; +{ + Arg arg[1]; + XFontStruct *fontstruct; + Display *display; + XtAppContext appContext; + PPFontPtr ppfont; + FILE *fp; + int wid, ht, base, i; + char ch; + Pixmap pixmap; + XGCValues gcv; + GC gc; + unsigned long black, white; + XImage *image; + int row, col; + + for (i = 1; i < argc; i++) { + switch (cmd_srch(argv[i], tbl_options)) { + case OPT_FILE: + if (++i >= argc) { + printf("No file name given with flag '%s'\n", + argv[i-1]); + exit (1); + } + cmdLine_resources.file = strdup(argv[i]); + break; + case OPT_FONT: + if (++i >= argc) { + printf("No font name given with flag '%s'\n", + argv[i-1]); + exit (1); + } + cmdLine_resources.font = strdup(argv[i]); + break; + default: + printf("Unknown flag '%s'\n", + argv[i]); + exit(1); + } + } + + if (cmdLine_resources.font == NULLCP) { + printf("No font specified\n"); + exit(0); + } + + XtToolkitInitialize(); + + appContext = XtCreateApplicationContext(); + + display = XtOpenDisplay(appContext, + (String) NULL, + (String) argv[0], + (String) "PPCONVERTERS", + NULL, 0, + &argc, + argv); + + if (display == NULL) { + printf("%s\n", "unable to open display"); + exit(1); + } + + + black = XBlackPixel(display, XDefaultScreen(display)); + white = XWhitePixel(display, XDefaultScreen(display)); + + if ((fontstruct = XLoadQueryFont(display, + cmdLine_resources.font)) == NULL) { + printf("display %s doesn't know about font '%s'\n", + DisplayString(display), cmdLine_resources.font); + exit(1); + } + + ht = fontstruct->max_bounds.ascent + + fontstruct->max_bounds.descent; + wid = fontstruct->max_bounds.lbearing + + fontstruct->max_bounds.rbearing; + base = fontstruct->max_bounds.ascent; + + pixmap = XCreatePixmap(display, + XRootWindow(display, XDefaultScreen(display)), + wid, ht, + (unsigned int)1); + + + gcv.font = fontstruct->fid; + + gcv.foreground = black; + gcv.background = white; + + gc = XCreateGC(display, pixmap, + (GCFont | GCForeground |GCBackground), &gcv); + + ppfont = new_font(MAXASCII+1); + + for (i = 0;i < MAXASCII+1;i++) { + /* step through ascii codes */ + CharPtr temp = new_char(); + temp->ascii = i; + + if (isprint(ch = (char) i)) { + char buf[1]; + buf[0] = ch; + + clear_pixmap(display, pixmap, gc, + wid, ht); + + temp->wid = XTextWidth(fontstruct, + buf, + 1); + temp->ht = ht; + + XDrawImageString(display, + pixmap, + gc, + 0, + base, + buf, + 1); + + image = XGetImage(display, + pixmap, + 0, 0, + temp->wid, temp->ht, + XAllPlanes(), + XYPixmap); + + /* convert x bitmap into pp bitmap */ + temp->bits = new_bitmap(temp->wid, temp->ht); + + for (row = 0; row < temp->ht; row++) { + for (col = 0; col < temp->wid; col++) { + if (XGetPixel(image, col, row) == white) + BL_CLR(col, temp->bits[row]); + else + BL_SET(col, temp->bits[row]); + } + } + } + ppfont->chars[i] = temp; + } + + if (cmdLine_resources.file) { + if ((fp = fopen(cmdLine_resources.file, "w")) == NULL) { + printf("unable to open output file '%s'", + cmdLine_resources.file); + exit (1); + } + } else + fp = stdout; + + font2file (fp, ppfont); + + if (fp != stdout) + fclose(fp); + exit(0); +} diff --git a/Format/ascii2fax/bitmap_util.c b/Format/ascii2fax/bitmap_util.c new file mode 100644 index 0000000..d88140b --- /dev/null +++ b/Format/ascii2fax/bitmap_util.c @@ -0,0 +1,150 @@ +/* bitmap_util.c: utility routines for a bitmap */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/bitmap_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/bitmap_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: bitmap_util.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ +#include "fonts.h" + +BitMap +new_bitmap(wid, ht) +int wid, ht; +{ + BitMap ret = (BitMap) calloc(ht, sizeof (BitLine)); + int i; + for (i = 0; i < ht; i++) + ret[i] = (BitLine) calloc(BL_WD2INT(wid), sizeof(int)); + return ret; +} + +clr_bitmap(map, wid, ht) +BitMap map; +int wid, ht; +{ + int i; + for (i =0;i < ht;i++) + bzero((char *)map[i], BL_WD2INT(wid) * sizeof(int)); +} + +free_bitmap(b, w, h) +BitMap b; +int w, h; +{ + int i; + for (i = 0; i < h; i++) + free(b[i]); + free(b); +} + +bitmap2file(fp, b, w, h) +FILE *fp; +BitMap *b; +int w, h; +{ + int iy, ix, count = 0; + fprintf(fp, "%d %d\n", w, h); + for (iy = 0; iy < h; iy++) + for (ix = 0; ix < BL_WD2INT(w); ix ++) { + fprintf(fp, "0x%8.8x\n", b[iy][ix]); +#ifdef NOTDEF + if (++count >= 10) { + fprintf(fp, "\n"); + count = 0; + } +#endif + } +#ifdef NOTDEF + if (w || h) + fprintf(fp, "\n"); +#endif +} + +BitMap +file2bitmap(fp, pw, ph) +FILE *fp; +int *pw, *ph; +{ + char buf[BUFSIZ], *argv[15]; + int argc, ia, iw, ih; + long temp; + BitMap ret; + + if (fgets(buf, BUFSIZ, fp) == NULLCP) { + fprintf(stderr, + "Incorrect file encoding of bitmap: unexpected EOF\n"); + return (BitMap) NOTOK; + } + + if ((argc = sstr2arg(buf, 15, argv, " ")) != 2) { + fprintf(stderr, + "Incorrect file encoding of bitmap: expecting 'width height'\n"); + return (BitMap) NOTOK; + } + + *pw = (int) strtol(argv[0], NULL, 0); + *ph = (int) strtol(argv[1], NULL, 0); + + ret = new_bitmap(*pw, *ph); + + ia = argc = 0; + for (ih = 0; ih < *ph; ih ++) + for (iw = 0; iw < BL_WD2INT(*pw); iw ++) { + if (ia == argc) { + /* read in another line */ + if (fgets(buf, BUFSIZ, fp) == NULLCP) { + fprintf(stderr, + "Incorrect file encoding of bitmap: unexpected EOF\n"); + return (BitMap) NOTOK; + } + + argc = sstr2arg(buf, 15, argv, " "); + ia = 0; + } + temp = strtol(argv[ia++], NULL, 0); + + ret[ih][iw] = (int) temp; + } + return ret; +} + + +int +insertbitmap(to, to_wid, to_ht, + from, from_wid, from_ht, + x, y) +BitMap to; +int to_wid, to_ht; +BitMap from; +int from_wid, from_ht, + x, y; +{ + int ix, iy; + if (from_wid + x > to_wid) { + fprintf(stderr, + "insertbitmap: bitmap too wide to insert"); + return NOTOK; + } + if (from_ht + y > to_ht) { + fprintf(stderr, + "insertbitmap: bitmap too tall to insert"); + return NOTOK; + } + + for (iy = 0; iy < from_ht && y+iy < to_ht; iy++) { + for (ix = 0; ix < from_wid && x+ix < to_wid; ix++) { + if (BL_ISSET(ix, from[iy])) + BL_SET(x+ix, to[y+iy]); + else + BL_CLR(x+ix, to[y+iy]); + } + } + return OK; +} diff --git a/Format/ascii2fax/char_util.c b/Format/ascii2fax/char_util.c new file mode 100644 index 0000000..8bd8f19 --- /dev/null +++ b/Format/ascii2fax/char_util.c @@ -0,0 +1,64 @@ +/* char_util.c: utility routines for chars */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/char_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/char_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: char_util.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + +#include "fonts.h" + +extern BitMap file2bitmap(); + +CharPtr +new_char() +{ + return (CharPtr) calloc(1, sizeof(Char)); +} + +free_char(c) +CharPtr c; +{ + if (c -> bits) + free_bitmap(c->bits, c->wid, c->ht); + free((char *)c); +} + +char2file(fp, c) +FILE *fp; +CharPtr c; +{ + fprintf(fp, "%d\n", c->ascii); + bitmap2file(fp, c->bits, c->wid, c->ht); +} + +CharPtr +file2char(fp) +FILE *fp; +{ + char buf[BUFSIZ]; + CharPtr ret; + + if (fgets(buf, BUFSIZ, fp) == NULLCP) { + fprintf(stderr, + "Incorrect file encoding of bitmap: unexpected EOF\n"); + return (CharPtr) NOTOK; + } + + ret = new_char(); + ret->ascii = (int) strtol(buf, NULL, 0); + if ((ret->bits = file2bitmap(fp, &(ret->wid), &(ret->ht))) == (BitMap) NOTOK) { + ret->bits = NULL; + free_char(ret); + return (CharPtr) NOTOK; + } + return ret; +} + diff --git a/Format/ascii2fax/font_util.c b/Format/ascii2fax/font_util.c new file mode 100644 index 0000000..8144b85 --- /dev/null +++ b/Format/ascii2fax/font_util.c @@ -0,0 +1,84 @@ +/* font_util.c: utility routines for fonts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/font_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/font_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: font_util.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + +#include "fonts.h" + +extern CharPtr file2char(); + +PPFontPtr +new_font(nchars) +int nchars; +{ + PPFontPtr ret = (PPFontPtr) malloc(sizeof(PPFont)); + ret->nchars = nchars; + ret->chars = (CharPtr *) calloc(ret->nchars, + sizeof(Char)); + return ret; +} + +free_font(f) +PPFontPtr f; +{ + int i; + for (i = 0; i < f->nchars; i++) + if (f->chars[i]) + free_char(f->chars[i]); + free((char *) f->chars); + free((char *) f); +} + +font2file(fp, f) +FILE *fp; +PPFontPtr f; +{ + int i; + + fprintf(fp, "%d\n", f->nchars); + for (i = 0; i < f->nchars; i++) + char2file(fp, f->chars[i]); +} + +PPFontPtr +file2font(fp) +FILE *fp; +{ + PPFontPtr ret; + char buf[BUFSIZ]; + int i; + + if (fgets(buf, BUFSIZ, fp) == NULLCP) { + fprintf(stderr, + "Incorrect file encoding of font: unexpected EOF"); + return (PPFontPtr) NOTOK; + } + + ret = (PPFontPtr) malloc(sizeof(PPFont)); + ret -> max_wid = ret -> max_ht = 0; + ret -> nchars = (int)strtol(buf, NULL, 0); + ret->chars = (CharPtr *) calloc(ret->nchars, + sizeof(CharPtr)); + for (i = 0; i < ret->nchars; i++) { + if ((ret->chars[i] = file2char(fp)) == (CharPtr) NOTOK) { + ret->chars[i] = NULL; + free_font(ret); + return (PPFontPtr) NOTOK; + } + if (ret->chars[i] -> wid > ret -> max_wid) + ret -> max_wid = ret -> chars[i] -> wid; + if (ret->chars[i] -> ht > ret -> max_ht) + ret -> max_ht = ret -> chars[i] -> ht; + } + return ret; +} diff --git a/Format/ascii2fax/fonts.h b/Format/ascii2fax/fonts.h new file mode 100644 index 0000000..883b310 --- /dev/null +++ b/Format/ascii2fax/fonts.h @@ -0,0 +1,47 @@ +/* fonts.h: local representation of font */ + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/fonts.h,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: fonts.h,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + * + */ +#include "util.h" +#include "sys.file.h" + +typedef int *BitLine; +typedef BitLine *BitMap; + +#define BITSPERCHAR 8 +#define BITSPERINT 16 +#define MAXCHARPERINT 8 + +/* nicked from FD_SET etc in sys/types.h */ +#define BL_SET(n, l) ((l)[(n)/BITSPERINT] |= (1 << ((n) % BITSPERINT))) +#define BL_CLR(n, l) ((l)[(n)/BITSPERINT] &= ~(1 << ((n) % BITSPERINT))) +#define BL_ISSET(n, l) ((l)[(n)/BITSPERINT] & (1 << ((n) % BITSPERINT))) + +#define BL_WD2CHAR(w) ((w)/BITSPERCHAR + 1) +#define BL_WD2INT(w) ((w)/BITSPERINT + 1) + +typedef struct _char { + int ascii; + int wid; /* in pixels */ + int ht; /* in pixels */ + BitMap bits; +} Char, *CharPtr; + +typedef struct _font { + int max_wid, max_ht; + int nchars; + CharPtr *chars; /* [nchars] indexed by ascii value */ +} PPFont, *PPFontPtr; + +typedef struct _str { + int nchars; + CharPtr *chars; + char *orig; +} Str, *StrPtr; diff --git a/Format/ascii2fax/g3.h b/Format/ascii2fax/g3.h new file mode 100644 index 0000000..1e287ed --- /dev/null +++ b/Format/ascii2fax/g3.h @@ -0,0 +1,242 @@ +/* g3.h - header file for group 3 FAX compression filters */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/g3.h,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: g3.h,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _G3_H_ +#define _G3_H_ + +typedef struct tableentry { + int tabid; + int code; + int length; + int count; + } tableentry; + +#define TWTABLE 23 +#define MWTABLE 24 +#define TBTABLE 25 +#define MBTABLE 26 +#define EXTABLE 27 +#define VRTABLE 28 + +struct tableentry twtable[] = { + { TWTABLE, 0x35, 8, 0 }, + { TWTABLE, 0x7, 6, 1 }, + { TWTABLE, 0x7, 4, 2 }, + { TWTABLE, 0x8, 4, 3 }, + { TWTABLE, 0xb, 4, 4 }, + { TWTABLE, 0xc, 4, 5 }, + { TWTABLE, 0xe, 4, 6 }, + { TWTABLE, 0xf, 4, 7 }, + { TWTABLE, 0x13, 5, 8 }, + { TWTABLE, 0x14, 5, 9 }, + { TWTABLE, 0x7, 5, 10 }, + { TWTABLE, 0x8, 5, 11 }, + { TWTABLE, 0x8, 6, 12 }, + { TWTABLE, 0x3, 6, 13 }, + { TWTABLE, 0x34, 6, 14 }, + { TWTABLE, 0x35, 6, 15 }, + { TWTABLE, 0x2a, 6, 16 }, + { TWTABLE, 0x2b, 6, 17 }, + { TWTABLE, 0x27, 7, 18 }, + { TWTABLE, 0xc, 7, 19 }, + { TWTABLE, 0x8, 7, 20 }, + { TWTABLE, 0x17, 7, 21 }, + { TWTABLE, 0x3, 7, 22 }, + { TWTABLE, 0x4, 7, 23 }, + { TWTABLE, 0x28, 7, 24 }, + { TWTABLE, 0x2b, 7, 25 }, + { TWTABLE, 0x13, 7, 26 }, + { TWTABLE, 0x24, 7, 27 }, + { TWTABLE, 0x18, 7, 28 }, + { TWTABLE, 0x2, 8, 29 }, + { TWTABLE, 0x3, 8, 30 }, + { TWTABLE, 0x1a, 8, 31 }, + { TWTABLE, 0x1b, 8, 32 }, + { TWTABLE, 0x12, 8, 33 }, + { TWTABLE, 0x13, 8, 34 }, + { TWTABLE, 0x14, 8, 35 }, + { TWTABLE, 0x15, 8, 36 }, + { TWTABLE, 0x16, 8, 37 }, + { TWTABLE, 0x17, 8, 38 }, + { TWTABLE, 0x28, 8, 39 }, + { TWTABLE, 0x29, 8, 40 }, + { TWTABLE, 0x2a, 8, 41 }, + { TWTABLE, 0x2b, 8, 42 }, + { TWTABLE, 0x2c, 8, 43 }, + { TWTABLE, 0x2d, 8, 44 }, + { TWTABLE, 0x4, 8, 45 }, + { TWTABLE, 0x5, 8, 46 }, + { TWTABLE, 0xa, 8, 47 }, + { TWTABLE, 0xb, 8, 48 }, + { TWTABLE, 0x52, 8, 49 }, + { TWTABLE, 0x53, 8, 50 }, + { TWTABLE, 0x54, 8, 51 }, + { TWTABLE, 0x55, 8, 52 }, + { TWTABLE, 0x24, 8, 53 }, + { TWTABLE, 0x25, 8, 54 }, + { TWTABLE, 0x58, 8, 55 }, + { TWTABLE, 0x59, 8, 56 }, + { TWTABLE, 0x5a, 8, 57 }, + { TWTABLE, 0x5b, 8, 58 }, + { TWTABLE, 0x4a, 8, 59 }, + { TWTABLE, 0x4b, 8, 60 }, + { TWTABLE, 0x32, 8, 61 }, + { TWTABLE, 0x33, 8, 62 }, + { TWTABLE, 0x34, 8, 63 }, + }; + +struct tableentry mwtable[] = { + { MWTABLE, 0x1b, 5, 64 }, + { MWTABLE, 0x12, 5, 128 }, + { MWTABLE, 0x17, 6, 192 }, + { MWTABLE, 0x37, 7, 256 }, + { MWTABLE, 0x36, 8, 320 }, + { MWTABLE, 0x37, 8, 384 }, + { MWTABLE, 0x64, 8, 448 }, + { MWTABLE, 0x65, 8, 512 }, + { MWTABLE, 0x68, 8, 576 }, + { MWTABLE, 0x67, 8, 640 }, + { MWTABLE, 0xcc, 9, 704 }, + { MWTABLE, 0xcd, 9, 768 }, + { MWTABLE, 0xd2, 9, 832 }, + { MWTABLE, 0xd3, 9, 896 }, + { MWTABLE, 0xd4, 9, 960 }, + { MWTABLE, 0xd5, 9, 1024 }, + { MWTABLE, 0xd6, 9, 1088 }, + { MWTABLE, 0xd7, 9, 1152 }, + { MWTABLE, 0xd8, 9, 1216 }, + { MWTABLE, 0xd9, 9, 1280 }, + { MWTABLE, 0xda, 9, 1344 }, + { MWTABLE, 0xdb, 9, 1408 }, + { MWTABLE, 0x98, 9, 1472 }, + { MWTABLE, 0x99, 9, 1536 }, + { MWTABLE, 0x9a, 9, 1600 }, + { MWTABLE, 0x18, 6, 1664 }, + { MWTABLE, 0x9b, 9, 1728 }, + }; + +struct tableentry tbtable[] = { + { TBTABLE, 0x37, 10, 0 }, + { TBTABLE, 0x2, 3, 1 }, + { TBTABLE, 0x3, 2, 2 }, + { TBTABLE, 0x2, 2, 3 }, + { TBTABLE, 0x3, 3, 4 }, + { TBTABLE, 0x3, 4, 5 }, + { TBTABLE, 0x2, 4, 6 }, + { TBTABLE, 0x3, 5, 7 }, + { TBTABLE, 0x5, 6, 8 }, + { TBTABLE, 0x4, 6, 9 }, + { TBTABLE, 0x4, 7, 10 }, + { TBTABLE, 0x5, 7, 11 }, + { TBTABLE, 0x7, 7, 12 }, + { TBTABLE, 0x4, 8, 13 }, + { TBTABLE, 0x7, 8, 14 }, + { TBTABLE, 0x18, 9, 15 }, + { TBTABLE, 0x17, 10, 16 }, + { TBTABLE, 0x18, 10, 17 }, + { TBTABLE, 0x8, 10, 18 }, + { TBTABLE, 0x67, 11, 19 }, + { TBTABLE, 0x68, 11, 20 }, + { TBTABLE, 0x6c, 11, 21 }, + { TBTABLE, 0x37, 11, 22 }, + { TBTABLE, 0x28, 11, 23 }, + { TBTABLE, 0x17, 11, 24 }, + { TBTABLE, 0x18, 11, 25 }, + { TBTABLE, 0xca, 12, 26 }, + { TBTABLE, 0xcb, 12, 27 }, + { TBTABLE, 0xcc, 12, 28 }, + { TBTABLE, 0xcd, 12, 29 }, + { TBTABLE, 0x68, 12, 30 }, + { TBTABLE, 0x69, 12, 31 }, + { TBTABLE, 0x6a, 12, 32 }, + { TBTABLE, 0x6b, 12, 33 }, + { TBTABLE, 0xd2, 12, 34 }, + { TBTABLE, 0xd3, 12, 35 }, + { TBTABLE, 0xd4, 12, 36 }, + { TBTABLE, 0xd5, 12, 37 }, + { TBTABLE, 0xd6, 12, 38 }, + { TBTABLE, 0xd7, 12, 39 }, + { TBTABLE, 0x6c, 12, 40 }, + { TBTABLE, 0x6d, 12, 41 }, + { TBTABLE, 0xda, 12, 42 }, + { TBTABLE, 0xdb, 12, 43 }, + { TBTABLE, 0x54, 12, 44 }, + { TBTABLE, 0x55, 12, 45 }, + { TBTABLE, 0x56, 12, 46 }, + { TBTABLE, 0x57, 12, 47 }, + { TBTABLE, 0x64, 12, 48 }, + { TBTABLE, 0x65, 12, 49 }, + { TBTABLE, 0x52, 12, 50 }, + { TBTABLE, 0x53, 12, 51 }, + { TBTABLE, 0x24, 12, 52 }, + { TBTABLE, 0x37, 12, 53 }, + { TBTABLE, 0x38, 12, 54 }, + { TBTABLE, 0x27, 12, 55 }, + { TBTABLE, 0x28, 12, 56 }, + { TBTABLE, 0x58, 12, 57 }, + { TBTABLE, 0x59, 12, 58 }, + { TBTABLE, 0x2b, 12, 59 }, + { TBTABLE, 0x2c, 12, 60 }, + { TBTABLE, 0x5a, 12, 61 }, + { TBTABLE, 0x66, 12, 62 }, + { TBTABLE, 0x67, 12, 63 }, + }; + +struct tableentry mbtable[] = { + { MBTABLE, 0xf, 10, 64 }, + { MBTABLE, 0xc8, 12, 128 }, + { MBTABLE, 0xc9, 12, 192 }, + { MBTABLE, 0x5b, 12, 256 }, + { MBTABLE, 0x33, 12, 320 }, + { MBTABLE, 0x34, 12, 384 }, + { MBTABLE, 0x35, 12, 448 }, + { MBTABLE, 0x6c, 13, 512 }, + { MBTABLE, 0x6d, 13, 576 }, + { MBTABLE, 0x4a, 13, 640 }, + { MBTABLE, 0x4b, 13, 704 }, + { MBTABLE, 0x4c, 13, 768 }, + { MBTABLE, 0x4d, 13, 832 }, + { MBTABLE, 0x72, 13, 896 }, + { MBTABLE, 0x73, 13, 960 }, + { MBTABLE, 0x74, 13, 1024 }, + { MBTABLE, 0x75, 13, 1088 }, + { MBTABLE, 0x76, 13, 1152 }, + { MBTABLE, 0x77, 13, 1216 }, + { MBTABLE, 0x52, 13, 1280 }, + { MBTABLE, 0x53, 13, 1344 }, + { MBTABLE, 0x54, 13, 1408 }, + { MBTABLE, 0x55, 13, 1472 }, + { MBTABLE, 0x5a, 13, 1536 }, + { MBTABLE, 0x5b, 13, 1600 }, + { MBTABLE, 0x64, 13, 1664 }, + { MBTABLE, 0x65, 13, 1728 }, + }; + +struct tableentry extable[] = { + { EXTABLE, 0x8, 11, 1792 }, + { EXTABLE, 0xc, 11, 1856 }, + { EXTABLE, 0xd, 11, 1920 }, + { EXTABLE, 0x12, 12, 1984 }, + { EXTABLE, 0x13, 12, 2048 }, + { EXTABLE, 0x14, 12, 2112 }, + { EXTABLE, 0x15, 12, 2176 }, + { EXTABLE, 0x16, 12, 2240 }, + { EXTABLE, 0x17, 12, 2304 }, + { EXTABLE, 0x1c, 12, 2368 }, + { EXTABLE, 0x1d, 12, 2432 }, + { EXTABLE, 0x1e, 12, 2496 }, + { EXTABLE, 0x1f, 12, 2560 }, + }; + +#endif /*_G3_H_*/ diff --git a/Format/ascii2fax/hdr2fax.c b/Format/ascii2fax/hdr2fax.c new file mode 100644 index 0000000..4a52dc0 --- /dev/null +++ b/Format/ascii2fax/hdr2fax.c @@ -0,0 +1,891 @@ +/* hdr2fax.c: convert 822 hdr to fax image */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/hdr2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/hdr2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: hdr2fax.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ +#include +#include "util.h" +#include +#include "or.h" +#include "IOB-types.h" +#include "table.h" +#include "fonts.h" +#include "ap.h" +#include "pg_sizes.h" + +extern BitMap new_bitmap(), file2bitmap(); + +char *myname; +static char buffer[BUFSIZ], buf2[BUFSIZ]; +static char *read822hdr(); +static int draw2Str(), drawStr(); +char *loc_telfax_number; +char *loc_company; +char *postscript; +char *outmta; + +#define OPT_FROM 1 +#define OPT_TO 2 +#define OPT_SUBJECT 3 +#define OPT_TABLE 4 +#define OPT_OUTMTA 6 + +CMD_TABLE tbl_options [] = { /* hdr2fax commandline options */ + "-from", OPT_FROM, + "-to", OPT_TO, + "-subject", OPT_SUBJECT, + "-table", OPT_TABLE, + "-outmta", OPT_OUTMTA, + 0, -1 + }; + +char *to, + *from, + *subject, + *page, + *display_str, + *date = NULLCP, + *from822 = NULLCP; +int x_start, + y_start, + page_x, + page_y; +PPFontPtr large = NULL, + bold = NULL, + norm = NULL; + +double res = 3.85; /*7.7;*/ /* pixels/lines per mm in y direction */ +double xres = FAX_WIDTH_LINES/FAX_WIDTH; /* pixels per mm in x direct */ +int tab; +Table *table = NULLTBL; + +main(argc, argv) +int argc; +char **argv; +{ + struct type_IOB_G3FacsimileBodyPart *p2; + BitMap coversheet; + + sys_init(argv[0]); + argv++; + while (*argv != NULL) { + switch (cmd_srch(*argv,tbl_options)) { + case OPT_FROM: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no sender given with flag %s", *argv); + else { + argv++; + from = *argv; + } + break; + + case OPT_TO: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no recipient given with flag %s", *argv); + else { + argv++; + to = *argv; + } + break; + + case OPT_OUTMTA: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no recipient given with flag %s", *argv); + else { + argv++; + if (lexequ(*argv, "none") != 0) + outmta = *argv; + } + break; + + case OPT_SUBJECT: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no subject given with flag %s", *argv); + else { + argv++; + subject = *argv; + } + break; + + case OPT_TABLE: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no table given with flag %s", *argv); + else { + argv++; + if (lexequ(*argv, "none") != 0 + && ((table = tb_nm2struct (*argv)) == NULLTBL)) { + fprintf(stderr, + "Cannot initialise table '%s'\n", *argv); + exit (1); + } + } + break; + + default: + fprintf(stderr, + "unknown option '%s'", *argv); + exit(1); + } + argv++; + } + + if (table == NULLTBL) { + fprintf(stderr, + "No table passed over in info field for filter '%s'", + argv[0]); + exit(1); + } + + if (initialise_globals() != OK) { + fprintf(stderr, + "Unable to initialise fonts"); + exit(1); + } + + p2 = (struct type_IOB_G3FacsimileBodyPart *) + calloc (1, sizeof(struct type_IOB_G3FacsimileBodyPart)); + + p2 -> parameters = (struct type_IOB_G3FacsimileParameters *) + calloc (1, sizeof(struct type_IOB_G3FacsimileParameters)); + + p2 -> parameters -> optionals = + opt_IOB_G3FacsimileParameters_number__of__pages; + + coversheet = new_bitmap(FAX_WIDTH_LINES, FAX_HEIGHT_LINES); + + if (create_cover_sheet(coversheet, + FAX_WIDTH_LINES, FAX_HEIGHT_LINES) != OK) + exit(1); + + encodeImage(coversheet, + FAX_WIDTH_LINES, FAX_HEIGHT_LINES, + p2); + outputFax(p2, stdout); + free_bitmap(coversheet, FAX_WIDTH_LINES, FAX_HEIGHT_LINES); + exit(0); +} + +/* */ + +/* replace \n's with \n's ! */ + +static char *mystrdup(str) +char *str; +{ + char *retstr = malloc((strlen(str)+1) * sizeof(char)); + char *ix, *iy; + + for (ix = str, iy = retstr; *ix != '\0'; ix++, iy++) { + if (*ix == '\\') { + switch (*(ix+1)) { + case 'n': + *iy = '\n'; + ix++; + break; + default: + *iy = *ix; + break; + } + } else + *iy = *ix; + } + *iy = '\0'; + return retstr; +} + +extern PPFontPtr file2font(); + +int +initialise_globals() +{ + FILE *fp; + x_start = LEFT_PAD_LINES; + y_start = TOP_PAD_LINES; + page = NULLCP; page_x = 0; page_y = 0; + tab = 50; /* mm */ + loc_company = NULLCP; + loc_telfax_number = NULLCP; + postscript = NULLCP; + + if (table != NULLTBL) { + if (tb_k2val (table, "keyfont", buffer, TRUE) != NOTOK) { + if ((fp = fopen(buffer, "r")) == NULL + || (large = file2font(fp)) == (PPFontPtr) NOTOK) + return NOTOK; + fclose(fp); + } + + if (tb_k2val (table, "valuefont", buffer, TRUE) != NOTOK) { + if ((fp = fopen(buffer, "r")) == NULL + || (bold = file2font(fp)) == (PPFontPtr) NOTOK) + return NOTOK; + fclose(fp); + } + if (tb_k2val (table, "textfont", buffer, TRUE) != NOTOK) { + if ((fp = fopen(buffer, "r")) == NULL + || (norm = file2font(fp)) == (PPFontPtr) NOTOK) + return NOTOK; + fclose(fp); + } + if (tb_k2val (table, "xstart", buffer, TRUE) != NOTOK) + x_start = str2mm(buffer) * xres + X_ALLOWED_NOT_PRINT; + if (tb_k2val (table, "ystart", buffer, TRUE) != NOTOK) + y_start = (str2mm(buffer) + Y_ALLOWED_NOT_PRINT_TOP) * res; + if (tb_k2val (table, "tab", buffer, TRUE) != NOTOK) + tab = str2mm(buffer); + if (tb_k2val (table, "coverpage", buffer, TRUE) != NOTOK) + page = strdup(buffer); + if (tb_k2val (table, "localOrg", buffer, TRUE) != NOTOK) + loc_company = mystrdup(buffer); + if (tb_k2val (table, "localNumber", buffer, TRUE) != NOTOK) + loc_telfax_number = strdup(buffer); + if (tb_k2val (table, "postscript", buffer, TRUE) != NOTOK) + postscript = mystrdup(buffer); + } else + return NOTOK; + return OK; +} + +/* copied from Chans/fax_aux.c */ +get_fax_number(adr, ptelno, porg) +char *adr; +char **ptelno, **porg; +{ + OR_ptr or, or2; + char *telno = NULLCP; + + *porg = NULLCP; + *ptelno = NULLCP; + + or = or_std2or(adr); + or2 = or; + while (or2 = or_locate (or2, OR_DD)) { + if (cmd_srch(or2->or_ddname, + ortbl_ddvalid) == OR_DDVALID_FAX) { + telno = strdup (or2->or_value); + break; + } else if (or2 -> or_next != NULLOR) + or2 = or2 -> or_next; + else + break; + + } + + /* use outmta */ + if (telno == NULLCP + && outmta != NULLCP) + telno = strdup(outmta); + + if (telno != NULLCP + && table != NULLTBL + && tb_k2val (table, telno, buffer, TRUE) != NOTOK) { + free(telno); + tblentry2num(buffer, ptelno, porg); + } else { + *ptelno = telno; + } + or_free(or); +} + +tblentry2num(buf, ptelno, porg) +char *buf; +char **ptelno; +char **porg; +{ + char *telno = NULLCP, *org = NULLCP, *ix, *iy; + + if ((ix = index(buf, ',')) == NULLCP) { + /* must all be number */ + compress(buf,buf); + } else { + *ix++ = '\0'; + compress(buf, buf); + /* for now rest is company */ + if (*ix != '\0') + org = strdup(ix); + } + telno = malloc(strlen(buf)*sizeof(char)); + + ix = buf; + iy = telno; + + while (*ix != '\0') + switch (*ix) { + case 'p': + case 'P': + ix++; + break; + default: + *iy++ = *ix++; + break; + } + + *iy = '\0'; + + if (ptelno != NULL) + *ptelno = telno; + else if (telno != NULLCP) + free(telno); + + if (porg != NULL) + *porg = org; + else if (org != NULLCP) + free(org); +} + +extern char *loc_or; + +int +create_cover_sheet(p, wid, ht) +BitMap p; +int wid, ht; +{ + int x = x_start, y = y_start, nx, ny1, remain; + char *rfchdr = NULLCP, *telno = NULLCP, *org = NULLCP; + AP_ptr tree, group, name, local, domain, route; + + if (page != NULLCP) { + BitMap b; + int w, h; + FILE *fp; + if ((fp = fopen(page, "r")) == NULL) { + PP_SLOG(LLOG_EXCEPTIONS, page, + ("Can't open cover page bitmap file")); + return NOTOK; + } + if ((b = file2bitmap(fp, &w, &h)) == (BitMap) NOTOK) { + fprintf(stderr, + "Unable to read in bitmap from file '%s'", + page); + return NOTOK; + } + /* center on x */ + remain = (wid - w - page_x)/2; + + if (insertbitmap(p, wid, ht, + b, w, h, + remain + page_x, page_y) == NOTOK) { + free_bitmap(b, w, h); + return NOTOK; + } + free_bitmap(b, w, h); + } + + rfchdr = read822hdr(&subject); + + if (to != NULLCP) { + OR_ptr or, or2; + int doneTo = FALSE; + or = or_std2or (to); + + or2 = or; + while (or2 = or_locate (or2, OR_DD)) { + if (cmd_srch(or2->or_ddname, + ortbl_ddvalid) == OR_DDVALID_ATTN) { + char *str; + (void) sprintf(buf2, + "For the attention of: "); + str = mystrdup(or2 -> or_value); + draw2Str(p, wid, ht, + &x, &y, + buf2, large, + str, bold); + free(str); + doneTo = TRUE; + } + if (or2 -> or_next != NULLOR) + or2 = or2 -> or_next; + else + break; + } + + if (doneTo == FALSE) { + if (or_getpn(or, buffer) != TRUE) + buffer[0] = '\0'; + if (or2 = or_locate (or, OR_OU)) { + /* see if local or not */ + or_or2std(or2, buf2, FALSE); + if (lexequ(buf2, loc_or) != 0) { + /* not local so add in mail box */ + if (or_or2rfc (or, buf2) == NOTOK) + /* failed to convert to 822 */ + /* use x400 address */ + strcpy(buf2, to); + if (buffer[0] == '\0') + strcpy(buffer, buf2); + else { + strcat(buffer, " ("); + strcat(buffer, buf2); + strcat(buffer, ")"); + } + } + } + + if (buffer[0] == '\0') + strcpy(buffer, to); + (void) sprintf(buf2, "To: "); + draw2Str(p, wid, ht, + &x, &y, + buf2, large, + buffer, bold); + } + + get_fax_number(to, &telno, &org); + if (org != NULLCP) { + char *cp; + (void) sprintf (buf2, "At: "); + cp = mystrdup(org); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + cp, bold); + free(org); + free(cp); + } + if (telno != NULLCP && atoi(telno) != 0) { + (void) sprintf (buf2, "TeleFax-No: "); + + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + telno, bold); + free(telno); + } + or_free(or); + } + + y += large->max_ht*2; + + /* try one from hdr.822 first */ + if (from822 != NULLCP + && ap_s2p(from822, + &tree, &group, &name, + &local, &domain, &route) != (char *) NOTOK) { + char *m; + if (name != NULLAP) { + char *ix; + m = ap_p2s(NULLAP, name, + NULLAP, NULLAP, + NULLAP); + if ((ix = rindex(m, '<')) != NULLCP) + *ix = '\0'; + strcpy(buffer, m); + free (m); + } else + strcpy(buffer, local->ap_obvalue); + m = ap_p2s(NULLAP, NULLAP, + local, domain, + NULLAP); + strcat(buffer, "(email=\""); + strcat(buffer, m); + strcat(buffer, "\")"); + free (m); + ap_sqdelete(tree, NULLAP); + ap_free(tree); + free(from822); + + (void) sprintf(buf2, "From: "); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + buffer, bold); + + } else if (from != NULLCP) { + /* try one from envelope */ + OR_ptr or, or2; + or = or_std2or (from); + + or2 = or; + if (or_getpn(or, buffer) == TRUE) { + if (or2 = or_locate(or, OR_OU)) { + /* see if local or not */ + or_or2std(or2, buf2, FALSE); + if (lexequ(buf2, loc_or) != 0) { + or2 = or; + (void) strcat (buffer, " ("); + while (or2 = or_locate (or2, OR_OU)) { + (void) sprintf(buffer, "%s%s;", + buffer, or2 -> or_value); + if (or2 -> or_next != NULLOR) + or2 = or2 -> or_next; + else + break; + } + if (or2 = or_locate (or, OR_O)) + (void) sprintf(buffer, "%s%s;", + buffer, or2 -> or_value); + + if (or2 = or_locate (or, OR_PRMD)) + (void) sprintf(buffer, "%s%s;", + buffer, or2 -> or_value); + + if ((or2 = or_locate (or, OR_ADMD)) + && lexequ(or2 -> or_value, " ") != 0) + (void) sprintf(buffer, "%s%s;", + buffer, or2 -> or_value); + + if (or2 = or_locate (or, OR_C)) + (void) sprintf(buffer, "%s%s", + buffer, or2 -> or_value); + (void) strcat (buffer, ")"); + } + } + } else if ((or2 = or_find(or, OR_DD, "RFC-822")) != NULLOR) + or_ps2asc(or2->or_value, buffer); + else + strcat(buffer, from); + + (void) sprintf(buf2, "From: "); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + buffer, bold); + + or_free(or); + } + + if (loc_company != NULLCP) { + (void) sprintf(buf2, "Organisation: "); + (void) sprintf(buffer, loc_company); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + buffer, bold); + } + + if (loc_telfax_number != NULLCP) { + (void) sprintf(buf2, "TeleFax-No: "); + (void) sprintf(buffer, "%s", loc_telfax_number); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + buffer, bold); + } + + y += large->max_ht*2; + + if (date != NULLCP) { + (void) sprintf(buf2, "Date: "); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + date, bold); + free(date); + date = NULLCP; + } + + if (subject != NULLCP) { + (void) sprintf(buf2, "Subject: "); + draw2Str (p, wid, ht, + &x, &y, + buf2, large, + subject, bold); + } + + y += large->max_ht; + + if (rfchdr != NULLCP) { + drawStr(p, wid, ht, + norm, + x, y, + rfchdr, + &nx, &y); + free(rfchdr); + rfchdr = NULLCP; + } + + y += large->max_ht; + + if (postscript != NULLCP) { + drawStr(p, wid, ht, + norm, + x, y, + postscript, + &nx, &ny1); + y = ny1; + } + return OK; +} + +/* */ + +static int +draw2Str(p, w, h, px, py, s1, f1, s2, f2) +BitMap p; +int w, h; +int *px, *py; +char *s1; +PPFontPtr f1; +char *s2; +PPFontPtr f2; +{ + int nx, y1, y2; + + drawStr(p, w, h, + f1, + *px, *py, + s1, + &nx, &y1); + if (nx - *px < tab * xres) + nx = *px + (tab * xres); + drawStr(p, w, h, + f2, + nx, *py, + s2, + &nx, &y2); + *py = (y2 > y1) ? y2 : y1; +} + +static int drawStr (p, w, h, f, x, y, s, nx, ny) +BitMap p; +int w, h; +PPFontPtr f; +int x, y; +char *s; +int *nx, *ny; +{ + int nolines, ix, my_y = y, longest_x = 0; + char *lines[100]; + + nolines = sstr2arg (s, 100, lines, "\n"); + + for (ix = 0; ix < nolines; ix++) { + int dy, i = 0, dx; + char *buffer = lines[ix]; + char *cix = &(buffer[0]); + /* take care of any folding */ + while (cix - buffer < (int)strlen(buffer)) { + i = str_into_bitmap(p,f,x,my_y, &dx, &dy, + FAX_WIDTH_LINES - LEFT_PAD_LINES, + cix, + strlen(cix)); + cix += i; + if (dx > longest_x) longest_x = dx; + my_y += dy; + } + } + + *ny = my_y; + *nx = x + longest_x; +} + +/* */ + +str2mm(s) +char *s; +{ + int n, div = 1; + if (*s == NULL) return 0; + + n = 0; + while (*s != NULL && isspace(*s)) s++; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + s++; + } + if (*s == '.') { + /* after decimal points */ + s++; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + if (div == 1) + div = 10; + else + div *= 10; + s++; + } + } + while (*s != NULL && isspace(*s)) s++; + if (*s != NULL && isalpha(*s)) { + if (lexequ (s, "cm") == 0) + n *= 10; + else if (lexequ (s, "in") == 0) { + n *= 254; + if (div == 1) + div = 10; + else + div *= 10; + } + } + n = n / div; + return n; +} + +/* */ +/* straight from submit/rd_rfchdr.c */ + +/* -- basic states for the state machine -- */ +#define HDV_EOH 0 +#define HDV_NEW 1 +#define HDV_MORE 2 + +/* -- munge the header lines of the message -- */ +#define HDR_FROM 1 +#define HDR_SENDER 2 +#define HDR_CC 3 +#define HDR_TO 4 +#define HDR_SUBJECT 5 +#define HDR_DATE 6 + +static CMD_TABLE htbl_rfc [] = { + "from", HDR_FROM, + "sender", HDR_SENDER, + "cc", HDR_CC, + "to", HDR_TO, + "subject", HDR_SUBJECT, + "date", HDR_DATE, + 0, 0 + }; + +static int getline (bp, fp) +char **bp; +FILE *fp; +{ + static char *buf; + static int bufsiz = 0; + int count; + char *cp; + int c; + + if (buf == NULLCP) + buf = smalloc (bufsiz = BUFSIZ); + for (cp = buf, count = 0; ; count ++) { + if (count >= bufsiz - 5) { + int curlen = cp - buf; + buf = realloc (buf, (unsigned) (bufsiz += BUFSIZ)); + if (buf == NULL) { + fprintf(stderr, + "Out of memory"); + exit(1); + } + cp = buf + curlen; + } + switch (c = getc (fp)) { + case '\n': + if ((c = getc(fp)) == ' ' || c == '\t') { + *cp ++ = '\n'; + continue; + } + ungetc (c, fp); + break; + case EOF: + if (cp == buf) + return NOTOK; + break; + default: + *cp ++ = c; + continue; + } + break; + } + *cp = '\0'; + *bp = buf; + return OK; +} + +static int hdr_parse (txt, name, contents) /* -- parse one header line -- */ +register char *txt; /* -- a line of header text -- */ +char **name; /* -- location of field's name -- */ +char **contents; /* -- location of field's contents -- */ +{ + char linetype; + + + PP_DBG (("submit/hdr_parse (%s)", txt)); + + + if (isspace (*txt)) { + /* -- continuation text -- */ + if (*txt == '\n' || *txt == '\0') + return (HDV_EOH); + linetype = HDV_MORE; + } + else { + linetype = HDV_NEW; + + *name = txt; + while (*txt && *txt != ':') + txt ++; + if (*txt == '\0' || *txt == '\n') + return NOTOK; + *txt ++ = '\0'; + + (void) compress (*name, *name); + } + + + *contents = txt; + + return (linetype); +} + +static char *read822hdr (psubject) +char **psubject; +{ + char *retstr = NULLCP, *bp, *temp, *addon, *name, *contents; + int retval, type, len; + + while (getline (&bp, stdin) == OK) { + switch (retval = hdr_parse (bp, &name, &contents)) { + case HDV_MORE: + continue; + case HDV_NEW: + if ((type = cmd_srch (name, htbl_rfc)) > 0) { + switch (type) { + case HDR_DATE: + date = strdup(contents); + break; + + case HDR_SUBJECT: + *psubject = strdup(contents); + break; + case HDR_FROM: + from822 = strdup(contents); + case HDR_SENDER: + case HDR_CC: + case HDR_TO: + len = strlen(name) + strlen(contents) + 2; + addon = calloc(len, sizeof(char)); + (void) sprintf(addon, "%s:%s",name,contents); + + if (retstr == NULLCP) + retstr = addon; + else { + len = strlen(addon) + strlen(retstr) + 1; + temp = calloc(len, sizeof(char)); + (void) sprintf (temp, "%s\n%s", retstr, addon); + free(retstr); + free(addon); + retstr = temp; + } + break; + default: + break; + } + } + continue; + case HDV_EOH: + break; + case NOTOK: + fprintf(stderr, + "hdr2fax: Unable to parse '%s' as key:field", bp); + break; + } + break; + } + return retstr; +} diff --git a/Format/ascii2fax/ia52fax.c b/Format/ascii2fax/ia52fax.c new file mode 100644 index 0000000..1bf3a5e --- /dev/null +++ b/Format/ascii2fax/ia52fax.c @@ -0,0 +1,204 @@ +/* ia52fax: convert ia5 to fax */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/ia52fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/ia52fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: ia52fax.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + + +#include +#include "util.h" +#include "IOB-types.h" +#include +#include "table.h" +#include "fonts.h" +#include "pg_sizes.h" + +#define OPT_TABLE 1 +#define OPT_FONT 2 + +CMD_TABLE tbl_options [] = { + "-table", OPT_TABLE, + "-font", OPT_FONT, + 0, -1 + }; + +char *display_str; +char *myname; +Table *table = NULLTBL; +char *font = NULLCP; + +extern BitMap new_bitmap(); +extern PPFontPtr file2font(); + +main(argc, argv) +int argc; +char **argv; +{ + PPFontPtr ppfont; + int cont = TRUE; + struct type_IOB_G3FacsimileBodyPart *p2; + BitMap page; + int y; + FILE *fp; + char buffer[BUFSIZ], *start = NULLCP, *postCtrlL = NULLCP; + + myname = *argv++; + + sys_init(myname); + + p2 = (struct type_IOB_G3FacsimileBodyPart *) + calloc (1, sizeof(struct type_IOB_G3FacsimileBodyPart)); + + p2 -> parameters = (struct type_IOB_G3FacsimileParameters *) + calloc (1, sizeof(struct type_IOB_G3FacsimileParameters)); + + p2 -> parameters -> optionals = + opt_IOB_G3FacsimileParameters_number__of__pages; + + + while (*argv != NULL) { + switch (cmd_srch(*argv,tbl_options)) { + case OPT_TABLE: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no table given with flag %s", *argv); + else { + argv++; + if (lexequ(*argv, "none") != 0 + && ((table = tb_nm2struct (*argv)) == NULLTBL)) { + fprintf(stderr, + "Cannot initialise table '%s'\n", *argv); + exit (1); + } + } + break; + + case OPT_FONT: + if (*(argv+1) == NULLCP) + fprintf(stderr, + "no argument given with flag %s", *argv); + else { + argv++; + font = *argv; + } + break; + + default: + fprintf(stderr, + "unknown option '%s'\n", *argv); + exit(1); + } + argv++; + } + + /* Load the font to use */ + + initialise_globals(); + + if (font == NULLCP) { + fprintf(stderr, + "No font specified"); + exit(1); + } + if ((fp = fopen(font, "r")) == NULL + || (ppfont = file2font(fp)) == (PPFontPtr) NOTOK) { + fprintf(stderr, + "unable to read in font from file '%s'",font); + exit(1); + } + + page = new_bitmap(FAX_WIDTH_LINES, FAX_HEIGHT_LINES); + + /* read the stdin a line at a time */ + while( cont == TRUE ) { + /* do a page */ + clr_bitmap(page,FAX_WIDTH_LINES, FAX_HEIGHT_LINES); + + y = TOP_PAD_LINES; + + while (y + ppfont-> max_ht <= TEXT_HEIGHT_LINES + && cont == TRUE) { + + if (start == NULLCP) { + if (fgets(buffer, BUFSIZ, stdin) == NULL) + cont = FALSE; + else { + /* knock off trailing \n */ + if ((start = rindex(buffer, '\n')) != NULLCP) + *start = '\0'; + start = &(buffer[0]); + } + } + if (cont == TRUE) { + if (*start == '\0') { + y += ppfont->max_ht; + start = NULLCP; + } else { + int dy, dx, i = 0; + char *ix; + if ((postCtrlL = index(start, ' ')) != NULLCP) + *postCtrlL++ = '\0'; + + ix = start; + while (ix - start < (int)strlen(start) + && y + ppfont->max_ht <= TEXT_HEIGHT_LINES) { + i = str_into_bitmap(page, + ppfont, + LEFT_PAD_LINES, + y, + &dx, + &dy, + FAX_WIDTH_LINES - LEFT_PAD_LINES, + ix, + strlen(ix)); + ix += i; + y += dy; + } + + if (ix - start >= (int) strlen(start)) + start = NULLCP; + else + start = ix; + + if (postCtrlL != NULLCP) { + /* force new page */ + if (*postCtrlL == '\0') + start = NULLCP; + else + start = postCtrlL; + postCtrlL = NULLCP; + y = TEXT_HEIGHT_LINES; + } + } + } + } + encodeImage(page, + FAX_WIDTH_LINES, FAX_HEIGHT_LINES, + p2); + } + + outputFax(p2, stdout); + exit(0); +} + +int +initialise_globals() +{ + char buffer[BUFSIZ]; + + if (table != NULLTBL) { + if (font == NULLCP + && tb_k2val (table, "textfont", buffer, TRUE) != NOTOK) + font = strdup(buffer); + } +} + diff --git a/Format/ascii2fax/image2fax.c b/Format/ascii2fax/image2fax.c new file mode 100644 index 0000000..5e58ab1 --- /dev/null +++ b/Format/ascii2fax/image2fax.c @@ -0,0 +1,322 @@ +/* image2fax.c: conversion routines from PP image to x400 fax */ +/* code "borrowed" from QUIPU */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/image2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/image2fax.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: image2fax.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + +#include +#include "util.h" +#include "IOB-types.h" +#include "g3.h" +#include +#include "fonts.h" + +# define BITSPERBYTE 8 + +void advise (); +void adios (); + +#define ps_advise(ps, f) \ + advise (NULLCP, "%s: %s", (f), ps_error ((ps) -> ps_errno)) + +static char *store = NULLCP; +static int storeix = 0, store_allocd = 0; +static void putwhitespan(), putblackspan(), + putcode(), puteol(), putinit(), + myputchar(), putbit(); +static int shdata; +static int shbit = 0x80; + +encodeImage(page, wd, ht, fax) +BitMap page; +unsigned int wd, ht; +struct type_IOB_G3FacsimileBodyPart *fax; +{ + int row; + + putinit(); + + for(row = 0; row < ht; row++) { + + tofax(page,row,wd); + + } + + for( row = 0; row < 5; row++ ) + puteol( ); + + flushbits(fax); + +} + +/* */ + +/* encode a row of the image */ + +tofax(image,row,wd) +BitMap image; +int row; +unsigned int wd; +{ + int c = 0; + int n = 0; + + while(n < wd) { + c = 0; + while(!BL_ISSET(n, image[row]) && (n < wd)) { + c++; + n++; + } + putwhitespan(c); + c = 0; + if(n == wd) + break; + while(BL_ISSET(n, image[row]) && (n < wd)) { + c++; + n++; + } + putblackspan(c); + } + puteol(); +} + +/* */ +/* wrap up encoded page in ASN1 */ + +flushbits(fax) +struct type_IOB_G3FacsimileBodyPart *fax; +{ + struct type_IOB_G3FacsimileData *new, *ix; + + if (shbit != 0x01 ){ + myputchar(shdata); + shdata = 0; + shbit = 0x01; + } + + new = (struct type_IOB_G3FacsimileData *) + calloc (1, sizeof(struct type_IOB_G3FacsimileData)); + new -> element_IOB_0 = strb2bitstr (store, + (storeix * BITSPERBYTE), + PE_CLASS_UNIV, + PE_PRIM_BITS); + if (fax -> data == NULL) + fax -> data = new; + else { + for (ix = fax -> data; ix -> next != NULL; ix = ix -> next); + ix -> next = new; + } + fax -> parameters -> number__of__pages++; + storeix = 0; +} + +/* */ + + +/* */ +/* encode and splurt out the fax */ + +outputFax (fax,fp) +struct type_IOB_G3FacsimileBodyPart *fax; +FILE *fp; +{ + PE pe = NULLPE; + PS psout; + + encode_IOB_G3FacsimileBodyPart (&pe, 1, 0, NULLCP, fax); + + /* IMPLICIT TAG */ + pe->pe_class = PE_CLASS_CONT; + pe->pe_id = 3; + + /* output */ + if ((psout = ps_alloc(std_open)) == NULLPS) { + ps_advise (psout, "ps_alloc"); + exit(1); + } + + if (std_setup (psout, fp) == NOTOK) { + advise (NULLCP, "std_setup loses"); + exit (1); + } + + if (pe2ps(psout, pe) == NOTOK) { + ps_advise(psout, "pe2ps loses"); + exit(1); + } + + ps_free(psout); + + if (pe != NULLPE) pe_free (pe); +} + +/* */ +/* basic output routines for fax bits */ + +static void putwhitespan(c) +int c; +{ + int tpos; + tableentry *te; + + if(c>=64) { + tpos = (c/64)-1; + te = mwtable+tpos; + c -= te->count; + putcode(te); + } + tpos = c; + te = twtable+tpos; + putcode(te); +} + +static void putblackspan(c) +int c; +{ + int tpos; + tableentry *te; + + if(c>=64) { + tpos = (c/64)-1; + te = mbtable+tpos; + c -= te->count; + putcode(te); + } + tpos = c; + te = tbtable+tpos; + putcode(te); +} + +static void putcode(te) +tableentry *te; +{ + unsigned int mask; + int code; + + mask = 1<<(te->length-1); + code = te->code; + while(mask) { + if(code&mask) + putbit(1); + else + putbit(0); + mask >>= 1; + } + +} + +static void puteol() +{ + int i; + + for(i=0; i<11; i++) + putbit(0); + putbit(1); +} + +static void putinit() +{ + shdata = 0; + shbit = 0x01; + storeix = 0; + puteol(); +} + +#define INC 512 + +extern unsigned char flip_bits(); + +static void myputchar (ch) +char ch; +{ + if (storeix == store_allocd) { + /* resize */ + store_allocd += INC; + if (store != NULLCP) + store = realloc (store, + (unsigned) (store_allocd * sizeof (char))); + else + store = calloc ((unsigned) store_allocd, + sizeof (char *)); + } + store[storeix++] = flip_bits((unsigned char) ch); +} + +static void putbit(d) +int d; +{ + if(d) + shdata = shdata|shbit; + shbit = shbit<<1; + + if((shbit&0xff) == 0) { + myputchar(shdata); + shdata = 0; + shbit = 0x01; + } +} + +/* ERRORS */ + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Format/ascii2fax/make b/Format/ascii2fax/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/ascii2fax/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/ascii2fax/pg_sizes.h b/Format/ascii2fax/pg_sizes.h new file mode 100644 index 0000000..7298e90 --- /dev/null +++ b/Format/ascii2fax/pg_sizes.h @@ -0,0 +1,42 @@ +/* pg_sizes.h: various macros/defines to do with fax page sizes */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/pg_sizes.h,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: pg_sizes.h,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + * + */ + +#define X_ALLOWED_NOT_PRINT 56 +/* pixels standard allows not to print in both x directions */ +#define Y_ALLOWED_NOT_PRINT_TOP 4 +/* mm standard allows not to print at top of page */ +#define Y_ALLOWED_NOT_PRINT_BOTTOM 7 /* really 6.77 */ +/* mm standard allows not to print at bottom of page */ + +/* a4 */ +#ifdef A4 +# define FAX_WIDTH 210 /* mm */ +# define FAX_HEIGHT 297 /* mm */ +#else +# define FAX_WIDTH 216 /* mm */ +# define FAX_HEIGHT 273 /* mm */ +#endif + + +/* res */ +# define LINES_PER_MM 3.85 /* 7.7 */ + +# define LEFT_PAD 30 /* mm */ /* 29.5 */ +# define TOP_PAD 6 /* mm */ +# define BOTTOM_PAD 2 /* mm */ + +# define FAX_WIDTH_LINES 1728 /* standard ? */ + +# define FAX_HEIGHT_LINES ((int)(FAX_HEIGHT * LINES_PER_MM)) +# define TEXT_HEIGHT_LINES ((int)((FAX_HEIGHT - BOTTOM_PAD - Y_ALLOWED_NOT_PRINT_BOTTOM) * LINES_PER_MM)) +# define LEFT_PAD_LINES ((int)(LEFT_PAD * LINES_PER_MM) + X_ALLOWED_NOT_PRINT) +# define TOP_PAD_LINES ((int)((TOP_PAD + Y_ALLOWED_NOT_PRINT_TOP) * LINES_PER_MM)) diff --git a/Format/ascii2fax/str_util.c b/Format/ascii2fax/str_util.c new file mode 100644 index 0000000..15dab7a --- /dev/null +++ b/Format/ascii2fax/str_util.c @@ -0,0 +1,147 @@ +/* str_util.c: utility routines for manipulating strings of chars inconjunction with bitmaps */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/str_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/ascii2fax/RCS/str_util.c,v 6.0 1991/12/18 20:15:19 jpo Rel $ + * + * $Log: str_util.c,v $ + * Revision 6.0 1991/12/18 20:15:19 jpo + * Release 6.0 + * + */ + +#include "fonts.h" + +static int numTabs(s) +char *s; +{ + int ret = 0; + for (;s && *s != '\0';s++) + if (*s == '\t') + ret++; + return ret; +} + +StrPtr new_str(f, s, l) +PPFontPtr f; +char *s; +int l; +{ + int i, j, k, tabs; + StrPtr ret = (StrPtr) malloc(sizeof(Str)); + + ret->orig = strdup(s); + tabs = numTabs(s); + ret->nchars = l + (6 * tabs); /* 6 because l contains number of tabs */ + + ret->chars = (CharPtr *) calloc(ret->nchars, + sizeof(CharPtr)); + for (i = 0, j = 0;i < l; i++) { + if (tabs > 0 && + s[i] == '\t') { + tabs--; + for (k = 0; k < 7; k ++) + ret->chars[j++] = f->chars[32]; /* space */ + } else + ret->chars[j++] = f->chars[(int)s[i]]; + } + return ret; +} + +free_str(s) +StrPtr s; +{ + if (s->chars != NULL) + free((char *) s->chars); + if (s->orig) + free(s->orig); + free(s); +} + +static int longestFit(s, maxwid, pw, ph) +StrPtr s; +int maxwid, *pw, *ph; +{ + int tallest = 0, count = 0; + int ix; + *pw = 0; + *ph = 0; + + for (ix = 0; ix < s->nchars; ix++) { + if (s->chars[ix] && count + s->chars[ix]->wid <= maxwid) { + count += s->chars[ix]->wid; + if (s->chars[ix]->ht > tallest) + tallest = s->chars[ix]->ht; + } else { + ix--; + break; + } + } + *ph = tallest; + *pw = count; + return ix; +} + +static int insertcharbitline(into, x, ch, y) +BitLine into; +int x; +CharPtr ch; +int y; +{ + int i; + for (i = 0; i < ch->wid;i++) { + if (BL_ISSET(i, ch->bits[y])) + BL_SET(x+i, into); + else + BL_CLR(x+i, into); + } + return x+i; +} + +static void insert_1yline(into, x, s, y, num) +BitLine into; +int x; +StrPtr s; +int y, num; +{ + int i; + + for (i = 0; i < num; i++) + x = insertcharbitline(into, x, s->chars[i], y); +} + +static int insert_str(bm, s, x, y, dx, dy, widest) +BitMap bm; +StrPtr s; +int x, y, *dx, *dy, widest; +{ + int wid, ht, numInserted, iy; + + numInserted = longestFit(s, widest - x, &wid, &ht); + + for (iy = 0; iy < ht; iy++) + insert_1yline(bm[y+iy], x, s, iy, numInserted); + *dy = ht; + *dx = wid; + return numInserted; +} + +int str_into_bitmap(bm, f, x, y, dx, dy, widest, str, len) +BitMap bm; +PPFontPtr f; +int x, y, *dx, *dy, widest; +char *str; +int len; +{ + int numInserted; + StrPtr s = new_str(f, str, len); + numInserted = insert_str(bm, s, x, y, dx, dy, widest); + free_str(s); + return numInserted; +} + + + diff --git a/Format/asn/Makefile b/Format/asn/Makefile new file mode 100644 index 0000000..d55bd23 --- /dev/null +++ b/Format/asn/Makefile @@ -0,0 +1,217 @@ +# asn - takes a ASN.1 Body Part and converts it into another +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/asn/RCS/Makefile,v 6.0 1991/12/18 20:15:43 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:15:43 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = asn.c asn_charset.c asn_dec.c asn_enc.c asn_proc.c asn_rd.c f_6937.c \ + f_gentxt.c f_teletex.c opt_cmdln.c opt_functs.c ut_asn.c ut_ext.c \ + ut_f.c +OBJS = asn.o asn_charset.o asn_dec.o asn_enc.o asn_proc.o asn_rd.o f_6937.o \ + f_gentxt.o f_teletex.o opt_cmdln.o opt_functs.o ut_asn.o ut_ext.o \ + ut_f.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LIBASN1 = asn1/libasn1.a +LIBASN1-MADE = asn1/asn1-made + +CFLAGS = $(CCOPTIONS) -g $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) -g $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xasn + +default: $(PROGS) + +xasn: $(LIBASN1) $(LIBASN1-MADE) $(LIBPP) $(OBJS) + (echo "cd asn1; $(MAKE)"; cd asn1; $(MAKE)) + $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LIBASN1) $(LIBPP) $(LIBSYS) + +$(LIBASN1) $(LIBASN1-MADE): + (echo "cd asn1; $(MAKE)"; cd asn1; $(MAKE)) + + + +install: inst-dir inst-asn +inst-dir: $(CHANDIR) +inst-asn: $(FORMDIR)/asn + +$(FORMDIR)/asn: xasn + -$(BACKUP) $@ zxasn + rm -f $@ + $(INSTALL) xasn $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "asn filter installed normally"; echo "" + + + + +clean: tidy + (echo "cd asn1; $(MAKE) $@"; cd asn1; $(MAKE) $@) + rm -f $(OBJS) + +tidy: + (echo "cd asn1; $(MAKE) $@"; cd asn1; $(MAKE) $@) + rm -f $(PROGS) core a.out *.old *.BAK zxasn + + +lint: l-asn + +l-asn: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) asn1/l-asn1 $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +asn.o: asn.c +asn.o: ../../h/head.h +asn.o: ../../h/util.h +asn.o: ../../h/config.h +asn.o: ../../h/ll_log.h +asn.o: ../../h/retcode.h +asn.o: ./asn.h +asn_charset.o: asn_charset.c +asn_charset.o: ../../h/head.h +asn_charset.o: ../../h/util.h +asn_charset.o: ../../h/config.h +asn_charset.o: ../../h/ll_log.h +asn_charset.o: ../../h/retcode.h +asn_charset.o: ../../h/charset.h +asn_charset.o: ./asn.h +asn_dec.o: asn_dec.c +asn_dec.o: ../../h/head.h +asn_dec.o: ../../h/util.h +asn_dec.o: ../../h/config.h +asn_dec.o: ../../h/ll_log.h +asn_dec.o: ../../h/retcode.h +asn_dec.o: ./asn.h +asn_enc.o: asn_enc.c +asn_enc.o: ../../h/head.h +asn_enc.o: ../../h/util.h +asn_enc.o: ../../h/config.h +asn_enc.o: ../../h/ll_log.h +asn_enc.o: ../../h/retcode.h +asn_enc.o: ./asn.h +asn_proc.o: asn_proc.c +asn_proc.o: ../../h/head.h +asn_proc.o: ../../h/util.h +asn_proc.o: ../../h/config.h +asn_proc.o: ../../h/ll_log.h +asn_proc.o: ../../h/retcode.h +asn_proc.o: ./asn.h +asn_rd.o: asn_rd.c +asn_rd.o: ../../h/head.h +asn_rd.o: ../../h/util.h +asn_rd.o: ../../h/config.h +asn_rd.o: ../../h/ll_log.h +asn_rd.o: ../../h/retcode.h +asn_rd.o: ./asn.h +f_6937.o: f_6937.c +f_6937.o: ../../h/head.h +f_6937.o: ../../h/util.h +f_6937.o: ../../h/config.h +f_6937.o: ../../h/ll_log.h +f_6937.o: ../../h/retcode.h +f_6937.o: ../../h/IOB-types.h +f_6937.o: ../../h/MTA-types.h +f_6937.o: ../../h/Toks-types.h +f_6937.o: ../../h/Auth-types.h +f_6937.o: ./asn.h +f_gentxt.o: f_gentxt.c +f_gentxt.o: ../../h/head.h +f_gentxt.o: ../../h/util.h +f_gentxt.o: ../../h/config.h +f_gentxt.o: ../../h/ll_log.h +f_gentxt.o: ../../h/retcode.h +f_gentxt.o: ./asn.h +f_teletex.o: f_teletex.c +f_teletex.o: ../../h/head.h +f_teletex.o: ../../h/util.h +f_teletex.o: ../../h/config.h +f_teletex.o: ../../h/ll_log.h +f_teletex.o: ../../h/retcode.h +f_teletex.o: ../../h/IOB-types.h +f_teletex.o: ../../h/MTA-types.h +f_teletex.o: ../../h/Toks-types.h +f_teletex.o: ../../h/Auth-types.h +f_teletex.o: ./asn.h +opt_cmdln.o: opt_cmdln.c +opt_cmdln.o: ../../h/head.h +opt_cmdln.o: ../../h/util.h +opt_cmdln.o: ../../h/config.h +opt_cmdln.o: ../../h/ll_log.h +opt_cmdln.o: ../../h/retcode.h +opt_cmdln.o: ./asn.h +opt_functs.o: opt_functs.c +opt_functs.o: ../../h/head.h +opt_functs.o: ../../h/util.h +opt_functs.o: ../../h/config.h +opt_functs.o: ../../h/ll_log.h +opt_functs.o: ../../h/retcode.h +opt_functs.o: ./asn.h +ut_asn.o: ut_asn.c +ut_asn.o: ../../h/head.h +ut_asn.o: ../../h/util.h +ut_asn.o: ../../h/config.h +ut_asn.o: ../../h/ll_log.h +ut_asn.o: ../../h/retcode.h +ut_asn.o: ./asn.h +ut_ext.o: ut_ext.c +ut_ext.o: ../../h/head.h +ut_ext.o: ../../h/util.h +ut_ext.o: ../../h/config.h +ut_ext.o: ../../h/ll_log.h +ut_ext.o: ../../h/retcode.h +ut_ext.o: ./asn.h +ut_ext.o: ./oid.h +ut_f.o: ut_f.c +ut_f.o: ../../h/head.h +ut_f.o: ../../h/util.h +ut_f.o: ../../h/config.h +ut_f.o: ../../h/ll_log.h +ut_f.o: ../../h/retcode.h +ut_f.o: ./asn.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/asn/asn.c b/Format/asn/asn.c new file mode 100644 index 0000000..6f81645 --- /dev/null +++ b/Format/asn/asn.c @@ -0,0 +1,77 @@ +/* asn - A body part converter */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + +char *myname; + + +static ASNCMD *Asnfilt; +static ASNCMD *asnfilt_new(); + + + + +/* ------------------------- Main Routine --------------------------------- */ + + + +/* ARGSUSED */ +main(argc, argv) +int argc; +char **argv; +{ + int retval; + + /* -- Program Initialisation -- */ + myname = *argv++; + sys_init(myname); + + /* -- Malloc -- */ + Asnfilt = asnfilt_new(); + + /* -- Read the command line and set struct fields -- */ + opt_cmdln (argv, Asnfilt); + + /* -- Set encoder/decoder functs from cmd line asn vals -- */ + opt_functs (Asnfilt); + + /* -- Process info received from stdin, and output to stdout -- */ + asn_process (Asnfilt); + + exit(0); +} + + + + +/* ---------------------- Static Routines -------------------------------- */ + + + + +static ASNCMD *asnfilt_new () /* -- create new asn struct -- */ +{ + register ASNCMD *ap; + + PP_TRACE (("asnfilt_new ()")); + + ap = (ASNCMD *) smalloc (sizeof(ASNCMD)); + bzero ((char *) ap, sizeof (*ap)); + return(ap); +} diff --git a/Format/asn/asn.h b/Format/asn/asn.h new file mode 100644 index 0000000..50c5b76 --- /dev/null +++ b/Format/asn/asn.h @@ -0,0 +1,52 @@ +/* asnfilter.h: Used by the asnfilter code */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn.h,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn.h,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_ASNFILTER +#define _H_ASNFILTER + + + +typedef struct funct_struct { + char *name; /* plain, motis-86-6937, generaltxt ... etc */ + int (*ffunc) (); /* function performing the asn encode/decode */ +} ASNFUNCT; + + + +typedef struct asn_cmd_line_struct { + char *in_charset; + char *out_charset; + ASNFUNCT in_asn; + ASNFUNCT out_asn; +} ASNCMD; + + + +typedef struct asn_body_struct { /* -- holds the body part contents -- */ + char *line; + int length; + struct asn_body_struct *next; +} ASNBODY; + + +extern int errno; +extern char *sys_errlist[]; +extern PE asn_rd_stdin(); + + +#define NULLASNCMD ((ASNCMD *)0) +#define NULLASNBODY ((ASNBODY *)0) +#define IGNORE_PRMS 1 + +#endif diff --git a/Format/asn/asn1/Makefile b/Format/asn/asn1/Makefile new file mode 100644 index 0000000..31fb1c7 --- /dev/null +++ b/Format/asn/asn1/Makefile @@ -0,0 +1,111 @@ +# asn1 - Decoder/Encoder Routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/asn/asn1/RCS/Makefile,v 6.0 1991/12/18 20:16:32 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:16:32 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ExtDef-print.c ExtDef.c GenTxt-print.c GenTxt.c +OBJS = ExtDef-print.o ExtDef.o GenTxt-print.o GenTxt.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +#LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -g $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) -g $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) +SHADOW = asn1-made + + +############################################################ +# +# Suffix rules +# +############################################################ + + + + +############################################################ +# +# Building Rules +# +############################################################ + + +default: ${SRCS} ${SHADOW} + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) libasn1.a $? + $(RANLIB) libasn1.a + touch $@ + +GenTxt.c GenTxt-types.h: GenTxt.py + $(PEPY) -a PY_advise GenTxt.py + +GenTxt-print.c: gentxt.py + $(PEPY) -a PY_advise -S PRINT -o $@ gentxt.py + +GenTxt.py: + $(POSY) $(POFLAGS) -f -h -o GenTxt.py gentxt.py + +ExtDef.c ExtDef-types.h: ExtDef.py + $(PEPY) -a PY_advise ExtDef.py + +ExtDef-print.c: extdefbp.py + $(PEPY) -a PY_advise -S PRINT -o $@ extdefbp.py + +ExtDef.py: + $(POSY) $(POFLAGS) -f -h -o ExtDef.py extdefbp.py + +clean: tidy + rm -f [A-Z]*.[ch] [A-Z]*.py *.ph $(OBJS) *.a + +tidy: + rm -f core a.out *.old *.BAK ${SHADOW} *.ph + + +lint: l-asn1 + +l-asn1: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ExtDef-print.o: ExtDef-print.c +ExtDef.o: ExtDef.c +ExtDef.o: ./ExtDef-types.h +GenTxt-print.o: GenTxt-print.c +GenTxt.o: GenTxt.c +GenTxt.o: ./GenTxt-types.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/asn/asn1/extdefbp.py b/Format/asn/asn1/extdefbp.py new file mode 100644 index 0000000..72aeff5 --- /dev/null +++ b/Format/asn/asn1/extdefbp.py @@ -0,0 +1,39 @@ +-- externalbp.py: Externally defined Body Parts + +-- @(#) $Header: /xtel/pp/pp-beta/Format/asn/asn1/RCS/extdefbp.py,v 6.0 1991/12/18 20:16:32 jpo Rel $ +-- +-- $Log: extdefbp.py,v $ +-- Revision 6.0 1991/12/18 20:16:32 jpo +-- Release 6.0 +-- +-- +-- + +-- +-- +-- This is EXTENDED-BODY-PART-TYPE START +-- +-- + + +ExtDef DEFINITIONS IMPLICIT TAGS ::= + +%{ +#ifndef lint +static char *Rcsid = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/asn1/RCS/extdefbp.py,v 6.0 1991/12/18 20:16:32 jpo Rel $"; +#endif lint +%} + +BEGIN + +ExtDefBodyPart ::= SEQUENCE { + parameters [0] ExtDefParameters OPTIONAL, + data ExtDefData + } + +ExtDefParameters ::= EXTERNAL + +ExtDefData ::= EXTERNAL + + +END diff --git a/Format/asn/asn1/gentxt.py b/Format/asn/asn1/gentxt.py new file mode 100644 index 0000000..d7abe2a --- /dev/null +++ b/Format/asn/asn1/gentxt.py @@ -0,0 +1,46 @@ +-- gentxt.py: + +-- @(#) $Header: /xtel/pp/pp-beta/Format/asn/asn1/RCS/gentxt.py,v 6.0 1991/12/18 20:16:32 jpo Rel $ +-- +-- $Log: gentxt.py,v $ +-- Revision 6.0 1991/12/18 20:16:32 jpo +-- Release 6.0 +-- +-- +-- + +-- +-- +-- This is an EXTENDED-BODY-PART-TYPE FOR GENERAL TEXT +-- +-- + + +GenTxt DEFINITIONS IMPLICIT TAGS ::= + +%{ +#ifndef lint +static char *Rcsid = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/asn1/RCS/gentxt.py,v 6.0 1991/12/18 20:16:32 jpo Rel $"; +#endif lint +%} + +BEGIN + +GenTxtBodyPart ::= SEQUENCE { + parameters GenTxtParameters, + data GenTxtData + } + +GenTxtParameters ::= SET { + g0-designator [0] CharacterSetDesignator OPTIONAL, + g1-designator [1] CharacterSetDesignator OPTIONAL, + g2-designator [2] CharacterSetDesignator OPTIONAL, + g3-designator [3] CharacterSetDesignator OPTIONAL, + c0-designator [4] CharacterSetDesignator OPTIONAL, + c1-designator [5] CharacterSetDesignator OPTIONAL + } + +CharacterSetDesignator ::= GeneralString (SIZE (3..5)) + +GenTxtData ::= GeneralString +END diff --git a/Format/asn/asn1/make b/Format/asn/asn1/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Format/asn/asn1/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/asn/asn_charset.c b/Format/asn/asn_charset.c new file mode 100644 index 0000000..8303b08 --- /dev/null +++ b/Format/asn/asn_charset.c @@ -0,0 +1,97 @@ +/* asn_charset.c - calls strncnv to perform the character set conversions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_charset.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_charset.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn_charset.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "charset.h" +#include "asn.h" + +static CHARSET *Iset, *Oset; +extern int MnemonicsRequired; + + + +/* ------------------------ Start Routine --------------------------------- */ + + + + +asn_charset(inset, outset, body) +char *inset; /* -- in character set -- */ +char *outset; /* -- out character set -- */ +ASNBODY *body; /* -- body to be converted -- */ +{ + ASNBODY *bp, *bak; + + PP_TRACE(("asn_charset (%s, %s)", inset, outset)); + + if ((Iset = getchset (inset, DEFAULT_ESCAPE)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown input charset %s", inset)); + exit (1); + } + + if ((Oset = getchset (outset, DEFAULT_ESCAPE)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown output charset %s", outset)); + exit (1); + } + + + for (bp = body; bp; bp = bp -> next) + call_strncnv (bp); +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static call_strncnv (bp) +ASNBODY *bp; +{ + char *cp; + int blen, length; + + PP_TRACE (("call_strncnv (%d)", bp -> length)); + + if (bp -> length == 0 && bp -> line == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("Error unable to convert")); + exit (1); + } + + blen = (bp -> length * 3) + 4; + cp = malloc (blen); + bzero (cp, blen); + + switch (MnemonicsRequired) { + case TRUE: + length = strncnv (Oset, Iset, (CHAR8U*)cp, + (CHAR8U*) bp->line, blen, TRUE); + break; + default: + length = strncnv (Oset, Iset, (CHAR8U*)cp, + (CHAR8U*) bp->line, bp -> length, FALSE); + break; + } + + free (bp -> line); + bp -> line = realloc (cp, length); + bp -> length = length; +} diff --git a/Format/asn/asn_dec.c b/Format/asn/asn_dec.c new file mode 100644 index 0000000..2b26891 --- /dev/null +++ b/Format/asn/asn_dec.c @@ -0,0 +1,83 @@ +/* asn_dec.c - decode ASN after reading from stdin */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_dec.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_dec.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn_dec.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + +#define SLEN 128 + + + + + + + +/* ------------------------ Start Routine --------------------------------- */ + + + + +asn_decode(func_decode, data) +int (*func_decode) (); +ASNBODY **data; +{ + int retval; + + PP_TRACE (("asn_decode()")); + + /* --- *** --- + get body part from stdin this can be plain or wrapped + if ffunc is set then it is wrapped. + --- *** --- */ + + if (func_decode == NULL) { + rd_stdin (data); + return; + } + + retval = (*func_decode)(data); +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static rd_stdin (data) +ASNBODY **data; +{ + int len; + char *buf; + + PP_TRACE (("rd_stdin()")); + + buf = smalloc (SLEN); + bzero (buf, SLEN); + + while ((len = read (0, buf, SLEN)) > 0) { + buf[len] = '\0'; + asnbody_add (data, buf, len); + + buf = smalloc (SLEN); + bzero (buf, SLEN); + } + + free (buf); +} diff --git a/Format/asn/asn_enc.c b/Format/asn/asn_enc.c new file mode 100644 index 0000000..31994e8 --- /dev/null +++ b/Format/asn/asn_enc.c @@ -0,0 +1,119 @@ +/* asn_enc.c - encode ASN after body part conversion */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_enc.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_enc.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn_enc.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + + + + +/* ------------------------ Start Routine --------------------------------- */ + + + + +asn_encode(func_encode, data) +int (*func_encode) (); +ASNBODY *data; +{ + PE pe; + + PP_TRACE (("asn_encode()")); + + /* --- *** --- + write body part in plain or wrapped mode. + if ffunc is set then wrapped. + --- *** --- */ + + + if (func_encode == NULL) { + wr_stdout (data); + return; + } + + + /* -- call encoder function -- */ + (*func_encode)(&pe, data); + + asn_wr_stdout (pe); + pe_free(pe); +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static asn_wr_stdout(pe) +PE pe; +{ + register PS ps; + + + PP_TRACE (("asn_wr_stdout(%x)", pe)); + + if (pe == NULLPE) { + PP_LOG(LLOG_EXCEPTIONS, ("pe is null")); + exit (1); + } + + if ((ps = ps_alloc(std_open)) == NULLPS) { + PP_LOG(LLOG_EXCEPTIONS, ("ps_alloc(stdout) error")); + exit (1); + } + + if (std_setup(ps, stdout) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, ("std_setup(stdout) error")); + exit (1); + } + + (void) ps_get_abs(pe); + + if (pe2ps(ps, pe) == NOTOK) { + if (ps->ps_errno) + PP_LOG(LLOG_EXCEPTIONS, + ("ps2pe: %s", ps_error(ps->ps_errno))); + else + PP_LOG(LLOG_EXCEPTIONS, ("ps2pe error")); + exit (1); + } + + ps_free(ps); +} + + + + + +static wr_stdout (data) +ASNBODY *data; +{ + ASNBODY *dp; + int n; + char *c; + + PP_TRACE (("wr_stdout()")); + + for (dp = data; dp; dp = dp -> next) + for (n = dp -> length, c = dp -> line; n > 0; n--, c++) + putchar (*c); + + fflush (stdout); +} diff --git a/Format/asn/asn_proc.c b/Format/asn/asn_proc.c new file mode 100644 index 0000000..fcd82d8 --- /dev/null +++ b/Format/asn/asn_proc.c @@ -0,0 +1,58 @@ +/* asn_proc - decode/read stdin, call filter, encode/output stdout */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_proc.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_proc.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn_proc.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + + + + +/* ------------------------ Start Routine --------------------------------- */ + + + + +/* --- *** ---- +1) Read plain or ASN1 - and decode if required. +2) Call the body part filter +3) Encode if required - and output the info on stdout. +--- *** --- */ + + +asn_process(ap) +ASNCMD *ap; +{ + ASNBODY *data; + + PP_TRACE (("asn_process(%x)", ap)); + + data = NULLASNBODY; + + asn_decode (ap->in_asn.ffunc, &data); + + switch (lexequ (ap -> in_charset, ap -> out_charset)) { + case 0: + PP_NOTICE (("'%s' = '%s' - No character set conversion done", + ap->in_charset, ap->out_charset)); + break; + default: + asn_charset (ap->in_charset, ap->out_charset, data ); + break; + } + + asn_encode (ap->out_asn.ffunc, data); +} diff --git a/Format/asn/asn_rd.c b/Format/asn/asn_rd.c new file mode 100644 index 0000000..c299d11 --- /dev/null +++ b/Format/asn/asn_rd.c @@ -0,0 +1,126 @@ +/* asn_rd.c - reads ASN from stdin */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_rd.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/asn_rd.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: asn_rd.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + + + +extern PE ps2pe_aux(); + + + + +/* ------------------------ Start Routine --------------------------------- */ + + + + +PE asn_rd_stdin (flag) +int flag; +{ + register PE pe; + register PS ps; + + + PP_TRACE (("asn_rd_stdin()")); + + if ((ps = ps_alloc(std_open)) == NULLPS) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: ps_alloc(std_open)")); + exit(1); + } + + if (std_setup(ps, stdin) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: std_setup()")); + exit(1); + } + + + if (flag == IGNORE_PRMS) + ignore_parameters (ps); + + + if ((pe = ps2pe(ps)) == NULLPE) { + if (ps->ps_errno) + PP_LOG(LLOG_EXCEPTIONS, ("Error: ps2pe: %s", + ps_error(ps->ps_errno))); + else + PP_LOG(LLOG_EXCEPTIONS, ("Error: ps2pe()")); + + exit(1); + } + + ps_free(ps); + return pe; +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static int ignore_parameters (psin) +PS psin; +{ + + PE pe; + + PP_TRACE (("ignore_parameters()")); + + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Error: ps2pe_aux reading SEQUENCE info failed [%s]", + ps_error(psin -> ps_errno))); + exit (1); + } + + +#ifdef DEBUG + (void) testdebug (pe, "asnfilter/ignore_parameters (BEGIN)"); +#endif + + PP_TRACE (("Ignoring (class=%d, id=%d)", pe -> pe_class, pe -> pe_id)); + pe_free (pe); + + + if ((pe = ps2pe_aux (psin, 1, 0)) == NULLPE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Error: ps2pe_aux reading SET info failed [%s]", + ps_error(psin -> ps_errno))); + exit (1); + } + + + +#ifdef DEBUG + (void) testdebug (pe, "asnfilter/ignore_parameters (SET)"); +#endif + + + if (PE_ID(pe -> pe_class, pe -> pe_id) != + PE_ID(PE_CLASS_UNIV, PE_CONS_SET)) { + PP_LOG(LLOG_EXCEPTIONS, ("Unexpected pe: expected a SET")); + exit (1); + } + + + PP_TRACE (("Ignoring (class=%d, id=%d)", pe -> pe_class, pe -> pe_id)); + pe_free (pe); +} diff --git a/Format/asn/doc/asn.aux b/Format/asn/doc/asn.aux new file mode 100644 index 0000000..70add22 --- /dev/null +++ b/Format/asn/doc/asn.aux @@ -0,0 +1,6 @@ +\relax +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1}ASN.1 Filter}{1}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.1}Description}{1}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2}Runtime Options}{1}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.3}Tailoring}{2}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {1.3.1}Tailoring Examples}{2}} diff --git a/Format/asn/doc/asn.dvi b/Format/asn/doc/asn.dvi new file mode 100644 index 0000000000000000000000000000000000000000..695e45dfa11f8d4a781abcc118d28590411c4c88 GIT binary patch literal 5396 zcmcIoU5p!76`rh}6os@jN~xd(NKC3tz;@TW-TW-wRI5!xD@a?HGG@n^koyRd-u%-@aTn zM}J0g!@1!zSh0?l-RZN8&s^Wtp`od{j~~Ap&h`CD{P(4+;nbABTTxnj9{P9c`^tUA zqOuXbHfZJiWNzSQ&hrnyvpjb6a5m?!e`V`I-Ef)h&F=Wi2a(ypTkjm6Q#Qeb{z|jK zzac))KlY|_fH|72S6tmPz1fFeUzS^?zWu?Ab!B5~NNlxUE8Dq&@K}k>B)``XTXDG$ z-`RTjW2Jwjy%g?UJvY!)9W&g;b%$3SR^YnHHOo9zH8t9YPv~xmyCud?GLzY=!8cLN zv?SwQy!ZSC5rb=6hQaJcV!qfcYBS4~-&>|@bIS zf^*ClRR_66(Q(U!VUZ7VZTiaglBH|R8SySY7#aWIL&E$c-qrI7XkWah{GnhT=V*u|=d+jYZj&obH`o86tAKk_`2ZS z>uaB#%kS?joiZrCsH=^8zH>E9Et)94FhvQwc8V{GdK@AC=Z^dLoe$t((NcrSLs9preKeNb^1zb1jvTR{Viw4g-?e^UT9g+y{OCOBq4t7l)vHg zM-;!$ytP<{myNAK@?uQy*%co5yxFa&ZBp5145m5)eUvT}g;RtOS)kPfINU+1gGN&V z4@QP#hCxbo8oI&i6Wp>3j!-G75=NEbtIYz*cGZY$ugk|%Map4+MtAy&I*urDsS?mO zllNyV`J@aXQe$mPbCRVR7|&}667r+2>HYc^>AeKqApLdJGOUDEX35o9IH^2cNHFF7sr^qnhz9#w`s`WTQbZL>D5(KyM<_Q!fRBsKAC0#tTdwY8_U_K?-Z!*o<@s>@++_xXY19$A5_Jr-R>Hm9%uI%l zG&5x$Msq@26^eDf#4typBtn%xn|*X(FJA(6@a2%n%9g2Xx6LuxXtn|~g!k&7Iw(XN zQO*Bsg0SG_$OXnEe5;z6rL2>tj#&v$iJjRnxfGMpH5Ai}jQnP&E=3QdJAA zjxPdHsUQ#Wb%64;_Kkq*N8SW_hMUJwC^AjDz?bk91rVmip%HmU_rSw*&z+$;pAMQN+%sMuwJIL$%nvX;_Z4 zmJbJ!Q#M4tXlq?uDv*NO=%*MGpNPCW774OMvJ^oki&OzQL!7Ev&$)(OrE4Xn=d zdZ4>b5cj@lNI`;TbGN=K=f|a7c8D&FFZ^gT%CYrAT#kNnaO#OkwTu>pDRNtMeT;tb z6X!;Ajl`E5;duK(MMT436o}YxhqFi;gLpI#2pZhws7qM1tcuHGTYv)yGnEgfwAdh? z<)e#|xF+v>@1KuNc229Vn;ZBu+MVgIf8*EDmaauAzj^;BRPUoj;73)KhWoS1<&U0p zO4h_^Dq1@Ov&?>RIl;P`yx{SoxM-)^CZZBYBa<|3C5v$s8?_gqxY#Ha6SLFgmi&!U zNu(jxjyt+l4D-&%z{Vc13$_ikL> z^PET-Lr;7c(05hH%4>n!kEsJ7TO3$M{ME>Y8`J7=U)-EA86A z{Vy1=22|kO4gGBxBclS@F04}^ZrPKu)ps;eEtjeO}yj) literal 0 HcmV?d00001 diff --git a/Format/asn/doc/asn.tex b/Format/asn/doc/asn.tex new file mode 100644 index 0000000..5b3bcb6 --- /dev/null +++ b/Format/asn/doc/asn.tex @@ -0,0 +1,146 @@ +\documentstyle [11pt,a4] {article} +\begin{document} +\section {ASN.1 Filter} + +\bigskip +\subsection {Description} +\medskip +\noindent The ASN.1 Filter ({\em asn}) is used in conjunction with the +general filter controller {\em fcontrol}, and is located in the +{\em formdir} directory. + +\medskip +\noindent It is a general body part conversion filter and can do +a variety of conversions depending on its specified options. +These options are: + +\begin {enumerate} + +\item Accept as input one of 2 choices: +\begin {itemize} +\item An ASN.1 wrapped body part +\item A body part that is not encoded in any way (unwrapped ia5 text). +\end{itemize} + +\item Optionally perform a character set conversion on the body part. + +\item Produce as output one of 2 choices: +\begin {itemize} +\item an ASN.1 wrapped body part. +\item A body part that is not encoded in any way (unwrapped ia5 text). +\end {itemize} +\end {enumerate} + + +\bigskip\bigskip +\subsection {Runtime Options} +\medskip + + +\begin {tabbing} + +{\bf {\em asn}} \\ +\ \ \ \ \= +\= \begin{math} [-ia \ \ "none"\ |\ input.asn1] \end{math}\ \ \ \ +\= \begin{math} [-oa \ \ "none"\ |\ output.asn1] \end{math} \\ + +\> \begin{math} [-is \ \ input.character.set] \end{math} +\>\> \begin{math} [-os \ \ output.character.set] \end{math} \\ + +\> \begin{math} [ -x \ | \ -m ] \ \ \ [ -l ] \end{math} +\end{tabbing} + +\smallskip +\noindent Please note the following: +\begin {itemize} +\item All keywords and values are optional. +\item If '-is' is specified then '-os' is mandatory, and vice versa. +\item If '-is' has the same value as '-os' +then {\bf no} character set conversion is performed. +\item If the -ia and/or -oa is not specified, then the default is +'none', which means 'No ASN.1 encoding and/or decoding is required', +i.e the body part is read and/or output as is. +\item For available character set values, please refer to +Appendix A - "Character Sets supported by the {\em charset} filter". +\clearpage +\item At present, there are only 5 available {\em input.asn1} and +{\em output.asn1} values, they are: +\begin{enumerate} +\item none +\item ia5 (unwrapped) +\item generaltext +\item motis-86-6937 +\item teletex +\end{enumerate} +\item The {\em -x}/{\em -m} options specify {\bf either} a X.408 +{\bf or} a Mnemonic conversion. The default is {\em -x}, +where mnemonics are unrecognised. See the {\em charset} filter documentation +for more information. +\item Sometimes quite legally, remote sites leave out the \begin{math} +\end{math} characters terminating ASN.1 encoded body part lines. +The {\em -l} option prevents on decoding, the concatenation of such lines. +\end {itemize} +\bigskip + +\subsection {Tailoring} +\medskip + +\noindent The following fields need to be set within the tailor file. +\begin {itemize} +\item {\bf prog}, set to the value {\em fcontrol}, +because the {\em asn} filter is only used in conjunction +with the general filter controller. +\item {\bf bptin} and {\bf bptout}, set to specified {\bf bodypart}s. +\item {\bf type}, set to {\em shaper}. +\item {\bf conv}, set to either {\em conv} or {\em loss}. +\item {\bf cost}, only set if conv={\em loss}. +\item {\bf info}, set to the ASN.1 filter name {\em asn} followed +by its required options. +\end {itemize} + +\bigskip +\subsubsection {Tailoring Examples} +\bigskip + +\noindent {\bf Example 1} Converting an ASN.1 iso6937 body part into an +unwrapped ia5 body part: + +\begin{verbatim} +chan iso6937toia5 prog=fcontrol, + show="iso6937 -> ia5 conversion filter", + bptin=iso6937, bptout=ia5, + type=shaper, conv=loss, cost=99, + info="asn -is iso_6937-2-add -os ccitt_x.408_ia5irv + -ia motis-86-6937 -oa ia5" +\end{verbatim} + + +\clearpage +\noindent {\bf Example 2} Converting a ia5 unwrapped body part into an +ASN.1 iso6937 body part. + +\begin{verbatim} +chan ia5toiso6937 prog=fcontrol, + show="ia5 -> iso6937 conversion filter", + bptin=ia5, bptout=iso6937, + type=shaper, conv=loss, cost=99, + info="asn -is ccitt_x.408_ia5irv -os iso_6937-2-add + -ia ia5 -oa motis-86-6937" +\end{verbatim} + + + +\bigskip\bigskip +\noindent {\bf Example 3} Converting a ASN.1 iso6937 body part into a +ASN.1 teletex body part. + +\begin{verbatim} +chan iso6937toteletex prog=fcontrol, + show="iso6937 -> teletex conversion filter", + bptin=iso6937, bptout=ttx, + type=shaper, conv=loss, cost=99, + info="asn -is iso_6937-2-add -os t.61-8bit + -ia motis-86-6937 -oa teletex" +\end{verbatim} + +\end {document} diff --git a/Format/asn/f_6937.c b/Format/asn/f_6937.c new file mode 100644 index 0000000..7355f62 --- /dev/null +++ b/Format/asn/f_6937.c @@ -0,0 +1,113 @@ +/* f_6937.c: motis-86-6937 Encoder/Decoder Function Routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/f_6937.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/f_6937.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: f_6937.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + + +#include "head.h" +#include "IOB-types.h" +#include "asn.h" + + + + + + +/* ------------------------ Start Routines --------------------------------- */ + + + + +decode_motis_6937(body) +ASNBODY **body; +{ + PE pe; + int retval; + struct type_IOB_ISO6937Data *asndata; + + PP_TRACE (("decode_motis6937()")); + + pe = asn_rd_stdin (IGNORE_PRMS); + + retval = decode_IOB_ISO6937Data (pe, 1, NULLIP, NULLVP, &asndata); + + if (retval == NOTOK) + pe_done (pe); + + pe_free (pe); + + /* -- set ASNBODY -- */ + struct2body (asndata, body); + + free_IOB_ISO6937Data (asndata); +} + + + + +encode_motis_6937(ppe, body) +PE *ppe; +ASNBODY *body; +{ + int retval = NOTOK; + PE pe; + struct type_IOB_ISO6937TextBodyPart *info = NULL; + + PP_TRACE (("encode_motis6937()")); + + /* -- set Data structure -- */ + set_6937_data (&info, body); + + retval = encode_IOB_ISO6937TextBodyPart (&pe, 1, NULLIP, NULLVP, info); + if (retval == NOTOK) + pe_done (pe); /* -- exit -- */ + + pe -> pe_class = PE_CLASS_CONT; + pe -> pe_id = 13; + *ppe = pe; + + free_IOB_ISO6937TextBodyPart (info); + return OK; +} + + + + +/* ----------------------- Static Routines ------------------------------- */ + + + + +static set_6937_data (dstruct, body) +struct type_IOB_ISO6937TextBodyPart **dstruct; +ASNBODY *body; +{ + struct type_IOB_ISO6937TextBodyPart *tbptr; + + + PP_TRACE (("set_6937_data()")); + + /* -- malloc main structure -- */ + tbptr = (struct type_IOB_ISO6937TextBodyPart *) + smalloc (sizeof *tbptr); + bzero (tbptr, sizeof *tbptr); + + tbptr -> parameters = (struct type_IOB_ISO6937Parameters *) + smalloc (sizeof *tbptr -> parameters); + bzero (tbptr -> parameters, sizeof *tbptr -> parameters); + + body2struct (body, &tbptr -> data); + *dstruct = tbptr; +} diff --git a/Format/asn/f_gentxt.c b/Format/asn/f_gentxt.c new file mode 100644 index 0000000..eb33b6c --- /dev/null +++ b/Format/asn/f_gentxt.c @@ -0,0 +1,122 @@ +/* f_gentxt.c: General Text Encoder/Decoder Function Routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/f_gentxt.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/f_gentxt.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: f_gentxt.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" +#include "oid.h" +#include "asn1/GenTxt-types.h" + + + + +/* ------------------------ Start Routines --------------------------------- */ + + + + +decode_gentext(body) +ASNBODY **body; +{ + PE pe; + PE pe_prm = NULLPE; + PE pe_data = NULLPE; + int retval; + struct type_GenTxt_GenTxtData *asndata; + + PP_TRACE (("decode_gentext()")); + + pe = asn_rd_stdin (NULL); + + external2pe (pe, &pe_prm, &pe_data, GENERALTEXT); + pe_free (pe_prm); + + retval = decode_GenTxt_GenTxtData (pe_data, 1, NULLIP, + NULLVP, &asndata); + if (retval == NOTOK) + pe_done (pe_data); + + pe_free (pe_data); + + /* -- set ASNBODY -- */ + qbuf2body (asndata, body); + + free_GenTxt_GenTxtData (asndata); +} + + + + +encode_gentext(pe, body) +PE *pe; +ASNBODY *body; +{ + int retval = NOTOK; + PE pe_data = NULLPE; + PE pe_prm = NULLPE; + struct type_GenTxt_GenTxtBodyPart *info = NULL; + + PP_TRACE (("encode_gentext()")); + + /* -- set the Data structure -- */ + set_gentext_data (&info, body); + + retval = encode_GenTxt_GenTxtParameters (&pe_prm, 1, NULLIP, + NULLVP, info -> parameters); + if (retval == NOTOK) + pe_done (pe_prm); /* -- exit -- */ + + retval = encode_GenTxt_GenTxtData (&pe_data, 1, NULLIP, + NULLVP, info -> data); + if (retval == NOTOK) + pe_done (pe_data); /* -- exit -- */ + + free_GenTxt_GenTxtBodyPart (info); + pe2external (pe, pe_prm, pe_data, GENERALTEXT); + return OK; +} + + + + +/* ----------------------- Static Routines ------------------------------- */ + + + + +static set_gentext_data (dstruct, body) +struct type_GenTxt_GenTxtBodyPart **dstruct; +ASNBODY *body; +{ + struct type_GenTxt_GenTxtBodyPart *tbptr; + struct type_GenTxt_GenTxtParameters *parameters; + + + PP_TRACE (("set_gentext_data()")); + + /* -- malloc main structure -- */ + tbptr = (struct type_GenTxt_GenTxtBodyPart *) + smalloc (sizeof *tbptr); + parameters = (struct type_GenTxt_GenTxtParameters *) + smalloc (sizeof *parameters); + + bzero (tbptr, sizeof *tbptr); + bzero (parameters, sizeof *parameters); + + tbptr -> parameters = parameters; + body2qbuf (body, &tbptr -> data); + *dstruct = tbptr; +} diff --git a/Format/asn/f_teletex.c b/Format/asn/f_teletex.c new file mode 100644 index 0000000..a901ef0 --- /dev/null +++ b/Format/asn/f_teletex.c @@ -0,0 +1,112 @@ +/* f_teletex.c: teletex Encoder/Decoder Function Routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/f_teletex.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/f_teletex.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: f_teletex.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "IOB-types.h" +#include "asn.h" + + + + + + +/* ------------------------ Start Routines --------------------------------- */ + + + + +decode_teletex(body) +ASNBODY **body; +{ + PE pe; + int retval; + struct type_IOB_TeletexData *asndata; + + PP_TRACE (("decode_teletex()")); + + pe = asn_rd_stdin (IGNORE_PRMS); + + retval = decode_IOB_TeletexData (pe, 1, NULLIP, NULLVP, &asndata); + + if (retval == NOTOK) + pe_done (pe); + + pe_free (pe); + + /* -- set ASNBODY -- */ + struct2body (asndata, body); + + free_IOB_TeletexData (asndata); +} + + + + +encode_teletex(ppe, body) +PE *ppe; +ASNBODY *body; +{ + int retval = NOTOK; + PE pe; + struct type_IOB_TeletexBodyPart *info = NULL; + + PP_TRACE (("encode_teletex()")); + + /* -- set the Data structure -- */ + set_teletex_data (&info, body); + + retval = encode_IOB_TeletexBodyPart (&pe, 1, NULLIP, NULLVP, info); + if (retval == NOTOK) + pe_done (ppe); /* -- exit -- */ + + pe -> pe_class = PE_CLASS_CONT; + pe -> pe_id = 5; + *ppe = pe; + + free_IOB_TeletexBodyPart (info); + return OK; +} + + + + +/* ----------------------- Static Routines ------------------------------- */ + + + + +static set_teletex_data (dstruct, body) +struct type_IOB_TeletexBodyPart **dstruct; +ASNBODY *body; +{ + struct type_IOB_TeletexBodyPart *tbptr; + + + PP_TRACE (("set_teletex_data()")); + + /* -- malloc main structure -- */ + tbptr = (struct type_IOB_TeletexBodyPart *) + smalloc (sizeof *tbptr); + bzero (tbptr, sizeof *tbptr); + + tbptr -> parameters = (struct type_IOB_TeletexParameters *) + smalloc (sizeof *tbptr -> parameters); + bzero (tbptr -> parameters, sizeof *tbptr -> parameters); + + body2struct (body, &tbptr -> data); + *dstruct = tbptr; +} diff --git a/Format/asn/make b/Format/asn/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/asn/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/asn/oid.h b/Format/asn/oid.h new file mode 100644 index 0000000..8198e88 --- /dev/null +++ b/Format/asn/oid.h @@ -0,0 +1,19 @@ +/* oid.h: Used by the asnfilter code for object ids */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/asn/RCS/oid.h,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: oid.h,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + * + */ + + +#ifndef _H_OID +#define _H_OID + +#define GENERALTEXT 1 + +#endif diff --git a/Format/asn/opt_cmdln.c b/Format/asn/opt_cmdln.c new file mode 100644 index 0000000..270cf96 --- /dev/null +++ b/Format/asn/opt_cmdln.c @@ -0,0 +1,165 @@ +/* opt_cmdln.c: sets the ASNCMD structure to the command line values */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/opt_cmdln.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/opt_cmdln.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: opt_cmdln.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + + +#include "head.h" +#include "asn.h" +#include + + +extern char *myname; +int MnemonicsRequired = FALSE; +int CRline = FALSE; + + +/* -- command line option definitions -- */ +#define OPT_ISET 1 /* -- input character set -- */ +#define OPT_OSET 2 /* -- output character set -- */ +#define OPT_IASN 3 /* -- input asn coding used -- */ +#define OPT_OASN 4 /* -- output asn coding used -- */ +#define OPT_X408 5 +#define OPT_MNEMONICS 6 +#define OPT_CR 7 + + +static CMD_TABLE tbl_cmdln[] = {/* -- command line options -- */ + "-is", OPT_ISET, + "-os", OPT_OSET, + "-ia", OPT_IASN, + "-oa", OPT_OASN, + "-x", OPT_X408, + "-m", OPT_MNEMONICS, + "-l", OPT_CR, + 0, -1 + }; + + + + + +/* ------------------------ Start Routine --------------------------------- */ + + + +opt_cmdln (opts, ap) +char **opts; +ASNCMD *ap; +{ + + int retval; + char *key; + + PP_NOTICE (("%s", myname)); + + while(*opts != NULL) { + switch(cmd_srch(*opts, tbl_cmdln)) { + case OPT_ISET: + key = *opts; + opts++; + set_val (key, *opts, &ap -> in_charset); + break; + case OPT_OSET: + key = *opts; + opts++; + set_val (key, *opts, &ap -> out_charset); + break; + case OPT_IASN: + key = *opts; + opts++; + set_val (key, *opts, &ap -> in_asn.name); + break; + case OPT_OASN: + key = *opts; + opts++; + set_val (key, *opts, &ap -> out_asn.name); + break; + case OPT_X408: + MnemonicsRequired = FALSE; + break; + case OPT_MNEMONICS: + MnemonicsRequired = TRUE; + break; + case OPT_CR: + CRline = TRUE; + break; + default: + PP_LOG(LLOG_EXCEPTIONS, ("unknown option '%s'", *opts)); + exit (1); + } + opts++; + } + + cmdln_chks (ap); +} + + + + +/* ---------------------- Static Routines -------------------------------- */ + + + + +static cmdln_chks(ap) +ASNCMD *ap; +{ + + PP_TRACE (("cmdln_chks()")); + + if ((lexequ (ap -> in_charset, ap -> out_charset) == 0) && + (lexequ (ap -> in_asn.name, ap -> out_asn.name) == 0)) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: no conversion is required")); + exit (1); + } + + /* -- outchar then must specify inchar -- */ + if ((ap -> out_charset) && (ap -> in_charset == NULLCP)) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: inchar not specified")); + exit (1); + } + + /* -- inchar then must specify outchar -- */ + if ((ap -> in_charset) && (ap -> out_charset == NULLCP)) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: outchar not specified")); + exit (1); + } + +} + + + +static int set_val (key, val, base) +char *key; +char *val; +char **base; +{ + + PP_NOTICE (("\t%s='%s'", key, val)); + + + if (val == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, ("Error: No value specified")); + exit (1); + } + + if (val[0] == '-') { + PP_LOG(LLOG_EXCEPTIONS, ("Error: Bad value '%s'", val)); + exit (1); + } + + *base = strdup (val); +} diff --git a/Format/asn/opt_functs.c b/Format/asn/opt_functs.c new file mode 100644 index 0000000..9a00abf --- /dev/null +++ b/Format/asn/opt_functs.c @@ -0,0 +1,107 @@ +/* opt_functs.c: sets the Encoder/Decoder Function Routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/opt_functs.c,v 6.0 1991/12/18 20:15:43 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/opt_functs.c,v 6.0 1991/12/18 20:15:43 jpo Rel $ + * + * $Log: opt_functs.c,v $ + * Revision 6.0 1991/12/18 20:15:43 jpo + * Release 6.0 + * + */ + + + + +#include "head.h" +#include "asn.h" + + + +typedef struct funct_tbl { + char *key; + int (*func_encode) (); + int (*func_decode) (); + } TBL_FUNCTS; + + +extern int encode_gentext(); +extern int decode_gentext(); +extern int encode_teletex(); +extern int decode_teletex(); +extern int encode_motis_6937(); +extern int decode_motis_6937(); + + +static TBL_FUNCTS tbl_functs [] = {/* -- Encoder/Decoder of an asn1 -- */ + "ia5", 0, 0, + "generaltext", encode_gentext, decode_gentext, + "motis-86-6937", encode_motis_6937, decode_motis_6937, + "teletex", encode_teletex, decode_teletex, + "none", 0, 0, + 0, 0, 0 + }; + + + +#define IN 1 +#define OUT 2 + + + +/* ------------------------ Start Routine --------------------------------- */ + + + +opt_functs (ap) +ASNCMD *ap; +{ + + PP_TRACE (("opt_functs()")); + + if (ap->in_asn.name) + tbl_srch (ap->in_asn.name, IN, &ap->in_asn.ffunc); + + if (ap->out_asn.name) + tbl_srch (ap->out_asn.name, OUT, &ap->out_asn.ffunc); +} + + + + + +/* ---------------------- Static Routines -------------------------------- */ + + + +static tbl_srch (str, type, base) +char *str; +int type; +int (**base) (); +{ + TBL_FUNCTS *tbl = tbl_functs; + + PP_TRACE (("tbl_srch (%s)", str)); + + for(; tbl->key != NULLCP; tbl++) + if(lexequ(str, tbl->key) == 0) { + switch (type) { + case IN: + *base = tbl->func_decode; + return; + case OUT: + *base = tbl->func_encode; + return; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Error: Unknown type '%d'", type)); + exit(1); + } + } + + PP_LOG (LLOG_EXCEPTIONS, ("Error: Unknown ASN1 '%s'", str)); + exit(1); +} diff --git a/Format/asn/ut_asn.c b/Format/asn/ut_asn.c new file mode 100644 index 0000000..184af11 --- /dev/null +++ b/Format/asn/ut_asn.c @@ -0,0 +1,71 @@ +/* ut_asn.c - Common routines to manipulate ASNBODY */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_asn.c,v 6.0 1991/12/18 20:16:07 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_asn.c,v 6.0 1991/12/18 20:16:07 jpo Rel $ + * + * $Log: ut_asn.c,v $ + * Revision 6.0 1991/12/18 20:16:07 jpo + * Release 6.0 + * + */ + + + + +#include "head.h" +#include "asn.h" + + + + +/* ------------------------ Start Routines --------------------------------- */ + + + + +asnbody_add (base, value, len) +ASNBODY **base; +char *value; +int len; +{ + ASNBODY *ap = *base; + ASNBODY *new; + + + PP_TRACE (("asnbody_add (%d)", len)); + + + new = (ASNBODY *) smalloc (sizeof(ASNBODY)); + bzero ((char *) new, sizeof (*new)); + new -> line = value; + new -> length = len; + + + if (ap == NULLASNBODY) + *base = new; + else { + while (ap -> next != NULLASNBODY) + ap = ap -> next; + ap -> next = new; + } +} + + + + +asnbody_free (data) +ASNBODY *data; +{ + ASNBODY *ap; + + for (; data; data = ap) { + ap = data -> next; + if (data -> line) + free (data -> line); + free ((char *)data); + } +} diff --git a/Format/asn/ut_ext.c b/Format/asn/ut_ext.c new file mode 100644 index 0000000..be14c30 --- /dev/null +++ b/Format/asn/ut_ext.c @@ -0,0 +1,198 @@ +/* ut_ext.c: Common Function Routines for external body parts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_ext.c,v 6.0 1991/12/18 20:16:07 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_ext.c,v 6.0 1991/12/18 20:16:07 jpo Rel $ + * + * $Log: ut_ext.c,v $ + * Revision 6.0 1991/12/18 20:16:07 jpo + * Release 6.0 + * + */ + + +#include "asn1/ExtDef-types.h" +#include "head.h" +#include "asn.h" +#include "oid.h" + + +/* -- stuff from pepsy -- */ +#define EXT_BP struct type_ExtDef_ExtDefBodyPart +#define EXT_UNIV struct type_UNIV_EXTERNAL +#define EXT_UNIV_CHOICE struct choice_UNIV_0 +#define Choice_Asn1 choice_UNIV_0_single__ASN1__type + + + +typedef struct oid_struct { + int type; + char *oid_prm; + char *oid_data; + } TBL_OIDS; + + +static TBL_OIDS tbl_oids [] = {/* -- oids for external body parts -- */ + GENERALTEXT, "2.6.1.11.11", "2.6.1.4.11", + 0, 0, 0 + }; + + + + +/* ---------------------------- Begin Routines ----------------------------- */ + + + + +pe2external (pptr, pe_prm, pe_data, type) +PE *pptr; +PE pe_prm; +PE pe_data; +int type; +{ + EXT_BP *ext_bp; + EXT_UNIV *ext_prm, *ext_data; + char *oid_prm, *oid_data; + int retval; + + oid_srch (type, &oid_prm, &oid_data); + + PP_TRACE (("pe2external (%d, %s, %s)", type, oid_prm, oid_data)); + + ext_bp = (EXT_BP *) smalloc (sizeof (EXT_BP)); + bzero ((char *) ext_bp, sizeof (EXT_BP)); + + malloc_univ_external (&ext_prm, oid_prm, pe_prm); + malloc_univ_external (&ext_data, oid_data, pe_data); + + ext_bp -> parameters = ext_prm; + ext_bp -> data = ext_data; + + retval = encode_ExtDef_ExtDefBodyPart + (pptr, 1, NULLIP, NULLVP, ext_bp); + if (retval == NOTOK) pe_done (*pptr); /* -- exit -- */ + + PP_PDUP (ExtDef_ExtDefBodyPart, *pptr, + "External Body Part", PDU_WRITE); + + free_ExtDef_ExtDefBodyPart(ext_bp); +} + + + + +external2pe (pe, pe_prm, pe_data, type) +PE pe; +PE *pe_prm; +PE *pe_data; +int type; +{ + EXT_BP *ext_bp; + EXT_UNIV *ext_prm, *ext_data; + char *oid_prm, *oid_data, *cp; + int retval; + + oid_srch (type, &oid_prm, &oid_data); + + PP_TRACE (("pe2external (%d, %s, %s)", type, oid_prm, oid_data)); + + PP_PDUP (ExtDef_ExtDefBodyPart, pe, + "External Body Part", PDU_READ); + + retval = decode_ExtDef_ExtDefBodyPart + (pe, 1, NULLIP, NULLVP, &ext_bp); + if (retval == NOTOK) pe_done (pe); /* -- exit -- */ + + ext_prm = ext_bp -> parameters; + ext_data = ext_bp -> data; + + if ((ext_prm -> encoding -> offset != Choice_Asn1) || + (ext_data -> encoding -> offset != Choice_Asn1)) { + PP_LOG (LLOG_EXCEPTIONS, ("Error: No External ASN1 found")); + exit(1); + } + + + cp = sprintoid (ext_prm -> direct__reference); + if (lexequ (cp, oid_prm) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Error: Parameter OID mismatch %s %s", cp, oid_prm)); + exit (1); + } + + cp = sprintoid (ext_data -> direct__reference); + if (lexequ (cp, oid_data) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Error: Data OID mismatch %s %s", cp, oid_data)); + exit(1); + } + + *pe_prm = ext_prm -> encoding -> un.single__ASN1__type; + *pe_data = ext_data -> encoding -> un.single__ASN1__type; + + ext_prm -> encoding -> un.single__ASN1__type = NULLPE; + ext_data -> encoding -> un.single__ASN1__type = NULLPE; + free (oid_prm); + free (oid_data); + free_ExtDef_ExtDefBodyPart(ext_bp); +} + + + + +/* ----------------------------- Static Routines ---------------------------- */ + + + + +static oid_srch (type, prm, data) +int type; +char **prm; +char **data; +{ + TBL_OIDS *tbl = tbl_oids; + + PP_TRACE (("oid_srch (%d)", type)); + + for(*prm = *data = NULLCP; tbl->type != NULL; tbl++) + if (type == tbl->type) { + *prm = strdup (tbl->oid_prm); + *data = strdup (tbl->oid_data); + } + + + if (*prm == NULLCP && *data == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("Error: Unknown OIDS for %d", type)); + exit(1); + } +} + + + + +malloc_univ_external (pptr, oid, pe) +EXT_UNIV **pptr; +char *oid; +PE pe; +{ + EXT_UNIV *ExtUniv; + int n; + + n = sizeof (EXT_UNIV); + ExtUniv = (EXT_UNIV *) smalloc (n); + bzero ((char *) ExtUniv, n); + + n = sizeof (EXT_UNIV_CHOICE); + ExtUniv -> encoding = (EXT_UNIV_CHOICE *) smalloc (n); + bzero ((char *) ExtUniv -> encoding, n); + + ExtUniv -> direct__reference = oid_cpy (str2oid (oid)); + ExtUniv -> encoding -> offset = Choice_Asn1; + ExtUniv -> encoding -> un.single__ASN1__type = pe; + + *pptr = ExtUniv; +} diff --git a/Format/asn/ut_f.c b/Format/asn/ut_f.c new file mode 100644 index 0000000..41bd796 --- /dev/null +++ b/Format/asn/ut_f.c @@ -0,0 +1,288 @@ +/* ut_f.c: Common Function Routines (used by f_*.c files) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_f.c,v 6.0 1991/12/18 20:16:07 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/asn/RCS/ut_f.c,v 6.0 1991/12/18 20:16:07 jpo Rel $ + * + * $Log: ut_f.c,v $ + * Revision 6.0 1991/12/18 20:16:07 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "asn.h" + + +extern int CRline; + + +typedef struct decoded_struct { + struct qbuf *line; + struct decoded_struct *next; +} DECODED; + + +#define NULLDECODED ((DECODED *)0) +#define STR2QB(s) str2qb(s, strlen(s), 1) + + + + +/* ------------------------ Start Routines --------------------------------- */ + + + + +/* --- *** --- +writes an asn1 decoded body part info into a common struct called ASNBODY +--- *** --- */ + + + +struct2body (dstruct, body) +DECODED *dstruct; +ASNBODY **body; +{ + DECODED *dp; + char *cp, *np; + + PP_TRACE (("struct2body()")); + + for (dp = dstruct; dp; dp = dp -> next) { + if ((cp = qb2str (dp -> line)) == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to decode - qb2str error")); + exit (1); + } + + rn2n (cp, strlen(cp), &np); + free (cp); + asnbody_add (body, np, strlen(np)); + } +} + + + + +body2struct (asnbody, dstruct) +ASNBODY *asnbody; +DECODED **dstruct; +{ + ASNBODY *body; + DECODED *new, *bak; + char *np; + + PP_TRACE (("body2struct()")); + + + for (bak=NULLDECODED, body=asnbody; body; body=body->next) { + + n2rn (body->line, body->length, &np); + + new = (DECODED *) smalloc (sizeof *new); + bzero (new, sizeof (*new)); + + new -> line = str2qb(NULLCP, 0, 1); + new -> line -> qb_forw -> qb_data = np; + new -> line -> qb_forw -> qb_len = strlen(np); + + + /* -- free body lines now to reduce space -- */ + if (body->line) free (body->line); + body -> line = NULLCP; + body -> length = 0; + + if (bak) + bak -> next = new; + else + *dstruct = new; + bak = new; + } + + asnbody_free (asnbody); +} + + + + +qbuf2body (qstruct, body) +struct qbuf *qstruct; +ASNBODY **body; +{ + struct qbuf *qp; + char *np; + + PP_TRACE (("qbuf2body()")); + + for (qp = qstruct -> qb_forw; qp != qstruct; qp = qp -> qb_forw) { + + if (qp -> qb_len == 0) + asnbody_add (body, strdup(""), 0); + else { + rn2n (qp -> qb_data, qp -> qb_len, &np); + asnbody_add (body, np, strlen(np)); + } + } +} + + + + +body2qbuf (asnbody, qb) +ASNBODY *asnbody; +struct qbuf **qb; +{ + ASNBODY *body; + struct qbuf *new, *bak; + char *np; + + PP_TRACE (("body2qbuf()")); + + for (bak=NULL, body=asnbody; body; body=body->next) { + + n2rn (body->line, body->length, &np); + + if (bak == NULL) { + new = str2qb(NULLCP, 0, 1); + new -> qb_forw -> qb_data = np; + new -> qb_forw -> qb_len = strlen (np); + *qb = new; + bak = new -> qb_forw; + } + else { + new = str2qb(NULLCP, 0, 0); + new -> qb_data = np; + new -> qb_len = strlen (np); + bak -> qb_forw = new; + new -> qb_back = bak; + bak = new; + } + + if (body -> line) free (body -> line); + body -> line = NULLCP; + body -> length = NULL; + } + + bak -> qb_forw = *qb; + + asnbody_free (asnbody); +} + + + + +pe_done(pe, msg) /* -- writes to oper log -- */ +PE pe; +char *msg; +{ + + PP_TRACE (("pe_done(%x)", pe)); + + if (pe->pe_errno) + PP_OPER(NULLCP, + ("%s: [%s] %s", msg, PY_pepy, pe_error(pe->pe_errno))); + else + PP_LOG(LLOG_EXCEPTIONS, + ("pe_done failure: [%s]", PY_pepy)); + + exit (1); +} + + + + +/* ----------------------- Static Routines ------------------------------- */ + + + + +static rn2n (oldp, len, newpp) /* convert from \r\n to \n */ +char *oldp; +int len; +char **newpp; +{ + char *op, *buf, *start; + char lastr = NULL, lastn = TRUE; + int n; + + + PP_TRACE (("rn2n(%d)", len)); + + n = len * 2; + start = buf = smalloc (n); + bzero (buf, n); + + for (op=oldp, n=len; n > 0; n--, op++) { + switch (*op) { + case '\r': + lastr = *op; + break; + case '\n': + *buf++ = *op; + lastr = lastn = NULL; + break; + default: + if (lastr) { + *buf++ = lastr; + lastr = NULL; + } + + *buf++ = *op; + break; + } + } + + if (lastn && CRline) + *buf++ = '\n'; + + *buf++ = '\0'; + *newpp = realloc (start, buf - start); +} + + + + +static n2rn (oldp, len, newpp) /* convert from \n -> \r\n */ +char *oldp; +int len; +char **newpp; +{ + char *op, *buf, *start; + char lastr = NULL, lastn = TRUE; + int n; + + PP_TRACE (("n2rn(%d)", len)); + + + n = len * 2; + start = buf = smalloc (n); + bzero (buf, n); + + + for (op=oldp, n=len; n > 0; n--, op++) { + switch (*op) { + case '\n': + *buf++ = '\r'; + *buf++ = '\n'; + lastn = 0; + break; + default: + *buf++ = *op; + break; + } + } + + if (lastn && CRline) { + *buf++ = '\r'; + *buf++ = '\n'; + } + + *buf++ = '\0'; + *newpp = realloc (start, buf - start); +} diff --git a/Format/charset/Makefile b/Format/charset/Makefile new file mode 100644 index 0000000..3ab9298 --- /dev/null +++ b/Format/charset/Makefile @@ -0,0 +1,101 @@ +# charset for Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/charset/RCS/Makefile,v 6.0 1991/12/18 20:19:34 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:19:34 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = conv.c +OBJS = conv.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) + + + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xcharset + +default: $(OBJS) $(PROGS) + -rm -rf README copyright design + -ln ../../Lib/charset/copyright + -ln ../../Lib/charset/design + -ln ../../Lib/charset/README + + +all: $(PROGS) + + +charset: xcharset +xcharset: conv.o + $(CC) $(CCFLAGS) conv.o $(LIBPP) -o $@ + + +install: inst-dir inst-charset +inst-dir: $(FORMDIR) + +inst-charset : $(FORMDIR)/charset +$(FORMDIR)/charset : xcharset + -$(BACKUP) $@ zxcharset + rm -f $@ + $(INSTALL) xcharset $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Character Set filter installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) xcharset $(CSDIR) +tidy: + rm -rf core a.out *.old *.BAK zxcharset $(PROGS) + +lint: l-charset +l-charset : conv.c + $(LINT) $(LLFLAGS) conv.c + +depend: + $(DEPEND) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +conv.o: conv.c +conv.o: ../../h/charset.h +conv.o: conv.c +conv.o: ../../h/charset.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/charset/README b/Format/charset/README new file mode 100644 index 0000000..48f4a8a --- /dev/null +++ b/Format/charset/README @@ -0,0 +1,16 @@ +******************************************************************************** + + + This code needs to be geared for compatibility on all m/cs. + To use the code effectively you may wish to update the + following files: + Lib/charset/charset_conf.c + ../../h/charset.h + + For more information please read: + The PP Documentation Vol 1 + And the copyright and design documents. + + + +******************************************************************************** diff --git a/Format/charset/conv.c b/Format/charset/conv.c new file mode 100644 index 0000000..93830eb --- /dev/null +++ b/Format/charset/conv.c @@ -0,0 +1,130 @@ +/* conv.c - Reads a character set from stdin converts and outputs to stdout */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/charset/RCS/conv.c,v 6.0 1991/12/18 20:19:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/charset/RCS/conv.c,v 6.0 1991/12/18 20:19:34 jpo Rel $ + * + * $Log: conv.c,v $ + * Revision 6.0 1991/12/18 20:19:34 jpo + * Release 6.0 + * + */ + + +#include +#include +#include "charset.h" + +extern int errno; + +#define SLEN 256 /* max length in octets of images */ +static CHARSET *in; +static CHARSET *out; +static int MnemonicsRequired = FALSE; + + +/* -- input args -- */ +static char arg_Iset [SLEN]; +static char arg_Oset [SLEN]; +static INT16S arg_Idef = DEFAULT_ESCAPE; +static INT16S arg_Odef = DEFAULT_ESCAPE; + + + +main(argc, argv) +int argc; +char **argv; +{ + extern int optind; + extern char *optarg; + int opt; + int len, i; + CHAR8U s[SLEN], r[SLEN*4]; + + + /* -- initialise -- */ + bzero (arg_Iset, SLEN); + bzero (arg_Oset, SLEN); + + + while ((opt = getopt (argc, argv, "I:O:i:o:xm")) != EOF) + switch (opt) { + case 'x': + MnemonicsRequired = FALSE; + break; + case 'm': + MnemonicsRequired = TRUE; + break; + case 'i': + (void) strcpy (arg_Iset, optarg); + break; + case 'o': + (void) strcpy (arg_Oset, optarg); + break; + case 'I': + arg_Idef = (INT16S) atoi (optarg); + break; + case 'O': + arg_Odef = (INT16S) atoi (optarg); + break; + default: + print_usage (argv[0]); + } + + + + if (arg_Iset[0] == NULL || arg_Oset[0] == NULL) + print_usage (argv[0]); + + + in = getchset (arg_Iset, arg_Idef); + out = getchset (arg_Oset, arg_Odef); + + if (in == NULL || out == NULL) { + fprintf (stderr, "\n\n*** Error: Unknown Charset/s\n\n"); + exit (1); + } + + + /* should output records of unlimited length by + outputting one part at a time */ + + + while ((len = read (0, s, SLEN)) > 0) { + + s[len] = '\0'; + bzero (r, SLEN); + + switch (MnemonicsRequired) { + case TRUE: + len = strncnv (out,in,r,s,SLEN*4,TRUE); + break; + default: + len = strncnv (out,in,r,s,len,FALSE); + break; + } + + for (i = 0; i < len; i++) + fprintf (stdout, "%c", r[i]); + } + + + fflush (stdout); + exit (0); +} + + + + +static print_usage (prog) +char *prog; +{ + fprintf (stderr, "\n\n"); + fprintf (stderr, + "Usage: %s -i charsetin -o charsetout [-x | -m]", prog); + fprintf (stderr, "\n\n"); + exit (1); +} diff --git a/Format/charset/copyright b/Format/charset/copyright new file mode 100644 index 0000000..ce08262 --- /dev/null +++ b/Format/charset/copyright @@ -0,0 +1,20 @@ +The material provided here is copyright Keld Simonsen 1990, 1991. +The material is allowed for copying, also for commercial products, +as long as the following 3 rules are obeyed: + +1. The character and character set codes and names in the material + may not be changed. +2 You are allowed to change the programming code as long as + it is backwards compatible. +3. Due credit must be given to "Keld Simonsen, RAP, Sct. Joergens Alle 8, + DK-1615 Copenhagen V, Denmark". + +The restriction on altering of names is done so that all versons +of the code have a chance of being compatible. If you want alterations +or additions, please mail me (preferably email to keld@dkuug.dk) +and I will consider it for future releases. + +If the material is included in commercial products, donations +will be most appreciated. + +Keld Simonsen diff --git a/Format/charset/design b/Format/charset/design new file mode 100644 index 0000000..39c5109 --- /dev/null +++ b/Format/charset/design @@ -0,0 +1,161 @@ +Guidelines for character mnemonics in a minimal character set. + +By Keld Simonsen, Danish UNIX User Group (DKUUG) +Representative to SC22 WG on Character Set Usage +for Danish Standards Association (DS), Denmark. + +Draft January 1991. + +Aim of Character Mnemonics + +The aim of the mnemonics is to be able to represent all characters +in all standard coded character sets in any standard coded +character set. Thus all standard coded character sets will be +related, and a conversion can take place. + +The usage of the character mnemonics is primarily intended +within computer operating systems, programming languages and +applications, and this work with character mnemonics is the current +state of work which has been presented to the ISO working group +responsible for these computer related issues, namely the +ISO/IEC JTC1/SC22 special working group on character set usage. + +Covered Coded Character Sets + +Almost all characters in the standard coded character sets have been +given a mnemonic name in the minimal character set. +The minimal character set is defined as the basic character set +of ISO 646, where 12 positions are left undefined. +The standard coded character sets are taken as the sum of +all ISO defined or ISO registered character sets. + +The most significant ISO coded character set is the 10646 coded character +set, whose aim is to code in 32 bits all characters in the world. +These guidelines can be seen as assigning mnemonic attributes +to most characters in 10646, currently at DIS stage. + +Other ISO coded character sets covered include all parts of +ISO 8859, ISO 6937-2 and all ISO 646 conforming coded character +sets in the ISO character set registry managed by ECMA +according to ISO 4873. +Some non-ISO character sets are also covered for convenience. + +The Character Mnemonics Classes + +The character mnemonics are classified into two groups: + +1. A group with two-character mnemonics + - Primarily intended for alphabetic scripts like Latin, Greek, + Cyrillian, Hebrew and Arabic, and special characters. +2. A group with variable-length mnemonics + - primarily intended for non-alphabetic scripts like Japanese + and Chinese. + +All mnemonics are given a long descriptive name, written in the +reference character set and taken from ISO 10646, if possible. + + +The Two-Character mnemonics + +The two-character mnemonics include various accented Latin letters, +Greek, Cyrillic, Hebrew, Arabic, Hiragana, Katakana and Bopomofo. +Also quite some special characters are included. +Almost all ISO or ISO registered 7- and 8-bit coded +character sets are covered with these two-character mnemonics. +Thus conversions between these character sets can be done via a +two-character conversion table. + +The two characters are chosen so the graphical appearence in the +reference set resembles as much as possible (within the posibilities +available) the graphical appearance of the character. The basic character +set of ISO 646 is used as the reference set, as mentioned above. + +The characters in the reference character set are chosen to represent +themselves. You may consider them as two-character mnemonics where +the second char is a space. + +Control characters mnemonics are chosen according to ISO 2047 and ISO 6429 . + +Letters, including Greek, Cyrillic, Arabic and Hebrew, are represented +with the base letter as the first letter, and the second letter +represents an accent or relation to a non-Latin script. +Non-Latin letters are translitterated to Latin letters, +following translitteration standards as closely as possible. + +After a letter, the second character signifies the following: + + Exclamation mark ! Grave + Apostrophe ' Acute accent + Greater-Than sign > Circumflex accent + Question Mark ? tilde + Hyphen-Minus - Macron + Left parenthesis ( Breve + Full Stop . Dot Above/Ring above + Colon : Diaeresis + Comma , Cedilla + Underline _ Underline + Solidus / Stroke + Quotation mark " Double acute accent + Semicolon ; Ogonek + Less-Than sign < Caron + + Equals = Cyrillian + Asterisk * Greek + Percent sign % Greek/Cyrillian special + Plus + smalls: Arabic, capitals: Hebrew + Four 4 Bopomofo + Five 5 Hiragana + Six 6 Katakana + +The ampersand & is reserved as an intro character, indicating that the +following string is in the mnemonic character set. This character +could also be another character, e.g. in the control character set. +One common choice in the control character set is decimal 29, +which seems to have no effect on almost all current equipment. +The intro character can be negotiated between the communicating parties, +but the default is the ampersand "&". Two intro characters in a row +signifies the intro character itself. + +The underscore is reserved for the variable-length mnemonics. +This use does not eliminate usage as an accent or language identifier. +The right-pointing parenthesis ")" is not in use at the moment +for accent or language identifying. +This is also the case for some digits. + +Special characters are encoded with some mnemonic value. +These are not systematic thruout, but most mnemonics start +with a special character of the reference set. +Special chars with some sort of reference to the reference +character set normally have this character as the first character +in the mnemonic. + + +The Variable-length Character Mnemonics + +The Variable-length Character Mnemonics are primarily meant for the +ideographic characters in larger Asian character sets. +To have the mnemonics as short as possible, which both saves storage +and is easier to type in, a quite short name is preferred. +Considering the Chinese standard GB 2312-1980 and the Japanese standards +JIS X0208 and JIS X0212, they are all given by row and column +numbers between 1 and 99. So two positions for row and column and +a character set identifier of one character would be almost as short +as possible. The following character set identifiers are defined: + + c GB 2312-1980 + j JIS X0208-1990 + J JIS X0212-1990 + k KS C 5601-1987 + +The first idea was to have a name in Latin describing the pronunciation +but that is not possible according to Asian sources. + +One prominent character in the reference character set is reserved +for identifying variable-length mnemonics, namely the underscore "_". This character +is intended as a delimiter both in the front and in the end +of the mnemonic. An example of its use would be: (&=intro): + + &_j3210_ &_j4436_&_j6530_ + +The Variable-Length Character Mnemonics can also be used for less-used +Latin letters with more than one accent or other less-used special characters. diff --git a/Format/charset/doc/charset.tex b/Format/charset/doc/charset.tex new file mode 100644 index 0000000..283c724 --- /dev/null +++ b/Format/charset/doc/charset.tex @@ -0,0 +1,229 @@ +\documentstyle [11pt,a4] {article} +\begin{document} +\section {CHARACTER SET CONVERSION FILTER} + +\bigskip +\subsection {Description} +\medskip +\noindent The Character Set Filter {\em charset}, was written by: +Keld Simonsen, RAP, Sct. Joergens Alle 8, DK-1615 Copenhagen V, Denmark. +\\ +Electronic mail address: "Keld Simonsen +\begin{math} <\end{math} keld@dkuug.dk \begin{math} >\end{math} ". +\\ +The Copyright and the design documentation for this filter, +are located in the PP/Lib/charset source directory. + +\medskip +\noindent +{\em Charset} which is located in the {\em formdir}, +is a general character set conversion filter +that converts data belonging to one character set into that belonging +to another. +Although the code is mainly used by the {\em asn} filter and the +{\em rfc822norm} filter, it may be run on its own by using it in +conjunction with the general filter {\em fcontrol}. +This is useful when a message originating from another +country has characters of data within its body part that is unacceptable +to the host country, so rather than have a body part containing +unreadable characters, those characters of data +will either get converted into acceptable ones or omitted altogether. + + +\bigskip\bigskip +\subsection {Runtime Options} +\medskip + +\begin {tabbing} +{\bf {\em charset}} \\ +\ \ \ \ \= +\begin{math} \{-i \ \ input.character.set\} \end{math} \ \ \ +\= \begin{math} \{-o \ \ output.character.set\} \end{math} \ \ \ +\= \begin{math} [ -x \ | \ -m ] \end{math} +\end{tabbing} + + +\bigskip +\noindent Where: +\begin {itemize} +\item Standard input (stdin), output (stdout) and error (stderr), are used. +\item The available input and output character sets, can be found in +"Appendix A - Character Sets supported by the {\em charset} filter". +\item The {\em -x}/{\em -m} options specify {\bf either} a X.408 +{\bf or} a Mnemonic conversion. The default is {\em -x}, +where mnemonics are unrecognised. +If the {\em -m} option is specified, then those characters of data which +cannot get converted are replaced by their 2 character mnemonics, +preceded by an {\bf identification character} of value 29 (GS), +which used to distinguish between real and mnemonic characters. +\end {itemize} + +\bigskip\bigskip +\subsection {Compiling} +\medskip + +Before compiling you may wish to: + +\begin {itemize} +\item Go into the PP/Lib/charset source directory and +edit the {\em Make.defs} file, to modify the CSDIR option. This +is only necessary if you wish to change the directory location +of the generated character set tables. The default is +{\em formdir/charset\_tables}. +\end {itemize} + + +\bigskip\bigskip +\subsection {Tailoring} + +\noindent The following fields need to be set within the tailor file. +\begin {itemize} +\item {\bf prog}, set to the value {\em fcontrol}, +because the {\em charset} filter is only used in conjunction +with the general filter controller. +\item {\bf bptin} and {\bf bptout}, set to specified {\bf bodypart}s. +\item {\bf type}, set to {\em shaper}. +\item {\bf conv}, set to {\em loss}. +\item {\bf cost}, set because information is lost. +\item {\bf info}, set to the charset filter name {\em charset}, followed +by its required options. +\end {itemize} + + +\bigskip\bigskip\noindent +\subsubsection {Example:} + +\begin{verbatim} + + bodypart FR + bodypart IA5IRV + + chan fr2irv prog=fcontrol, + show="fr->irv charset filter", + type=shaper, + bptin=fr, + bptout=ia5irv, + conv=loss, + cost=1, + info="charset -i FR -o CCITT_X.408_IA5IRV" +\end{verbatim} + + +\clearpage +\section {APPENDIX A} +\bigskip +\subsection {Character sets supported by charset filter} +\bigskip\medskip\noindent + + +\begin {tabular} {l l l} +437 & 850 & 860 \\ +863 & 865 & ANSI\_X3.110-1983 \\ +ANSI\_X3.4-1968 & APL & ARABIC \\ +ARABIC7 & ASCII & ASMO\_449 \\ +BS\_4730 & BS\_VIEWDATA & CA \\ +CCITT\_T.50.IRV:1988 & CCITT\_X.408\_IA5IRV & CHARDEFS \\ +CHARMAP.10646 & CHARMNEM & CHARSETS \\ +CN & CODAR-U & CP437 \\ +CP850 & CP860 & CP863 \\ +CP865 & CSA7-1 & CSA7-2 \\ +CSA\_T500-1983 & CSA\_Z243.4-1985-1 & CSA\_Z243.4-1985-2 \\ +CSA\_Z243.4-1985-GR & CSN\_369103 & CUBA \\ +CYRILLIC & DE & DEC \\ +DEC-MCS & DIN\_31624 & DIN\_31625 \\ +DIN\_66003 & DK & DK-US \\ +DS2089 & DS\_2089 & E13B \\ +EBCDIC-AT-DL & EBCDIC-AT-DL-A & EBCDIC-BE \\ +EBCDIC-BR & EBCDIC-CA-FR & EBCDIC-DK-NO \\ +EBCDIC-DK-NO-A & EBCDIC-ES & EBCDIC-ES-A \\ +EBCDIC-ES-S & EBCDIC-FI-SE & EBCDIC-FI-SE-A \\ +EBCDIC-FR & EBCDIC-INT & EBCDIC-IT \\ +EBCDIC-JP-E & EBCDIC-PT & EBCDIC-UK \\ +EBCDIC-US & ECMA-CYRILLIC & ELOT\_928 \\ +ES & ES2 & FI \\ +FR & GB & GB\_1988-80 \\ +GOST\_19768-74 & GREEK & GREEK-CCITT \\ +GREEK7 & HEBREW & HU \\ +IEC\_P27-1 & INIS & INIS-8 \\ +INIS-CYRILLIC & IRV & ISO-IR-10 \\ +ISO-IR-100 & ISO-IR-101 & ISO-IR-102 \\ +ISO-IR-103 & ISO-IR-109 & ISO-IR-11 \\ +ISO-IR-110 & ISO-IR-111 & ISO-IR-121 \\ +ISO-IR-122 & ISO-IR-123 & ISO-IR-126 \\ +ISO-IR-127 & ISO-IR-128 & ISO-IR-129 \\ +ISO-IR-13 & ISO-IR-137 & ISO-IR-138 \\ +ISO-IR-139 & ISO-IR-14 & ISO-IR-141 \\ +ISO-IR-142 & ISO-IR-143 & ISO-IR-144 \\ +ISO-IR-146 & ISO-IR-147 & ISO-IR-148 \\ +ISO-IR-15 & ISO-IR-150 & ISO-IR-151 \\ +\end {tabular} + +\clearpage +{\bf Character sets supported by charset filter (cont)} +\bigskip\bigskip\noindent + +\begin {tabular} {l l l} +ISO-IR-152 & ISO-IR-153 & ISO-IR-154 \\ +ISO-IR-155 & ISO-IR-157 & ISO-IR-158 \\ +ISO-IR-16 & ISO-IR-17 & ISO-IR-18 \\ +ISO-IR-19 & ISO-IR-2 & ISO-IR-21 \\ +ISO-IR-25 & ISO-IR-27 & ISO-IR-31 \\ +ISO-IR-37 & ISO-IR-38 & ISO-IR-39 \\ +ISO-IR-4 & ISO-IR-47 & ISO-IR-49 \\ +ISO-IR-50 & ISO-IR-51 & ISO-IR-53 \\ +ISO-IR-54 & ISO-IR-55 & ISO-IR-57 \\ +ISO-IR-59 & ISO-IR-6 & ISO-IR-60 \\ +ISO-IR-61 & ISO-IR-68 & ISO-IR-69 \\ +ISO-IR-70 & ISO-IR-71 & ISO-IR-72 \\ +ISO-IR-8-1 & ISO-IR-8-2 & ISO-IR-84 \\ +ISO-IR-85 & ISO-IR-86 & ISO-IR-88 \\ +ISO-IR-89 & ISO-IR-9-1 & ISO-IR-9-2 \\ +ISO-IR-90 & ISO-IR-91 & ISO-IR-92 \\ +ISO-IR-93 & ISO-IR-94 & ISO-IR-95 \\ +ISO-IR-96 & ISO-IR-98 & ISO-IR-99 \\ +ISO\_2033-1983 & ISO\_5426:1980 & ISO\_5427 \\ +ISO\_5427:1981 & ISO\_5428 & ISO\_5428:1980 \\ +ISO\_646.BASIC:1983 & ISO\_646.IRV:1983 & ISO\_6937-2-25 \\ +ISO\_6937-2-ADD & ISO\_8859-1 & ISO\_8859-1:1987 \\ +ISO\_8859-2 & ISO\_8859-2:1987 & ISO\_8859-3 \\ +ISO\_8859-3:1988 & ISO\_8859-4 & ISO\_8859-4:1988 \\ +ISO\_8859-5 & ISO\_8859-5:1988 & ISO\_8859-6 \\ +ISO\_8859-6:1987 & ISO\_8859-7 & ISO\_8859-7:1987 \\ +ISO\_8859-8 & ISO\_8859-8:1988 & ISO\_8859-9 \\ +ISO\_8859-9:1989 & ISO\_8859-SUPP & ISO\_9036 \\ +IT & JIS\_C\_6229-1984-HAND & JIS\_C\_6229-1984-A \\ +JIS\_C\_6229-1984-B & JIS\_C\_6229-1984-B-ADD & JIS\_C\_6220-1969 \\ +JIS\_C\_6229-1984-HAND-ADD & JIS\_C\_6229-1984-KANA & JIS\_X0201 \\ +JP & JP-OCR-A & JP-OCR-B \\ +JP-OCR-HAND & JP-OCR-HAND-ADD & JS \\ +JUS\_I.B1.002 & JUS\_I.B1.003-MAC & JUS\_I.B1.003-SERB \\ +KATAKANA & L1 & L2 \\ +L3 & L4 & L5 \\ +L6 & LAP & LATIN-GREEK \\ +LATIN-GREEK-1 & LATIN-LAP & LATIN1 \\ +LATIN1-2-5 & LATIN2 & LATIN3 \\ +LATIN4 & LATIN5 & LATIN6 \\ +MAC & MACEDONIAN & MACINTOSH \\ +\end {tabular} + +\clearpage +{\bf Character sets supported by charset filter (cont)} +\bigskip\bigskip\noindent + + +\begin {tabular} {l l l} +MOSAIC-2 & MOSAIC-3 & MSZ\_7795.3 \\ +NAPLPS & NATS-DANO & NATS-DANO-ADD \\ +NATS-SEFI & NATS-SEFI-ADD & NC\_NC00-10:81 \\ +NF\_Z\_62-010 & NF\_Z\_62-010\_(1973) & NO \\ +NO2 & NS\_4551-1 & NS\_4551-2 \\ +PT & PT2 & R8 \\ +REF & ROMAN8 & SE \\ +SE2 & SEN\_850200\_B & SEN\_850200\_C \\ +SERBIAN & ST\_SEV\_358-88 & T.101-DS1 \\ +T.101-G2 & T.101-G3 & T.61 \\ +T.61-8BIT & UK & US \\ +US-DK & VIDEOTEX-SUPPL & X0201 \\ +X0201-7 & & \\ +\end {tabular} +\end {document} diff --git a/Format/charset/doc/notforPPdoc/design.more b/Format/charset/doc/notforPPdoc/design.more new file mode 100644 index 0000000..0b3d9c4 --- /dev/null +++ b/Format/charset/doc/notforPPdoc/design.more @@ -0,0 +1,13 @@ +Q: Why is Escape character 29 chosen in conv.c + +A: The escape character is not equal to ESC - that would be very + dangerous! ESC (=27) introduces in many cases a control sequence + which may mean many strange things on different types of terminal + equipment. Think of the escape char as 'compose character'. + The escape character can be any character, the code is designed + for that. 29 was chosen, because no foul up occurs with the ordinary + printable characters, as this escape character has to be typed twice + to get a real one. 29 also has the property of being invisible in + pagers like more and pg. 29 seldom has any real meaning on terminal + equipment. 29 is also the default escape char in telnet, maybe + for the same reasons as stated above. diff --git a/Format/charset/doc/notforPPdoc/uclstuff b/Format/charset/doc/notforPPdoc/uclstuff new file mode 100644 index 0000000..16a368e --- /dev/null +++ b/Format/charset/doc/notforPPdoc/uclstuff @@ -0,0 +1,160 @@ +\documentstyle[11pt,a4]{article} +\begin{document} + +\section {Report on the Character set converter obtained from DUKNET} +\subsection {What is available} + +\bigskip\noindent +\subsubsection {Supported character sets} +\medskip\noindent + +\begin {tabular} {l l l l} +ANSI\_X3.4-1968 & BS\_4730 & cp437 & cp850 \\ +cp860 & cp863 & cp865 & DEC-MCS \\ +DIN\_66003 & dk-us & DS\_2089 & EBCDIC-AT-DL \\ +EBCDIC-AT-DL-A & EBCDIC-BE & EBCDIC-BR & EBCDIC-CA-FR \\ +EBCDIC-DK-NO & EBCDIC-DK-NO-A & EBCDIC-ES & EBCDIC-ES-A \\ +EBCDIC-ES-S & EBCDIC-FI-SE & EBCDIC-FI-SE-A & EBCDIC-FR \\ +EBCDIC-INT & EBCDIC-IT & EBCDIC-JP-E & EBCDIC-PT \\ +EBCDIC-UK & EBCDIC-US & ES & ES2 \\ +FI & GB\_1988-80 & ISO\_646.basic & ISO\_646.irv \\ +ISO\_6937-2 & ISO\_8859-1 & ISO\_8859-2 & ISO\_8859-3 \\ +ISO\_8859-4 & ISO\_8859-5 & ISO\_8859-6 & ISO\_8859-7 \\ +ISO\_8859-8 & ISO\_8859-9 & ISO\_8859-supp & IT \\ +JIS\_C\_6220 & JIS\_C\_6229 & JUS\_I.B1.002 & latin-lap \\ +latin6 & macintosh & MSZ\_7795.3 & NF\_Z\_62-010 \\ +NS\_4551-1 & NS\_4551-2 & PT & PT2 \\ +roman8 & SEN\_850200\_B & SEN\_850200\_C & us-dk \\ +\end{tabular} + + +\bigskip\bigskip\bigskip +\noindent\subsubsection {Information Files that are available} + +\begin {itemize} +\item CHARSETS - (39K) specifies the above character mnemonic sets. These +sets must hold values which are validly defined in the {\em superset} +consisting of the 3 files specified below. + +\item ISO\_10646 - (32K) specifies the character mnemonics according to +ISO /10646. However only the alphabetic characters like latin, greek, +cyrillian, hebrew and arabic are included. + +\item CONTROL - (2K) specifies the control character mnemonics as defined in +ISO 2047 and ISO 6429-1988. + +\item OTHER - (1K) specifies the character mnemonics used privately. +The mnemonics held here are those specified: + +\begin {description} +\item In ISO\_6937-2 (Annex B). +\item To cover IBM symbols (e.g the Dutch gilder sign) +\item To cover HP ROMAN8 symbols (Italian lira sign) +\item To cover the Macintosh symbols. +\end {description} +\end {itemize} + +\clearpage +\noindent\subsubsection {Progs that are available} + +\medskip\noindent prog {\em GC} + +\begin {itemize} + +\item Reads ISO\_10646, CONTROL and OTHER to produce a superset +file called CHARMNEM containing all the valid mnemonics. + +\item Reads CHARSETS, and creates for each specified +character set, a unique file which contains: + +\begin {description} +\item A super matrix where each mnemonic held is placed as a numeric +2 byte value obtained from the superset. + +\item A super matrix where each mnemonic held is placed into its rightful +position. +\end {description} + +\item Produces a file CHARMAP.10646 to be used by POSIX.2 +\end {itemize} + +\bigskip\noindent prog {\em CONV} + +\begin {description} +\item CONV character-set-in character-set-out [ < file-in > file-out] +\end {description} + +\begin {itemize} +\item Reads one character set values and converts to another character +set. Reads from stdin, Outputs to stdout. If a character cannot be mapped +then it is output as Esc followed by its 2 byte mnemonic. An Esc followed +by an Esc is taken to mean one Esc. +\end {itemize} + + +\bigskip\bigskip +\subsection {Future developments} + +\begin {itemize} +\item The code will be PC compatible and as DOS is unable to create +links, all the files generated by program {\em GC} will be concatenated +into one large file. + +\item All files will have names not greater than 8 characters in length +again to be compatible with PCs. + +\item a quick table lookup having the superset already described above + +a longer table lookup of variable length names. The variable mnemonics +will be prefixed with Esc followed by \_ and postfixed with \_ + +\item Hexadecimal representations for the ISO 10646 codes. + +\item Will be able to replace two symbols to one abstract symbol, by the use +of POSIX locales. This should cope with the T.61 non-spacing accents, +and replacing say a IA5 FF to T.61 FF,CR. + +\end {itemize} + + +\clearpage +\subsection {Current Modifications for PP compatibility} + +\begin {itemize} +\item More stringent checking on the opening reading and writing of files. +GC core dumps of if cannot open CHARDEFS. +\item Separation into code, manual CHARSETS, and generated CHARSETS +should be configurable. +\item Add PP RCSing. +\item Replace constants with #define. +\item Replace the "nickname" keyword to "alias" this +conforms with PP's keywords. +\item Replace "unsigned char" and "short int" with typedef statements. - so +code is more independent and is run correctly at the discretion of the +administrator. +\end {itemize} + + +\clearpage +\subsection {Future PP Requirements} + +\begin {itemize} +\item A general mapping program that can map any character set into any +other. (This requirement is satisfied). +\item To decide whether all the different character set mappings should +be put into 1 huge file ?. How to break down the mnemonic superset into +smaller ones so that only certain character sets can be mapped by the +breakdown ?. +\item Decision whether or not the fixed and variable character mnemonics +table lookup should be intermingled. (I do not think so). +\item Decision whether or not to put the core of the code into the +library so that other PP routines can perform conversions. +\item Seperation of the master information and generated mapping files +from the source code and to decide into which directory to place this. +\item Generation of a warning message about the source code +being m/c specific so that it is in keeping with the ISO 16 bit matrix. +\item Decision on whats to be done about the 1 symbol mapping into 2. +E.g In CCITT X.408 FF (Form Feed) is mapped into "CR,FF" in the +T.61 string. (I do not think Keld's code is able to cope with this.) +\end {itemize} + +\end {document} diff --git a/Format/charset/make b/Format/charset/make new file mode 100755 index 0000000..4ea2372 --- /dev/null +++ b/Format/charset/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f ../../Lib/charset/Make.defs -f Makefile ${1+"$@"} diff --git a/Format/charset/test/files/dotranslate b/Format/charset/test/files/dotranslate new file mode 100755 index 0000000..4816f00 --- /dev/null +++ b/Format/charset/test/files/dotranslate @@ -0,0 +1,17 @@ +#!/bin/sh +#set -x + +CURR=`pwd` + +cd $CURR +pwd + +TYPE=`ls $CURR | egrep "orig."` + +for x in $TYPE +do + xnew=`echo $x | sed 's/orig.//'` + ../progs/translate < $x > $xnew +done + +exit 0 diff --git a/Format/charset/test/files/keld b/Format/charset/test/files/keld new file mode 100644 index 0000000..66162ec --- /dev/null +++ b/Format/charset/test/files/keld @@ -0,0 +1,6 @@ +test {|} +dansk tegns{t 7-bit +mon det g}r? + +bl}b{rsyltet|j! +bl}b{rgr|d! diff --git a/Format/charset/test/files/orig.czeck b/Format/charset/test/files/orig.czeck new file mode 100644 index 0000000..9809243 --- /dev/null +++ b/Format/charset/test/files/orig.czeck @@ -0,0 +1,17 @@ +Ya en 1961, el ex campe|on mundial Mijail Botvinnik se~nalaba esta +circunstancia con ocasi|on de su conferencia en la Universidad Humboldt +de Berl|in: . diff --git a/Format/charset/test/files/orig.english b/Format/charset/test/files/orig.english new file mode 100644 index 0000000..51ab88f --- /dev/null +++ b/Format/charset/test/files/orig.english @@ -0,0 +1,3 @@ +This file: +has a # character which is 0 (NULL). +has a + character which is GS. diff --git a/Format/charset/test/files/orig.italian b/Format/charset/test/files/orig.italian new file mode 100644 index 0000000..7384321 --- /dev/null +++ b/Format/charset/test/files/orig.italian @@ -0,0 +1,14 @@ +Transmissione dati $E l'invio di dati da un calcolatore o parte di esso +ad un altro. Usualmente, tuttavia, il termine $e applicato specificatamente +all'invio do dati mediante linea telefonica per mezzo di un modem (data +transmission). + +Tubo a raggi catodici $E lo stesso sistema utilizzato per gli abituali +televisori ed $e il modo pi$u comune per visualizzare istruzioni o dati +sul calcolatore. Un fascido di elettroni $e lanciato contro uno schermo +al fosforo sul quale produce dei punti luminosi. La direzione e +l'intensit$a del fascio $e variabile, generando cosi un grande numero +di punti che formano un'immagine. Questo fenomeno ha luogo in un tubo +di vetro vacuo (il tubo catodico) ed $e questa la ragione per la quale i +televisori, e in generale i video, possono esplodere se maneggiati +con poca cura. diff --git a/Format/charset/test/files/t.61-8.1 b/Format/charset/test/files/t.61-8.1 new file mode 100644 index 0000000..ab0a851 --- /dev/null +++ b/Format/charset/test/files/t.61-8.1 @@ -0,0 +1,2 @@ +ohm ae test tilde-a diaeresis-A +àátestÄaÈA diff --git a/Format/charset/test/files/t.61-8.all b/Format/charset/test/files/t.61-8.all new file mode 100644 index 0000000..b48564e --- /dev/null +++ b/Format/charset/test/files/t.61-8.all @@ -0,0 +1,18 @@ + +00  0 @ P ` p €   ° À Ð à ð +01   ! 1 A Q a q ‘ ¡ ± Á Ñ á ñ +02   " 2 B R b r ‚ ’ ¢ ² Â Ò â ò +03   # 3 C S c s ƒ “ £ ³ Ã Ó ã ó +04   $ 4 D T d t „ ” ¤ ´ Ä Ô ä ô +05   % 5 E U e u … • ¥ µ Å Õ å õ +06   & 6 F V f v † – ¦ ¶ Æ Ö æ ö +07   ' 7 G W g w ‡ — § · Ç × ç ÷ +08   ( 8 H X h x ˆ ˜ ¨ ¸ È Ø è ø +09  ) 9 I Y i y ‰ ™ © ¹ É Ù é ù +10 +  * : J Z j z Š š ª º Ê Ú ê ú +11  + ; K [ k { ‹ › « » Ë Û ë û +12  , < L \ l | Œ œ ¬ ¼ Ì Ü ì ü +13  - = M ] m } ­ ½ Í Ý í ý +14   . > N ^ n ~ Ž ž ® ¾ Î Þ î þ +15   / ? O _ o  Ÿ ¯ ¿ Ï ß ï ÿ diff --git a/Format/charset/test/progs/Makefile b/Format/charset/test/progs/Makefile new file mode 100644 index 0000000..9973bd1 --- /dev/null +++ b/Format/charset/test/progs/Makefile @@ -0,0 +1,85 @@ +# Makefile for the bpfilt test progs +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = bit2ch.c ch255.c ch2val.c translate.c +OBJS = bit2ch.o ch255.o ch2val.o translate.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../../../h +LIBPP = + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) $(LCF) -D +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = ch255 bit2ch ch2val translate + +default: $(OBJS) $(PROGS) +all: $(PROGS) + + +bit2ch: bit2ch.o + $(CC) $(LDFLAGS) bit2ch.o -o $@ + +ch2val: ch2val.o + $(CC) $(LDFLAGS) ch2val.o -o $@ + +ch255: ch255.o + $(CC) $(LDFLAGS) ch255.o -o $@ + + +translate: translate.o + $(CC) $(LDFLAGS) translate.o -o $@ + + +install: ; + +clean: tidy + rm -f $(OBJS) $(PROGS) + +tidy: + rm -rf core a.out *.old *.BAK + +depend: + $(DEPEND) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +bit2ch.o: bit2ch.c +ch255.o: ch255.c +ch2val.o: ch2val.c +translate.o: translate.c + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/charset/test/progs/bit2ch b/Format/charset/test/progs/bit2ch new file mode 100755 index 0000000000000000000000000000000000000000..f935d272afcac3c2ffe02aa05a5377d85c6c5a5c GIT binary patch literal 16384 zcmeI2-)oyy7{{MC@B8LWlhVD-x^`u~I5caSo0=)!s5kG}hLfQp>_TCfq)plevZTIw zH>#HH?bwCjE@FtIjtyUAY$8K?Ark7Kr3&77QO5p&*oh2(fFKNoLi|3-o9evq&I{o= z^yGZcbDrlp=X}mdZcdkUEkUHHThVliQlX$bwxUfvaO!$+?1O_U(uf2`BjUtIi0pgg zt)@;C+n}kKUn4Ezlc6EdA&Pg~Sg-%ywN#)Sis^s1U%$ULmqz?&d$tY?qOB#z`w@Gx zjyZ4J6vLdSx!C-D5zp*=b!w+%^^iOjCfgWTx^dP^b2Xi+}(&~mk80I}u zLoURdBZ}xsvK3jjX&5=5xeEJD%u$Qb&|SpB#|nLtq0gbKHVuV&yl{Q{5S!xleTrDj zIT!9bu`{2so~+w6_>X*h5I4eeB4$1?*0mo}!Qzjp!2dZFTxpnU;t1g-x5rlNRw7E52XV$2Bfk-FJ3 z?wRWZAA@~hy8x}R=2J_bt-9$_aVlNPKUu9%I$t=Ke!JjSFvw+e+Vu`Ur^*%esAIf4 zOq1R5M+eoJ-28m8Jga7M#nM@~5IPV2m8&;PcjWs0FN2zO2dlBp*X{k}-&7jTd0-Xn zU|ZxdFprJF0^Yu{V0!BGbiwn$XW%WIYSb zZpRTDut33YgZ@@m(yJO-?}Yj_jbeLQX9`|n!9$bJc{w!YJXO7%>vcafGo?xnqnW}& z5zU!gvCKZ_if#oWbL{n(kG%BaQJ6Zzvjwk8nW@g#B{T09%iauTFiSp9giUZW%^y;P zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwWKe@g)Gdk)^}oc;ek zjd{8|?x1zDcotki#rvWG-6_apY(r(k|0OuZZ*nlw(t5V@sK{@r7uxM@eqapsAJAH; z`OP*G>ffOCQ2z>Tg!&g~ev{lO&Vkfp`%e^d`GVV7f1D1YsN=3%ag{e$tSbDKE1t@! zsiIf)@G>_Wr-{6JLQPEXWDy|*gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@F VKnMr{As_^VfDjM@Lg4>R;7@rtcLe|d literal 0 HcmV?d00001 diff --git a/Format/charset/test/progs/bit2ch.c b/Format/charset/test/progs/bit2ch.c new file mode 100644 index 0000000..7ed1bda --- /dev/null +++ b/Format/charset/test/progs/bit2ch.c @@ -0,0 +1,64 @@ +/* bit2ch.c - converts one 8 bit string at a time into a one byte character */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + + +#include +#include "charset.h" + +#define BITS 8 + + +main (argc, argv) +int argc; +CHAR8U *argv[]; +{ + CHAR8U buf[BUFSIZ]; + int i = 0; + + bzero (buf, sizeof (buf)); + + if (argc == 1) + while (gets (buf) != NULL) { + convert (&buf[0]); + bzero (buf, sizeof (buf)); + } + else + while (i < argc-1) + convert (argv[++i]); + + printf ("\n"); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + +static convert(str) +CHAR8U *str; +{ + int i; + CHAR8U c=0; + + for (i=BITS-1; i >= 0; i--) { + if (str[i] == '1') + c |= 1 << (BITS - (i+1)); + else if (str[i] == '0') + continue; + else { + printf ("**** Error this is not a bitstring\n"); + return; + } + } + + printf ("%d - %c", c, c); +} diff --git a/Format/charset/test/progs/ch255 b/Format/charset/test/progs/ch255 new file mode 100755 index 0000000000000000000000000000000000000000..5375a0f1b83f92fa3508c8101c0fa4e57cb05563 GIT binary patch literal 16384 zcmeI2&ud&&6vxl|HSc9o%F8r0Rta1(NvXDUq`L4YJh5V>s9S|%<|Q*RBh#7qGA%(u z`=)du*u^-+B1Q2cr3)#pLJ2`gmi;q!-|=Cz6_aPFV~?5C~80_wlozjJ5|zLlHWgW8jA?0G$;0DGR| z=e1C&^b4hODZRnz-&~E!2Axis*8# zYkv~bLs;{vE118AJz6%6|A1QL_$DW3at>b!Y22*SFz0&|wRt|@m#D>_i{{>=_x5wQ zbM27E{;}SE)J^c7s9DnPw)Jyful|zP>D|1(IAqw#>kpvA4iz=@C7!)+1>S~tKDwnSYu-ikW;b9)sJGi**S+m+6LMV6!Q6Rh zi#5Ns!kOiyP_4`rs->gLbt;s~XAAF_lRAPt4$LQwC!STcx_U4%I|$RkLHxm>Ivp=9 zRci03g}72Zlax*J`0iT6T?P?+C-fMu7Lk9hl~Wt*p`s1g4cO)cJp$g7$8a~!*~IsP zJ@Pi!LYhR)dtg6#Bh$6gYuzxj)%$J3S0U#h_Ac^nu4go2Iy|`5yUXhiS>paxBKLBy z*8}Bfg=mEJI`l;%kM(uv7QWi7|1fv9;TdlLV~tnVHy57GGnRp8^No$ba}5vHeEA_q z6#18krmteo_bKxu_Wcfe?+AI{8@pSNr;uAj zn-l#@=V=)C7kQxn>5jv{Y5q&_Jo5U@(B^ir-z4SU?)hHtFK(C`{U@|#^zYEN(Z53D zT)QJWlz(jcL^&>%lm0ogG;{RH(hD>5+1$Z;$EQNwKWrm8(u>-|P0V@4B?ogJ z;rC@%DgQ&Il0Lo2^{qX@Q9sD{;QcVa-!Xz*%LoeFMlk!4MOxGJ`{QvBH82+HtszBp zKDnh|aA_~beC#6pE1099)4&bXBFBz%l5x%>7hM{N$EnBbdjPd5Uf(CE#hkP8zI%4( zGdGe=m-_!P-XQ9Rcuv$*19LZWa0*`_H(!0(1lW z&_4K@2y-tkUEgw+?jX^p#2M@j)`Wc)R);m-+f>vYe~YEBwj5@JdcA3FnK!KsLXOEf z@STR%So2rQoS3g==1NnUxx#_@3S|n#lbN@QwF-jVhNo-wN1ssTin=$kI||cS6u&p9 zj_0e@Qu&yg$(QC%)QWNPz+Yo^W{Dz~Z(Y04u-C8}`&82%C4WU}6F&8QIi@uD7C8py z4$j(Obe3q4eR0hjT;r~{f92R+``V7b;yv`)0j2Ntsq1QjhOZ`+>4EEJg6Q)^PUHC4 zdV7cc9j-W+!Db(Y^Njd(Uq7F9yx&0o7X3SP_F+A*HB8S&<&y<*1tnv!tccTHuT3ty{uosSQfg2ZlYs1 zVZ)Ij-a7kqbk1R47dq$IaqorYTKxNAjNx~_Bm1~O2I#@kue3!Ev->vJCd~DBI6X%2=+!3Hd!^)u0lU)ll?d}r#*w(fCU=< zZR5>I(n}iIZ^!yojhy>gXN&dXLLH`%ujgUP1)8ttYxU@votdlT5zQ7CN-)Rsr84K7 zEY&Iy*@LgW@YM6qJq=eFK31&HQ+6sm?%8UsRIblp25Z016JZl=!KV$OB=cHQj+ggPq*7Ud_fuOKcKZ(^PR08>tCRa zSl@*DmYlj(w5m`pFI%4E8-4|n0a*&>915D)@F xKnMr{As_^VfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2>d?@{0aQ@UhMz? literal 0 HcmV?d00001 diff --git a/Format/charset/test/progs/ch2val.c b/Format/charset/test/progs/ch2val.c new file mode 100644 index 0000000..7df07ff --- /dev/null +++ b/Format/charset/test/progs/ch2val.c @@ -0,0 +1,54 @@ +/* bit2ch.c - converts one 8 bit string at a time into a one byte character */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + + +#include +#include "charset.h" + +#define BITS 8 + + +main (argc, argv) +int argc; +CHAR8U *argv[]; +{ + CHAR8U buf[BUFSIZ]; + int i; + + bzero (buf, sizeof (buf)); + + if (argc == 1) + while (gets (buf) != NULL) { + convert (&buf[0]); + bzero (buf, sizeof (buf)); + } + else + while (i < argc-1) + convert (argv[++i]); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + +static convert(str) +CHAR8U *str; +{ + while (*str != 0) { + printf ("%c(d=%d x=%x o=%o) ", *str, *str, *str, *str); + str++; + } + + printf ("\n"); + return; +} diff --git a/Format/charset/test/progs/make b/Format/charset/test/progs/make new file mode 100755 index 0000000..b6ce556 --- /dev/null +++ b/Format/charset/test/progs/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/charset/test/progs/translate.c b/Format/charset/test/progs/translate.c new file mode 100644 index 0000000..85a60ab --- /dev/null +++ b/Format/charset/test/progs/translate.c @@ -0,0 +1,72 @@ +/* converts certain characters to t.61-8bit ones */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + + + +#include + + + +/* --- *** --- + # -> 0/0 + + -> GS + < -> 10/11 + > -> 11/11 + $ -> 12/1 + | -> 12/2 + ~ -> 12/4 + @ -> 12/11 +--- *** --- */ + + + +main() +{ + char s[BUFSIZ]; + int c; + + + while ((c = getchar()) != EOF) { + switch (c) { + case '#': + c = 0; + break; + case '+': + c = 29; + break; + case '<': + c = 171; + break; + case '>': + c = 187; + break; + case '$': + c = 193; + break; + case '|': + c = 194; + break; + case '~': + c = 196; + break; + case '@': + c = 206; + break; + } + + + fprintf (stdout, "%c", c); + } + + fflush (stdout); + exit (0); +} diff --git a/Format/make b/Format/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Format/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/p2explode/Makefile b/Format/p2explode/Makefile new file mode 100644 index 0000000..7b5889d --- /dev/null +++ b/Format/p2explode/Makefile @@ -0,0 +1,173 @@ +# P2explode -takes P2 and splits into directory structure +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/p2explode/RCS/Makefile,v 6.0 1991/12/18 20:20:02 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:20:02 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = p2explode.c explode_only.c explode_chan.c +OBJS = p2explode.o explode_only.o expode_chan.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +CHAN_SRCS = p2explode.c explode_chan.c +CHAN_OBJS = p2explode.o explode_chan.o +ALONE_SRCS = p2explode.c explode_only.c +ALONE_OBJS = p2explode.o explode_only.o +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SRCS) xexplode_chan + +clean: tidy + rm -f $(OBJS) *.o + +tidy: + rm -f zx* xexplode_chan core a.out *.old *.BAK *.ph *.log + +lint: l-p2explode l-explode_only +l-p2explode: $(CHAN_SRCS) + $(LINT) $(LLFLAGS) $(CHAN_SRCS) $(LINTLIBS) + +l-explode_only: $(ALONE_SRCS) + $(LINT) $(LLFLAGS) $(ALONE_SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: $(SRCS) + $(DEPEND) -I$(HEADERS) -I$(ISODEHDRS) $(SRCS) + + +xexplode_chan: $(CHAN_OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(CHAN_OBJS) -o $@ $(LIBPP) $(LIBSYS) + +alone: $(ALONE_OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(ALONE_OBJS) -o xexplode_only \ + $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-p2explode + +inst-p2explode: $(CHANDIR)/p2explode +$(CHANDIR)/p2explode: xexplode_chan + -$(BACKUP) $@ zxexplode_chan + rm -f $@ + $(INSTALL) xexplode_chan $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "The P2 explode channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +saber_src: $(CHAN_SRCS) + #load -C $(CFLAGS) $(CHAN_SRCS) $(LIBPP) $(LIBSYS) + +saber_obj:$(CHAN_OBJS) + #load -C $(CHAN_OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +p2explode.o: p2explode.c +p2explode.o: ../../h/util.h +p2explode.o: ../../h/config.h +p2explode.o: ../../h/ll_log.h +p2explode.o: ../../h/retcode.h +p2explode.o: ../../h/tb_bpt88.h +p2explode.o: ../../h/IOB-types.h +p2explode.o: ../../h/MTA-types.h +p2explode.o: ../../h/Toks-types.h +p2explode.o: ../../h/Auth-types.h +p2explode.o: ../../h/q.h +p2explode.o: ../../h/adr.h +p2explode.o: ../../h/list_rchan.h +p2explode.o: ../../h/chan.h +p2explode.o: ../../h/table.h +p2explode.o: ../../h/list_bpt.h +p2explode.o: ../../h/auth.h +p2explode.o: ../../h/list_bpt.h +p2explode.o: ../../h/extension.h +p2explode.o: ../../h/mta.h +p2explode.o: ../../h/adr.h +p2explode.o: ../../h/list_bpt.h +p2explode.o: ../../h/aparse.h +p2explode.o: ../../h/ap.h +p2explode.o: ../../h/util.h +p2explode.o: ../../h/or.h +p2explode.o: ../../h/chan.h +p2explode.o: ../../h/auth.h +p2explode.o: ../../h/list_rchan.h +p2explode.o: ../../h/mta.h +p2explode.o: ../../h/list_bpt.h +explode_only.o: explode_only.c +explode_only.o: ../../h/util.h +explode_only.o: ../../h/config.h +explode_only.o: ../../h/ll_log.h +explode_only.o: ../../h/retcode.h +explode_only.o: ../../h/util.h +explode_chan.o: explode_chan.c +explode_chan.o: ../../h/util.h +explode_chan.o: ../../h/config.h +explode_chan.o: ../../h/ll_log.h +explode_chan.o: ../../h/qmgr.h +explode_chan.o: ../../h/Qmgr-types.h +explode_chan.o: ../../h/Qmgr-ops.h +explode_chan.o: ../../h/q.h +explode_chan.o: ../../h/adr.h +explode_chan.o: ../../h/list_rchan.h +explode_chan.o: ../../h/chan.h +explode_chan.o: ../../h/table.h +explode_chan.o: ../../h/list_bpt.h +explode_chan.o: ../../h/auth.h +explode_chan.o: ../../h/list_bpt.h +explode_chan.o: ../../h/extension.h +explode_chan.o: ../../h/mta.h +explode_chan.o: ../../h/adr.h +explode_chan.o: ../../h/list_bpt.h +explode_chan.o: ../../h/aparse.h +explode_chan.o: ../../h/ap.h +explode_chan.o: ../../h/util.h +explode_chan.o: ../../h/or.h +explode_chan.o: ../../h/chan.h +explode_chan.o: ../../h/auth.h +explode_chan.o: ../../h/list_rchan.h +explode_chan.o: ../../h/mta.h +explode_chan.o: ../../h/prm.h +explode_chan.o: ../../h/retcode.h +explode_chan.o: ../../h/tb_bpt88.h +explode_chan.o: ../../h/dr.h +explode_chan.o: ../../h/extension.h +explode_chan.o: ../../h/mta.h +explode_chan.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/p2explode/explode_chan.c b/Format/p2explode/explode_chan.c new file mode 100644 index 0000000..1933c23 --- /dev/null +++ b/Format/p2explode/explode_chan.c @@ -0,0 +1,328 @@ +/* p2explode: channel to explode a P2 message into body parts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2explode/RCS/explode_chan.c,v 6.0 1991/12/18 20:20:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2explode/RCS/explode_chan.c,v 6.0 1991/12/18 20:20:02 jpo Rel $ + * + * $Log: explode_chan.c,v $ + * Revision 6.0 1991/12/18 20:20:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "retcode.h" +#include "tb_bpt88.h" +#include "dr.h" +#include +#include "sys.file.h" +#include + +extern CMD_TABLE bptbl_body_parts88[/* x400 84 body_parts */]; +extern char *quedfldir; +extern CHAN *ch_nm2struct(); +extern char *cont_p2; +extern void rd_end(), sys_init(), err_abrt(); +extern struct type_Qmgr_DeliveryStatus *delivery_resetDRs(); +extern int err_fatal; +static CHAN *mychan; +static char *this_msg, *this_chan; + +static int processMsg(); +static int doSplit(); +static struct type_Qmgr_DeliveryStatus *process(); +static int initialise(); +static int security_check(), x40084; +static void dirinit(); +static ADDR *getnthrecip (); +int first_failureDR; +/* */ +/* main routine */ + +main(argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control (argc, argv, initialise, process, NULLIFP); + else +#endif + channel_control(argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt( RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/p2explode : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + return OK; +} + +/* */ + +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, + *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str(msg->qid); + msg_chan = qb2str(msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan, mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan channel err: '%s'",msg_chan)); + result = FALSE; + } + + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine to do explode */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *error; + + bzero((char *)&que,sizeof(que)); + bzero((char *)&prm,sizeof(prm)); + first_failureDR = TRUE; + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_TRACE, + ("P2 explode on msg '%s' through '%s'",this_msg,this_chan)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + for (ix = arg->users; ix; ix=ix->next) { + error = NULLCP; + err_fatal = NOTOK; + if ((adr = getnthrecip(&que, ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan : failed to find recipient %d",ix->RecipientId->parm)); + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + switch(chan_acheck (adr, mychan, 1, (char **) NULL)) { + case OK: + if (processMsg(this_msg,adr,&que,&error) == NOTOK) { + if (err_fatal == OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan : failed to process message '%s' for recipient %d: %s",this_msg,adr->ad_no, error)); + set_1dr(&que, adr->ad_no, this_msg, + DRR_CONVERSION_NOT_PERFORMED, + DRD_CONTENT_SYNTAX_ERROR, + (error == NULLCP) ? "Unable to parse the p2" : error); + delivery_set(adr->ad_no, + (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + } else + delivery_setstate(adr -> ad_no, + int_Qmgr_status_messageFailure, + (error == NULLCP) ? "" : error); + } else { + adr->ad_rcnt++; + wr_ad_rcntno(adr, adr->ad_rcnt); + delivery_set(adr->ad_no,int_Qmgr_status_success); + } + if (error != NULLCP) free(error); + break; + default: + break; + } + } + if (rp_isbad(retval = wr_q2dr(&que, this_msg))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs(int_Qmgr_status_messageFailure); + } + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + +/* */ + +extern LIST_BPT *outbound_bpts, *outbound_hdrs; + +/* returns ok if processed msg on mychan for recip */ +static int processMsg (msg,recip, qp, perr) +char *msg; +ADDR *recip; +Q_struct *qp; +char **perr; +{ + char *origdir = NULL, + *newdir = NULL, + *encr_str = NULLCP; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan original directory not found for recipient %d of message '%s'",recip->ad_no, msg)); + *perr = strdup("Unable to find source directory"); + return NOTOK; + } + + /* temporary change to get new directory name */ + recip->ad_rcnt++; + if (qid2dir(msg, recip, FALSE, &newdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/explode_chan couldn't construct new directory name for recipient %d of message '%s'", recip->ad_no, msg)); + *perr = strdup ("Unable to construct new directory"); + return NOTOK; + } + recip->ad_rcnt--; + + if (stat(newdir, &statbuf) == OK + && (statbuf.st_mode & S_IFMT) == S_IFDIR) { + /* new directory already exists, os processing already done */ + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + x40084 = (lexequ(qp->cont_type, cont_p2) == 0) ? TRUE : FALSE; + + /* HACK for undeclared bodyparts that are supported by outchan */ + if (recip -> ad_outchan && recip -> ad_outchan -> li_chan + && recip -> ad_outchan -> li_chan -> ch_bpt_out) + outbound_bpts = recip -> ad_outchan -> li_chan -> ch_bpt_out; + else + outbound_bpts = NULLIST_BPT; + + if (recip -> ad_outchan && recip -> ad_outchan -> li_chan + && recip -> ad_outchan -> li_chan -> ch_hdr_out) + outbound_hdrs = recip -> ad_outchan -> li_chan -> ch_hdr_out; + else + outbound_hdrs = NULLIST_BPT; + + + if (doSplit(origdir,newdir,msg,qp,perr) != OK) + return NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; +} + +/* */ +/* explodes p2 in orig into files in new */ +static int doSplit (old, new,msg,qp,perr) +char *old, + *new, + *msg; +Q_struct *qp; +char **perr; +{ + struct stat statbuf; + char tmpdir[MAXPATHLENGTH], buf[BUFSIZ]; + int result = OK; + + (void) sprintf(tmpdir, "%s/tmp.%s", + msg,mychan->ch_name); + + if (stat(tmpdir, &statbuf) == OK) { + /* exists so remove it */ + char *cmdline = malloc((unsigned) (strlen("rm -rf ") + strlen(tmpdir) + 1)); + (void) sprintf(cmdline, "rm -rf %s",tmpdir); + system(cmdline); + if (cmdline != NULL) free(cmdline); + } + + if (mkdir(tmpdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, tmpdir, + ("Can't make directory")); + (void) sprintf(buf, + "Failed to make temporary directory '%s'", + tmpdir); + *perr = strdup(buf); + return NOTOK; + } + result = unflatten(old,tmpdir, x40084, qp, perr); + if ((result == OK) && (rename(tmpdir,new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Can't rename directory '%s' to '%s'", + tmpdir, new)); + result = NOTOK; + } + return result; +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + diff --git a/Format/p2explode/explode_only.c b/Format/p2explode/explode_only.c new file mode 100644 index 0000000..5421cc1 --- /dev/null +++ b/Format/p2explode/explode_only.c @@ -0,0 +1,47 @@ +/* explode_alone: standalone p2 explode + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2explode/RCS/explode_only.c,v 6.0 1991/12/18 20:20:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2explode/RCS/explode_only.c,v 6.0 1991/12/18 20:20:02 jpo Rel $ + * + * $Log: explode_only.c,v $ + * Revision 6.0 1991/12/18 20:20:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" + +/* + * parameters - + * argv[0] = program name + * argv[1] = source directory + * argv[2] = destination directory + */ +#include "util.h" +extern int unflatten(); +static int x40084; + +main(argc, argv) +int argc; +char **argv; +{ + int result = OK; + char *error; + if (isatty (fileno(stderr))) + ll_dbinit(pp_log_norm, argv[0]); + + if(argc < 3) + err_abrt(RP_MECH, "Usage: %s src-dir dest-dir", argv[0]); + x40084 = FALSE; + if (argc == 4) + if (lexequ(argv[3], "-84") == 0) x40084 = TRUE; + result = unflatten(argv[1],argv[2],x40084,NULL, &error); + printf("Unflatten result was %s\n", (result == OK) ? "ok" : "notok"); +} diff --git a/Format/p2explode/make b/Format/p2explode/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/p2explode/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/p2explode/p2explode.c b/Format/p2explode/p2explode.c new file mode 100644 index 0000000..72b5037 --- /dev/null +++ b/Format/p2explode/p2explode.c @@ -0,0 +1,868 @@ +/* p2explode: explode a P2 structure up into component parts in hierachy */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2explode/RCS/p2explode.c,v 6.0 1991/12/18 20:20:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2explode/RCS/p2explode.c,v 6.0 1991/12/18 20:20:02 jpo Rel $ + * + * $Log: p2explode.c,v $ + * Revision 6.0 1991/12/18 20:20:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include +#include +#include "tb_bpt88.h" +#include "IOB-types.h" +#include +#include "q.h" +#include "list_bpt.h" +static int process(); +static FILE *open_IOB_file(); +static char curdir[MAXPATHLENGTH]; /* directory stack */ +int err_fatal = NOTOK; + +extern CMD_TABLE bptbl_body_parts88[/* x400 84 body_parts */]; +extern char *quedfldir; +extern char *hdr_p22_bp, *hdr_p2_bp, *hdr_ipn_bp, *cont_p22, *cont_p2; +LIST_BPT *outbound_bpts = NULLIST_BPT; +LIST_BPT *outbound_hdrs = NULLIST_BPT; + +void advise (); +void adios (); +#define ps_advise(ps, f) \ + advise (LLOG_EXCEPTIONS, NULLCP, "%s: %s",\ + (f), ps_error ((ps) -> ps_errno)) +char *makename(); + +unflatten(old, new, x40084, qp, perr) +char *old, + *new; +int x40084; +Q_struct *qp; +char **perr; +{ + char curpart[LINESIZE], buf[BUFSIZ]; + + setname (new); /* set initial directory */ + msg_rinit(old); + err_fatal = NOTOK; + if (!(msg_rfile(curpart) == RP_OK && isP2(curpart, x40084))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2explode cannot find %s file in '%s'", + (x40084 == TRUE) ? cont_p2 : cont_p22, + old)); + (void) sprintf (buf, + "Unable to find %s file in '%s'", + (x40084 == TRUE) ? cont_p2 : cont_p22, + old); + *perr = strdup(buf); + return NOTOK; + } + if (process (curpart, x40084, qp, perr) == NOTOK) + return NOTOK; + return OK; +} + +/* + * isP2: check to see if the current body part should be + * processed or not. + */ + +isP2(curpart, x40084) +char *curpart; +int x40084; +{ + char *cp; + + if ((cp = rindex(curpart,'/')) != NULLCP) + cp ++; + else cp = curpart; + + return (strcmp(cp, ((x40084 == TRUE) ? cont_p2 : cont_p22)) == 0); +} + +extern errno; + +/* linkthem: no reformatting needed so just link across */ + +linkthem(src, dest, perr) +char *src, *dest, **perr; +{ + char buf[BUFSIZ]; + + if(link(src, dest) < 0 && errno != EEXIST) { + PP_SLOG(LLOG_EXCEPTIONS, "link", + ("cannot link %s to %s", src, dest)); + (void) sprintf (buf, + "Unable to link %s to %s", + src, dest); + *perr = strdup(buf); + return NOTOK; + } + return OK; +} + +/* process: start the splitting operation on the given file */ +static int process (file, x40084, qp, perr) +register char *file; +int x40084; +Q_struct *qp; +char **perr; +{ + register PE pe; + register PS psin; + FILE *fp; + char buf[BUFSIZ]; + int retval = NOTOK; + struct type_IOB_InformationObject *infoob; + + if((fp = fopen (file, "r")) == (FILE *)0) { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open input file '%s'", + file); + *perr = strdup(buf); + return NOTOK; + } + + if ((psin = ps_alloc (std_open)) == NULLPS) + { + (void) fclose (fp); + ps_advise (psin, "ps_alloc"); + return NOTOK; + } + + if (std_setup (psin, fp) == NOTOK) + { + ps_free (psin); + (void) fclose (fp); + advise (LLOG_EXCEPTIONS, NULLCP, "%s: std_setup loses", file); + return NOTOK; + } + + if ((pe = ps2pe (psin)) == NULLPE) { /* EOF or error? */ + (void) fclose (fp); + err_fatal = OK; + (void) sprintf(buf, + "Unable to parse the p2 - ps2pe failed"); + *perr = strdup(buf); + ps_done(psin, "ps2pe"); + return NOTOK; + } + PY_pepy[0] = 0; + + if(decode_IOB_InformationObject(pe, 1, NULLIP, NULLVP, &infoob) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_InformationObject failure [%s]", + PY_pepy)); + pe_done(pe, "Parse failure IOB_InformationObject"); + err_fatal = OK; + (void) sprintf (buf, + "Unable to parse the p2 [%s]", + PY_pepy); + *perr = strdup (buf); + (void) fclose(fp); + return NOTOK; + } + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("parse_IOB_InformationObject non fatal failure [%s]", + PY_pepy)); + if (write_out_parts (infoob, x40084, qp, perr) == OK) + retval = OK; + if( pe != NULLPE) + pe_free (pe); + (void) fclose (fp); + return retval; +} + +write_out_parts (infoob, x40084, qp, perr) +struct type_IOB_InformationObject *infoob; +int x40084; +Q_struct *qp; +char **perr; +{ + char buf[BUFSIZ]; + + switch (infoob -> offset) { + case type_IOB_InformationObject_ipm: + return write_ipm (infoob -> un.ipm, x40084, qp, perr); + + case type_IOB_InformationObject_ipn: + return write_ipn (infoob -> un.ipn, x40084, qp, perr); + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown P2 type %d", infoob -> offset)); + (void) sprintf (buf, + "Unknown P2 type %d", + infoob -> offset); + *perr = strdup(buf); + return NOTOK; + } +} + +int write_ipm (ipm, x40084, qp, perr) +struct type_IOB_IPM *ipm; +int x40084; +Q_struct *qp; +char **perr; +{ + if (write_heading (x40084, ipm -> heading, qp, perr) == NOTOK) + return NOTOK; + + return write_bodies (ipm -> body, 1, x40084, qp, perr); +} + +int write_bodies (bpp, number, x40084, qp, perr) +struct type_IOB_Body *bpp; +int number; +int x40084; +Q_struct *qp; +char **perr; +{ + struct type_IOB_BodyPart *bp; + FILE *fp; + char buf[BUFSIZ]; + + while (bpp) { + bp = bpp -> BodyPart; + bpp = bpp->next; + + switch (bp -> offset) { + case type_IOB_BodyPart_ia5__text: + if ((fp = open_IOB_file (BPT_IA5, number, + qp, perr)) == NULLFILE) + return NOTOK; + dumpCRLFstring (fp, bp -> un.ia5__text -> data); + if (fclose (fp) == EOF) + return NOTOK; + break; + + case type_IOB_BodyPart_tlx: + if (write_pefile (BPT_TLX, number, 1, + (caddr_t)bp -> un.tlx, + &_ZIOB_mod, _ZTLXBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_voice: + if (write_pefile (BPT_VOICE, number, 2, + (caddr_t) bp -> un.voice, + &_ZIOB_mod, _ZVoiceBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + + case type_IOB_BodyPart_g3__facsimile: + if (write_pefile (BPT_G3FAX, number, 3, + (caddr_t) bp -> un.g3__facsimile, + &_ZIOB_mod, _ZG3FacsimileBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_g4__class1: + if (write_pefile (BPT_TIF0, number, 4, + (caddr_t) bp -> un.g4__class1, + &_ZIOB_mod, _ZG4Class1BodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_teletex: + if (write_pefile (BPT_TTX, number, 5, + (caddr_t) bp -> un.teletex, + &_ZIOB_mod, _ZTeletexBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_videotex: + if (write_pefile (BPT_VIDEOTEX, number, 6, + (caddr_t) bp -> un.videotex, + &_ZIOB_mod, _ZVideotexBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_encrypted: + if (write_pefile (BPT_ENCRYPTED, number, 8, + (caddr_t) bp -> un.encrypted, + &_ZIOB_mod, _ZEncryptedBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_message: + pushdir (number); + if (do_fip (bp -> un.message, x40084, qp, perr) == NOTOK) + return NOTOK; + popdir (); + break; + + case type_IOB_BodyPart_sfd: + if (write_pefile (BPT_SFD, number, 10, + (caddr_t) bp -> un.sfd, + &_ZIOB_mod, _ZSFDBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_mixed__mode: + if (write_pefile (BPT_TIF1, number, 11, + (caddr_t) bp -> un.mixed__mode, + &_ZIOB_mod, _ZMixedModeBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + case type_IOB_BodyPart_odif: + if (write_odif (bp -> un.odif, number, qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_nationally__defined: + if (write_pefile (BPT_NATIONAL, number, 7, + (caddr_t) bp -> un.nationally__defined, + &_ZIOB_mod, _ZNationallyDefinedBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_bilaterally__defined: + if (write_pefile (BPT_BILATERAL, number, 14, + (caddr_t) bp -> un.bilaterally__defined, + &_ZIOB_mod, _ZBilaterallyDefinedBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_externally__defined: + if (write_pefile (BPT_EXTERNAL, number, 15, + (caddr_t) bp -> un.externally__defined, + &_ZIOB_mod, _ZExternallyDefinedBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + case type_IOB_BodyPart_iso6937Text: + if (write_pefile (BPT_ISO6937TEXT, number, 13, + (caddr_t) bp -> un.iso6937Text, + &_ZIOB_mod, _ZISO6937TextBodyPartIOB, + qp, perr) == NOTOK) + return NOTOK; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown body part type %d", + bp -> offset)); + (void) sprintf (buf, + "Unknown body part type %d", + bp->offset); + *perr = strdup (buf); + return NOTOK; + } + number ++; + } + return OK; +} + +write_heading (x40084, heading, qp, perr) +int x40084; +struct type_IOB_Heading *heading; +Q_struct *qp; +char **perr; +{ + FILE *fp; + PE pe; + char buf[BUFSIZ]; + + if (encode_IOB_Heading(&pe, 1, NULL, NULLCP, heading) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode heading - %s", + PY_pepy)); + (void) sprintf (buf, + "Unable to encode heading - %s", + PY_pepy); + *perr = strdup(buf); + } + + if ((fp = open_IOB_file ((x40084 == TRUE) ? BPT_HDR_P2 : BPT_HDR_P22, + 0, qp, perr)) == NULLFILE) { + pe_free (pe); + return NOTOK; + } + + if (write_pe (pe, fp) == NOTOK) { + (void) fclose (fp); + pe_free (pe); + *perr = strdup("Unable to write_heading"); + return NOTOK; + } + + pe_free (pe); + if (fclose (fp) == EOF) + return NOTOK; + return OK; +} + +write_pefile (type, number, tag, parm, pmod, idx, qp, perr) +int type, number, tag; +caddr_t parm; +modtyp *pmod; +int idx; +Q_struct *qp; +char **perr; +{ + FILE *fp; + PE pe; + char buf[BUFSIZ]; + if (enc_f(idx, pmod, &pe, 1, NULL, NULLCP, parm) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode - %s", + PY_pepy)); + (void) sprintf (buf, + "Unable to encode - %s", + PY_pepy); + *perr = strdup(buf); + return NOTOK; + } + /* IMPLICIT TAG */ + pe->pe_class = PE_CLASS_CONT; + pe->pe_id = tag; + + if ((fp = open_IOB_file (type, number, qp, perr)) == NULLFILE) { + pe_free (pe); + return NOTOK; + } + if (write_pe (pe, fp) == NOTOK) { + (void) fclose (fp); + pe_free (pe); + *perr = strdup("Unable to write_pefile"); + return NOTOK; + } + pe_free (pe); + if (fclose (fp) == EOF) + return NOTOK; + return OK; +} + +int write_odif (op, number, Qp, perr) +struct type_IOB_ODIFBodyPart *op; +int number; +Q_struct *Qp; +char **perr; +{ + struct qbuf *qp; + FILE *fp; + + if ((fp = open_IOB_file (BPT_ODIF, number, Qp, perr)) == NULLFILE) + return NOTOK; + + for (qp = op -> qb_forw; qp != op; qp = qp -> qb_forw) + if (fwrite (qp -> qb_data, 1, qp -> qb_len, fp) + != qp -> qb_len) { + (void) fclose (fp); + return NOTOK; + } + if (fclose (fp) == EOF) + return NOTOK; + return OK; +} + +write_ipn (ipn, x40084, qp, perr) +struct type_IOB_IPN *ipn; +int x40084; +Q_struct *qp; +char **perr; +{ + PE pe; + if (ipn->choice->offset == choice_IOB_0_non__receipt__fields + && ipn->choice->un.non__receipt__fields->returned__ipm != NULL) { + pushdir(2); + if (write_ipm (ipn -> choice -> un.non__receipt__fields->returned__ipm, x40084, qp, perr) == NOTOK) + return NOTOK; + free_IOB_IPM(ipn -> choice -> un.non__receipt__fields->returned__ipm); + ipn -> choice -> un.non__receipt__fields -> returned__ipm = NULL; + popdir(); + } + + if (encode_IOB_IPN (&pe, 1, 0, NULLCP, ipn) == NOTOK) + return NOTOK; + + if (write_bp (hdr_ipn_bp, pe, perr) == NOTOK) + return NOTOK; + return OK; +} + +int do_fip (forwarded, x40084, qp, perr) +struct type_IOB_MessageBodyPart *forwarded; +int x40084; +Q_struct *qp; +char **perr; +{ + PE pe; + + if (forwarded -> parameters != NULL + && (forwarded -> parameters -> delivery__time != NULL + || forwarded -> parameters -> delivery__envelope != NULL)) { + /* have delivery info put out */ + if (encode_IOB_MessageParameters(&pe, 1, 0, + NULLCP, + forwarded -> parameters) == NOTOK) { + *perr = strdup("Unable to encode IOB_MessageParameters for forwarded message"); + return NOTOK; + } + if (write_bp (rcmd_srch (BPT_P2_DLIV_TXT, bptbl_body_parts88), + pe,perr) == NOTOK) + return NOTOK; + } + return write_ipm (forwarded -> data, x40084, qp, perr); +} + +/* pe_done: utility routine to do the right thing for pe errors */ +int pe_done (pe, msg) +PE pe; +char *msg; +{ + if (pe->pe_errno) + { + PP_OPER(NULLCP, + ("%s: [%s] %s",msg,PY_pepy,pe_error(pe->pe_errno))); + pe_free (pe); + return NOTOK; + } + else + { + pe_free (pe); + return OK; + } +} + +/* ps_done: like pe_done */ +int ps_done (ps, msg) +PS ps; +char *msg; +{ + ps_advise (ps, msg); + ps_free (ps); + return NOTOK; +} + +/* */ +/* convert from \r\n to \n */ + +dumpCRLFstring(fp, pstr) +FILE *fp; +struct type_UNIV_IA5String *pstr; +{ + char lastc = NULL; + char *cp; + struct qbuf *qb; + int n; + + for (qb = pstr -> qb_forw; qb != pstr; qb = qb -> qb_forw) { + for (n = qb -> qb_len, cp = qb -> qb_data; + n > 0; n--, cp++) { + switch (*cp) { + case '\r': + lastc = *cp; + break; + + case '\n': + putc (*cp, fp); + lastc = NULL; + break; + + default: + if (lastc) { + putc (lastc, fp); + lastc = NULL; + } + putc (*cp, fp); + break; + } + } + } + if (lastc) putc (lastc, fp); +} + +/* + * write_bp: write a body part contained in pe out to the file named + * name. name is converted into the correct place in the directory + * tree. + */ + +write_bp(name, pe, perr) +char *name; +PE pe; +char **perr; +{ + FILE *fp; + char filename[MAXPATHLENGTH], buf[BUFSIZ]; + + if (name[0] == '/' || + strncmp (name, "./", 2) == 0 || strncmp (name, "../", 3) == 0) + sprintf(filename,"%s",name); + else + sprintf(filename, "%s/%s",curdir,name); + PP_LOG(LLOG_TRACE, + ("Chans/p2explode writing %s...", filename)); + + if((fp = fopen(filename, "w")) == NULL) + { + PP_SLOG(LLOG_EXCEPTIONS, filename, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open output file '%s'", + filename); + *perr = strdup(buf); + return NOTOK; + } + + if (write_pe (pe, fp) == NOTOK) { + (void) sprintf (buf, + "Failed to write output file '%s'", + filename); + *perr = strdup(buf); + return NOTOK; + } + (void) fclose (fp); + return OK; +} + +write_pe (pe, fp) +PE pe; +FILE *fp; +{ + PS psout; + if ((psout = ps_alloc(std_open)) == NULLPS) + { + ps_advise (psout, "ps_alloc"); + (void) fclose (fp); + return NOTOK; + } + if (std_setup (psout, fp) == NOTOK) + { + advise (LLOG_EXCEPTIONS, NULLCP, "std_setup loses"); + (void) fclose (fp); + return NOTOK; + } + + if(pe2ps(psout, pe) == NOTOK) + { + ps_advise(psout, "pe2ps loses"); + return NOTOK; + } + ps_free (psout); + return OK; +} + +/* pushdir: used in forwarded ip messages. Decend a level in the + * directory hierachy. + */ +pushdir (n) +int n; +{ + char *p; + char name_buf[MAXPATHLENGTH]; + + (void) sprintf(name_buf, "%d.ipm", n); + p = makename (name_buf); + setname (p); /* clever bit - set new dir name */ + if( mkdir(p, 0755) == NOTOK) + adios("mkdir", "Can't create directory %s", p); + PP_LOG(LLOG_TRACE, ("Created %s\n", p)); +} + +/* makename: convert name into directory path */ +char *makename (name) +char *name; +{ + static char name_buf[MAXPATHLENGTH]; + if (name[0] == '/' || strncmp (name,"./", 2) == 0 || + strncmp (name, "../", 3) ==0) + /* fullname already */ + return strdup(name); + else + (void) sprintf (name_buf, "%s/%s", curdir, name); + return name_buf; +} + +/* initialise name for above */ +setname (name) +char *name; +{ + (void) strcpy (curdir, name); +/* printf ("setname -> %s\n", curdir);*/ +} + +/* popdir: counterpart of pushdir */ +popdir() +{ + char *p; + + if(( p = rindex(curdir, '/')) != NULLCP) + *p = '\0'; + else{ + advise (LLOG_EXCEPTIONS,NULLCP, "Popdir - underflow"); + } +} + +pepy2type (type) +int type; +{ + switch (type) { + case 0: + return BPT_IA5; + case 1: + return BPT_TLX; + case 2: + return BPT_VOICE; + case 3: + return BPT_G3FAX; + case 4: + return BPT_TIF0; + case 5: + return BPT_TTX; + case 6: + return BPT_VIDEOTEX; + case 7: + return BPT_NATIONAL; + case 8: + return BPT_ENCRYPTED; +/* case 9: + forwarded message should be dealt with else where */ + case 10: + return BPT_SFD; + case 11: + return BPT_TIF1; + case 12: + return BPT_ODIF; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2explode unknown bpt type %d\n",type)); + return BPT_UNDEFINED; + } +} + +static FILE *open_IOB_file(type, num, qp, perr) +int type, + num; +Q_struct *qp; +char **perr; +{ + char *p = NULLCP, + filename[MAXPATHLENGTH], buf[BUFSIZ]; + FILE *fp; + + if ((p = rcmd_srch(type, bptbl_body_parts88)) != NULLCP + && qp != NULL + && list_bpt_find (qp->encodedinfo.eit_types, + p) == NULLIST_BPT) { + /* HACK for undeclared bp that are supported by outchan */ + if (outbound_bpts && + list_bpt_find (outbound_bpts, p) != NULLIST_BPT) + PP_LOG(LLOG_NOTICE, + ("Bodypart '%s' present but undeclared. Outbound channel supports it so letting through", p)); + else if (outbound_hdrs && + list_bpt_find (outbound_hdrs, p) != NULLIST_BPT) + PP_LOG(LLOG_NOTICE, + ("Headertype '%s' present but undeclared. Outbound channel supports it so letting through", p)); + else { + sprintf (buf, + "body type '%s' present but undeclared in envelope", + p); + *perr = strdup(buf); + err_fatal = OK; + return NULL; + } + } + + if(p == NULLCP) { + advise(LLOG_EXCEPTIONS, NULLCP, "Unknown body type %d", type); + sprintf (filename, "%s/%d", curdir,num); + } if (type == BPT_HDR_P2 || type == BPT_HDR_P22) + sprintf (filename, "%s/%s", curdir, p); + else + sprintf(filename, "%s/%d.%s", curdir,num, p); + + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2explode writing %s",filename)); + + if ((fp = fopen(filename, "w")) == NULL) + { + PP_SLOG(LLOG_EXCEPTIONS, filename, + ("Can't open file")); + (void) sprintf(buf, + "Failed to open output file '%s'", + filename); + *perr = strdup(buf); + return NULL; + } + return fp; +} +/* ERRORS */ + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Format/p2flatten/Makefile b/Format/p2flatten/Makefile new file mode 100644 index 0000000..7cf4fae --- /dev/null +++ b/Format/p2flatten/Makefile @@ -0,0 +1,149 @@ +# +# P2flattener -takes P2 split into directory structure +# and flattens it to one file +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/Makefile,v 6.0 1991/12/18 20:20:12 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:20:12 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = flatten_only.c flatten_chan.c p2flatten.c +OBJS = flatten_only.o flatten_chan.o p2flatten.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +CHAN_SRCS = p2flatten.c flatten_chan.c +CHAN_OBJS = p2flatten.o flatten_chan.o +ALONE_SRCS = p2flatten.c flatten_only.c +ALONE_OBJS = p2flatten.o flatten_only.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SRCS) xflatten_chan + +clean: tidy + rm -f $(OBJS) *.o +tidy: + rm -f xflatten_only xflatten_chan zxflatten_chan p2flatten \ + core a.out *.old *.BAK *.ph *.log + +lint: l-p2flatten l-flatten-alone + +l-p2flatten: $(CHAN_SRCS) + $(LINT) $(LLFLAGS) $(CHAN_SRCS) $(LINTLIBS) + +l-flatten-alone: $(ALONE_SRCS) + $(LINT) $(LLFLAGS) $(ALONE_SRCS) S(LINTLIBS) +define: + $(DEFINE) Makefile + +depend: $(SRCS) + $(DEPEND) -I$(HEADERS) -I$(ISODEHDRS) $(SRCS) + + +xflatten_chan: $(CHAN_OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(CHAN_OBJS) -o $@ $(LIBPP) $(LIBSYS) + +alone: $(ALONE_OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(ALONE_OBJS) -o xflatten_only \ + $(LIBPP) $(LIBSYS) + +install: inst-dir inst-p2flatten + +inst-p2flatten: $(CHANDIR)/p2flatten +$(CHANDIR)/p2flatten: xflatten_chan + -$(BACKUP) $@ zxflatten_chan + rm -f $@ + $(INSTALL) xflatten_chan $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "p2flatten channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +saber_src: $(CHAN_SRCS) + #load -C $(CFLAGS) $(CHAN_SRCS) $(LIBPP) $(LIBSYS) + +saber_obj:$(CHAN_OBJS) + #load -C $(CHAN_OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +flatten_only.o: flatten_only.c +flatten_only.o: ../../h/retcode.h +flatten_only.o: ../../h/util.h +flatten_only.o: ../../h/config.h +flatten_only.o: ../../h/ll_log.h +flatten_chan.o: flatten_chan.c +flatten_chan.o: ../../h/util.h +flatten_chan.o: ../../h/config.h +flatten_chan.o: ../../h/ll_log.h +flatten_chan.o: ../../h/qmgr.h +flatten_chan.o: ../../h/Qmgr-types.h +flatten_chan.o: ../../h/Qmgr-ops.h +flatten_chan.o: ../../h/q.h +flatten_chan.o: ../../h/adr.h +flatten_chan.o: ../../h/list_rchan.h +flatten_chan.o: ../../h/chan.h +flatten_chan.o: ../../h/table.h +flatten_chan.o: ../../h/list_bpt.h +flatten_chan.o: ../../h/auth.h +flatten_chan.o: ../../h/list_bpt.h +flatten_chan.o: ../../h/extension.h +flatten_chan.o: ../../h/mta.h +flatten_chan.o: ../../h/adr.h +flatten_chan.o: ../../h/list_bpt.h +flatten_chan.o: ../../h/aparse.h +flatten_chan.o: ../../h/ap.h +flatten_chan.o: ../../h/util.h +flatten_chan.o: ../../h/or.h +flatten_chan.o: ../../h/chan.h +flatten_chan.o: ../../h/auth.h +flatten_chan.o: ../../h/list_rchan.h +flatten_chan.o: ../../h/mta.h +flatten_chan.o: ../../h/prm.h +flatten_chan.o: ../../h/retcode.h +flatten_chan.o: ../../h/sys.file.h +p2flatten.o: p2flatten.c +p2flatten.o: ../../h/util.h +p2flatten.o: ../../h/config.h +p2flatten.o: ../../h/ll_log.h +p2flatten.o: ../../h/retcode.h +p2flatten.o: ../../h/tb_bpt88.h +p2flatten.o: ../../h/IOB-types.h +p2flatten.o: ../../h/MTA-types.h +p2flatten.o: ../../h/Toks-types.h +p2flatten.o: ../../h/Auth-types.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/p2flatten/flatten_chan.c b/Format/p2flatten/flatten_chan.c new file mode 100644 index 0000000..f2f48e5 --- /dev/null +++ b/Format/p2flatten/flatten_chan.c @@ -0,0 +1,316 @@ +/* flatten_chan: channel to flatten body parts into a P2 message */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/flatten_chan.c,v 6.0 1991/12/18 20:20:12 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/flatten_chan.c,v 6.0 1991/12/18 20:20:12 jpo Rel $ + * + * $Log: flatten_chan.c,v $ + * Revision 6.0 1991/12/18 20:20:12 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "dr.h" +#include "retcode.h" +#include +#include "sys.file.h" + +extern char *quedfldir; +extern CHAN *ch_nm2struct(); +extern char *cont_p2; +extern void rd_end(), sys_init(), err_abrt(); +static CHAN *mychan; +static char *this_msg, *this_chan; + +static struct type_Qmgr_DeliveryStatus *process(); +static int initialise(); +static int security_check(); +static void dirinit(); +static ADDR *getnthrecip (); +static int processMsg(); +static int doComb(); +static int x40084; +/* */ +/* main routine */ + +main(argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control (argc, argv, initialise, process, NULLIFP); + else +#endif + channel_control(argc, argv, initialise, process, NULLIFP); +} + +/* */ +/* move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt( RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/p2flatten : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + return OK; +} + +/* */ + +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, + *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str(msg->qid); + msg_chan = qb2str(msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan, mychan->ch_name) != 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan channel err: '%s'",msg_chan)); + result = FALSE; + } + + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine to do split */ + +extern int err_fatal; +int first_failureDR; + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *error; + + bzero((char *) &que,sizeof(que)); + bzero((char *) &prm,sizeof(prm)); + first_failureDR = TRUE; + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_TRACE, + ("P2 flatten on msg '%s' through '%s'",this_msg,this_chan)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + for (ix = arg->users; ix; ix=ix->next) { + error = NULLCP; + if ((adr = getnthrecip(&que, ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan : failed to find recipient %d",ix->RecipientId->parm)); + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch (chan_acheck (adr, mychan, 1, (char **) NULL)) { + case OK: + if (processMsg(this_msg,adr,&error) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan : failed to process message '%s' for recipient %d",this_msg,adr->ad_no)); + if (err_fatal == TRUE) { + set_1dr(&que, adr->ad_no, this_msg, + DRR_CONVERSION_NOT_PERFORMED, + DRD_CONTENT_SYNTAX_ERROR, + (error == NULLCP) ? "Unable to flatten the p2" : error); + delivery_set(adr->ad_no, + (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + } else + delivery_setstate(adr->ad_no, + int_Qmgr_status_messageFailure, + (error == NULLCP) ? "Failed to flatten message" : error); + } else { + adr->ad_rcnt++; + wr_ad_rcntno(adr, adr->ad_rcnt); + delivery_set(adr->ad_no, + int_Qmgr_status_success); + } + break; + default: + break; + } + if (error != NULLCP) + free(error); + } + if (rp_isbad(retval = wr_q2dr(&que, this_msg))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs(int_Qmgr_status_messageFailure); + } + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + +/* */ +/* returns ok if processed msg on mychan for recip */ +static int processMsg (msg,recip, perr) +char *msg; +ADDR *recip; +char **perr; +{ + char *origdir = NULL, + *newdir = NULL; + int result = OK; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan original directory not found for recipient %d of message '%s'",recip->ad_no, msg)); + *perr = strdup("Can't find source directory"); + result = NOTOK; + } + + /* temporary change to get new directory name */ + recip->ad_rcnt++; + if ((result == OK) + && (qid2dir(msg, recip, FALSE, &newdir) != OK)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/flatten_chan couldn't construct new directory name for recipient %d of message '%s'", recip->ad_no, msg)); + *perr = strdup("Can't construct destination directory"); + result = NOTOK; + } + recip->ad_rcnt--; + + if ((result == OK) + && (stat(newdir, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* new directory already exists, os processing already done */ + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + x40084 = (lexequ(recip->ad_content, cont_p2) == 0) ? TRUE : FALSE; + if ((result == OK) && (doComb(origdir,newdir,msg, perr) != OK)) + result = NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return result; +} + +/* */ +/* combs files in orig into p2 in new */ +static int doComb (old, new,msg,perr) +char *old, + *new, + *msg, + **perr; +{ + struct stat statbuf; + char tmpdir[MAXPATHLENGTH], buf[BUFSIZ]; + int result = OK; + + (void) sprintf(tmpdir, "%s/tmp.%s", + msg,mychan->ch_name); + + if (stat(tmpdir, &statbuf) == OK) { + /* exists so remove it */ + char *cmdline = malloc((unsigned) (strlen("rm -rf ") + strlen(tmpdir)+1)); + (void) sprintf(cmdline, "rm -rf %s",tmpdir); + system(cmdline); + if (cmdline != NULL) free(cmdline); + } + + if (mkdir(tmpdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, tmpdir, + ("Can't make directory")); + (void) sprintf (buf, + "Unable to make temp directory '%s'", + tmpdir); + *perr = strdup(buf); + result = NOTOK; + } + if (result == OK) + result = flatten(old,tmpdir, x40084, perr); + if ((result == OK) && (rename(tmpdir,new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Unable to rename directory '%s' to '%s'", + tmpdir, new)); + (void) sprintf (buf, + "Unable to rename directory '%s' to '%s'", + tmpdir, new); + *perr = strdup(buf); + result = NOTOK; + } + + return result; +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + diff --git a/Format/p2flatten/flatten_only.c b/Format/p2flatten/flatten_only.c new file mode 100644 index 0000000..a632d54 --- /dev/null +++ b/Format/p2flatten/flatten_only.c @@ -0,0 +1,47 @@ +/* flatten_alone: standalone flatten a P2 directory structure into a message again */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/flatten_only.c,v 6.0 1991/12/18 20:20:12 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/flatten_only.c,v 6.0 1991/12/18 20:20:12 jpo Rel $ + * + * $Log: flatten_only.c,v $ + * Revision 6.0 1991/12/18 20:20:12 jpo + * Release 6.0 + * + */ + + + +#include "retcode.h" +#include "util.h" + +static char *myname = "p2flatten_alone"; + +/* + * parameters - + * argv[0] = program name + * argv[1] = source directory + * argv[2] = destination directory + */ + +static int x40084; + +main(argc, argv) +int argc; +char **argv; +{ + int result = OK; + if (isatty (fileno(stderr))) + ll_dbinit(pp_log_norm, argv[0]); + if (argc < 3) + err_abrt(RP_MECH, "Usage: %s src-dir dest-dir", argv[0]); + x40084 = FALSE; + if (argc == 4) + if (lexequ(argv[3], "-84") == 0) + x40084 = TRUE; + result = flatten(argv[1], argv[2], x40084); + printf("Flatten result was %s\n", (result == OK) ? "ok" : "notok"); +} diff --git a/Format/p2flatten/make b/Format/p2flatten/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/p2flatten/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/p2flatten/p2flatten.c b/Format/p2flatten/p2flatten.c new file mode 100644 index 0000000..f6fc3ea --- /dev/null +++ b/Format/p2flatten/p2flatten.c @@ -0,0 +1,990 @@ +/* p2flatten: flatten a P2 directory structure into a message again */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/p2flatten.c,v 6.0 1991/12/18 20:20:12 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2flatten/RCS/p2flatten.c,v 6.0 1991/12/18 20:20:12 jpo Rel $ + * + * $Log: p2flatten.c,v $ + * Revision 6.0 1991/12/18 20:20:12 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include +#include "retcode.h" +#include +#include "tb_bpt88.h" +#include "IOB-types.h" + +extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */]; +extern char *quedfldir; +extern char *cont_p2, *cont_p22; +extern void err_abrt(); +static char curdir[MAXPATHLENGTH]; /* directory stack */ +static caddr_t read_bpfile(); + +char curfile[MAXPATHLENGTH]; +int curdepth = 0; +int more = TRUE; +int flatresult = OK, err_fatal = FALSE; + +void advise (); +void adios (); +#define ps_advise(ps, f) \ + advise (NULLCP, "%s: %s", (f), ps_error ((ps) -> ps_errno)) + +flatten(old,new, x40084, perr) +char *old; +char *new; +int x40084; +char **perr; +{ + PE pe = NULLPE; + struct type_IOB_InformationObject *infoobj = NULL; + char buf[BUFSIZ]; + + curdepth = depth(old) + 1; + (void) sprintf(curdir, old); + msg_rinit(old); + flatresult = OK; + + if (getname(curfile) != OK) { + (void) sprintf (buf, + "Source directory '%s' is empty", + old); + *perr = strdup(buf); + PP_LOG(LLOG_EXCEPTIONS, + ("No files in %s", old)); + flatresult = NOTOK; + } + setname(old); + more = TRUE; + + fillin_infoobj(&infoobj, x40084, perr); + + msg_rend(); + + PY_pepy[0] = 0; + + if (flatresult == OK) { + if (encode_IOB_InformationObject (&pe, 1, 0, NULLCP, infoobj) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("p2flatten failed to encode InformationObject [%s]", + PY_pepy)); + (void) sprintf (buf, + "Failed to encode message as p2 (%s)", + (x40084 == TRUE) ? "84" : "88"); + *perr = strdup(buf); + err_fatal = TRUE; + flatresult = NOTOK; + } else + pe_fragment (pe, 128); + } + + if (flatresult == OK) { + setname (new); + write_bp((x40084 == TRUE) ? cont_p2 : cont_p22, pe, perr); + if (flatresult == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2flatten : write_bp failed")); + *perr = strdup("Failed to write out p2 body part"); + } + } else + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2flatten : encode_IOB_InformationObject failed")); + free_IOB_InformationObject(infoobj); + if (pe != NULLPE) pe_free (pe); + + return flatresult; +} + +extern errno; + +/* pe_done: utility routine to do the right thing for pe errors */ +int pe_done (pe, msg) +PE pe; +char *msg; +{ + if (pe->pe_errno) + { + advise (LLOG_EXCEPTIONS,NULLCP,"%s: %s", msg, pe_error(pe->pe_errno)); + pe_free (pe); + return 1; + } + else + { + pe_free (pe); + return 0; + } +} + +/* */ + +int fillin_infoobj(pinfoobj, x40084, perr) +struct type_IOB_InformationObject **pinfoobj; +int x40084; +char **perr; +{ + char buf[BUFSIZ]; + int type = bp_type(curfile); + *pinfoobj = (struct type_IOB_InformationObject *) calloc(1, + sizeof(struct type_IOB_InformationObject)); + /* what to do about sr ? */ + if (type == ((x40084 == TRUE) ? BPT_HDR_P2 : BPT_HDR_P22)) { + (*pinfoobj)->offset = type_IOB_InformationObject_ipm; + fillin_ipm(&((*pinfoobj)->un.ipm), x40084, perr); + } else if (type == BPT_HDR_IPN) { + (*pinfoobj)->offset = type_IOB_InformationObject_ipn; + fillin_ipn (&((*pinfoobj)->un.ipn), x40084, perr); + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Expected %s header got '%s'", + (x40084 == TRUE) ? "p2" : "p22", + curfile)); + (void) sprintf(buf, + "Expected %s header got '%s'", + (x40084 == TRUE) ? "p2" : "p22", + curfile); + *perr = strdup(buf); + flatresult = NOTOK; + } +} + +int fillin_ipn (pipn, x40084, perr) +struct type_IOB_IPN **pipn; +int x40084; +char **perr; +{ + if ((*pipn = (struct type_IOB_IPN *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZIPNIOB)) == NULL) + return; + + if ((*pipn)->choice->offset == choice_IOB_0_non__receipt__fields + && getname(curfile) == OK) + fillin_ipm(&((*pipn) -> choice -> un.non__receipt__fields -> returned__ipm), + x40084, perr); + else + more = FALSE; +} + +int fillin_ipm(pipm, x40084, perr) +struct type_IOB_IPM **pipm; +int x40084; +char **perr; +{ + *pipm = (struct type_IOB_IPM *) + calloc(1, sizeof(struct type_IOB_IPM)); + + fillin_heading(&((*pipm)->heading), x40084, perr); + if (flatresult == OK) + fillin_body(&((*pipm)->body), x40084, perr); +} + +int fillin_heading(pheading, x40084, perr) +struct type_IOB_Heading **pheading; +int x40084; +char **perr; +{ + char buf[BUFSIZ]; + extern char *hdr_p2_bp, *hdr_p22_bp; + + int type = bp_type(curfile); + if (type == (x40084 == TRUE) ? BPT_HDR_P2 : BPT_HDR_P22) { + *pheading = (struct type_IOB_Heading *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZHeadingIOB); + if (getname(curfile) != OK) + more = FALSE; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Expected '%s' got '%s'", + (x40084 == TRUE) ? hdr_p2_bp : hdr_p22_bp, + curfile)); + (void) sprintf(buf, + "Expected '%s' got '%s'", + (x40084 == TRUE) ? hdr_p2_bp : hdr_p22_bp, + curfile); + *perr = strdup(buf); + flatresult = NOTOK; + } +} + +int fillin_body(pbody, x40084, perr) +struct type_IOB_Body **pbody; +int x40084; +char **perr; +{ + struct type_IOB_Body *end = NULL, *list = NULL, *temp; + char buf[BUFSIZ]; + + while (more == TRUE + && curfile != NULL + && depth(curfile) >= curdepth + && lexnequ(curfile, curdir, strlen(curdir)) == 0 + && flatresult == OK) { + + temp = (struct type_IOB_Body *) + calloc(1, sizeof(struct type_IOB_Body)); + + if (depth(curfile) > curdepth) + fillin_forwarded(&(temp->BodyPart), x40084, perr); + else { + temp->BodyPart = (struct type_IOB_BodyPart *) + calloc(1, sizeof(struct type_IOB_BodyPart)); + + switch (bp_type(curfile)) { + case BPT_HDR_P2: + case BPT_HDR_P22: + case BPT_HDR_IPN: + case BPT_P2_DLIV_TXT: + /* should not get these as dealt with by forwarded */ + PP_LOG(LLOG_EXCEPTIONS, + ("Unexpected p2 header or delivery text file '%s' ", curfile)); + (void) sprintf (buf, + "Unexpected p2 header or delivery text file '%s'", + curfile); + *perr = strdup(buf); + flatresult = NOTOK; + break; + + case BPT_HDR_822: + PP_LOG(LLOG_EXCEPTIONS, + ("822 header in p2 message '%s'", curfile)); + (void) sprintf (buf, + "822 header in p2 message '%s'", + curfile); + *perr = strdup(buf); + flatresult = NOTOK; + break; + + case BPT_IA5: + temp->BodyPart->offset = type_IOB_BodyPart_ia5__text; + fillin_ia5(&(temp->BodyPart->un.ia5__text)); + break; + + case BPT_TLX: + temp->BodyPart->offset = type_IOB_BodyPart_tlx; + temp->BodyPart->un.tlx = + (struct type_IOB_TLXBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZTLXBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in telex bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding telex bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_VOICE: + temp->BodyPart->offset = type_IOB_BodyPart_voice; + temp->BodyPart->un.voice = + (struct type_IOB_VoiceBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZVoiceBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in voice bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding voice bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_G3FAX: + temp->BodyPart->offset = type_IOB_BodyPart_g3__facsimile; + temp->BodyPart->un.g3__facsimile = + (struct type_IOB_G3FacsimileBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZG3FacsimileBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in g3fax bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding g3fax bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_TIF0: + temp->BodyPart->offset = type_IOB_BodyPart_g4__class1; + temp->BodyPart->un.g4__class1 = + (struct type_IOB_G4Class1BodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZG4Class1BodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in g4 bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding g4 bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_TTX: + temp->BodyPart->offset = type_IOB_BodyPart_teletex; + temp->BodyPart->un.teletex = + (struct type_IOB_TeletexBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZTeletexBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in teletex bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding teletex bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_VIDEOTEX: + temp->BodyPart->offset = type_IOB_BodyPart_videotex; + temp->BodyPart->un.videotex = + (struct type_IOB_VideotexBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZVideotexBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in videotex bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding videotex bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_NATIONAL: + temp->BodyPart->offset = type_IOB_BodyPart_nationally__defined; + temp->BodyPart->un.nationally__defined = + (struct type_IOB_NationallyDefinedBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZNationallyDefinedBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in nationally defined bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding nationally defined bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_ENCRYPTED: + temp->BodyPart->offset = type_IOB_BodyPart_encrypted; + temp->BodyPart->un.encrypted = + (struct type_IOB_EncryptedBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZEncryptedBodyPartIOB); + + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in encrypted bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding encrypted bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_SFD: + temp->BodyPart->offset = type_IOB_BodyPart_sfd; + temp->BodyPart->un.sfd = + (struct type_IOB_SFDBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZSFDBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in SFD bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding SFD bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_TIF1: + temp->BodyPart->offset = type_IOB_BodyPart_mixed__mode; + temp->BodyPart->un.mixed__mode = + (struct type_IOB_MixedModeBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZMixedModeBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in mixed mode bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding mixed mode bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_ODIF: + temp->BodyPart->offset = type_IOB_BodyPart_odif; + fillin_odif(&(temp->BodyPart->un.odif)); + break; + + case BPT_ISO6937TEXT: + temp->BodyPart->offset = type_IOB_BodyPart_iso6937Text; + temp->BodyPart->un.iso6937Text = + (struct type_IOB_ISO6937TextBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZISO6937TextBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in ISO 6937 bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding ISO 6937 bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + break; + + case BPT_BILATERAL: + if (x40084 == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown p2 84 body part '%s'", + curfile)); + (void) sprintf (buf, + "Unknown p2 84 body part '%s'", + curfile); + *perr = strdup (buf); + err_fatal = TRUE; + flatresult = NOTOK; + } else { + temp->BodyPart->offset = type_IOB_BodyPart_bilaterally__defined; + temp->BodyPart->un.bilaterally__defined = + (struct type_IOB_BilaterallyDefinedBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZBilaterallyDefinedBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in bilaterally defined bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding bilaterally defined bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + } + break; + + case BPT_EXTERNAL: + if (x40084 == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown p2 84 body part '%s'", + curfile)); + (void) sprintf (buf, + "Unknown p2 84 body part '%s'", + curfile); + *perr = strdup (buf); + err_fatal = TRUE; + flatresult = NOTOK; + } else { + temp->BodyPart->offset = type_IOB_BodyPart_externally__defined; + temp->BodyPart->un.externally__defined = + (struct type_IOB_ExternallyDefinedBodyPart *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZExternallyDefinedBodyPartIOB); + if (flatresult != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to read in externally defined bodypart '%s'", + curfile)); + (void) sprintf (buf, + "problem decoding externally defined bodypart"); + err_fatal = TRUE; + *perr = strdup(buf); + } + + } + break; + + + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown p2 body part '%s'", curfile)); + (void) sprintf (buf, + "Unknown p2 body part '%s'", + curfile); + *perr = strdup (buf); + flatresult = NOTOK; + err_fatal = TRUE; + break; + } + if (flatresult == OK + && getname(curfile) != OK) + more = FALSE; + + } + + if (flatresult == OK) { + if (list == NULL) + list = end = temp; + else { + end -> next = temp; + end = temp; + } + } + } + *pbody = list; +} + +/* ps_done: like pe_done */ +int ps_done (ps, msg) +PS ps; +char *msg; +{ + if (ps->ps_errno) + { + ps_advise (ps, msg); + ps_free (ps); + return 1; + } + else + { + ps_free (ps); + return 0; + } +} + +getname(str) +char *str; +{ + /* msg_rfile returns full pathname need to split of curdir */ + if (msg_rfile(str) != RP_OK) { + str = NULL; + return NOTOK; + } + return OK; +} + +/* initialise name for above */ +setname (name) +char *name; +{ + (void) strcpy (curdir, name); +/* printf ("setname -> %s\n", curdir);*/ +} +/* + * write_bp: write a body part contained in pe out to the file named + * name. name is converted into the correct place in the directory + * tree. + */ + +write_bp(name, pe, perr) +char *name; +PE pe; +char **perr; +{ + PS psout; + FILE *fp; + static char fullname[MAXPATHLENGTH]; + char buf[BUFSIZ]; + sprintf(fullname,"%s/%s", curdir, name); + PP_LOG(LLOG_TRACE, + ("Chans/p2flatten : Writing %s", fullname)); + + if((fp = fopen(fullname, "w")) == NULL) + { + PP_SLOG(LLOG_EXCEPTIONS, fullname, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open output file '%s'", + fullname); + *perr = strdup(buf); + flatresult = NOTOK; + return NOTOK; + } + + if ((psout = ps_alloc(std_open)) == NULLPS) + { + ps_advise (psout, "ps_alloc"); + (void) fclose (fp); + flatresult = NOTOK; + return NOTOK; + } + if (std_setup (psout, fp) == NOTOK) + { + advise (NULLCP, "std_setup loses", fullname); + (void) fclose (fp); + flatresult = NOTOK; + return NOTOK; + } + + if(pe2ps(psout, pe) == NOTOK) + { + ps_advise(psout, "pe2ps loses"); + flatresult = NOTOK; + return NOTOK; + } + (void) fclose (fp); + ps_free(psout); +/* printf (" done\n");*/ + return OK; +} + +/* + * read_bpfile: read in a body part and stuff in pe and decode. + */ + +static caddr_t read_bpfile(name, pmod, idx) +char *name; +modtyp *pmod; +int idx; +{ + PS psout; + PE pe; + FILE *fp; + caddr_t ret; + + PP_LOG(LLOG_TRACE, + ("Chans/p2flatten : Reading %s", name)); + + if((fp = fopen(name, "r")) == NULL) + { + PP_SLOG(LLOG_EXCEPTIONS, name, + ("Can't open file")); + flatresult = NOTOK; + return NULL; + } + + if ((psout = ps_alloc(std_open)) == NULLPS) + { + ps_advise (psout, "ps_alloc"); + (void) fclose (fp); + flatresult = NOTOK; + return NULL; + } + if (std_setup (psout, fp) == NOTOK) + { + advise (NULLCP, "std_setup loses", name); + (void) fclose (fp); + flatresult = NOTOK; + return NULL; + } + + if((pe = ps2pe(psout)) == NULLPE) + { + ps_advise(psout, "ps2pe loses"); + flatresult = NOTOK; + return NULL; + } + + if (dec_f(idx, pmod, pe, 0, NULL, NULLCP, &ret) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't decode - %s", + PY_pepy)); + flatresult = NOTOK; + return NULL; + } + + pe_free(pe); + (void) fclose (fp); + ps_free(psout); + return ret; +} + +bp_type (str) +char *str; +{ + char *s, *ix; + int retval; + if ((s = rindex(str,'/')) == NULLCP) + s = str; + else + s++; + /* search for those files that aren't num.str */ + if (strcmp(s,rcmd_srch(BPT_HDR_P2,bptbl_body_parts88)) == 0) + return BPT_HDR_P2; + if (strcmp(s,rcmd_srch(BPT_HDR_P22,bptbl_body_parts88)) == 0) + return BPT_HDR_P22; + if (strcmp(s,rcmd_srch(BPT_HDR_822,bptbl_body_parts88)) == 0) + return BPT_HDR_822; + if (strcmp(s,rcmd_srch(BPT_HDR_IPN,bptbl_body_parts88)) == 0) + return BPT_HDR_IPN; + if (strcmp(s,rcmd_srch(BPT_P2_DLIV_TXT,bptbl_body_parts88)) == 0) + return BPT_P2_DLIV_TXT; + + /* not hdr so n.xxx where n is number and xxx bpt name */ + + if ((ix = index(s,'.')) == NULL) { +/* printf("cannot find '.' char in %s",s);*/ + retval = -1; + } else { + ix++; + retval = (cmd_srch(ix, bptbl_body_parts88)); /* returns # defined number of bp type */ + } + if (retval == -1) { + /* bomb out */ + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/p2flatten : Unknown body type '%s'",str)); + flatresult = NOTOK; + } + return retval; +} + +depth (file) +char *file; +{ + char *p; + int count = 0; + + for (p = file; *p; p++) + if (*p == '/') { + count ++; + while(*p == '/') p++; + } + return count; +} + +char *readoctet (file, len) +char *file; +int *len; +{ + char *p; + int fd; + struct stat st; + + PP_LOG(LLOG_TRACE, + ("Chans/p2flatten reading octet %s",file)); + + if ((fd = open(file ,0)) == NOTOK) + { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + flatresult = NOTOK; + return NULLCP; + } + if (fstat (fd, &st) == NOTOK) + { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't stat file")); + flatresult = NOTOK; + return NULLCP; + } + *len = st.st_size; + p = smalloc (*len + 1); + if (read (fd, p, *len) != *len) { + advise ("read", "Read failed"); + flatresult = NOTOK; + } + close (fd); +/* printf ("done\n"); */ + return p; +} + +#define BUF_INC 128 + +char *readCRLFstring (file, plen) +char *file; +int *plen; +{ + char *p; + FILE *fd; + unsigned int c, + len, + count; + + PP_LOG(LLOG_TRACE, + ("Chans/p2flatten reading CRLF string %s",file)); + + if ((fd = fopen(file ,"r")) == (FILE *) 0) + { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + flatresult = NOTOK; + return NULLCP; + } + len = BUF_INC; + p = smalloc (len); + count = 0; + while ((c = getc(fd)) != EOF) { + if (c == (int) ('\n')) { + if (count >= len) { + len += BUF_INC; + p = realloc(p, len); + } + p[count++] = '\r'; + } + if (count >= len) { + len += BUF_INC; + p = realloc(p, len); + } + p[count++] = (char) c; + } + if (count >= len) { + len += 1; + p = realloc(p, len); + } + *plen = count; + fclose (fd); +/* printf ("done\n"); */ + return p; +} + +fillin_ia5(pia5text) +struct type_IOB_IA5TextBodyPart **pia5text; +{ + int len = 0; + char *str; + + *pia5text = (struct type_IOB_IA5TextBodyPart *) + calloc(1, sizeof(struct type_IOB_IA5TextBodyPart)); + (*pia5text)->parameters = (struct type_IOB_IA5TextParameters *) + calloc(1, sizeof(struct type_IOB_IA5TextParameters)); + (*pia5text)->parameters->parm = int_IOB_Repertoire_ia5; + str = readCRLFstring(curfile, &len); + (*pia5text)->data = str2qb(str, len, 1); + + free(str); +} + +fillin_odif(podif) +struct type_IOB_ODIFBodyPart **podif; +{ + int len = 0; + char *str; + + str = readoctet(curfile, &len); + if (str != NULL) { + *podif = str2qb(str, len, 1); + free(str); + } +} + +fillin_forwarded(pbp, x40084, perr) +struct type_IOB_BodyPart **pbp; +int x40084; +char **perr; +{ + int oldepth = curdepth; + char olddir[MAXPATHLENGTH]; + char *ix = rindex(curfile, '/'); + (void) sprintf(olddir, curdir); + + *pbp = (struct type_IOB_BodyPart *) + calloc (1, sizeof(struct type_IOB_BodyPart)); + (*pbp)->offset = type_IOB_BodyPart_message; + (*pbp)->un.message = (struct type_IOB_MessageBodyPart *) + calloc(1, sizeof(struct type_IOB_MessageBodyPart)); + + curdepth = depth(curfile); + if (ix != NULLCP) + *ix = '\0'; + (void) sprintf(curdir, curfile); + if (ix != NULLCP) + *ix = '/'; + + PY_pepy[0] = 0; + if (bp_type(curfile) == BPT_P2_DLIV_TXT) { + if (((*pbp)->un.message->parameters = + (struct type_IOB_MessageParameters *) + read_bpfile(curfile, + &_ZIOB_mod, + _ZMessageParametersIOB)) == NULL) + return; + if (getname(curfile) != OK) + more = FALSE; + } else + (*pbp)->un.message->parameters = (struct type_IOB_MessageParameters *) calloc (1, sizeof(struct type_IOB_MessageParameters)); + + fillin_ipm(&((*pbp)->un.message->data), x40084, perr); + + curdepth = oldepth; + (void) sprintf(curdir, olddir); +} + + +/* ERRORS */ + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Format/p2norm/Makefile b/Format/p2norm/Makefile new file mode 100644 index 0000000..73c7af7 --- /dev/null +++ b/Format/p2norm/Makefile @@ -0,0 +1,99 @@ +# P2 normalisation including P22 to P2 downgrade +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/p2norm/RCS/Makefile,v 6.0 1991/12/18 20:20:24 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:20:24 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = p2norm.c +OBJS = p2norm.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +#LIBDSAP = -ldsap +#LIBASN1 = ../../Chans/x40088/asn1/libasn1.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xp2norm + +default: $(PROGS) + +xp2norm: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(OBJS) $(LIBPP) \ + $(LIBDSAP) $(LIBSYS) -o $@ + +install: inst-p2norm + +inst-p2norm: $(FORMDIR)/p2norm +$(FORMDIR)/p2norm: xp2norm + -$(BACKUP) $@ zp2norm + rm -f $@ + $(INSTALL) xp2norm $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "p2 normalisation filter installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f $(PROGS) core a.out Makefile.old + + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lint: l-targets + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +p2norm.o: p2norm.c +p2norm.o: ../../h/head.h +p2norm.o: ../../h/util.h +p2norm.o: ../../h/config.h +p2norm.o: ../../h/ll_log.h +p2norm.o: ../../h/retcode.h +p2norm.o: ../../h/util.h +p2norm.o: ../../h/IOB-types.h +p2norm.o: ../../h/MTA-types.h +p2norm.o: ../../h/Toks-types.h +p2norm.o: ../../h/Auth-types.h +p2norm.o: ../../h/or.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/p2norm/make b/Format/p2norm/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/p2norm/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/p2norm/p2norm.c b/Format/p2norm/p2norm.c new file mode 100644 index 0000000..724a0c7 --- /dev/null +++ b/Format/p2norm/p2norm.c @@ -0,0 +1,442 @@ +/* p2norm.c: p2 heading normalisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/p2norm/RCS/p2norm.c,v 6.0 1991/12/18 20:20:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/p2norm/RCS/p2norm.c,v 6.0 1991/12/18 20:20:24 jpo Rel $ + * + * $Log: p2norm.c,v $ + * Revision 6.0 1991/12/18 20:20:24 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "util.h" +#include "IOB-types.h" +#include "or.h" +#include "adr.h" +#include +#include + +extern char *dn2ufn(); +extern char *local_dit; +extern struct type_IOB_ORName *orn2orname(); + +static void parse_cmdline(); + +main(argc, argv) +int argc; +char **argv; +{ + PE pe = NULLPE; + PS ps = NULLPS; + int ishead = TRUE; + + sys_init(argv[0]); + or_myinit(); + quipu_syntaxes(); + dsap_init ((int *) NULL, (char ***) NULL); + local_dit = NULLCP; /* hack to get full DNs */ + + parse_cmdline(argc, argv); + + if (((ps = ps_alloc (std_open)) == NULLPS) || + (std_setup(ps, stdin) == NOTOK)) + { + PP_LOG (LLOG_EXCEPTIONS, + ("P22toP2() failed to setup inbound PS")); + return error_exit(); + } + + if ((pe = ps2pe(ps)) == NULLPE) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ps2pe error on input")); + return error_exit(); + } + + if (ishead == TRUE) + convert_p2_header(&pe); + else + convert_p2_ipn(&pe); + + if (ps) ps_free(ps); + + if (((ps = ps_alloc (std_open)) == NULLPS) || + (std_setup(ps, stdout) == NOTOK)) + { + PP_LOG (LLOG_EXCEPTIONS, + ("P22toP2() failed to setup outbound PS")); + return error_exit(); + } + + if (pe2ps(ps, pe) == NOTOK) + { + PP_LOG (LLOG_EXCEPTIONS, + ("pe2ps error on input")); + return error_exit(); + } + + if (ps) ps_free(ps); + if (pe) pe_free(pe); + exit(0); + return OK; +} + +/* */ +/* parse commmand line arguments */ +int do_downgrade = FALSE, do_normalise = TRUE, internal = FALSE; + +#define ARG_NONORM 1 +#define ARG_DOWNGRADE 2 +#define ARG_EXTERNAL 3 +#define ARG_INTERNAL 4 + +static CMD_TABLE tbl_args[] = { + "-nonorm", ARG_NONORM, + "-downgrade", ARG_DOWNGRADE, + "-external", ARG_EXTERNAL, + "-internal", ARG_INTERNAL, + 0, -1 +}; + +static void parse_cmdline(argc, argv) +int argc; +char **argv; +{ + int i; + + for (i = 1; i < argc; i++) { + switch (cmd_srch(argv[i], + tbl_args)) { + case ARG_NONORM: + do_normalise = FALSE; + break; + + case ARG_DOWNGRADE: + do_downgrade = TRUE; + break; + + case ARG_EXTERNAL: + internal = FALSE; + break; + + case ARG_INTERNAL: + internal = TRUE; + break; + + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown command line argument '%s'", + argv[i])); + break; + } + } +} + +/* */ +/* convert header */ + +convert_p2_header(ppe) +PE *ppe; +{ + struct type_IOB_Heading *head; + + PY_pepy[0] = 0; + + if (decode_IOB_Heading (*ppe, 0, NULLIP, NULLVP, &head) != OK) + { + PP_OPER(NULLCP, + ("decode_IOB_Heading() failed : [%s]", PY_pepy)); + return error_exit(); + } + + if (PY_pepy[0] != 0) + PP_LOG (LLOG_EXCEPTIONS, + ("decode_IOB_Heading non-fatal failure [%s]",PY_pepy)); + + convert_header(head); + + if (*ppe) pe_free(*ppe); + + PY_pepy[0] = 0; + + if (encode_IOB_Heading (ppe, 0, 0, NULLCP, head) != OK) + { + PP_OPER(NULLCP, + ("encode_IOB_Heading() failed : [%s]", PY_pepy)); + return error_exit(); + } + if (PY_pepy[0] != 0) + PP_LOG (LLOG_EXCEPTIONS, + ("encode_IOB_Heading non-fatal failure [%s]", PY_pepy)); + return OK; +} + +convert_header(hd) +struct type_IOB_Heading *hd; +{ + if (hd -> this__IPM) + convert_IPMIdentifier (hd -> this__IPM); + + if (hd -> originator) + convert_ORDescriptor(hd -> originator); + + if (hd -> authorizing__users) + convert_ORDescriptorSeq(hd -> authorizing__users); + + if (hd -> primary__recipients) + convert_RecipientSeq(hd -> primary__recipients); + + if (hd -> copy__recipients) + convert_RecipientSeq(hd -> copy__recipients); + + if (hd -> blind__copy__recipients) + convert_RecipientSeq(hd -> blind__copy__recipients); + + if (hd -> replied__to__IPM) + convert_IPMIdentifier (hd -> replied__to__IPM); + + if (hd -> obsoleted__IPMs) + convert_IPMIdentifierSeq (hd -> obsoleted__IPMs); + + if (hd -> related__IPMs) + convert_IPMIdentifierSeq (hd -> related__IPMs); + + if (hd -> reply__recipients) + convert_ORDescriptorSeq(hd -> reply__recipients); + + if (do_downgrade == TRUE && hd -> extensions) { + free_IOB_ExtensionsField(hd -> extensions); + hd -> extensions = (struct type_IOB_ExtensionsField *) NULL; + } +} + +convert_ORDescriptorSeq (seq) +struct type_IOB_ORDescriptorSequence *seq; +{ + while (seq != (struct type_IOB_ORDescriptorSequence *) NULL) { + if (seq -> ORDescriptor) + convert_ORDescriptor (seq -> ORDescriptor); + seq = seq -> next; + } +} + +convert_RecipientSeq (seq) +struct type_IOB_RecipientSequence *seq; +{ + while (seq != (struct type_IOB_RecipientSequence *) NULL) { + if (seq -> RecipientSpecifier) + convert_RecipientSpecifier (seq -> RecipientSpecifier); + seq = seq -> next; + } +} + +convert_RecipientSpecifier (recip) +struct type_IOB_RecipientSpecifier *recip; +{ + if (recip -> recipient) + convert_ORDescriptor(recip -> recipient); +} + +convert_IPMIdentifierSeq (seq) +struct type_IOB_IPMIdentifierSequence *seq; +{ + while (seq != (struct type_IOB_IPMIdentifierSequence *) NULL) { + if (seq -> IPMIdentifier) + convert_IPMIdentifier(seq -> IPMIdentifier); + seq = seq -> next; + } +} + +convert_IPMIdentifier (ipmid) +struct type_IOB_IPMIdentifier *ipmid; +{ + char *str; + + if (ipmid -> user) { + convert_ORName (&(ipmid -> user), + &str); + if (str) free(str); + } +} + +convert_ORName (pname, pdn) +struct type_IOB_ORName **pname; +char **pdn; +{ + ORName *orn; + + *pdn = NULLCP; + + if ((orn = orname2orn (*pname)) == NULLORName) + return; + + if (do_normalise == TRUE) { + Aparse_ptr ap = aparse_new(); + + ap->orname->on_or = or_tdup(orn->on_or); + ap -> ad_type = AD_X400_TYPE; + ap -> dmnorder = CH_USA_PREF; + ap -> normalised = APARSE_NORM_NEXTHOP; + ap -> percents = TRUE; + ap -> internal = internal; + if (aparse_norm (ap) == OK) { + or_free(orn->on_or); + orn->on_or = ap->orname->on_or; + ap->orname->on_or = NULLOR; + } + aparse_free(ap); + free((char *) ap); + } + + if (do_downgrade == TRUE) { + /* downgrade orn -> on_or */ + or_downgrade(&(orn->on_or)); + + if ((*pname) -> directory__name && orn->on_dn != NULL) { + *pdn = dn2ufn(orn->on_dn, FALSE); + dn_free (orn->on_dn); + orn->on_dn = NULL; + } + } + + free_IOB_ORName (*pname); + *pname = orn2orname(orn); +} + +convert_ORDescriptor (desc) +struct type_IOB_ORDescriptor *desc; +{ + char *dn; + + if (!desc || !desc -> formal__name) + return; + + convert_ORName (&(desc->formal__name), &dn); + + if (dn != NULLCP) { + char *ffn, *res; + int len; + if (desc -> free__form__name != NULL) { + /* incorporate dn as comment in free__form__name */ + ffn = qb2str (desc -> free__form__name); + free_IOB_FreeFormName (desc -> free__form__name); + } else + ffn = NULLCP; + + len = strlen(dn) + strlen(" (DN=)") + 1; + if (ffn != NULLCP) + len += strlen(ffn); + res = malloc(len * sizeof(char)); + + if (ffn == NULLCP) + sprintf(res, "(DN=%s)", dn); + else + sprintf(res, "%s (DN=%s)", ffn, dn); + + desc -> free__form__name = + str2qb(res, strlen(res), 1); + if (dn) free(dn); + if (ffn) free(ffn); + if (res) free(res); + } +} + +/* */ +/* convert ipn */ + +convert_p2_ipn(ppe) +PE *ppe; +{ + struct type_IOB_IPN *head; + + PY_pepy[0] = 0; + + if (decode_IOB_IPN (*ppe, 0, NULLIP, NULLVP, &head) != OK) + { + PP_OPER(NULLCP, + ("decode_IOB_IPN() failed : [%s]", PY_pepy)); + return error_exit(); + } + + if (PY_pepy[0] != 0) + PP_LOG (LLOG_EXCEPTIONS, + ("decode_IOB_IPN non-fatal failure [%s]",PY_pepy)); + + convert_ipn(head); + + if (*ppe) pe_free(*ppe); + + PY_pepy[0] = 0; + + if (encode_IOB_IPN (ppe, 0, 0, NULLCP, head) != OK) + { + PP_OPER(NULLCP, + ("encode_IOB_IPN() failed : [%s]", PY_pepy)); + return error_exit(); + } + if (PY_pepy[0] != 0) + PP_LOG (LLOG_EXCEPTIONS, + ("encode_IOB_IPN non-fatal failure [%s]", PY_pepy)); + return OK; +} + +convert_ipn(ipn) +struct type_IOB_IPN *ipn; +{ + + if (ipn -> subject__ipm) + convert_IPMIdentifier (ipn -> subject__ipm); + + if (ipn -> ipn__originator) + convert_ORDescriptor (ipn -> ipn__originator); + + if (ipn -> ipn__preferred__recipient) + convert_ORDescriptor (ipn -> ipn__preferred__recipient); + + /* should really do something about ReturnedIPMField + in non recipt fields but will assume message has + been exploded */ +} + +/* */ +/* misc */ + +error_exit() +{ + exit(1); +} + +#ifndef lint + +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + (void) _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} + +#else +/* VARARGS */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + diff --git a/Format/p2norm/pac b/Format/p2norm/pac new file mode 100644 index 0000000000000000000000000000000000000000..c09092f12c5e3c8a61bba424b5d7580be5672bc4 GIT binary patch literal 499 zcmXqP$c{^}GO$Qw5oU6CN@5mfR9GY;EEJ&|lA5CsoLW?tnVedz;8T*)%u-R3nzNL@ zfvYG#F(o@MGd-iEi7`=FAtx~}IkC7TwMb9T(9{xWl%9dHo~5Clp`o6MnVzxv0$)nZ zZ{QEf&#P1jg4?;M!LVULLqdgt5fM&~0QzDnX9G)4X&%tA=?k0;91OV)IN6v(S=d1S zHIz1x1aY{q`PfjzKnNtsEX?g*l$e^Es^9}OrhyH@X=F1oG%_=>U|?uuWME)0^j_eW zU}|7YtfROZSd;V1Q}db_3mRAgQcF@B*&*gB0F5*BU*JV#pn-je9w`khpg@DU5bVAc O>>{issl_Em3=9Co;*H(_ literal 0 HcmV?d00001 diff --git a/Format/rfc1148/Makefile b/Format/rfc1148/Makefile new file mode 100644 index 0000000..4fe698a --- /dev/null +++ b/Format/rfc1148/Makefile @@ -0,0 +1,303 @@ +# 1148 stuff +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/Makefile,v 6.0 1991/12/18 20:20:34 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:20:34 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = P2toRFC.c c-P2toRFC.c t-P2toRFC.c \ + RFCtoP2.c c-RFCtoP2.c t-RFCtoP2.c +OBJS = P2toRFC.o c-P2toRFC.o t-P2toRFC.o \ + RFCtoP2.o c-RFCtoP2.o t-RFCtoP2.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Suffix rules +# +############################################################ + +.SUFFIXES: .py + +.py.c: + $(PEPY) -P -a PY_advise $(PYFLAGS) $< +.py.o: + $(PEPY) -P $(PYFLAGS) -a PY_advise $< + $(CC) $(CFLAGS) -c $*.c + rm $*.c + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xc-P2toRFC xc-RFCtoP2 + +default: $(SRCS) $(PROGS) + +xt-P2toRFC: t-P2toRFC.o P2toRFC.o $(LIBPP) + $(CC) $(LDFLAGS) P2toRFC.o \ + $(LIBPP) $(LIBSYS) -o $@ + +xc-P2toRFC: c-P2toRFC.o P2toRFC.o $(LIBPP) + $(CC) $(LDFLAGS) c-P2toRFC.o P2toRFC.o \ + $(LIBPP) $(LIBSYS) -o $@ + +xt-RFCtoP2: t-RFCtoP2.o RFCtoP2.o rfc-hdr.h $(LIBPP) + $(CC) $(LDFLAGS) t-RFCtoP2.o RFCtoP2.o \ + $(LIBPP) $(LIBSYS) -o $@ + +xc-RFCtoP2: c-RFCtoP2.o RFCtoP2.o rfc-hdr.h $(LIBPP) + $(CC) $(LDFLAGS) c-RFCtoP2.o RFCtoP2.o \ + $(LIBPP) $(LIBSYS) -o $@ + +install: inst-c-RFCtoP2 inst-c-P2toRFC + +inst-c-P2toRFC: $(CHANDIR)/P2toRFC +$(CHANDIR)/P2toRFC: xc-P2toRFC + -$(BACKUP) $@ zc-P2toRFC + rm -f $@ + $(INSTALL) xc-P2toRFC $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "P2 to RFC (1138) channel installed normally"; echo "" + +inst-c-RFCtoP2: $(CHANDIR)/RFCtoP2 +$(CHANDIR)/RFCtoP2: xc-RFCtoP2 + -$(BACKUP) $@ zc-RFCtoP2 + rm -f $@ + $(INSTALL) xc-RFCtoP2 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "RFC to P2 (1138) channel installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) p2.c + +tidy: + rm -f $(PROGS) zc-* P2-types* P2.ph core a.out \ + Makefile.old t-RFCtoP2 t-P2toRFC xt-* + +lint: l-P2toRFC l-RFCtoP2 +l-P2toRFC: P2toRFC.c c-P2toRFC.c t-P2toRFC.c + $(LINT) $(LLFLAGS) P2toRFC.c c-P2toRFC.c t-P2toRFC.c \ + $(LINTLIBS) +l-RFCtoP2: RFCtoP2.c c-RFCtoP2.c t-RFCtoP2.c rfc-hdr.h + $(LINT) $(LLFLAGS) RFCtoP2.c c-RFCtoP2.c t-RFCtoP2.c \ + $(LINTLIBS) + +saber_src_p2torfc: c-P2toRFC.c P2toRFC.c + #load -C $(CFLAGS) c-P2toRFC.c P2toRFC.c $(LIBPP) $(LIBSYS) + +saber_obj_p2torfc: c-P2toRFC.o P2toRFC.o + #load -C $(CFLAGS) c-P2toRFC.o P2toRFC.o $(LIBPP) $(LIBSYS) + +saber_src_rfctop2: c-RFCtoP2.c RFCtoP2.c + #load -C $(CFLAGS) c-RFCtoP2.c RFCtoP2.c $(LIBPP) $(LIBSYS) + +saber_obj_rfctop2: c-RFCtoP2.o RFCtoP2.o + #load -C $(CFLAGS) c-RFCtoP2.o RFCtoP2.o $(LIBPP) $(LIBSYS) + +define: + $(DEFINE) Makefile +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +P2toRFC.o: P2toRFC.c +P2toRFC.o: ../../h/head.h +P2toRFC.o: ../../h/util.h +P2toRFC.o: ../../h/config.h +P2toRFC.o: ../../h/ll_log.h +P2toRFC.o: ../../h/retcode.h +P2toRFC.o: ../../h/util.h +P2toRFC.o: ../../h/IOB-types.h +P2toRFC.o: ../../h/MTA-types.h +P2toRFC.o: ../../h/Toks-types.h +P2toRFC.o: ../../h/Auth-types.h +P2toRFC.o: ../../h/Ext-types.h +P2toRFC.o: ../../h/MTA-types.h +P2toRFC.o: ../../h/Toks-types.h +P2toRFC.o: ../../h/Auth-types.h +P2toRFC.o: ../../h/q.h +P2toRFC.o: ../../h/adr.h +P2toRFC.o: ../../h/list_rchan.h +P2toRFC.o: ../../h/chan.h +P2toRFC.o: ../../h/table.h +P2toRFC.o: ../../h/list_bpt.h +P2toRFC.o: ../../h/auth.h +P2toRFC.o: ../../h/list_bpt.h +P2toRFC.o: ../../h/extension.h +P2toRFC.o: ../../h/mta.h +P2toRFC.o: ../../h/adr.h +P2toRFC.o: ../../h/list_bpt.h +P2toRFC.o: ../../h/aparse.h +P2toRFC.o: ../../h/ap.h +P2toRFC.o: ../../h/util.h +P2toRFC.o: ../../h/or.h +P2toRFC.o: ../../h/chan.h +P2toRFC.o: ../../h/auth.h +P2toRFC.o: ../../h/list_rchan.h +P2toRFC.o: ../../h/mta.h +P2toRFC.o: ../../h/tb_bpt88.h +P2toRFC.o: ../../h/or.h +P2toRFC.o: ../../h/ap.h +P2toRFC.o: oids.h +P2toRFC.o: ../../h/charset.h +c-P2toRFC.o: c-P2toRFC.c +c-P2toRFC.o: ../../h/util.h +c-P2toRFC.o: ../../h/config.h +c-P2toRFC.o: ../../h/ll_log.h +c-P2toRFC.o: ../../h/retcode.h +c-P2toRFC.o: ../../h/qmgr.h +c-P2toRFC.o: ../../h/Qmgr-types.h +c-P2toRFC.o: ../../h/Qmgr-ops.h +c-P2toRFC.o: ../../h/q.h +c-P2toRFC.o: ../../h/adr.h +c-P2toRFC.o: ../../h/list_rchan.h +c-P2toRFC.o: ../../h/chan.h +c-P2toRFC.o: ../../h/table.h +c-P2toRFC.o: ../../h/list_bpt.h +c-P2toRFC.o: ../../h/auth.h +c-P2toRFC.o: ../../h/list_bpt.h +c-P2toRFC.o: ../../h/extension.h +c-P2toRFC.o: ../../h/mta.h +c-P2toRFC.o: ../../h/adr.h +c-P2toRFC.o: ../../h/list_bpt.h +c-P2toRFC.o: ../../h/aparse.h +c-P2toRFC.o: ../../h/ap.h +c-P2toRFC.o: ../../h/util.h +c-P2toRFC.o: ../../h/or.h +c-P2toRFC.o: ../../h/chan.h +c-P2toRFC.o: ../../h/auth.h +c-P2toRFC.o: ../../h/list_rchan.h +c-P2toRFC.o: ../../h/mta.h +c-P2toRFC.o: ../../h/prm.h +c-P2toRFC.o: ../../h/chan.h +c-P2toRFC.o: ../../h/ap.h +c-P2toRFC.o: ../../h/dr.h +c-P2toRFC.o: ../../h/extension.h +c-P2toRFC.o: ../../h/mta.h +c-P2toRFC.o: ../../h/sys.file.h +c-P2toRFC.o: ../../h/tb_bpt88.h +t-P2toRFC.o: t-P2toRFC.c +t-P2toRFC.o: ../../h/head.h +t-P2toRFC.o: ../../h/util.h +t-P2toRFC.o: ../../h/config.h +t-P2toRFC.o: ../../h/ll_log.h +t-P2toRFC.o: ../../h/retcode.h +t-P2toRFC.o: ../../h/util.h +t-P2toRFC.o: ../../h/q.h +t-P2toRFC.o: ../../h/adr.h +t-P2toRFC.o: ../../h/list_rchan.h +t-P2toRFC.o: ../../h/chan.h +t-P2toRFC.o: ../../h/table.h +t-P2toRFC.o: ../../h/list_bpt.h +t-P2toRFC.o: ../../h/auth.h +t-P2toRFC.o: ../../h/list_bpt.h +t-P2toRFC.o: ../../h/extension.h +t-P2toRFC.o: ../../h/mta.h +t-P2toRFC.o: ../../h/adr.h +t-P2toRFC.o: ../../h/list_bpt.h +t-P2toRFC.o: ../../h/aparse.h +t-P2toRFC.o: ../../h/ap.h +t-P2toRFC.o: ../../h/util.h +t-P2toRFC.o: ../../h/or.h +t-P2toRFC.o: ../../h/chan.h +t-P2toRFC.o: ../../h/auth.h +t-P2toRFC.o: ../../h/list_rchan.h +t-P2toRFC.o: ../../h/mta.h +RFCtoP2.o: RFCtoP2.c +RFCtoP2.o: ../../h/head.h +RFCtoP2.o: ../../h/util.h +RFCtoP2.o: ../../h/config.h +RFCtoP2.o: ../../h/ll_log.h +RFCtoP2.o: ../../h/retcode.h +RFCtoP2.o: ../../h/util.h +RFCtoP2.o: ../../h/IOB-types.h +RFCtoP2.o: ../../h/MTA-types.h +RFCtoP2.o: ../../h/Toks-types.h +RFCtoP2.o: ../../h/Auth-types.h +RFCtoP2.o: rfc-hdr.h +RFCtoP2.o: ../../h/ap.h +RFCtoP2.o: ../../h/util.h +RFCtoP2.o: ../../h/or.h +RFCtoP2.o: oids.h +RFCtoP2.o: ../../h/charset.h +RFCtoP2.o: ../../h/chan.h +RFCtoP2.o: ../../h/table.h +RFCtoP2.o: ../../h/list_bpt.h +c-RFCtoP2.o: c-RFCtoP2.c +c-RFCtoP2.o: ../../h/util.h +c-RFCtoP2.o: ../../h/config.h +c-RFCtoP2.o: ../../h/ll_log.h +c-RFCtoP2.o: ../../h/head.h +c-RFCtoP2.o: ../../h/util.h +c-RFCtoP2.o: ../../h/retcode.h +c-RFCtoP2.o: ../../h/qmgr.h +c-RFCtoP2.o: ../../h/Qmgr-types.h +c-RFCtoP2.o: ../../h/Qmgr-ops.h +c-RFCtoP2.o: ../../h/q.h +c-RFCtoP2.o: ../../h/adr.h +c-RFCtoP2.o: ../../h/list_rchan.h +c-RFCtoP2.o: ../../h/chan.h +c-RFCtoP2.o: ../../h/table.h +c-RFCtoP2.o: ../../h/list_bpt.h +c-RFCtoP2.o: ../../h/auth.h +c-RFCtoP2.o: ../../h/list_bpt.h +c-RFCtoP2.o: ../../h/extension.h +c-RFCtoP2.o: ../../h/mta.h +c-RFCtoP2.o: ../../h/adr.h +c-RFCtoP2.o: ../../h/list_bpt.h +c-RFCtoP2.o: ../../h/aparse.h +c-RFCtoP2.o: ../../h/ap.h +c-RFCtoP2.o: ../../h/util.h +c-RFCtoP2.o: ../../h/or.h +c-RFCtoP2.o: ../../h/chan.h +c-RFCtoP2.o: ../../h/auth.h +c-RFCtoP2.o: ../../h/list_rchan.h +c-RFCtoP2.o: ../../h/mta.h +c-RFCtoP2.o: ../../h/prm.h +c-RFCtoP2.o: ../../h/chan.h +c-RFCtoP2.o: ../../h/sys.file.h +t-RFCtoP2.o: t-RFCtoP2.c +t-RFCtoP2.o: ../../h/head.h +t-RFCtoP2.o: ../../h/util.h +t-RFCtoP2.o: ../../h/config.h +t-RFCtoP2.o: ../../h/ll_log.h +t-RFCtoP2.o: ../../h/retcode.h +t-RFCtoP2.o: ../../h/util.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/rfc1148/P2toRFC.c b/Format/rfc1148/P2toRFC.c new file mode 100644 index 0000000..7fc41c6 --- /dev/null +++ b/Format/rfc1148/P2toRFC.c @@ -0,0 +1,2487 @@ +/* P2toRFC.c: p2 msg + optional p1 struct + optional bodypart -> RFC 822 hdr */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: P2toRFC.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "IOB-types.h" +#include "Ext-types.h" +#include "q.h" +#include +#include "tb_bpt88.h" +#include "or.h" +#include "ap.h" +#include "oids.h" +#include "charset.h" + +static int load_time(), load_addr(); +static FILE *fp_out; +static struct type_IOB_Heading *head; +static struct type_IOB_IPN *ipn; +static char ipn_body[MAXPATHLENGTH]; +static char abuf [BUFSIZ]; +static int decode_extension(); +static int decode_ext_char (), decode_ext_rdm(), + decode_ext_pdm(), decode_ext_int(), decode_ext_rnfa(), + decode_ext_pra(), decode_ext_redir(), ext_decode_dlexph(); +static Q_struct del_info_q; +static ADDR del_info_recip; + +extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */]; +extern CMD_TABLE atbl_rdm[], atbl_pd_modes[], atbl_reg_mail[]; +extern char *cont_p2, *cont_p22; +extern char *hdr_822_bp, *hdr_p2_bp, *ia5_bp, *hdr_p22_bp, *hdr_ipn_bp; +extern char *dn2str (); +extern int msgid2rfc(), encinfo2rfc(); +extern int order_pref; +extern UTC utclocalise(); +int convertresult; +extern char *dn2ufn(), *oid2lstr(); +static int firstLine; + +#define bit_ison(x,y) (bit_test(x,y) == 1) + +P2toRFC (p2_in, ext_in, qp, del_info, rfc_out, ipn_body_out, ep) +char *p2_in; +char *ext_in; +Q_struct *qp; +char *del_info; +char *rfc_out; +char *ipn_body_out; +char **ep; +{ + FILE *fp_in; + PE pe = NULLPE; + PS ps = NULLPS; + int retval, ishead; + char *ix; + char buf[BUFSIZ]; + + head = NULL; + ipn = NULL; + firstLine = TRUE; + convertresult = OK; + + if ((ix = rindex(p2_in, '/')) == NULL) + ix = p2_in; + else + ix++; + + if (lexnequ(ix, hdr_p2_bp, strlen(hdr_p2_bp)) == 0 + || lexnequ(ix, hdr_p22_bp, strlen(hdr_p22_bp)) == 0) + ishead = OK; + else if (lexnequ(ix, hdr_ipn_bp, strlen(hdr_ipn_bp)) == 0) + ishead = NOTOK; + else { + (void) sprintf(buf, + "Unknown x400 hdr type '%s'", + ix); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", buf)); + *ep = strdup(buf); + return (NOTOK); + } + + if (rfc_out == NULLCP) + fp_out = stdout; + else if ((fp_out = fopen (rfc_out, "w")) == NULL) + { + PP_SLOG (LLOG_EXCEPTIONS, rfc_out, + ("Can't open file")); + (void) sprintf (buf, + "Failed to open output file '%s'", + rfc_out); + *ep = strdup(buf); + return (NOTOK); + } + + if (ipn_body_out) + strcpy(ipn_body, ipn_body_out); + else + ipn_body[0] = '\0'; + + if (p2_in == NULLCP) + fp_in = stdin; + else if ((fp_in = fopen (p2_in, "r")) == NULL) + { + PP_SLOG (LLOG_EXCEPTIONS, p2_in, + ("Can't open file")); + fclose (fp_out); + (void) sprintf (buf, + "Failed to open input file '%s'", + p2_in); + *ep = strdup(buf); + return (NOTOK); + } + + if (((ps = ps_alloc (std_open)) == NULLPS) || + (std_setup (ps, fp_in) == NOTOK)) + { + PP_LOG (LLOG_EXCEPTIONS, ("p2to822() failed to setup PS")); + retval = NOTOK; + *ep = strdup("Failed to set up PS"); + goto cleanup; + } + + + if ((pe = ps2pe (ps)) == NULLPE) + { + PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error on file '%s'", p2_in)); + retval = NOTOK; + goto cleanup; + } + + PY_pepy[0] = 0; + if (ishead == OK) { + if (decode_IOB_Heading (pe, 0, NULLIP, NULLVP, &head) != OK) + { + PP_OPER(NULLCP, + ("decode_IOB_heading() failed : [%s]", PY_pepy)); + retval = NOTOK; + convertresult = NOTOK; + abort(); + *ep = strdup("Illegal ASN.1 in IOB Heading"); + goto cleanup; + } + + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_heading non-fatal failure [%s]", PY_pepy)); + + + if (qp != (Q_struct *) NULL + && do_p1 (qp, ishead, ep) != OK) + { + PP_TRACE (("P1 output failure")); + retval = NOTOK; + goto cleanup; + } + + if (NULLCP != del_info + && do_delinfo (del_info, ep) != OK) + { + PP_TRACE (("Delivery Info output failure")); + retval = NOTOK; + goto cleanup; + } + + if (do_p2_head (ep) != OK) + { + PP_TRACE (( "P2 output failure")); + retval = NOTOK; + goto cleanup; + } + + } else { + if (decode_IOB_IPN (pe, 0, NULLIP, NULLVP, &ipn) != OK) + { + PP_OPER(NULLCP, + ("decode_IOB_IPN() failed : [%s]", PY_pepy)); + retval = NOTOK; +/* convertresult = NOTOK;*/ + *ep = strdup("Illegal ASN.1 in IPN"); + goto cleanup; + } + + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_IPN non-fatal failure [%s]", + PY_pepy)); + + if ((Q_struct *) NULL != qp + && do_p1_ipn (qp, ishead, ep) != OK) + { + PP_TRACE (("P1 output failure")); + retval = NOTOK; + goto cleanup; + } + + if (NULLCP != del_info + && do_delinfo (del_info, ep) != OK) + { + PP_TRACE(("Delivery Info output failure")); + retval = NOTOK; + goto cleanup; + } + + if (do_p2_ipn(qp, ep) != OK) + { + PP_TRACE (("P2 output failure")); + retval = NOTOK; + goto cleanup; + } + + } + do_same_line ("\n"); /* Terminate header */ + + if (do_extra (ext_in, ep) != OK) + { + PP_TRACE (( "Extra bits output failure")); + retval = NOTOK; + goto cleanup; + } + + if (ishead != OK + && do_p2_ipn_body(qp, ep) != OK) + { + PP_TRACE((" IPN body output failure")); + retval = NOTOK; + goto cleanup; + } + + retval = OK; + cleanup: + fclose (fp_out); + fclose (fp_in); + + if (pe != NULLPE) pe_free(pe); + if (ps != NULLPS) ps_free(ps); + if (head != NULL) free_IOB_Heading (head); + if (ipn != NULL) free_IOB_IPN (ipn); + return (retval); +} + +/* */ + +/* ARGSUSED */ +do_p2_head(ep) +char **ep; +{ + int haveTo = FALSE; + + if (head -> authorizing__users != NULL) { + do_key ("From"); + do_ORD_seq (head -> authorizing__users); + } + + if (head -> originator != NULL) { + if (head -> authorizing__users == NULL) + do_key ("From"); + else + do_key ("Sender"); + + do_ORD (head -> originator); + } + + if (head -> this__IPM != NULL) + { + do_key ("Message-ID"); + if (do_mid (head -> this__IPM, TRUE) != OK) { + *ep = strdup("Invalid message id"); + return NOTOK; + } + } + + if (head -> primary__recipients != NULL) + { + do_key ("To"); + do_recip_seq (head -> primary__recipients); + haveTo = TRUE; + } + + if (head -> copy__recipients != NULL) + { + do_key ("Cc"); + do_recip_seq (head -> copy__recipients); + haveTo = TRUE; + } + + if (head -> blind__copy__recipients != NULL) + { + do_key ("Bcc"); + do_recip_seq (head -> blind__copy__recipients); + haveTo = TRUE; + } + + if (haveTo != TRUE) { + do_key ("To"); + do_token ("list:;"); + } + + if (head -> replied__to__IPM != NULL) + { + do_key ("In-Reply-To"); + if (do_mid (head -> replied__to__IPM, FALSE) != OK) { + *ep = strdup("Invalid In-Reply-To message id"); + return NOTOK; + } + } + + if (head -> obsoleted__IPMs != NULL) + { + do_key ("Obsoletes"); + if (do_mid_seq (head -> obsoleted__IPMs, TRUE) != OK) { + *ep = strdup("Invalid Obsoletes message id"); + return NOTOK; + } + } + + if (head -> related__IPMs != NULL) + { + do_key ("References"); + if (do_mid_seq (head -> related__IPMs, FALSE) != OK) { + *ep = strdup("Invalid References message id"); + return NOTOK; + } + } + + if (head -> subject != NULL) + { + do_key ("Subject"); + do_subject (head -> subject); + } + + if (head -> expiry__time != NULL) + { + do_key ("Expiry-Date"); + do_utc (head -> expiry__time); + } + + if (head -> reply__time != NULL) + { + do_key ("Reply-By"); + do_utc (head -> reply__time); + } + + if (head -> reply__recipients != NULL) + { + do_key ("Reply-To"); + do_ORD_seq (head -> reply__recipients); + } + + if (head -> importance != NULL + && head -> importance -> parm != int_IOB_ImportanceField_normal) + { + do_key ("Importance"); + do_importance (head -> importance -> parm); + } + + if (head -> sensitivity != NULL) + { + do_key ("Sensitivity"); + do_sensitivity (head -> sensitivity -> parm); + } + + if (head -> auto__forwarded != NULL + && head -> auto__forwarded -> parm) + { + do_key ("Autoforwarded"); + do_boolean (head -> auto__forwarded -> parm); + } + + if (head -> extensions != NULL) + do_extensions (head -> extensions); + + return (OK); +} + +/* ARGSUSED */ +do_p2_ipn(qp, ep) +Q_struct *qp; +char **ep; +{ + char buf[BUFSIZ]; + extern char *postmaster; + ADDR *ix; + + do_key ("From"); + if (ipn->ipn__originator) + do_ORD (ipn->ipn__originator); + else if ((Q_struct *) NULL != qp) + do_p1_addrs (qp -> Oaddress); + else { + sprintf(buf, "%s", postmaster); + do_token(buf); + } + + + do_key ("To"); + if ((Q_struct *) NULL != qp) { + for (ix = qp->Raddress; + ix != NULLADDR && ix -> ad_resp == NO; + ix = ix -> ad_next) + continue; + if (ix == NULLADDR) + ix = qp->Raddress; + + if (ix != NULLADDR) { + if (ix -> ad_redirection_history != (Redirection *) NULL) { + if (ix->ad_redirection_history->rd_addr != NULLCP) { + OR_ptr or = or_std2or(ix->ad_redirection_history->rd_addr); + or_or2rfc(or, buf); + or_free(or); + } else + sprintf(buf,"list:;"); + + if (ix -> ad_redirection_history -> rd_dn != NULLCP) + (void) sprintf(buf, "%s (DN=%s)", + buf, + ix -> ad_redirection_history -> rd_dn); + } else + (void) strcpy(buf, ix -> ad_r822adr); + do_token(buf); + } else + do_token("list:;"); + } else + do_token("list:;"); + + do_key ("Subject"); + do_token ("X.400 Inter-Personal Receipt Notification"); + + do_key ("Message-Type"); + do_token ("InterPersonal Notification"); + + if (ipn -> subject__ipm != NULL) + { + do_key ("References"); + if (do_mid (ipn -> subject__ipm, FALSE) != OK) { + *ep = strdup("Invalid References message id"); + return NOTOK; + } + } + + return OK; +} + +do_p2_ipn_body (qp, ep) +Q_struct *qp; +char **ep; +{ + FILE *fp; + char buf[BUFSIZ]; + + if (ipn_body[0] != '\0') { + if ((fp = fopen (ipn_body, "w")) == NULL) + { + PP_SLOG (LLOG_EXCEPTIONS, ipn_body, + ("Can't open file")); + (void) sprintf(buf, + "Unable to open output file '%s' for IPN body", + ipn_body); + *ep = strdup(buf); + return (NOTOK); + } + } else + fp = stdout; + + fputs("Your message to: ", fp); + + if (ipn -> ipn__preferred__recipient != NULL) { + get_ORD (ipn -> ipn__preferred__recipient, abuf); + fputs(abuf, fp); + if (ipn -> ipn__originator != NULL) { + fputs(" forwarded to: ", fp); + get_ORD (ipn -> ipn__originator, abuf); + fputs(abuf, fp); + } + } else if (ipn -> ipn__originator != NULL) { + get_ORD (ipn -> ipn__originator, abuf); + fputs(abuf, fp); + } else if ((Q_struct *) NULL != qp + && adr2rfc (qp->Oaddress, abuf, order_pref) == OK) + fputs(abuf, fp); + else + fputs("an unknown recipient", fp); + + fputs("\n", fp); + if (ipn -> choice != NULL) { + if (ipn -> choice -> offset == choice_IOB_0_non__receipt__fields) + do_p2_ipn_body_non__receipt(ipn -> choice -> un.non__receipt__fields, fp); + else + do_p2_ipn_body_receipt (ipn -> choice -> un.receipt__fields, fp); + } + if (ipn -> conversion__eits != NULL) + do_p2_ipn_body_eits (ipn -> conversion__eits, fp); + + + if (ipn -> choice != NULL && + ipn -> choice -> offset == choice_IOB_0_non__receipt__fields) { + if (ipn -> choice -> un.non__receipt__fields -> returned__ipm != NULL) + fputs("\nThe Original Message follows: \n\n", fp); + else + fputs("\nThe Original Message is not available\n", fp); + } else + fputs("\nThe Original Message is not returned with positive notifications\n", fp); + + fclose (fp); + return (OK); +} + +do_p2_ipn_body_non__receipt (non_receipt, fp) +struct type_IOB_NonReceiptFields *non_receipt; +FILE *fp; +{ + if (non_receipt -> non__receipt__reason -> parm == int_IOB_NonReceiptReasonField_ipm__discarded) + do_p2_ipn_discard (non_receipt, fp); + else + do_p2_ipn_auto_forward (non_receipt, fp); +} + +do_p2_ipn_discard (non_receipt, fp) +struct type_IOB_NonReceiptFields *non_receipt; +FILE *fp; +{ + fputs("was discarded for the following reason: ", fp); + switch (non_receipt -> discard__reason -> parm) { + case int_IOB_DiscardReasonField_ipm__expired: + fputs ("Expired.\n", fp); + break; + case int_IOB_DiscardReasonField_ipm__obsoleted: + fputs ("Obsoleted.\n", fp); + break; + case int_IOB_DiscardReasonField_user__subscription__terminated: + fputs ("User Subscription Terminated.\n", fp); + break; + } +} + +do_p2_ipn_auto_forward (non_receipt, fp) +struct type_IOB_NonReceiptFields *non_receipt; +FILE *fp; +{ + char *cp; + fputs ("was automatically forwarded.\n", fp); + if (non_receipt -> auto__forward__comment != NULL) { + cp = qb2str(non_receipt -> auto__forward__comment); + fputs ("The following comment was made: ", fp); + fputs (cp, fp); + fputs (".\n", fp); + free (cp); + } +} + +do_p2_ipn_body_receipt (receipt, fp) +struct type_IOB_ReceiptFields *receipt; +FILE *fp; +{ + do_p2_utc (receipt -> receipt__time, fp); + fputs("\n", fp); + if (receipt -> acknowledgment__mode != NULL) + do_p2_ack_mode (receipt -> acknowledgment__mode, fp); + if (receipt -> suppl__receipt__info != NULL) + do_p2_suppl_info (receipt -> suppl__receipt__info, fp); +} + +do_p2_ack_mode (mode, fp) +struct type_IOB_AcknowledgmentModeField *mode; +FILE *fp; +{ + fputs ("This notification was generated ", fp); + if (mode -> parm == int_IOB_AcknowledgmentModeField_manual) + fputs("Manually.\n", fp); + else + fputs ("Automatically.\n", fp); +} + +do_p2_suppl_info (info, fp) +struct type_IOB_SupplReceiptInfoField *info; +FILE *fp; +{ + char *cp; + fputs ("The following extra information was given:\n", fp); + cp = qb2str (info); + fputs(cp, fp); + fputs ("\n", fp); + free(cp); +} + +do_p2_ipn_body_eits (eits, fp) +struct type_IOB_ConversionEITsField *eits; +FILE *fp; +{ + int first = OK; + + fputs ("The following information types were converted:", fp); + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_undefined) == 1) { + if (first == OK) { + fputs ("Undefined", fp); + first = NOTOK; + } else + fputs (", Undefined", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_telex) == 1) { + if (first == OK) { + fputs ("Telex", fp); + first = NOTOK; + } else + fputs (", Telex", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_ia5__text) == 1) { + if (first == OK) { + fputs ("IA5-Text", fp); + first = NOTOK; + } else + fputs (", IA5-Text", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_g3__facsimile) == 1) { + if (first == OK) { + fputs ("G3-Fax", fp); + first = NOTOK; + } else + fputs (", G3-Fax", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_g4__class__1) == 1) { + if (first == OK) { + fputs ("TIF0", fp); + first = NOTOK; + } else + fputs (", TIF0", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_teletex) == 1) { + if (first == OK) { + fputs ("Teletex", fp); + first = NOTOK; + } else + fputs (", Teletex", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_videotex) == 1) { + if (first == OK) { + fputs ("Videotex", fp); + first = NOTOK; + } else + fputs (", Videotex", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_voice) == 1) { + if (first == OK) { + fputs ("Voice", fp); + first = NOTOK; + } else + fputs (", Voice", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_sfd) == 1) { + if (first == OK) { + fputs ("SFD", fp); + first = NOTOK; + } else + fputs (", SFD", fp); + } + + if (bit_test (eits -> built__in__encoded__information__types, + bit_MTA_BuiltInEncodedInformationTypes_mixed__mode) == 1) { + if (first == OK) { + fputs ("TIF1", fp); + first = NOTOK; + } else + fputs (", TIF1", fp); + } + + if (eits -> external__encoded__information__types != NULL) { + if (first == OK) { + fputs (", ", fp); + first = NOTOK; + } + fputs (oid2lstr (eits -> external__encoded__information__types), fp); + } + fputs(".\n", fp); +} + +do_p2_utc (utc_qb, fp) +struct qbuf *utc_qb; +FILE *fp; +{ + char *cp; + UTC ut, lut; + fputs ("was received at ", fp); + cp = qb2str (utc_qb); + if ((ut = str2utct (cp, strlen(cp))) == NULL) + ut = str2gent (cp, strlen(cp)); + lut = utclocalise(ut); + UTC2rfc (lut, abuf); + fputs(abuf, fp); + fputs(".\n", fp); + free(cp); + free ((char *)ut); + free ((char *)lut); +} + +/* */ + +static int moreThanHdrAndIa5(eit) +EncodedIT *eit; +{ + LIST_BPT *ix = eit->eit_types; + int found = 0; +static char *p2_txt = NULLCP; + if (p2_txt == NULLCP) + p2_txt = rcmd_srch(BPT_P2_DLIV_TXT, bptbl_body_parts88); + while (found == 0 && ix != NULL) { + if (strncmp(hdr_822_bp, ix->li_name, strlen(hdr_822_bp)) == 0 + || strncmp(p2_txt, ix->li_name, strlen(p2_txt)) == 0 + || strncmp(hdr_p2_bp, ix->li_name, strlen(hdr_p2_bp)) == 0 + || strncmp(ia5_bp, ix->li_name, strlen(ia5_bp)) == 0) + ix = ix->li_next; + else + /* not ia5 or hdr */ + found = 1; + } + return found; +} + +/* ARGSUSED */ +do_p1 (qp, ishead, ep) +Q_struct *qp; +int ishead; +char **ep; +{ + if (qp == (Q_struct *) 0) + return (OK); + + do_p1_trace (qp -> trace); + + do_key ("Date"); + + do_p1_utc (qp -> trace->trace_DomSinfo.dsi_time); + + if (ishead == OK && head -> originator == NULL) + { + if (head -> authorizing__users == NULL) + do_key("From"); + else + do_key("Sender"); + + do_p1_addrs (qp -> Oaddress); + } + + do_key ("X400-Originator"); + do_p1_addrs (qp -> Oaddress); + + if (ishead == OK && + head -> primary__recipients == NULL && + head -> copy__recipients == NULL && + head -> blind__copy__recipients == NULL) + { + do_key ("To"); + if (qp -> disclose_recips + || qp -> Raddress -> ad_next == NULLADDR) + do_p1_addrs (qp -> Raddress); + else + do_token ("non-disclosure:;"); + } + + do_key ("X400-Recipients"); + if (qp -> disclose_recips + || qp -> Raddress -> ad_next == NULLADDR) + do_p1_addrs (qp -> Raddress); + else + do_token ("non-disclosure:;"); + + do_key ("X400-MTS-Identifier"); + do_p1_mid (&(qp -> msgid)); + + if (qp -> orig_encodedinfo.eit_types != NULL + && moreThanHdrAndIa5 (&qp -> orig_encodedinfo)) { + do_key ("Original-Encoded-Information-Types"); + do_p1_eit (&(qp -> orig_encodedinfo)); + } else if (qp -> encodedinfo.eit_types != NULL + && moreThanHdrAndIa5 (&qp -> encodedinfo)) { + /* not just ia5 bodypart */ + do_key ("Original-Encoded-Information-Types"); + do_p1_eit (&(qp -> encodedinfo)); + } + + if (qp -> cont_type != NULLCP) { + do_key ("X400-Content-Type"); + if (lexequ (qp -> cont_type, cont_p2) == 0) + do_token ("P2-1984 (2)"); + else if (lexequ (qp -> cont_type, cont_p22) == 0) + do_token ("P2-1988 (22)"); + else + do_token (qp -> cont_type); + } + + if (qp -> ua_id != NULLCP) + { + do_key ("Content-Identifier"); + do_token (qp -> ua_id); + } + + if (qp -> priority != PRIO_NORMAL) + { + do_key ("Priority"); + do_p1_priority (qp -> priority); + } + + if (qp -> originator_return_address != NULL) + { + do_key ("Originator-Return-Address"); + do_p1_fullname (qp -> originator_return_address); + } + + if (qp -> dl_expansion_history != NULL) + do_p1_DLHistory (qp -> dl_expansion_history); + + if (qp -> implicit_conversion_prohibited == TRUE) + { + do_key("Conversion"); + do_token("Prohibited"); + } + + if (qp -> conversion_with_loss_prohibited) + { + do_key ("Conversion-With-Loss"); + do_token ("Prohibited"); + } + + + if (qp -> defertime != 0) + { + do_key ("Deferred-Delivery"); + do_p1_utc (qp -> defertime); + } + + if (qp -> latest_time != 0 + && qp -> latest_time_crit) + { + do_key ("Latest-Delivery-Time"); + do_p1_utc (qp -> latest_time); + } + + return (OK); +} + +/* ARGSUSED */ +do_p1_ipn (qp, ishead, ep) +Q_struct *qp; +int ishead; +char **ep; +{ + if (qp == (Q_struct *) 0) + return (OK); + + do_p1_trace (qp -> trace); + + do_key ("Date"); + + do_p1_utc (qp -> trace->trace_DomSinfo.dsi_time); + + do_key ("X400-Originator"); + do_p1_addrs (qp -> Oaddress); + + do_key ("X400-MTS-Identifier"); + do_p1_mid (&(qp -> msgid)); + + if (qp -> cont_type != NULLCP) { + do_key ("X400-Content-Type"); + if (lexequ (qp -> cont_type, cont_p2) == 0) + do_token ("P2-1984 (2)"); + else if (lexequ (qp -> cont_type, cont_p22) == 0) + do_token ("P2-1988 (22)"); + else + do_token (qp -> cont_type); + } + + if (qp -> orig_encodedinfo.eit_types != NULL + && moreThanHdrAndIa5 (&qp -> orig_encodedinfo)) { + do_key ("Original-Encoded-Information-Types"); + do_p1_eit (&(qp -> orig_encodedinfo)); + } else if (qp -> encodedinfo.eit_types != NULL + && moreThanHdrAndIa5 (&qp -> encodedinfo)) { + /* not just ia5 bodypart */ + do_key ("Original-Encoded-Information-Types"); + do_p1_eit (&(qp -> encodedinfo)); + } + + if (qp -> priority != PRIO_NORMAL) + { + do_key ("Priority"); + do_p1_priority (qp -> priority); + } + + if (qp -> ua_id != NULLCP) + { + do_key ("Content-Identifier"); + do_token (qp -> ua_id); + } + + return (OK); +} + +/* */ + +do_extra (extra, ep) +char *extra; +char **ep; +{ + char buf [BUFSIZ], tmp[BUFSIZ]; + FILE *fp_extra; + + if (extra == NULLCP || extra [0] == '\0') + return (OK); + + if ((fp_extra = fopen (extra, "r")) == NULL) + { + PP_SLOG (LLOG_EXCEPTIONS, extra, + ("Can't open file")); + (void) sprintf (tmp, + "Unable to open extra input file '%s'", + extra); + *ep = strdup(tmp); + return (NOTOK); + } + + if (fgets (buf, BUFSIZ - 1, fp_extra) == NULL) + { + PP_DBG (( "Null file '%s'", extra)); + (void) sprintf (tmp, + "Empty extra file '%s'", + extra); + *ep = strdup(tmp); + fclose (fp_extra); + return (NOTOK); + } + + buf [strlen(buf) - 1] = '\0'; /* remvove \n */ + if (lexnequ (buf, "RFC-822-HEADERS", + strlen("RFC-822-HEADERS")) != 0 + && lexnequ (buf, "Comments", + strlen("Comments")) != 0) + { + PP_DBG (( "Illegal first line '%s' in file '%s'", + buf, extra)); + (void) sprintf (tmp, + "Illegal first line '%s' in file '%s'", + buf, extra); + fclose (fp_extra); + *ep = strdup(tmp); + return (NOTOK); + } + + while (TRUE) + { + if ((fgets (buf, BUFSIZ -1, fp_extra) == NULL) + && !feof (fp_extra)) + { + PP_DBG (( "File read error")); + fclose (fp_extra); + return (NOTOK); + } + + if (!feof (fp_extra)) + fputs (buf, fp_out); + else + { + fclose (fp_extra); + return (OK); + } + } + +} + +/* */ +/* P2 structure bits */ +do_822_extension_88 (pe) +PE pe; +{ + char *hdr_txt, *cix; + + struct type_IOB_RFC822FieldList *list, *ix; + PY_pepy[0] = 0; + if (decode_IOB_RFC822FieldList (pe, 0, NULLIP, NULLVP, &list) != OK) + PP_OPER(NULLCP, + ("decode_IOB_RFC822Field () Failed : [%s]", PY_pepy)); + else { + for (ix = list; ix != NULL; ix = ix -> next) { + hdr_txt = qb2str(ix->RFC822Field); + if ((cix = index(hdr_txt, ':')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to parse extra 822 hdr '%s'", hdr_txt)); + free(hdr_txt); + continue; + } + *cix++ = '\0'; + while (isspace(*cix)) cix++; + do_key(hdr_txt); + do_token (cix); + free(hdr_txt); + } + free_IOB_RFC822FieldList(list); + } +} + +do_822_extension_84 (pe) +PE pe; +{ + char *hdr_txt, *ix; + + struct type_IOB_RFC822Field *hdr; + PY_pepy[0] = 0; + if (decode_IOB_RFC822Field (pe, 0, NULLIP, NULLVP, &hdr) != OK) + PP_OPER(NULLCP, + ("decode_IOB_RFC822Field () Failed : [%s]", PY_pepy)); + else { + hdr_txt = qb2str(hdr); + if ((ix = index(hdr_txt, ':')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to parse extra 822 hdr '%s'", hdr_txt)); + free(hdr_txt); + return; + } + *ix++ = '\0'; + while (isspace(*ix)) ix++; + do_key(hdr_txt); + do_token (ix); + free(hdr_txt); + free_IOB_RFC822Field(hdr); + } +} + +static char discard_extn[BUFSIZ]; + +do_discarded_extensions () +{ + do_key ("Discarded-X400-IPMS-Extensions"); + do_token(discard_extn); +} + +do_incomplete_copy() +{ + do_key ("Incomplete-Copy"); + do_token (""); +} + +do_languages (pe) +PE pe; +{ + char *lang_txt; + + struct type_IOB_Languages *lang, *ix; + PY_pepy[0] = 0; + if (decode_IOB_Languages (pe, 0, NULLIP, NULLVP, &lang) != OK) + PP_OPER(NULLCP, + ("decode_IOB_Languages () failed : [%s]", PY_pepy)); + else { + ix = lang; + while (ix != NULL) { + lang_txt = qb2str(ix -> Language); + do_key ("Language"); + do_token (lang_txt); + free(lang_txt); + ix = ix -> next; + } + free_IOB_Languages(lang); + } +} + + +do_extension (extension) +struct type_IOB_HeadingExtension *extension; +{ + OID oid; + + if (extension -> type == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("NULL oid in header extension")); + return; + } + if ((oid = str2oid(id_rfc_822_field_list)) == NULLOID) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert '%s' to an OID", + id_rfc_822_field_list)); + } + + if (oid != NULLOID + && oid_cmp (extension -> type, oid) == 0) + return do_822_extension_88 (extension -> value); + + if ((oid = str2oid(id_rfc_822_field)) == NULLOID) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert '%s' to an OID", + id_rfc_822_field)); + } + + if (oid != NULLOID + && oid_cmp (extension -> type, oid) == 0) + return do_822_extension_84 (extension -> value); + + if ((oid = str2oid(id_hex_incomplete_copy)) == NULLOID) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert '%s' to an OID", + id_hex_incomplete_copy)); + } + + if (oid != NULLOID + && oid_cmp (extension -> type, oid) == 0) + return do_incomplete_copy(); + + if ((oid = str2oid(id_hex_languages)) == NULLOID) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert '%s' to an OID", + id_hex_languages)); + } + + if (oid != NULLOID + && oid_cmp (extension -> type, oid) == 0) + return do_languages (extension -> value); + + PP_LOG(LLOG_EXCEPTIONS, + ("Unrecognised oid '%s' in header extension", + oid2lstr(extension -> type))); + if ('\0' != discard_extn[0]) + strcat(discard_extn, ", "); + strcat(discard_extn, oid2lstr(extension -> type)); +} + +do_extensions (extensions) +struct type_IOB_ExtensionsField *extensions; +{ + discard_extn[0] = '\0'; + while (extensions != NULL) { + do_extension (extensions -> HeadingExtension); + extensions = extensions -> next; + } + if ('\0' != discard_extn[0]) + do_discarded_extensions(); +} + +static CHARSET *ia5 = (CHARSET *) NULL; +static CHARSET *t61 = (CHARSET *) NULL; + +static CHAR8U *t61toasc (t61str) +CHAR8U *t61str; +{ + CHAR8U *ia5str; + + if (ia5 == (CHARSET *) NULL) + ia5 = getchset("CCITT_T.50.irv:1988", (INT16S) 29); + if (t61 == (CHARSET *) NULL) + t61 = getchset("T.61-8bit", (INT16S) 29); + + if (ia5 != (CHARSET *) NULL + && t61 != (CHARSET *) NULL) { + ia5str = (CHAR8U *) malloc(sizeof(CHAR8U) * strlen((char *) t61str)+1); + if (strncnv (ia5, t61, + ia5str, t61str, + strlen((char *) t61str),FALSE) >= 0) + return ia5str; + } + return (CHAR8U *) NULL; +} + +do_subject (qb) +struct qbuf *qb; +{ + CHAR8U *t61str, *ia5str; + t61str = (CHAR8U *) qb2str (qb); + if ((ia5str = t61toasc((CHAR8U *) t61str)) != (CHAR8U *) NULL) { + do_string (ia5str); + free(ia5str); + } else + do_string (t61str); + free (t61str); +} + + +do_recip_seq (recip_seq) +struct type_IOB_RecipientSequence *recip_seq; +{ + struct type_IOB_RecipientSpecifier *recip; + + recip = recip_seq -> RecipientSpecifier; + get_ORD (recip -> recipient, abuf); + + if (recip -> notification__requests != NULLPE && + bit_test (recip -> notification__requests, + bit_IOB_NotificationRequests_rn) == 1) { + strcat (abuf, " (Receipt Notification Requested)"); + } + + if (recip -> notification__requests != NULLPE && + bit_test (recip -> notification__requests, + bit_IOB_NotificationRequests_nrn) == 1) { + strcat (abuf, " (Non Receipt Notification Requested)"); + } + + if (recip -> notification__requests != NULLPE && + bit_test (recip -> notification__requests, + bit_IOB_NotificationRequests_ipm__return) == 1) { + strcat (abuf, " (IPM Return Requested)"); + } + + if (recip -> reply__requested) + strcat (abuf, " (Reply Requested)"); + + do_token (abuf); + if (recip_seq -> next != NULL) + { + do_same_line (","); + do_recip_seq (recip_seq -> next); + } +} + + + +do_ORD_seq (ord_seq) +struct type_IOB_ORDescriptorSequence *ord_seq; +{ + get_ORD (ord_seq -> ORDescriptor, abuf); + do_token (abuf); + if (ord_seq -> next != NULL) + { + do_same_line (","); + do_ORD_seq (ord_seq -> next); + } +} + + +do_ORD (ord) +struct type_IOB_ORDescriptor *ord; +{ + get_ORD (ord, abuf); + do_token (abuf); +} + +OR_ptr pe2or(); + +static void add_phrase(out, in) +char *out, *in; +{ + AP_ptr tree = NULLAP, group, name, local, domain, route; + + if (ap_s2p(in, &tree, &group, &name, + &local, &domain, &route) != (char *) NOTOK + && route != NULLAP && group == NULLAP) { + char *str; + group = ap_new(AP_PERSON_NAME, local->ap_obvalue); + str = ap_p2s(group, name, local, domain, route); + strcpy (out, str); + free(str); + ap_free(group); + } else + strcpy (out, in); + + if (tree != NULLAP) { + ap_sqdelete (tree, NULLAP); + ap_free (tree); + } +} + +get_ORD (ord, buf) +struct type_IOB_ORDescriptor *ord; +char *buf; +{ + /* see rfc1138 4.7.2 */ + ORName *orn; + char tbuf [BUFSIZ], asc[BUFSIZ]; + char *cp, *str = NULLCP, *dn = NULLCP; + + if ((orn = orname2orn(ord -> formal__name)) == NULLORName) { + PP_DBG (("Failed to convert IOB_orname to ORName")); + tbuf[0] = '\0'; + } else { + if (or_or2rfc (orn->on_or, tbuf) != OK) { + PP_DBG (("or_or2rfc failed")); + tbuf[0] = '\0'; + } + if (orn->on_dn != NULL) + dn = dn2ufn (orn->on_dn, FALSE); + ORName_free(orn); + } + + if (ord -> free__form__name == NULL) + if (tbuf[0] == '\0') + strcpy (buf, "Empty Address :;"); + else + if (tbuf[0] == '@') + sprintf (buf, "FOO <%s>", tbuf); + else + /* if route add phrase */ + add_phrase(buf, tbuf); + + else + { + CHAR8U *t61str, *ia5str; + + t61str = (CHAR8U *) qb2str (ord -> free__form__name); + + /* do t.61 -> ascii conversion */ + if ((ia5str = t61toasc((CHAR8U *) t61str)) != (CHAR8U *) NULL) { + strcpy (asc, (char *) ia5str); + free((char *) ia5str); + } else + strcpy (asc, (char *) t61str); + + if (tbuf [0] == '\0') + sprintf (buf, "\"%s\" :;", asc); + else + sprintf (buf, "\"%s\" <%s>", asc, tbuf); + free ((char *) t61str); + } + + if (dn != NULLCP) + { + strcat (buf, " (DN="); + strcat (buf, dn); + strcat (buf, ")"); + free(dn); + } + + if (ord -> telephone__number != NULL) + { + cp = qb2str (ord -> telephone__number); + if (*cp != '\0') { + strcat (buf, " (Tel "); + strcat (buf, cp); + strcat (buf, ")"); + free(cp); + } + } + ap_s2s (buf, &str, order_pref); + if (str != NULLCP + && *str != '\0') { + (void) strcpy(buf, str); + free(str); + } +} + +do_mid_seq (mid_seq, addMHS) +struct type_IOB_IPMIdentifierSequence *mid_seq; +int addMHS; +{ + if (do_mid (mid_seq -> IPMIdentifier, addMHS) != OK) + return NOTOK; + if (mid_seq -> next != NULL) + { + do_same_line (","); + return do_mid_seq (mid_seq -> next, addMHS); + } + return OK; +} + +extern char *loc_dom_site; + +do_mid (mid, addMHS) +struct type_IOB_IPMIdentifier *mid; +int addMHS; +{ + char *midstring; + ORName *orn; + char tbuf [BUFSIZ], buf[BUFSIZ]; + char *cp; + AP_ptr ap; + AP_ptr local; + AP_ptr domain; + /* see rfc 1138 4.7.3.4 */ + + if (mid -> user__relative__identifier != NULL) { + midstring = qb2str (mid -> user__relative__identifier); + or_ps2asc (midstring, abuf); + free(midstring); + + if (lexequ(abuf, "RFC-822") == 0) + return do_mid_987(mid); + + if (mid -> user == NULL) { + (void) sprintf (buf, "<%s>", abuf); + if ((index(buf, '@') != NULLCP) + && (ap_s2p (buf, &ap, (AP_ptr *) 0, (AP_ptr *) 0, + &local, &domain, + (AP_ptr *) 0) != (char *) NOTOK)) { + /* buf parses as 822.msg-id */ + do_token (buf); + ap_free(ap); + return OK; + } + } + } else + abuf[0] = '\0'; + + /* try as x400 generated */ + if (mid -> user) { + if ((orn = orname2orn (mid -> user)) != NULLORName) { + or_or2std (orn->on_or, tbuf, FALSE); + if (abuf[0] != '\0') + sprintf (buf, "%s*%s", abuf, tbuf); + else + sprintf (buf, "*%s", tbuf); + + local = ap_new (AP_MAILBOX, buf); + domain = ap_new (AP_DOMAIN, "MHS"); + cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP); + sprintf (abuf, "<%s>", cp); + free (cp); + ap_free (local); + ap_free (domain); + ORName_free(orn); + do_token (abuf); + return OK; + } + } + + /* no user */ + if (abuf[0] != '\0') { + if (addMHS == TRUE) { + (void) sprintf(buf, "%s*",abuf); + local = ap_new(AP_MAILBOX, buf); + domain = ap_new(AP_DOMAIN, "MHS"); + cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP); + sprintf (abuf, "<%s>", cp); + ap_free (domain); + } else { + /* generate phrase as 1148 4.7.3.5 says */ + local = ap_new (AP_GROUP_NAME, abuf); + cp = ap_p2s_nc(local, NULLAP, NULLAP, NULLAP, NULLAP); + strcpy(abuf, cp); + } + free (cp); + ap_free (local); + do_token (abuf); + return OK; + } + + PP_DBG (( "Highly dubious ID")); + (void) sprintf (abuf, "", loc_dom_site); + do_token(abuf); + /* gen mid */ + return NOTOK; +} + +do_mid_987(mid) +struct type_IOB_IPMIdentifier *mid; +{ + char buf[BUFSIZ], buf2[BUFSIZ]; + ORName *orn; + + if (mid -> user) { + if ((orn = orname2orn(mid->user)) != NULLORName + && orn->on_or != NULLOR + && or_or2rfc_aux(orn->on_or, buf, FALSE) == OK) { + (void) sprintf(buf2, "<%s>",buf); + do_token (buf2); + ORName_free(orn); + return OK; + } + if (orn) ORName_free(orn); + } + + PP_DBG(("Highly dubious 987 ID")); + (void) sprintf(buf, "", loc_dom_site); + do_token(buf); + return NOTOK; +} + +do_utc (utc_qb) +struct qbuf *utc_qb; +{ + char *cp; + UTC ut; + + cp = qb2str (utc_qb); + ut = str2utct (cp, strlen(cp)); + do_p1_utc (ut); + free (cp); +} + +do_importance (importance) +int importance; +{ + switch (importance) + { + case int_IOB_ImportanceField_low: + do_token ("Low"); + break; + case int_IOB_ImportanceField_normal: + do_token ("Normal"); + break; + case int_IOB_ImportanceField_high: + do_token ("High"); + break; + default: + sprintf(abuf, "Undefined (value=%d)", importance); + do_token (abuf); + break; + } +} + +do_sensitivity (sensitivity) +int sensitivity; +{ + switch (sensitivity) + { + case int_IOB_SensitivityField_personal: + do_token ("Personal"); + break; + case int_IOB_SensitivityField_private: + do_token ("Private"); + break; + case int_IOB_SensitivityField_company__confidential: + do_token ("Company-Confidential"); + break; + default: + sprintf(abuf, "Undefined (value=%d)", sensitivity); + do_token (abuf); + break; + } +} + +do_boolean (bool) +char bool; +{ + if (bool) + do_token ("TRUE"); + else + do_token ("FALSE"); +} + +/* */ +/* Stuff for P1 */ + +do_p1_utc (ut) +UTC ut; +{ + UTC lut; + lut = utclocalise(ut); + if (UTC2rfc (lut, abuf) == NOTOK) + strcpy(abuf, ">>INVALID UTC TIME<<"); + do_token (abuf); + free((char *) lut); +} + +do_p1_addrs (addr) +ADDR *addr; +{ + if (adr2rfc (addr, abuf, order_pref) == OK) + do_token (abuf); + if (addr -> ad_next != NULL) + { + do_same_line (","); + do_p1_addrs (addr -> ad_next); + } +} + +do_p1_mid (mid) +MPDUid *mid; +{ + msgid2rfc (mid, abuf); + do_token (abuf); +} + +do_p1_eit (eit) +EncodedIT *eit; +{ + x400eits2rfc (eit, abuf); + do_token (abuf); +} + +do_p1_priority (priority) +int priority; +{ + switch (priority) + { + case PRIO_NORMAL: + do_token ("Normal"); + break; + case PRIO_URGENT: + do_token ("Urgent"); + break; + case PRIO_NONURGENT: + do_token ("Non-Urgent"); + break; + } +} + +do_p1_trace (trace) +Trace *trace; +{ + + if (trace->trace_next != NULL) + do_p1_trace(trace->trace_next); + do_key ("X400-Received"); + x400trace2rfc (trace,abuf); + do_token (abuf); +} + +do_p1_fullname (fullname) +FullName *fullname; +{ + do_token (fullname->fn_addr); +} + +do_p1_DLHistory (history) +DLHistory *history; +{ + char temp[BUFSIZ]; + OR_ptr or; + UTC lut; + if (history -> dlh_next != NULL) + do_p1_DLHistory(history -> dlh_next); + do_key ("DL-Expansion-History"); + or = or_std2or(history -> dlh_addr); + or_or2rfc_aux(or, temp, FALSE); + (void) sprintf (abuf, + "%s", + temp); + if (history -> dlh_time != 0) { + lut = utclocalise(history -> dlh_time); + UTC2rfc (lut, temp); + free ((char *) lut); + (void) sprintf (abuf, + "%s ; %s;", + abuf, temp); + } + do_token (abuf); +} + + +/* */ +/* General purpose header output */ + +do_key (key) +char *key; +{ + if (firstLine != TRUE) + fputs ("\n", fp_out); + else + firstLine = FALSE; + fputs (key, fp_out); + fputs (": ", fp_out); +} + +do_string (string) /* fold string on spaces for unstructured */ +char *string; +{ + fputs (" ", fp_out); + fputs (string, fp_out); +} + +do_same_line (token) +char *token; +{ + fputs (token, fp_out); +} + +do_token (token) +char *token; +{ + fputs (" ", fp_out); + fputs (token, fp_out); +} + +/* */ + +do_delinfo (file, ep) +char *file; +char **ep; +{ + FILE *fp_in; + PE pe = NULLPE; + PS ps = NULLPS; + struct type_IOB_MessageParameters *params = (struct type_IOB_MessageParameters *) NULL; + char buf[BUFSIZ]; + + if ((fp_in = fopen (file, "r")) == NULL) + { + PP_SLOG (LLOG_EXCEPTIONS, file, + ("Can't open file for reading")); + fclose (fp_in); + (void) sprintf (buf, + "Failed to open input file '%s'", + file); + *ep = strdup(buf); + return NOTOK; + } + + if (((ps = ps_alloc (std_open)) == NULLPS) || + (std_setup (ps, fp_in) == NOTOK)) + { + PP_LOG (LLOG_EXCEPTIONS, ("p2to822() failed to setup PS")); + *ep = strdup("Failed to set up PS"); + fclose(fp_in); + if (ps) ps_free(ps); + return NOTOK; + } + + + if ((pe = ps2pe (ps)) == NULLPE) + { + PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error on file '%s'", file)); + fclose (fp_in); + if (pe) pe_free(pe); + if (ps) ps_free(ps); + } + + PY_pepy[0] = 0; + if (decode_IOB_MessageParameters(pe, 0, NULLIP, NULLVP, ¶ms) != OK) + { + PP_OPER(NULLCP, + ("decode_IOB_MessageParameters() failed : [%s]", PY_pepy)); + convertresult = NOTOK; + *ep = strdup("Illegal ASN.1 in forwarded message parameters"); + fclose (fp_in); + if (pe) pe_free(pe); + if (ps) ps_free(ps); + if (params) free_IOB_MessageParameters(params); + return NOTOK; + } + if (0 != PY_pepy[0]) + PP_LOG(LLOG_EXCEPTIONS, + ("decode_IOB_MessageParameters non-fatal failure [%s]", + PY_pepy)); + if (params->delivery__time) + do_delivery_time(params->delivery__time); + if (params->delivery__envelope) + do_delivery_envelope(params->delivery__envelope); + fclose (fp_in); + if (pe) pe_free(pe); + if (ps) ps_free(ps); + if (params) free_IOB_MessageParameters(params); + return OK; +} + +do_delivery_time(time) +struct type_MTA_MessageDeliveryTime *time; +{ + do_key("Delivery-Date"); + do_utc(time); +} + +do_delivery_envelope(envelope) +struct type_MTA_OtherMessageDeliveryFields *envelope; +{ + char buf[BUFSIZ]; + + do_key("X400-Content-Type"); + switch (envelope->member_MTA_8->offset) { + case choice_MTA_4_built__in: + do_built_in_content(envelope->member_MTA_8->un.built__in); + break; + case choice_MTA_4_external: + do_external_content (envelope->member_MTA_8->un.external); + break; + } + + if (head -> originator == NULL + && head -> authorizing__users == NULL) + do_key ("From"); + else + do_key("X400-Originator"); + do_MTA_ORName(envelope->originator__name, buf); + do_token(buf); + + if (envelope->original__encoded__information__types != NULL) { + do_key ("Original-Encoded-Information-Types"); + do_MTA_eits (envelope->original__encoded__information__types); + } + + if (envelope->priority + && envelope->priority->parm != int_MTA_Priority_normal) { + do_key ("Priority"); + do_MTA_priority (envelope->priority->parm); + } + + if (envelope->delivery__flags + && bit_ison (envelope->delivery__flags, + bit_MTA_DeliveryFlags_implicit__conversion__prohibited)) { + do_key("Conversion"); + do_token("Prohibited"); + } + + if (envelope->this__recipient__name) { + do_key("X400-Recipients"); + do_MTA_this_recipient(envelope->this__recipient__name, + envelope->originally__intended__recipient__name); + } + + if (envelope->converted__encoded__information__types != NULL) { + do_key ("Converted-Encoded-Information-Types"); + do_MTA_eits (envelope->converted__encoded__information__types); + } + + if (envelope->other__recipient__names) { + do_key("X400-Recipients"); + do_MTA_other_recips(envelope->other__recipient__names); + } + + do_key("Date"); + do_utc(envelope->message__submission__time); + + if (envelope->content__identifier) { + char *str = qb2str(envelope->content__identifier); + do_key("Content-Identifier"); + do_token(str); + free(str); + } + + if (envelope->extensions) + do_MTA_extensions(envelope->extensions); + +} + +do_MTS_discard_extensions () +{ + do_key ("Discarded-X400-MTS-Extensions"); + do_token(discard_extn); +} + +do_MTA_extensions(extns) +struct type_MTA_Extensions *extns; +{ + bzero((char *) &del_info_q, sizeof(del_info_q)); + bzero((char *) &del_info_recip, sizeof(del_info_recip)); + + discard_extn[0] = '\0'; + while (extns != (struct type_MTA_Extensions *) NULL) { + switch (extns->ExtensionField->type->offset) { + case type_MTA_ExtensionType_local: + do_MTA_local_extension (extns->ExtensionField); + break; + case type_MTA_ExtensionType_global: + do_MTA_global_extension (extns->ExtensionField); + break; + } + extns = extns -> next; + } + if ('\0' != discard_extn[0]) + do_MTS_discard_extensions(); +} + +do_MTA_local_extension (ext) +struct type_MTA_ExtensionField *ext; +{ + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown local extension '%s'", + oid2lstr(ext->type->un.local))); + if ('\0' != discard_extn[0]) + strcat (discard_extn, ", "); + strcat(discard_extn, oid2lstr(ext->type->un.local)); +} + +do_MTA_global_extension (ext) +struct type_MTA_ExtensionField *ext; +{ + char buffer[BUFSIZ]; + switch (ext->type->un.global) { + case EXT_CONVERSION_WITH_LOSS_PROHIBITED: + if (decode_extension + ((caddr_t) &(del_info_q.conversion_with_loss_prohibited), + _ZConversionWithLossProhibitedExt, + &_ZExt_mod, + "Extensions.ConversionWithLossProhibited", + decode_ext_char, + ext) == OK + && del_info_q.conversion_with_loss_prohibited) { + do_key ("Conversion-With-Loss"); + do_token("Prohibited"); + } + break; + case EXT_REQUESTED_DELIVERY_METHOD: + if (decode_extension + ((caddr_t)del_info_recip.ad_req_del, + _ZRequestedDeliveryMethodExt, + &_ZExt_mod, + "Extensions.RequestedDeliveryMethod", + decode_ext_rdm, + ext) == OK) { + if (del_info_recip.ad_req_del[0] != AD_RDM_NOTUSED + && del_info_recip.ad_req_del[0] != AD_RDM_ANY) { + int ix = 0, first = OK; + char *type; + + do_key("Requested-Delivery-Methods"); + buffer[0] = '\0'; + while (ix < AD_RDM_MAX + && del_info_recip.ad_req_del[ix] != AD_RDM_NOTUSED + && del_info_recip.ad_req_del[ix] != AD_RDM_ANY) { + if ((type = rcmd_srch(del_info_recip.ad_req_del[ix], atbl_rdm)) != NULLCP) { + if (OK != first ) + strcat(buffer, ", "); + strcat(buffer, + type); + } + ix++; + first = NOTOK; + } + do_token(buffer); + } + } + break; + case EXT_ORIGINATOR_RETURN_ADDRESS: + do_MTA_orig_ret_addr (ext); + break; + case EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST: + decode_extension + ((caddr_t)&(del_info_recip.ad_phys_fw_ad_req), + _ZPhysicalForwardingAddressRequestExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingAddressRequest", + decode_ext_char, + ext); + break; + case EXT_PHYSICAL_DELIVERY_MODES: + decode_extension + ((caddr_t)&(del_info_recip.ad_phys_modes), + _ZPhysicalDeliveryModesExt, + &_ZExt_mod, + "Extensions.PhysicalDeliveryModes", + decode_ext_pdm, + ext); + break; + case EXT_REGISTERED_MAIL: + decode_extension + ((caddr_t)&(del_info_recip.ad_reg_mail_type), + _ZRegisteredMailTypeExt, + + &_ZExt_mod, + "Extensions.RegisteredMailType", + decode_ext_int, + ext); + break; + case EXT_RECIPIENT_NUMBER_FOR_ADVICE: + decode_extension + ((caddr_t)&(del_info_recip.ad_recip_number_for_advice), + _ZRecipientNumberForAdviceExt, + &_ZExt_mod, + "Extensions.RecipientNumberForAdvice", + decode_ext_rnfa, + ext); + break; + case EXT_PHYSICAL_RENDITION_ATTRIBUTES: + decode_extension + ((caddr_t)&(del_info_recip.ad_phys_rendition_attribs), + _ZPhysicalRenditionAttributesExt, + &_ZExt_mod, + "Extensions.PhysicalRenditionAttributes", + decode_ext_pra, + ext); + break; + case EXT_PHYSICAL_DELIVERY_REPORT_REQUEST: + decode_extension + ((caddr_t)&(del_info_recip.ad_pd_report_request), + _ZPhysicalDeliveryReportRequestExt, + &_ZExt_mod, + "Extensions.PhysicalDeliveryReportRequest", + decode_ext_int, + ext); + break; + case EXT_PHYSICAL_FORWARDING_PROHIBITED: + decode_extension + ((caddr_t)&(del_info_recip.ad_phys_forward), + _ZPhysicalForwardingProhibitedExt, + &_ZExt_mod, + "Extensions.PhysicalForwardingProhibited", + decode_ext_char, + ext); + break; + case EXT_REDIRECTION_HISTORY: + decode_extension + ((caddr_t)&(del_info_recip.ad_redirection_history), + _ZRedirectionHistoryExt, + &_ZExt_mod, + "Extensions.RedirectionHistory", + decode_ext_redir, + ext); + + break; + case EXT_DL_EXPANSION_HISTORY: + if (decode_extension + ((caddr_t)&(del_info_q.dl_expansion_history), + _ZDLExpansionHistoryExt, + &_ZExt_mod, + "Extensions.DLExpansionHistory", + ext_decode_dlexph, + ext) == OK) + do_p1_DLHistory (del_info_q.dl_expansion_history); + break; + default: + break; + } +} + +do_MTA_orig_ret_addr(ext) +struct type_MTA_ExtensionField *ext; +{ + struct type_Ext_OriginatorReturnAddress *ora; + OR_ptr or; + char buf[BUFSIZ]; + + if (decode_Ext_OriginatorReturnAddress (ext -> value, 1, + NULLIP, NULLVP, + &ora) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't parse originator return address [%s]", + PY_pepy)); + return; + } + + or = oradr2ora (ora); + + if (or_or2rfc(or, buf) == OK) { + do_key("Originator-Return-Address"); + do_token(buf); + } + or_free(or); + free_Ext_OriginatorReturnAddress (ora); +} + +do_MTA_eits (eits) +struct type_MTA_EncodedInformationTypes *eits; +{ + int some; + + some = do_MTA_buildin_eits(eits->built__in__encoded__information__types); + if (eits->external__encoded__information__types) { + if (TRUE == some) + do_same_line(","); + do_MTA_external_eits(eits->external__encoded__information__types); + } +} + +do_MTA_external_eits(eits) +struct type_MTA_ExternalEncodedInformationTypes *eits; +{ + int some = FALSE; + + while (eits != (struct type_MTA_ExternalEncodedInformationTypes *) NULL) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token (oid2lstr(eits->ExternalEncodedInformationType)); + eits = eits -> next; + } +} + +do_MTA_buildin_eits (eits) +struct type_MTA_BuiltInEncodedInformationTypes *eits; +{ + int some = FALSE; + + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_undefined)) { + do_token("undefined (0)"); + some = TRUE; + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_telex)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("telex (1)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_ia5__text)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("ia5 text (2)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_g3__facsimile)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("g3 facsimile (3)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_g4__class__1)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("g4 class 1 (4)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_teletex)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("teletex (5)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_videotex)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("videotex (6)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_voice)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("voice (7)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_sfd)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("sfd (8)"); + } + if (bit_ison(eits, + bit_MTA_BuiltInEncodedInformationTypes_mixed__mode)) { + if (TRUE == some) + do_same_line(","); + else + some = TRUE; + do_token("mixed mode (9)"); + } + + return some; +} + + + +do_MTA_priority (priority) +int priority; +{ + switch (priority) + { + case int_MTA_Priority_normal: + do_token ("Normal"); + break; + case int_MTA_Priority_urgent: + do_token ("Urgent"); + break; + case int_MTA_Priority_non__urgent: + do_token ("Non-Urgent"); + break; + } +} + +do_MTA_ORName (orname, buf) +struct type_MTA_ORName *orname; +char *buf; +{ + ORName *orn; + char tbuf[BUFSIZ], *dn = NULLCP; + + if ((orn = orname2orn((struct type_IOB_ORName *) orname)) == NULLORName) { + PP_DBG (("Failed to convert MTA_orname to ORName")); + sprintf(buf, ""); + return; + } else { + if (or_or2rfc (orn->on_or, tbuf) != OK) { + PP_DBG (("or_or2rfc failed")); + tbuf[0] = '\0'; + } + if (orn->on_dn != NULL) + dn = dn2ufn (orn->on_dn, FALSE); + ORName_free(orn); + } + + if (dn != NULLCP) { + sprintf(buf, "%s (DN=%s)", + tbuf, dn); + free(dn); + } else + strcpy(buf, tbuf); +} + +do_MTA_other_recips (list) +struct type_MTA_OtherRecipientNames *list; +{ + char buf[BUFSIZ]; + while (list != (struct type_MTA_OtherRecipientNames *) NULL) { + do_MTA_ORName (list -> OtherRecipientName, buf); + do_token(buf); + list = list -> next; + if (list != (struct type_MTA_OtherRecipientNames *) NULL) + do_same_line (","); + } +} + +do_MTA_this_recipient (recip, orig) +struct type_MTA_ORName *recip, *orig; +{ + char buf[BUFSIZ]; + do_MTA_ORName(recip, buf); + if (orig != (struct type_MTA_ORName *) NULL) { + char tmp[BUFSIZ], tmp2[BUFSIZ]; + do_MTA_ORName(orig, tmp); + sprintf(tmp2, "(Originally To: %s Redirected)", + tmp); + strcat(buf, tmp2); + } + adr2comments(&del_info_recip, buf); + do_token(buf); +} + +do_built_in_content(content) +struct type_MTA_BuiltInContentType *content; +{ + char buf[BUFSIZ]; + + switch (content->parm) { + case int_MTA_BuiltInContentType_unidentified: + do_token("unidentified (0)"); + break; + case int_MTA_BuiltInContentType_external: + do_token("external (1)"); + break; + case int_MTA_BuiltInContentType_interpersonal__messaging__1984: + do_token("P2-1984 (2)"); + break; + case int_MTA_BuiltInContentType_interpersonal__messaging__1988: + do_token("P2-1988 (22)"); + break; + default: + sprintf(buf, "unknown (%d)", + content->parm); + do_token (buf); + break; + } +} + +do_external_content (content) +OID content; +{ + do_token (oid2lstr(content)); +} + + +/* nicked from x40088 */ +static int decode_extension (value, magic_num, mod, + label, decoder, ext) +caddr_t value; +int magic_num; +modtyp *mod; +IFP decoder; +char *label; +struct type_MTA_ExtensionField *ext; +{ + caddr_t *genp; + int retval; + +#if PP_DEBUG > 0 + if (pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, magic_num, mod, + ext -> value, label, PDU_READ); +#endif + if (dec_f(magic_num, mod, ext -> value, 1, + NULLIP, NULLVP, &genp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't parse %s value [%s]", label, PY_pepy)); + return DONE; + } + + if ((retval = (*decoder) (value, genp)) != OK) + return retval; + + fre_obj((char *) genp, mod->md_dtab[magic_num], mod, 1); + return OK; +} + +static int decode_ext_char (cp, ptr) +char *cp; +struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */ +{ + *cp = ptr -> parm; + return OK; +} + +static int decode_ext_rdm (value, genp) +int value[AD_RDM_MAX]; +struct type_Ext_RequestedDeliveryMethod *genp; +{ + int i; + + for (i = 0; i < AD_RDM_MAX && genp; + i++, genp = genp -> next) + value[i] = genp -> element_Ext_0; + return OK; +} + +static int decode_ext_pdm (value, genp) +int *value; +PE genp; +{ +#define setbit(t,v) \ + (*value) |= (bit_ison(genp, (t)) ? (v) : 0) + + setbit (bit_Ext_PhysicalDeliveryModes_ordinary__mail, + AD_PM_ORD); + setbit (bit_Ext_PhysicalDeliveryModes_special__delivery, + AD_PM_SPEC); + setbit (bit_Ext_PhysicalDeliveryModes_express__mail, + AD_PM_EXPR); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection, + AD_PM_CNT); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telephone__advice, + AD_PM_CNT_PHONE); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telex__advice, + AD_PM_CNT_TLX); + setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__teletex__advice, + AD_PM_CNT_TTX); + setbit (bit_Ext_PhysicalDeliveryModes_bureau__fax__delivery, + AD_PM_CNT_BUREAU); +#undef setbit + return OK; +} + +static int decode_ext_int (ip, ptr) +int *ip; +struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */ +{ + *ip = ptr -> parm; + return OK; +} + +static int decode_ext_rnfa (value, genp) +char **value; +struct qbuf *genp; +{ + if ((*value = qb2str (genp)) == NULL) + return NOTOK; + return OK; +} + +static int decode_ext_pra (value, gen) +OID *value; +OID gen; +{ + if ((*value = oid_cpy (gen)) != NULLOID) + return OK; + return NOTOK; +} + + +static int decode_1redir (rpp, redir) +Redirection **rpp; +struct type_Ext_Redirection *redir; +{ + ADDR *ad; + int retval; + + *rpp = (Redirection *) smalloc (sizeof **rpp); + if ((retval = + load_addr (&ad, redir -> intended__recipient__name -> address)) + != OK) + return retval; + (*rpp) -> rd_addr = ad -> ad_value; + ad -> ad_value = NULLCP; + (*rpp) -> rd_dn = ad -> ad_dn; + ad -> ad_dn = NULLCP; + adr_free (ad); + + if ((retval = load_time (&(*rpp) -> rd_time, + redir -> intended__recipient__name -> redirection__time)) != OK) + return retval; + (*rpp) -> rd_reason = redir -> redirection__reason -> parm; + return OK; +} + +static int decode_ext_redir (value, genp) +Redirection **value; +struct type_Ext_RedirectionHistory *genp; +{ + int retval; + + while (genp) { + if ((retval = decode_1redir (value, genp->Redirection)) != OK) + return retval; + value = &(*value) -> rd_next; + genp = genp -> next; + } + return OK; +} + +static int ext_decode_dlh (dlp, dpp) +struct type_Ext_DLExpansion *dlp; +DLHistory **dpp; +{ + UTC ut; + ADDR *ad; + int retval; + + if ((retval = load_time (&ut, dlp -> dl__expansion__time)) != OK) + return retval; + if ((retval = load_addr (&ad, dlp -> address)) != OK) + return retval; + + *dpp = dlh_new (ad -> ad_value, ad -> ad_dn , ut); + adr_free (ad); + + free ((char *)ut); + return OK; +} + +static int ext_decode_dlexph (dpp, genp) +DLHistory **dpp; +struct type_Ext_DLExpansionHistory *genp; +{ + struct type_Ext_DLExpansionHistory *dlhp; + DLHistory *dp; + int retval; + + for (dlhp = genp; dlhp; dlhp = dlhp -> next) { + if ((retval = ext_decode_dlh (dlhp -> DLExpansion, &dp)) != OK) + return retval; + dlh_add (dpp, dp); + } + return OK; +} + + +static int load_time (utc, utcstr) +UTC *utc; +struct type_UNIV_UTCTime *utcstr; +{ + char *str = qb2str (utcstr); + if (str == NULLCP) + return NOTOK; + *utc = str2utct (str, strlen(str)); + if (*utc == NULLUTC) + return NOTOK; + free (str); + *utc = utcdup (*utc); + return *utc ? OK : NOTOK; +} + +static int load_addr (app, orname) +ADDR **app; +struct type_MTA_ORName *orname; +{ + ORName *orn; + char buf[BUFSIZ]; + ADDR *ap; + + if ((orn = orname2orn (orname)) == NULL) + return NOTOK; + + or_or2std (orn -> on_or, buf, 0); + *app = ap = adr_new (buf, AD_X400_TYPE, 1); + ap -> ad_subtype = AD_X400_88; + + if (orn -> on_dn) + ap -> ad_dn = dn2str (orn -> on_dn); + ORName_free (orn); + return OK; +} diff --git a/Format/rfc1148/RFCtoP2.c b/Format/rfc1148/RFCtoP2.c new file mode 100644 index 0000000..fb99105 --- /dev/null +++ b/Format/rfc1148/RFCtoP2.c @@ -0,0 +1,1311 @@ +/* RFCtoP2.c : 1138 encoding 822 -> P2 for headers */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: RFCtoP2.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "IOB-types.h" +#include "rfc-hdr.h" +#include "ap.h" +#include "or.h" +#include "oids.h" +#include "charset.h" +#include "chan.h" + +static FILE *fp_P2_out; +static FILE *fp_rfc_in; +static FILE *fp_P2_ext; +static char P2_ext [MAXPATHLENGTH]; +static CHAR8U *asctot61(); +static struct type_IOB_Heading *head; +static char first_hdr = TRUE; +static int comments_started = FALSE; + +extern time_t time(); +extern struct type_IOB_ORName *orn2orname(); + +RFCtoP2 (rfc_in, P2_out, P2_ext_out, ep, x40084) +char *rfc_in; +char *P2_out; +char *P2_ext_out; +char **ep; +int x40084; +{ + PE pe; + PS ps; + int retval; + char buf[BUFSIZ]; + + first_hdr = TRUE; + comments_started = FALSE; + if (P2_ext_out) + strcpy (P2_ext, P2_ext_out); + else + P2_ext[0] = '\0'; + + head = (struct type_IOB_Heading *) + calloc (1, sizeof (struct type_IOB_Heading)); + + if ( head == (struct type_IOB_Heading *) NOTOK) + + { + PP_LOG (LLOG_EXCEPTIONS, ("RFCtoP2 - malloc failed")); + return NOTOK; + } /* allocate h, so that we can free */ + /* cleanly at the end of all this */ + + if (P2_out == NULLCP) + fp_P2_out = stdout; + + else if ((fp_P2_out = fopen (P2_out, "w")) == NULL ) + { + PP_SLOG (LLOG_EXCEPTIONS, P2_out, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open output file '%s'", + P2_out); + *ep = strdup(buf); + return NOTOK; + } + + if (rfc_in == NULLCP) + fp_rfc_in = stdin; + else if ((fp_rfc_in = fopen (rfc_in, "r")) == NULL ) + { + PP_SLOG (LLOG_EXCEPTIONS, rfc_in, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open input file '%s'", + rfc_in); + *ep = strdup(buf); + fclose (fp_P2_out); + return NOTOK; + } + + + + if (((ps = ps_alloc (std_open)) == NULLPS) || + (std_setup (ps, fp_P2_out) == NOTOK)) + { + PP_LOG (LLOG_EXCEPTIONS, ("RFC822toP2() failed to setup PS")); + *ep = strdup("Failed to setup PS"); + retval = NOTOK; + goto cleanup; + } + + + /* set defaults */ + + head -> importance = (struct type_IOB_ImportanceField *) calloc (1, sizeof(struct type_IOB_ImportanceField)); + head -> importance -> parm = int_IOB_ImportanceField_normal; + + if (build_hdr (x40084, ep) == NOTOK) + { + PP_LOG (LLOG_EXCEPTIONS, ("build_hdr blew it")); + retval = NOTOK; + goto cleanup; + } + + PY_pepy[0] = 0; + + if (encode_IOB_Heading (&pe, 0, 0, NULLCP, head) != OK) + { + PP_OPER (NULLCP, + ("RFCtoP2() failed to encode header [%s]", PY_pepy)); + (void) sprintf (buf, + "Unable to encode p2 hdr ['%s']", + PY_pepy); + *ep = strdup(buf); + retval = NOTOK; + goto cleanup; + } + + if (PY_pepy[0] != 0) + PP_LOG(LLOG_EXCEPTIONS, + ("encode_IOB_Heading non-fatal failure [%s]",PY_pepy)); + + if (pe2ps (ps, pe) == NOTOK) + { + PP_LOG (LLOG_EXCEPTIONS, ("RFCtoP2 failed to write heading")); + *ep = strdup("Failed to write header"); + pe_free (pe); + retval = NOTOK; + goto cleanup; + } + + retval = OK; + +cleanup: + ps_free (ps); + fclose (fp_P2_out); + fclose (fp_rfc_in); + if (fp_P2_ext != NULL) + fclose (fp_P2_ext); + free_IOB_Heading (head); + return retval; +} + +/* */ + +build_hdr(x40084, ep) +int x40084; +char **ep; +{ + char *field, *key; + struct type_IOB_RecipientSequence *from = NULL; + struct type_IOB_RecipientSequence *temp; + struct type_IOB_ORDescriptorSequence *ix, *tail = (struct type_IOB_ORDescriptorSequence *) 0; + struct type_IOB_RFC822FieldList *hdr_extns = NULL; + char buf[BUFSIZ]; + + while (TRUE) { + switch (get_hdr (&key, &field)) { + case HDR_EOH: + PP_DBG (("HDR_EOH")); + break; + + case HDR_ERROR: + PP_LOG (LLOG_EXCEPTIONS, + ("Error reading header")); + *ep = strdup("Error reading header"); + return NOTOK; + + case HDR_ILLEGAL: + PP_LOG (LLOG_EXCEPTIONS, + ("Erroneous header '%s' '%s'", key, field)); + (void) sprintf (buf, + "Erroneous header '%s' '%s'", + key, field); + *ep = strdup(buf); + return NOTOK; + + case HDR_IGNORE: + PP_DBG (("Ignoring header'%s'", key)); + continue; + + case HDR_COMMENT: + if (hdr_comment (key, field, ep, x40084) != OK) + return NOTOK; + continue; + + case HDR_MID: + if (hdr_mid (field, &(head -> this__IPM)) != OK) + PP_DBG (("Bad message id '%s'", field)); + continue; + + case HDR_FROM: + if (hdr_recip_set (field, &from, x40084) != OK) + PP_DBG (("Bad From '%s'", field)); + continue; + + case HDR_SENDER: + if (hdr_ordesc (field, &head -> originator, x40084) != OK) + PP_DBG (("Bad Sender '%s'", field)); + continue; + + case HDR_REPLY_BY: + if (hdr_reply_by (field, &(head -> reply__time)) != OK) + PP_DBG (("Bad reply date '%s'", field)); + continue; + + case HDR_REPLY_TO: + if (hdr_ordesc_seq (field, + &(head -> reply__recipients), + x40084) != OK) + PP_DBG (("Bad replied to '%s'", field)); + continue; + + case HDR_IMPORTANCE: + if (hdr_importance (field, + &(head->importance->parm)) != OK) + PP_DBG (("Bad importance '%s'", field)); + continue; + + case HDR_SENSITIVITY: + if (hdr_sensitivity (field, + &(head->sensitivity)) != OK) + PP_DBG (("Bad sensitivity '%s'", field)); + continue; + + case HDR_AUTOFORWARDED: + if (hdr_autoforwarded (field, + &(head->auto__forwarded)) != OK) + PP_DBG(("Bad autoforwarded '%s'", field)); + continue; + + case HDR_TO: + if (hdr_recip_set (field, + &(head -> primary__recipients), + x40084) != OK) + PP_DBG (("Bad to '%s'", field)); + continue; + + case HDR_CC: + if (hdr_recip_set (field, + &(head -> copy__recipients), + x40084) != OK) + PP_DBG (("Bad cc '%s'", field)); + continue; + + case HDR_BCC: + if (hdr_recip_set (field, + &(head -> blind__copy__recipients), + x40084) != OK) + PP_DBG (("Bad bcc '%s'", field)); + continue; + + case HDR_IN_REPLY_TO: + if (hdr_reply_to (field, + &(head -> replied__to__IPM), + &(head -> related__IPMs)) != OK) + PP_DBG (("Bad in reply to '%s'", field)); + continue; + + case HDR_OBSOLETES: + if (hdr_mid_seq (field, &(head -> obsoleted__IPMs)) != OK) + PP_DBG (("Bad obsoletes '%s'", field)); + continue; + + case HDR_REFERENCES: + if (hdr_mid_seq (field, &(head -> related__IPMs)) != OK) + PP_DBG (("Bad references '%s'", field)); + continue; + + case HDR_EXTENSIONS: + if (x40084 == TRUE) { + if (hdr_comment (key, field, ep, x40084) != OK) + return NOTOK; + } else if (hdr_extension (key, field, + &(hdr_extns)) != OK) + PP_DBG (("Bad extension '%s'", field)); + continue; + + case HDR_INCOMPLETE_COPY: + if (x40084 == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert to p2 (84) '%s %s'", + key, field)); + (void) sprintf (buf, + "Unable to convert to p2 (84) '%s %s'", + key, field); + *ep = strdup(buf); + return NOTOK; + } + if (hdr_incomplete_copy (&(head -> extensions)) != OK) + PP_DBG (("Bad incomplete_copy '%s'", field)); + continue; + + case HDR_LANGUAGE: + if (x40084 == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to convert to p2 (84) '%s %s'", + key, field)); + (void) sprintf (buf, + "Unable to convert to p2 (84) '%s %s'", + key, field); + *ep = strdup(buf); + return NOTOK; + } + if (hdr_language (field, &(head -> extensions)) != OK) + PP_DBG (("Bad language '%s'", field)); + continue; + + case HDR_SUBJECT: + if (hdr_subject (field, &(head -> subject)) != OK) + PP_DBG (("Bad subject '%s'", field)); + continue; + + case HDR_EXPIRY_DATE: + if (hdr_expiry_date (field, &(head-> expiry__time)) != OK) + PP_DBG(("Bad expiry date '%s'", field)); + continue; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unexpected Header Type")); + *ep = strdup("Unexpected Header Type"); + return NOTOK; + } + break; + } + + if (hdr_extns != (struct type_IOB_RFC822FieldList *) NULL) { + /* header extensions */ + struct type_IOB_ExtensionsField *temp = (struct type_IOB_ExtensionsField *) + calloc (1, sizeof (struct type_IOB_ExtensionsField)); + temp -> HeadingExtension = (struct type_IOB_HeadingExtension *) + calloc (1, sizeof (struct type_IOB_HeadingExtension)); + temp -> HeadingExtension -> type = oid_cpy(str2oid(id_rfc_822_field_list)); + PY_pepy[0] = 0; + if (encode_IOB_RFC822FieldList(&(temp -> HeadingExtension -> value), + 0, 0, NULLCP, hdr_extns)) { + PP_OPER (NULLCP, + ("failed to encode rfc822 FieldList extension [%s]", + PY_pepy)); + oid_free ((char *) temp -> HeadingExtension -> type); + free ((char *) temp -> HeadingExtension); + free ((char *) temp); + return NOTOK; + } else + free_IOB_RFC822FieldList(hdr_extns); + temp -> next = head->extensions; + head->extensions = temp; + } + + + if (head -> originator == (struct type_IOB_ORDescriptor *) 0) { + if (from != (struct type_IOB_RecipientSequence *) 0) { + head -> originator = from -> RecipientSpecifier -> recipient; + free ((char *) from -> RecipientSpecifier); + temp = from; + from = from -> next; + free ((char *) temp); + } + } + + /* convert RecipientSequence to ORDescriptorSequence */ + while (from != (struct type_IOB_RecipientSequence *) 0) { + ix = (struct type_IOB_ORDescriptorSequence *) calloc (1, + sizeof(struct type_IOB_ORDescriptorSequence)); + ix -> ORDescriptor = from -> RecipientSpecifier -> recipient; + free((char *) from -> RecipientSpecifier); + temp=from; + from=from->next; + free((char *) temp); + if (head -> authorizing__users == (struct type_IOB_ORDescriptorSequence *) 0) + head -> authorizing__users = tail = ix; + else { + tail -> next = ix; + tail = ix; + } + } + if (head -> this__IPM == NULL) + gen_mid (&(head -> this__IPM)); + + return OK; +} + +/* */ + +hdr_comment (key, field, ep, x40084) +char *key, + *field, + **ep; +int x40084; +{ + char buf[BUFSIZ]; + PP_DBG (("hdr_comments '%s'", field)); + if (P2_ext == NULLCP || P2_ext[0] == '\0') + return OK; + + if (!comments_started) { + comments_started = TRUE; + if ((fp_P2_ext = fopen (P2_ext, "w")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, P2_ext, + ("Can't open file")); + (void) sprintf (buf, + "Failed to open extension file '%s'", + P2_ext); + *ep = strdup(buf); + return NOTOK; + } + if (TRUE == x40084) + fputs("RFC-822-HEADERS:\n", fp_P2_ext); + else + fputs("Comments:\n", fp_P2_ext); + } + field_tidy(key); + fputs (key, fp_P2_ext); + fputs (": ", fp_P2_ext); + field_tidy(field); + fputs (field, fp_P2_ext); + fputs ("\n", fp_P2_ext); + return OK; +} + +hdr_mid_seq (field, seq_ptr) +char *field; +struct type_IOB_IPMIdentifierSequence **seq_ptr; +{ + char *p, *q; + struct type_IOB_IPMIdentifierSequence *temp, *ix; + + field_tidy (field); + p = q = field; + while (q != NULLCP) + { + if ((q = index (p, ',')) != NULLCP) + *q++ = '\0'; + temp = (struct type_IOB_IPMIdentifierSequence *) + calloc (1, sizeof (struct type_IOB_IPMIdentifierSequence)); + if (hdr_mid (p, &(temp -> IPMIdentifier)) != OK) { + free ((char *) temp); + return NOTOK; + } + p = q; + if (*seq_ptr == NULL) + *seq_ptr = temp; + else { + ix = *seq_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + } + return OK; +} + +hdr_mid (field, mid_ptr) +char *field; +struct type_IOB_IPMIdentifier **mid_ptr; +{ + /* see rfc 1138 4.7.3.3 */ + char *midstring, *cp; + char ps[BUFSIZ]; + ORName orn; + AP_ptr ap, local, domain; + + if ((midstring = index (field, '<')) == NULLCP + || (cp = rindex (field, '>')) == NULLCP) + return NOTOK; + *cp = '\0'; + midstring++; + + if (ap_s2p (midstring, &ap, (AP_ptr *) 0, (AP_ptr *) 0, &local, + &domain, (AP_ptr *) 0) == (char *) NOTOK) + { + PP_LOG (LLOG_EXCEPTIONS, + ( "Illegal Message ID '%s'", midstring)); + *mid_ptr = NULL; + return NOTOK; + } + + *mid_ptr = (struct type_IOB_IPMIdentifier *) + calloc (1, sizeof (struct type_IOB_IPMIdentifier)); + + if (domain != NULLAP && local != NULLAP + && lexequ (domain -> ap_obvalue, "MHS") == 0 + && (cp = index (local -> ap_obvalue, '*')) != NULLCP) { + /* x.400 generated */ + + if (cp != local -> ap_obvalue) { + *cp++ = '\0'; + (*mid_ptr)-> user__relative__identifier = + str2qb (local -> ap_obvalue, + strlen (local -> ap_obvalue), + 1); + } + if (*cp == '\0') + return OK; + + orn.on_or = or_std2or(cp); + orn.on_dn = NULL; + + ap_1delete(ap); + ap_free(ap); + + if (orn.on_or != NULLOR) { + (*mid_ptr) -> user = orn2orname(&orn); + or_free(orn.on_or); + } + + return OK; + } else { + or_asc2ps(midstring, ps); + (*mid_ptr) -> user__relative__identifier = str2qb (ps, + strlen(ps), + 1); + return OK; + } +} + +get_comments (buf, addr) +char *buf; +AP_ptr addr; +{ + AP_ptr ap; + + buf [0] = '\0'; + ap = addr; + while (TRUE) + { + if (ap -> ap_obtype == AP_COMMENT) + { + strcat (buf, " ("); + strcat (buf, ap -> ap_obvalue); + strcat (buf, ")"); + } + if (ap -> ap_next == NULLAP + || ap -> ap_next -> ap_ptrtype == AP_PTR_NXT) + break; + ap = ap -> ap_next; + } + PP_DBG (("Comment '%s'", buf)); + return OK; +} +PE or2pe(); + +#ifdef notdef + +static int ORstring2pe (orstring, pe) +char *orstring; +PE *pe; +{ + OR_ptr or; + *pe = NULLPE; + + if (or_rfc2or (orstring, &or) == NOTOK) + { + PP_DBG (("Failed to parse '%s'", orstring)); + return NOTOK; + } + + or = or_default (or); + + if ((*pe = or2pe (or)) == NULLPE) + { + PP_DBG (("Failed to decode OR_Ptr '%s'", orstring)); + return NOTOK; + } + or_free (or); + return OK; +} +#endif + +get_ordesc (cpp, or_desc_ptr, group_ptr, x40084) +char **cpp; +struct type_IOB_ORDescriptor **or_desc_ptr, **group_ptr; +int x40084; +{ + /* see rfc 1138 4.7.1 */ + AP_ptr ap, group, name, local, domain, route, ix; + char comment[BUFSIZ], freeform[BUFSIZ], buf[BUFSIZ]; + char *addr; + ORName orn; + + if (*cpp == NULLCP || **cpp == '\0') + return OK; + + PP_DBG (("get_ordesc ('%s')", *cpp)); + + if ((*cpp = ap_s2p (*cpp, &ap, + &group, &name, &local, + &domain, &route)) == (char *) NOTOK + || *cpp == (char *) DONE) + return NOTOK; + + *or_desc_ptr = (struct type_IOB_ORDescriptor *) + calloc (1, sizeof (struct type_IOB_ORDescriptor)); + + addr = ap_p2s_nc (NULLAP, NULLAP, local, domain, route); + + if (addr == NULLCP || *addr == '\0') { + orn.on_or = NULLOR; + orn.on_dn = NULL; + } else { + if (or_rfc2or(addr, &(orn.on_or)) == NOTOK) { + PP_DBG (("Failed to encode '%s'", addr)); + free (addr); + return NOTOK; + } else + /* maybe try to regain from comments ? */ + orn.on_dn = NULL; + + if (x40084 == TRUE) + or_downgrade(&(orn.on_or)); + } + + if (addr) + free(addr); + + if (orn.on_or != NULLOR) { + (*or_desc_ptr) -> formal__name = (struct type_IOB_ORName *) + calloc (1, sizeof (struct type_IOB_ORName)); + (*or_desc_ptr) -> formal__name = orn2orname(&orn); + or_free (orn.on_or); + } + + get_comments (comment, ap); + + freeform [0] = '\0'; + if (name != NULLAP) { + ix = name; + while (ix != NULLAP && + (ix -> ap_obtype == AP_COMMENT || + ix -> ap_obtype == AP_PERSON_END || + ix -> ap_obtype == AP_PERSON_NAME || + ix -> ap_obtype == AP_PERSON_START)) { + if (ix -> ap_obtype != AP_COMMENT && + ix -> ap_obvalue != NULLCP) { + if (freeform[0] != '\0') + strcat (freeform, " "); + strcat (freeform, ix -> ap_obvalue); + } + ix = ix -> ap_next; + } + } + + strcat (freeform, comment); + + if (freeform[0] != '\0') { + /* do ascii -> t.61 */ + CHAR8U *t61str; + int len; + + strcpy (buf, freeform); + + if ((t61str = asctot61 ((CHAR8U *) buf, &len)) + != (CHAR8U *) NULL) { + (*or_desc_ptr) -> free__form__name = + str2qb (t61str, strlen((char *) t61str), 1); + free(t61str); + } else + (*or_desc_ptr) -> free__form__name = + str2qb (buf, strlen(buf), 1); + } + + if (group != NULLAP) { + freeform[0] = '\0'; + ix = group; + while (ix != NULLAP && + (ix -> ap_obtype == AP_COMMENT || + ix -> ap_obtype == AP_GROUP_END || + ix -> ap_obtype == AP_GROUP_NAME || + ix -> ap_obtype == AP_GROUP_START)) { + if (ix -> ap_obtype != AP_COMMENT + && ix -> ap_obvalue != NULLCP) { + if (freeform[0] != '\0') + strcat (freeform, " "); + strcat (freeform, ix -> ap_obvalue); + } + ix = ix -> ap_next; + } + if (freeform[0] != '\0') { + CHAR8U *t61str; + int len; + + *group_ptr = (struct type_IOB_ORDescriptor *) + calloc (1, sizeof (struct type_IOB_ORDescriptor)); + /* do ascii -> t.61 conversion */ + strcpy (buf, freeform); + if ((t61str = asctot61 ((CHAR8U *) buf, &len)) + != (CHAR8U *) NULL) { + (*group_ptr) -> free__form__name = + str2qb (t61str, strlen((char *)t61str), 1); + free(t61str); + } else + (*group_ptr) -> free__form__name = + str2qb (buf, strlen(buf), 1); + } + } else + *group_ptr = NULL; + ap_1delete(ap); + ap_free (ap); + return OK; +} + +hdr_ordesc (field, or_desc_ptr, x40084) +char *field; +struct type_IOB_ORDescriptor **or_desc_ptr; +int x40084; +{ + struct type_IOB_ORDescriptor *gptr; + char *cp; + + field_tidy (field); + cp = field; + if (cp == NULLCP || *cp == '\0') + return OK; + + if (get_ordesc (&cp, or_desc_ptr, &gptr, x40084) != OK) { + PP_DBG(("Bad single OR desc '%s'", field)); + return NOTOK; + } + return OK; +} + +hdr_ordesc_seq (field, or_desc_ptr, x40084) +char *field; +struct type_IOB_ORDescriptorSequence **or_desc_ptr; +int x40084; +{ + char *cp; + struct type_IOB_ORDescriptorSequence *temp, *ix; + struct type_IOB_ORDescriptor *dptr, *gptr; + + field_tidy (field); + cp = field; + + if (cp == NULLCP || *cp == '\0') + return OK; + + while (get_ordesc (&cp, &dptr, &gptr, x40084) == OK) { + if (gptr != (struct type_IOB_ORDescriptor *) NULL) { + temp = (struct type_IOB_ORDescriptorSequence *) + calloc (1, sizeof (struct type_IOB_ORDescriptorSequence)); + temp -> ORDescriptor = gptr; + if (*or_desc_ptr == NULL) + *or_desc_ptr = temp; + else { + ix = *or_desc_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + } + temp = (struct type_IOB_ORDescriptorSequence *) + calloc (1, sizeof (struct type_IOB_ORDescriptorSequence)); + temp -> ORDescriptor = dptr; + if (*or_desc_ptr == NULL) + *or_desc_ptr = temp; + else { + ix = *or_desc_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + if (cp == NULLCP || *cp == '\0') + return OK; + } + PP_DBG (("Bad address field '%s'", field)); + return NOTOK; +} + +hdr_recip_set (field, or_recip_ptr, x40084) +char *field; +struct type_IOB_RecipientSequence **or_recip_ptr; +int x40084; +{ + /* see rfc 1138 4.7.1 */ + struct type_IOB_RecipientSequence *temp, *ix; + char *cp; + struct type_IOB_ORDescriptor *dptr, *gptr; + + field_tidy (field); + cp = field; + + if (cp == NULLCP || *cp == '\0') + return OK; + + while (get_ordesc (&cp, &dptr, &gptr, x40084) == OK) { + if (gptr != (struct type_IOB_ORDescriptor *) NULL) { + temp = (struct type_IOB_RecipientSequence *) + calloc (1, sizeof (struct type_IOB_RecipientSequence)); + temp -> RecipientSpecifier = (struct type_IOB_RecipientSpecifier *) + calloc (1, sizeof(struct type_IOB_RecipientSpecifier)); + temp -> RecipientSpecifier -> recipient = gptr; + /* defaults for other fields == 0 */ + if (*or_recip_ptr == NULL) + *or_recip_ptr = temp; + else { + ix = *or_recip_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + } + if (dptr != (struct type_IOB_ORDescriptor *) NULL + && (dptr->formal__name != (struct type_IOB_ORName *) NULL + || dptr->free__form__name != (struct type_IOB_FreeFormName *) NULL)) { + temp = (struct type_IOB_RecipientSequence *) + calloc (1, sizeof (struct type_IOB_RecipientSequence)); + temp -> RecipientSpecifier = (struct type_IOB_RecipientSpecifier *) + calloc (1, sizeof(struct type_IOB_RecipientSpecifier)); + temp -> RecipientSpecifier -> recipient = dptr; + /* defaults for other fields == 0 */ + if (*or_recip_ptr == NULL) + *or_recip_ptr = temp; + else { + ix = *or_recip_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + } + if (cp == NULLCP || *cp == '\0') + return OK; + } + PP_DBG (("Bad Address field '%s'", field)); + return NOTOK; +} + +hdr_reply_to (field, replied_ptr, related_ptr) +char *field; +struct type_IOB_IPMIdentifier **replied_ptr; +struct type_IOB_IPMIdentifierSequence **related_ptr; +{ + char *start, *end, savech; + struct type_IOB_IPMIdentifierSequence *temp, *ix; + struct type_IOB_IPMIdentifier *msgid; + + if ((start = index(field, '<')) == NULLCP) + /* no message id can't do anything */ + return OK; + + while (*(start+1) != '\0' && *(start+1) == '<') start++; + + if ((end = index(start, '>')) == NULLCP) + /* incomplete msgid can't do anything */ + return OK; + end++; + savech = *end; + *end = '\0'; + if (hdr_mid (start, &msgid) != OK) + return NOTOK; + *end = savech; + + if (*end == '\0' + || (start = index(end, '<')) == NULLCP) + /* only one so put in replied_ptr */ + *replied_ptr = msgid; + else { + /* more than one put in related_ptr */ + temp = (struct type_IOB_IPMIdentifierSequence *) + calloc (1, sizeof(struct type_IOB_IPMIdentifierSequence)); + temp -> IPMIdentifier = msgid; + + if (*related_ptr == NULL) + *related_ptr = temp; + else { + ix = *related_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + + while (end != NULLCP && *end != '\0') { + + if ((start = index(end, '<')) == NULLCP) + /* no message id can't do anything */ + return OK; + while (*(start+1) != '\0' && *(start+1) == '<') start++; + if ((end = index(start, '>')) == NULLCP) + /* incomplete msgid can't do anything */ + return OK; + temp = (struct type_IOB_IPMIdentifierSequence *) + calloc (1, sizeof(struct type_IOB_IPMIdentifierSequence)); + end++; + savech = *end; + *end = '\0'; + if (hdr_mid (start, &(temp -> IPMIdentifier)) != OK) { + free(temp); + return OK; + } + *end = savech; + if (*related_ptr == NULL) + *related_ptr = temp; + else { + ix = *related_ptr; + while (ix -> next != NULL) ix = ix -> next; + ix -> next = temp; + } + + } + } + return OK; +} + +hdr_extension (key, field, extensionptr) +char *field, *key; +struct type_IOB_RFC822FieldList **extensionptr; +{ + char buf[BUFSIZ]; + struct type_IOB_RFC822FieldList *temp = (struct type_IOB_RFC822FieldList *) + calloc(1, sizeof(*temp)); + struct type_IOB_RFC822Field *hdr; + if (field[strlen(field)-1] == '\n') + field[strlen(field)-1] = '\0'; + (void) sprintf (buf, "%s: %s", key, field); + temp->RFC822Field = str2qb (buf, strlen(buf), 1); + temp->next = *extensionptr; + *extensionptr = temp; + return OK; +} + +hdr_incomplete_copy (extensionptr) +struct type_IOB_ExtensionsField **extensionptr; +{ + struct type_IOB_ExtensionsField *temp = (struct type_IOB_ExtensionsField *) + calloc (1, sizeof (struct type_IOB_ExtensionsField)); + temp -> HeadingExtension = (struct type_IOB_HeadingExtension *) + calloc (1, sizeof (struct type_IOB_HeadingExtension)); + + PY_pepy[0] = 0; + + if (encode_IOB_IncompleteCopy (&(temp -> HeadingExtension -> value), + 0, 0, NULLCP, + (struct type_IOB_IncompleteCopy *) NULL) != OK) + { + PP_OPER (NULLCP, + ("failed to encode incomplete copy value [%s]", + PY_pepy)); + free ((char *)temp -> HeadingExtension); + free ((char *)temp); + return NOTOK; + } + + temp -> HeadingExtension -> type = oid_cpy(str2oid(id_hex_incomplete_copy)); + + temp -> next = *extensionptr; + *extensionptr = temp; + return OK; +} + +hdr_language (field, extensionptr) +char *field; +struct type_IOB_ExtensionsField **extensionptr; +{ + struct type_IOB_Languages *lang = (struct type_IOB_Languages *) + calloc (1, sizeof (struct type_IOB_Languages)); + + struct type_IOB_ExtensionsField *temp = (struct type_IOB_ExtensionsField *) + calloc (1, sizeof (struct type_IOB_ExtensionsField)); + + temp -> HeadingExtension = (struct type_IOB_HeadingExtension *) + calloc (1, sizeof (struct type_IOB_HeadingExtension)); + + while (isspace (*field)) field++; + + lang -> Language = str2qb(field, strlen(field), 1); + + PY_pepy[0] = 0; + + if (encode_IOB_Languages (&(temp -> HeadingExtension -> value), + 0, + 0, + NULLCP, + lang) != OK) + { + PP_OPER (NULLCP, + ("failed to encode language heading extension [%s]", + PY_pepy)); + free ((char *)lang); + free ((char *) temp -> HeadingExtension); + free ((char *) temp); + return NOTOK; + } + + temp -> HeadingExtension -> type = oid_cpy(str2oid(id_hex_languages)); + + temp -> next = *extensionptr; + *extensionptr = temp; + + return OK; +} + +static CHARSET *ia5 = (CHARSET *) NULL; +static CHARSET *t61 = (CHARSET *) NULL; + +/* needed for odd behaviour of keld's code */ +#define FUDGE 10 + +static CHAR8U *asctot61 (ia5str, plen) +CHAR8U *ia5str; +int *plen; +{ + CHAR8U *t61str; + + if (ia5 == (CHARSET *) NULL) + ia5 = getchset("CCITT_T.50.irv:1988", (INT16S) 29); + if (t61 == (CHARSET *) NULL) + t61 = getchset("T.61-8bit", (INT16S) 29); + + if (ia5 != (CHARSET *) NULL + && t61 != (CHARSET *) NULL) { + t61str = (CHAR8U *) malloc(sizeof(CHAR8U) * (strlen((char *)ia5str)+1)); + if ((*plen = strncnv (t61, ia5, + t61str, ia5str, + strlen((char *) ia5str), FALSE) >= 0)) + return t61str; + } + return (CHAR8U *) NULL; +} + +hdr_subject (field, subject_ptr) +char *field; +struct type_IOB_SubjectField **subject_ptr; +{ + CHAR8U *t61str; + int len; + while (isspace (*field)) field++; + + if (*field == '\0') { + *subject_ptr = NULL; + return OK; + } + if (*(field+strlen(field)-1) == '\n') + *(field+strlen(field)-1) = '\0'; + + if ((t61str = asctot61((CHAR8U *) field, &len)) != (CHAR8U *) NULL) { + *subject_ptr = str2qb(t61str, strlen((char *)t61str), 1); + free(t61str); + } else + *subject_ptr = str2qb (field, strlen(field), 1); + return OK; +} + +hdr_expiry_date(field, expiry) +char *field; +struct qbuf **expiry; +{ + UTC ut; + char *str; + if (rfc2UTC (field, &ut) != OK) + return NOTOK; + str = utct2str(ut); + *expiry = str2qb(str, strlen(str), 1); + return OK; +} + + +hdr_reply_by(field, reply) +char *field; +struct qbuf **reply; +{ + UTC ut; + char *str; + if (rfc2UTC (field, &ut) != OK) + return NOTOK; + str = utct2str(ut); + *reply = str2qb(str, strlen(str), 1); + return OK; +} + + +/* */ + +static char *hdrbuf; +static int hdrbuflen; +static char linebuf [LINESIZE]; + +static CMD_TABLE hdr_list[] = { +"autoforwarded", HDR_AUTOFORWARDED, +"bcc", HDR_BCC, +"cc", HDR_CC, +"comments", HDR_COMMENT, +"content-identifier", HDR_IGNORE, +"conversion", HDR_IGNORE, +"conversion-with-loss", HDR_IGNORE, +"date", HDR_IGNORE, +"deferred-delivery", HDR_IGNORE, +"discarded-x400-ipms-extensions", HDR_IGNORE, +"discarded-x400-mts-extensions", HDR_IGNORE, +"dl-expansion-history", HDR_IGNORE, +"expiry-date", HDR_EXPIRY_DATE, +"from", HDR_FROM, +"generate-delivery-report", HDR_IGNORE, +"importance", HDR_IMPORTANCE, +"in-reply-to", HDR_IN_REPLY_TO, +"incomplete-copy", HDR_INCOMPLETE_COPY, +"language", HDR_LANGUAGE, +"latest-delivery-time", HDR_IGNORE, +"message-id", HDR_MID, +"message-type", HDR_IGNORE, +"obsoletes", HDR_OBSOLETES, +"original-encoded-information-types", HDR_IGNORE, +"prevent-nondelivery-report", HDR_IGNORE, +"priority", HDR_IGNORE, +"received", HDR_IGNORE, +"references", HDR_REFERENCES, +"reply-by", HDR_REPLY_BY, +"reply-to", HDR_REPLY_TO, +"sender", HDR_SENDER, +"sensitivity", HDR_SENSITIVITY, +"subject", HDR_SUBJECT, +"to", HDR_TO, +"via", HDR_IGNORE, +"x400-content-type", HDR_IGNORE, +"x400-mts-identifier", HDR_IGNORE, +"x400-originator", HDR_IGNORE, +"x400-received", HDR_IGNORE, +(char *) 0, HDR_EXTENSIONS}; + +#define N_HDRS ((sizeof(hdr_list)/sizeof(CMD_TABLE)) - 1) + +get_hdr (key, field) +char **key; +char **field; +{ + char *cp; + int hval; + +PP_DBG (("get_hdr()")); + + if (first_hdr) + { + first_hdr = FALSE; + if (fgets (linebuf, LINESIZE - 1, fp_rfc_in) == NULL) + return HDR_ERROR; + hdrbuflen = LINESIZE; + hdrbuf = malloc (LINESIZE); + if (hdrbuf == NULL) + return HDR_ERROR; + } + + if (linebuf [0] == '\0') + return HDR_EOH; + + hdrbuf [0] = '\0'; + strcat (hdrbuf, linebuf); + linebuf [0] = '\0'; + + while (!feof (fp_rfc_in)) + { + if ((fgets (linebuf, LINESIZE -1, fp_rfc_in) == NULL) + && !feof (fp_rfc_in)) + return HDR_ERROR; + if (!isspace (linebuf[0])) + break; + /* continuation */ + if ((int)strlen (linebuf) <= 1) + { + PP_DBG (("Header terminated before EOF")); + linebuf [0] = '\0'; + break; + } + + if (hdrbuflen < (int)strlen (hdrbuf) + (int)strlen (linebuf)) + { + hdrbuflen = hdrbuflen * 2; + /* linebuf must be shorter */ + hdrbuf = realloc (hdrbuf, (unsigned int) hdrbuflen); + if (hdrbuf == NULL) + { + PP_LOG (LLOG_EXCEPTIONS, ("Malloc failed")); + return NOTOK; + } + } + strcat (hdrbuf, linebuf); + } + + if (feof (fp_rfc_in)) + /* set end of file condition ready for next call */ + linebuf[0] = '\0'; + + if ((cp = index (hdrbuf, ':')) == NULLCP) + { + PP_DBG (("Header without key '%s'", hdrbuf)); + *key = hdrbuf; + *field = hdrbuf; + return HDR_ERROR; + } + + *cp++ = '\0'; + *key = hdrbuf; + *field = cp; + field_tidy (*key); + + + hval = cmdbsrch(*key, hdr_list, N_HDRS); + PP_DBG (("Header: '%d' '%s' '%s'", hval, + *key, *field)); + return hval; +} + +field_tidy (field) +char *field; +{ /* strip newlines, leading/trailing space */ + register char *p, *q; + + p = field; + q = field; + + + while (isspace(*p)) + p++; + + while (*p != '\0') + if (*p != '\n') + *q++ = *p++; + else + p++; + *q-- = '\0'; + + while (isspace(*q)) + *q-- = '\0'; +} + +extern char *loc_dom_site; + +gen_mid (mid_ptr) /* generate random mailid */ +struct type_IOB_IPMIdentifier **mid_ptr; +{ + char buf [LINESIZE]; + long now; + (void) time (&now); + sprintf (buf, "<\"%ld %s", getpid(), ctime (&now)); + buf [strlen(buf) - 1] = '\0'; + strcat (buf, "\"@"); + strcat (buf, loc_dom_site); + strcat (buf, ">"); + return (hdr_mid (buf, mid_ptr)); +} + +hdr_importance (field, pparm) +char *field; +int *pparm; +{ + compress(field, field); + + if (lexequ(field, "low") == 0) + *pparm = int_IOB_ImportanceField_low; + else if (lexequ(field, "normal") == 0) + *pparm = int_IOB_ImportanceField_normal; + else if (lexequ (field, "high") == 0) + *pparm = int_IOB_ImportanceField_high; + else + return NOTOK; + return OK; +} + +hdr_sensitivity (field, psensitivity) +char *field; +struct type_IOB_SensitivityField **psensitivity; +{ + int parm; + + compress(field, field); + + if (lexequ(field, "personal") == 0) + parm = int_IOB_SensitivityField_personal; + else if (lexequ(field, "private") == 0) + parm = int_IOB_SensitivityField_private; + else if (lexequ(field, "company-confidential") == 0) + parm = int_IOB_SensitivityField_company__confidential; + else + return NOTOK; + + *psensitivity = (struct type_IOB_SensitivityField *) + calloc (1, sizeof(struct type_IOB_SensitivityField)); + (*psensitivity)->parm = parm; + return OK; +} + +hdr_autoforwarded (field, pauto) +char *field; +struct type_IOB_AutoForwardedField **pauto; +{ + int parm; + + compress(field, field); + + if (lexequ(field, "true") == 0) + parm = 1; + else if (lexequ(field, "false") == 0) + parm =0; + else + return NOTOK; + + *pauto = (struct type_IOB_AutoForwardedField *) + calloc(1, sizeof(struct type_IOB_AutoForwardedField)); + (*pauto)->parm = parm; + + return OK; +} diff --git a/Format/rfc1148/c-P2toRFC.c b/Format/rfc1148/c-P2toRFC.c new file mode 100644 index 0000000..02617a3 --- /dev/null +++ b/Format/rfc1148/c-P2toRFC.c @@ -0,0 +1,704 @@ +/* c-P2toRfc.c: rfc987(P2toRFC) filter channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: c-P2toRFC.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "chan.h" +#include "ap.h" +#include "dr.h" +#include +#include +#include "sys.file.h" +#include +#include "tb_bpt88.h" + +extern char *quedfldir; +extern char *chndfldir; +extern char *cont_p2, *hdr_p2_bp, *hdr_p22_bp, *hdr_822_bp, *hdr_ipn_bp; +extern void rd_end(), sys_init(), or_myinit(), err_abrt(), dsap_init(); +extern int convertresult; +extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */]; + +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static int filterMsg(); +static int doFilter(); +static int link_rest(); +static int security_check (); +static void dirinit (); +static ADDR *getnthrecip (); +int err_fatal; +int order_pref; +extern int ap_outtype; +extern char *local_dit; + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + or_myinit(); + quipu_syntaxes(); + dsap_init((char ***) NULL, (int *) NULL); + local_dit = NULLCP; /* hack to get full DNs */ + + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process,NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process,NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static void do_ch_info_flags(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + if ((margc = sstr2arg(info_copy, 20, margv, " \t")) > 0) { + for (ix = 0; ix < margc; ix++) { + if (lexequ (margv[ix], "uk") == 0) { + order_pref = CH_UK_PREF; + ap_outtype |= AP_PARSE_BIG; + } else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown ch_info flag '%s'", + margv[ix])); + } + } + free(info_copy); +} + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name = NULL; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/rfc987 : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + order_pref = CH_USA_PREF; + ap_outtype = AP_PARSE_SAME; + if (mychan->ch_out_info != NULLCP) + do_ch_info_flags(mychan->ch_out_info); + + + /* check if a rfc987 channel */ + if (name != NULL) free(name); + + ap_use_percent(); + ap_norm_all_domains(); + + return OK; +} + +/* */ +/* routine to check if allowed to rfc987 filter this message */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 channel err: '%s'",msg_chan)); + result = FALSE; + } + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to do rfc987 filter */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount, first_failureDR, retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *error = NULLCP; + + bzero((char *) &que,sizeof(que)); + first_failureDR = TRUE; + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_NOTICE, + ("Chans/rfc987 filtering msg '%s' through '%s'",this_msg, this_chan)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 : failed to find recipient %d of msg '%s'",ix->RecipientId->parm, this_msg)); + + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch (chan_acheck(adr, mychan, 1, (char **)NULL)) { + case OK: + if (filterMsg(this_msg,adr,&que, &error) == NOTOK) { + if (convertresult == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc1138 : completely failed to filter msg '%s' for recip '%d' on channel '%s'. Sending a DR", + this_msg, adr->ad_no, this_chan)); + set_1dr(&que, adr->ad_no, this_msg, + DRR_CONVERSION_NOT_PERFORMED, + DRD_CONTENT_SYNTAX_ERROR, + (error == NULLCP) ? "Unable to parse the p2 header" : error); + delivery_set(adr->ad_no, + (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 : failed to filter msg '%s' for recip '%d' on channel '%s'",this_msg, adr->ad_no, this_chan)); + delivery_setstate(adr->ad_no, + int_Qmgr_status_messageFailure, + (error == NULLCP) ? "Problems doing 1138 conversion" : error); + } + } else { + /* CHANGE update adr->ad_rcnt in struct and in file */ + adr->ad_rcnt++; + wr_ad_rcntno(adr,adr->ad_rcnt); + delivery_set(adr->ad_no, + int_Qmgr_status_success); + } + break; + default: + break; + } + if (error != NULLCP) { + free(error); + error = NULLCP; + } + } + if (rp_isbad(retval = wr_q2dr(&que, this_msg))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs(int_Qmgr_status_messageFailure); + } + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + +/* */ +static int filterMsg (msg,recip,qp, ep) +/* return OK if managed to filter msg through mychan for recip */ +char *msg; +ADDR *recip; +Q_struct *qp; +char **ep; +{ + char *origdir = NULL, + *newdir = NULL; + int result = OK; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 original directory not found for recipient %d of message '%s'",recip->ad_no, msg)); + *ep = strdup("source directory not found"); + result = NOTOK; + } + + /* temporary change to get new directory name */ + recip->ad_rcnt++; + if ((result == OK) + && (qid2dir(msg, recip, FALSE, &newdir) != OK)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 couldn't construct new directory for recipient '%d' of message '%s'",recip->ad_no, msg)); + *ep = strdup("Unable to construct destination directory"); + result = NOTOK; + } + recip->ad_rcnt--; + + if ((result == OK) + && (stat(newdir, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory already exists and so filter already done */ + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + + if ((result == OK) && (doFilter(origdir,newdir,msg, + qp, ep)!= OK)) + + result = NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return result; +} + +/* */ +char olddir[MAXPATHLENGTH], + newdir[MAXPATHLENGTH], + xtra_822hdrs[MAXPATHLENGTH]; + +int *dir_flags = NULL, + num_dir_flags = 0, + dirlevel = 0; + +#define INC 5 + +static void resize_dir_flags() +{ + num_dir_flags += INC; + if (dir_flags == NULL) + dir_flags = (int *) calloc((unsigned int)num_dir_flags, sizeof(int)); + else + dir_flags = (int *) realloc( (char *) dir_flags, + (unsigned) (num_dir_flags * sizeof(int))); +} + +static int is822hdrfile(file) +char *file; +{ + char buf[LINESIZE]; + FILE *fp; + + (void) sprintf(xtra_822hdrs, "%s/%s", olddir, file); + if ((fp = fopen(xtra_822hdrs,"r")) == NULL) + { + PP_SLOG(LLOG_EXCEPTIONS, xtra_822hdrs, + ("Can't open file")); + return FALSE; + } + + if (fgets (buf, LINESIZE - 1, fp) == NULL) + { + PP_DBG (("Null file '%s'",xtra_822hdrs)); + fclose(fp); + return FALSE; + } + + buf [strlen(buf) - 1] = '\0'; /* remove \n */ + if (lexnequ (buf, "RFC-822-HEADERS:", + strlen("RFC-822-HEADERS:")) != 0 + && lexnequ (buf, "Comments:", + strlen("Comments:")) != 0) + { + fclose (fp); + return FALSE; + } + + fclose(fp); + return TRUE; +} + + +static int is_xtra_822hdrs(entry) +struct dirent *entry; +{ + if ((strncmp(entry->d_name,"1.",2) == 0) + && (is822hdrfile(entry->d_name) == TRUE)) { + (void) sprintf(xtra_822hdrs, "%s/%s", olddir, entry->d_name); + return 1; + } + return 0; +} + +static char *get_xtra_822hdrs(dir) +char *dir; +{ + int num; + struct dirent **namelist; + + num = _scandir(dir, &namelist, is_xtra_822hdrs, NULL); + if (num == 0) { + dir_flags[dirlevel] = FALSE; + return NULLCP; + } else { + dir_flags[dirlevel] = TRUE; + return xtra_822hdrs; + } +} + +extern char *ia5_bp; + +static doFilter (orig, new, msg, qp, ep) +/* filters orig directory through mychan to new directory */ +char *orig, + *new, + *msg; +Q_struct *qp; +char **ep; +{ + char hdrp2[MAXPATHLENGTH], + hdr822[MAXPATHLENGTH], *ipn_body; + int result = OK; + struct stat statbuf; + char buf[BUFSIZ]; + (void) sprintf(newdir, "%s/tmp.%s", + msg, mychan->ch_name); + + if (stat(newdir, &statbuf) == OK) { + char *cmd_line; + /* exists so remove it */ + cmd_line = malloc((unsigned) (strlen("rm -rf ") + + strlen(newdir) + 1)); + sprintf(cmd_line, "rm -rf %s", newdir); + system(cmd_line); + if (cmd_line != NULL) free(cmd_line); + } + + if (mkdir(newdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, newdir, + ("Can't make directory")); + (void) sprintf(buf, + "Failed to make temp directory '%s'", + newdir); + *ep = strdup(buf); + result = NOTOK; + } + + if (result == OK) { + /* filter from orig to newdir */ + /* find p2 header to filter */ + LIST_BPT *ix = mychan -> ch_hdr_in; + int found = FALSE; + ipn_body = NULLCP; + + while (found == FALSE + && ix != NULLIST_BPT) { + sprintf(hdrp2,"%s/%s",orig, ix -> li_name); + if (stat(hdrp2, &statbuf) == OK) + found = TRUE; + else + ix = ix -> li_next; + } + + if (found == FALSE) { + PP_OPER(NULLCP, + ("Format/P2toRFC : cannot find p2 hdr")); + (void) sprintf (buf, + "Cannot find p2 hdr"); + *ep = strdup(buf); + return NOTOK; + } + + sprintf(hdr822, "%s/1.%s", newdir, ia5_bp); + ipn_body = strdup(hdr822); + + sprintf(hdr822,"%s/%s",newdir,hdr_822_bp); + sprintf(olddir,"%s",orig); + dirlevel = 0; + resize_dir_flags(); + + result = P2toRFC(hdrp2,get_xtra_822hdrs(orig),qp,NULLCP, + hdr822,ipn_body,ep); + + if (ipn_body) free(ipn_body); + if (result != NOTOK) { + err_fatal = FALSE; + link_rest(orig, ep); + if (err_fatal == TRUE) + result = NOTOK; + } + /* if success rename newdir to new */ + + if ((result == OK) && (rename(newdir,new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Can't rename directory '%s' to '%s'", + newdir, new)); + (void) sprintf (buf, + "Unable to rename temp dir from '%s' to '%s'", + newdir, new); + *ep = strdup(buf); + result = NOTOK; + } + } + return result; +} + +/* */ +/* link rest across from orig to newdir */ +/* may have to do some renumbering if 1.ia5 is extra headers */ + +/* origdir and newdir are set to current dirlevel of directories */ +char *linkerror = NULLCP; + +static int do_link(entry) +struct dirent *entry; +{ + struct stat statbuf; + struct dirent **namelist; + int num; + char oldfullname[MAXPATHLENGTH], + newfullname[MAXPATHLENGTH], + buf[BUFSIZ], + *ix; + + if ((strcmp(entry->d_name,".") == 0) + || (strcmp(entry->d_name,"..") == 0)) + return 0; + + if ((dir_flags[dirlevel] == TRUE) + && (strncmp(entry->d_name,"1.",2) == 0)) + /* already done so ignore */ + return 0; + + if (strcmp(entry->d_name, hdr_p2_bp) == 0 + || strcmp(entry->d_name, hdr_p22_bp) == 0 + || strcmp(entry->d_name, hdr_ipn_bp) == 0 + || strcmp (entry->d_name, + rcmd_srch (BPT_P2_DLIV_TXT, + bptbl_body_parts88)) == 0) + /* already dealt with */ + return 0; + + (void) sprintf(oldfullname, "%s/%s",olddir,entry->d_name); + + /* create new filename */ + + if (isdigit(*(entry->d_name)) + && (dir_flags[dirlevel] == TRUE)) { + /* need to alter number (decrement) */ + ix = index(entry->d_name,'.'); + *ix = '\0'; + num = atoi(entry->d_name); + *ix = '.'; + sprintf(newfullname,"%s/%d%s",newdir,--num,ix); + } else + /* just copy */ + sprintf(newfullname,"%s/%s",newdir,entry->d_name); + + + if ((stat(oldfullname,&statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory so do scandir on it */ + char hdrp2[MAXPATHLENGTH], + hdr822[MAXPATHLENGTH], + delivery_info[MAXPATHLENGTH], + *del_info; + struct stat statbuf; + int found; + LIST_BPT *bix = mychan -> ch_hdr_in; + + if (mkdir(newfullname, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, newfullname, + ("Can't make directory")); + exit(-1); + } + dirlevel++; + if (dirlevel >= num_dir_flags) + resize_dir_flags(); + + sprintf(olddir, "%s", oldfullname); + sprintf(newdir, "%s", newfullname); + + found = FALSE; + /* deal with p2 hdr in this directory if there */ + while (found == FALSE + && bix != NULLIST_BPT) { + sprintf(hdrp2,"%s/%s",olddir, bix -> li_name); + if (stat(hdrp2, &statbuf) == OK) + found = TRUE; + else + bix = bix -> li_next; + } + + if (found == FALSE) { + PP_OPER(NULLCP, + ("Format/P2toRFC : cannot find p2 hdr in forwarded msg")); + linkerror = strdup("cannot find p2 hdr in forwarded msg"); + return 0; + } + + sprintf(hdr822,"%s/%s", + newdir, hdr_822_bp); + sprintf(delivery_info, "%s/%s", + olddir, + rcmd_srch (BPT_P2_DLIV_TXT, + bptbl_body_parts88)); + if (stat(delivery_info, &statbuf) == OK) + del_info = delivery_info; + else + del_info = NULLCP; + + if (P2toRFC(hdrp2,get_xtra_822hdrs(olddir), + (Q_struct *) NULL, del_info, + hdr822, NULLCP, + &linkerror) != OK) { + err_fatal = TRUE; + return 0; + } + + num = _scandir(olddir,&namelist, do_link, NULL); + /* rewind newdir and olddir */ + ix = rindex(olddir,'/'); + *ix = '\0'; + ix = rindex(newdir,'/'); + *ix = '\0'; + dirlevel--; + + } else + /* just link */ + if (link(oldfullname, newfullname) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, "link", + ("Can't link from '%s' to '%s'",oldfullname,newfullname)); + exit(-1); + } + return 0; +} + + +static int link_rest(orig, ep) +char *orig; +char **ep; +{ + int num; + struct dirent **namelist; + + num = _scandir(orig,&namelist, do_link, NULL); + if (linkerror != NULLCP) { + if (*ep == NULLCP) + *ep = linkerror; + else + free(linkerror); + linkerror = NULLCP; + } +} + +/* */ +/* auxilary routines to extrRaddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc1148/c-RFCtoP2.c b/Format/rfc1148/c-RFCtoP2.c new file mode 100644 index 0000000..60ab2c8 --- /dev/null +++ b/Format/rfc1148/c-RFCtoP2.c @@ -0,0 +1,617 @@ +/* c-P2toRfc.c: rfc987(P2toRFC) filter channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: c-RFCtoP2.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "chan.h" +#include +#include +#include "sys.file.h" +#include + + +extern char *quedfldir; +extern char *chndfldir; +extern char *cont_p2, *hdr_822_bp, *hdr_p2_bp, *hdr_p22_bp; +extern void rd_end(), sys_init(), or_myinit(), err_abrt(); + +CHAN *mychan; +char *this_msg, *this_chan; +int err_fatal; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static int security_check (); +static int filterMsg(); +static int link_rest(); +static int x40084; +static int doFilter(); +static void dirinit (); +static ADDR *getnthrecip (); + +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + or_myinit(); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process,NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process,NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +extern int real987; + +static void do_ch_info_flags(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + if ((margc = sstr2arg(info_copy, 20, margv, " \t")) > 0) { + for (ix = 0; ix < margc; ix++) { + if (lexequ(margv[ix], "rfc987") == 0) + real987 = OK; + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown ch_out_info flag '%s'", + margv[ix])); + } + } + free(info_copy); +} + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/rfc987 : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + if (mychan->ch_out_info) + do_ch_info_flags(mychan->ch_out_info); + + /* check if a rfc987 channel */ + if (name != NULL) free(name); + + ap_use_percent(); + ap_norm_all_domains(); + + return OK; +} + +/* */ +/* routine to check if allowed to rfc987 filter this message */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc987 channel err: '%s'",msg_chan)); + result = FALSE; + } + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to do rfc987 filter */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *error = NULLCP; + + bzero((char *) &que,sizeof(que)); + + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_NOTICE, + ("Chans/rfc987 filtering msg '%s' through '%s'",this_msg, this_chan)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 : failed to find recipient %d of msg '%s'",ix->RecipientId->parm, this_msg)); + + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch (chan_acheck(adr, mychan, 1, (char **) NULL)) { + case OK: + if (filterMsg(this_msg,adr,&que, &error) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 : failed to filter msg '%s' for recip '%d' on channel '%s'",this_msg, adr->ad_no, this_chan)); + delivery_setstate(adr->ad_no, + int_Qmgr_status_messageFailure, + (error == NULLCP) ? "Failed to do 1138 conversion (RFC -> P2)" : error); + } else { + /* CHANGE update adr->ad_rcnt in struct and in file */ + adr->ad_rcnt++; + wr_ad_rcntno(adr,adr->ad_rcnt); + delivery_set(adr->ad_no,int_Qmgr_status_success); + } + default: + break; + } + if (error != NULLCP) { + free(error); + error = NULLCP; + } + } + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + +/* */ +static int filterMsg (msg,recip,qp,ep) +/* return OK if managed to filter msg through mychan for recip */ +char *msg; +ADDR *recip; +Q_struct *qp; +char **ep; +{ + char *origdir = NULL, + *newdir = NULL; + int result = OK; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 original directory not found for recipient %d of message '%s'",recip->ad_no, msg)); + *ep = strdup("source directory not found"); + result = NOTOK; + } + + /* temporary change to get new directory name */ + recip->ad_rcnt++; + if ((result == OK) + && (qid2dir(msg, recip, FALSE, &newdir) != OK)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 couldn't construct new directory for recipient '%d' of message '%s'",recip->ad_no, msg)); + *ep = strdup("Unable to construct destination directory"); + result = NOTOK; + } + recip->ad_rcnt--; + + if ((result == OK) + && (stat(newdir, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory already exists and so filter already done */ + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + + { + /* content not set go on hdr we're creating */ + LIST_BPT *ix = mychan -> ch_hdr_out; + x40084 = FALSE; + while (ix != NULLIST_BPT) { + if (lexequ(ix -> li_name, hdr_p2_bp) == 0) { + x40084 = TRUE; + ix = NULLIST_BPT; + } else + ix = ix->li_next; + } + } + if (result == OK && doFilter(origdir, + newdir, + msg, + qp, + ep, + x40084) != OK) + result = NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return result; +} + +/* */ +char olddir[MAXPATHLENGTH], + newdir[MAXPATHLENGTH]; + +int *dir_flags = NULL, + num_dir_flags = 0, + dirlevel = 0; + +#define INC 5 + +static void resize_dir_flags() +{ + num_dir_flags += INC; + if (dir_flags == NULL) + dir_flags = (int *) calloc((unsigned int) num_dir_flags, sizeof(int)); + else + dir_flags = (int *) realloc( (char *) dir_flags, + (unsigned) (num_dir_flags * sizeof(int))); +} + +static int is_822_hdr(entry) +struct dirent *entry; +{ + if (strncmp(entry->d_name,hdr_822_bp, strlen(hdr_822_bp)) == 0) + return 1; + else + return 0; +} + +static int get_822_hdr(dir,hdr) +char *dir; +char *hdr; +{ + int num; + struct dirent **namelist; + + num = _scandir(dir, &namelist, is_822_hdr, NULL); + if (num != 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 : cannot find unique 822 hdr file")); + return NOTOK; + } + sprintf(hdr,"%s/%s",dir,(*namelist)[0].d_name); + free((char *) namelist); + return OK; +} + +static doFilter (orig, new, msg, qp, ep, x40084) +/* filters orig directory through mychan to new directory */ +char *orig, + *new, + *msg; +Q_struct *qp; +char **ep; +int x40084; +{ + char hdrp2[MAXPATHLENGTH], + hdr822[MAXPATHLENGTH], + hdr_xtra[MAXPATHLENGTH]; + int result = OK; + struct stat statbuf; + char buf[BUFSIZ]; + + (void) sprintf(newdir, "%s/tmp.%s", + msg, mychan->ch_name); + + if (stat(newdir, &statbuf) == OK) { + char *cmd_line; + /* exists so remove it */ + cmd_line = malloc((unsigned) (strlen("rm -rf ") + + strlen(newdir) + 1)); + sprintf(cmd_line, "rm -rf %s", newdir); + system(cmd_line); + if (cmd_line != NULL) free(cmd_line); + } + + if (mkdir(newdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, newdir, + ("Can't make directory")); + (void) sprintf(buf, + "Failed to make temp directory '%s'", + newdir); + *ep = strdup(buf); + result = NOTOK; + } + + if (result == OK) { + /* filter from orig to newdir */ + sprintf(hdrp2,"%s/%s",newdir, + (x40084 == TRUE) ? hdr_p2_bp : hdr_p22_bp); + if (get_822_hdr(orig,hdr822) != OK) + return NOTOK; + + if (stat(hdr822, &statbuf) != OK) { + PP_OPER(NULLCP, + ("Format/RFCtoP2 : cannot find 822 hdr '%s'",hdr822)); + (void) sprintf (buf, + "Cannot find 822 hdr '%s'", + hdr822); + *ep = strdup(buf); + return NOTOK; + } + sprintf(hdr_xtra,"%s/1.ia5",newdir); + sprintf(olddir,"%s",orig); + + result = RFCtoP2(hdr822,hdrp2,hdr_xtra, ep, x40084); + resize_dir_flags(); + dirlevel = 0; + + if (stat(hdr_xtra, &statbuf) == OK) + /* something in header xtra */ + dir_flags[dirlevel] = TRUE; + else + dir_flags[dirlevel] = FALSE; + + err_fatal = FALSE; + + link_rest(orig, ep); + + if (err_fatal == TRUE) + result = NOTOK; + /* if success rename newdir to new */ + + if ((result == OK) && (rename(newdir,new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Can't rename directory '%s' to '%s'", + newdir, new)); + (void) sprintf (buf, + "Unable to rename temp dir from '%s' to '%s'", + newdir, new); + *ep = strdup(buf); + result = NOTOK; + } + } + return result; +} + +/* */ +/* link rest across from orig to newdir */ +/* may have to do some renumbering if 1.ia5 is extra headers */ + +/* origdir and newdir are set to current dirlevel of directories */ +char *linkerror = NULLCP; + +static int do_link(entry, x40084) +struct dirent *entry; +int x40084; +{ + struct stat statbuf; + struct dirent **namelist; + int num; + char oldfullname[MAXPATHLENGTH], + newfullname[MAXPATHLENGTH], + *ix; + + if ((strcmp(entry->d_name,".") == 0) + || (strcmp(entry->d_name,"..") == 0)) + return 0; + + if (strncmp(entry->d_name,"hdr.822",7) == 0) + /* already dealt with */ + return 0; + + (void) sprintf(oldfullname, "%s/%s",olddir,entry->d_name); + + /* create new filename */ + + if (isdigit(*(entry->d_name)) + && (dir_flags[dirlevel] == TRUE)) { + /* need to alter number (increment) */ + ix = index(entry->d_name,'.'); + *ix = '\0'; + num = atoi(entry->d_name); + *ix = '.'; + sprintf(newfullname,"%s/%d%s",newdir,++num,ix); + } else + /* just copy */ + sprintf(newfullname,"%s/%s",newdir,entry->d_name); + + + if ((stat(oldfullname,&statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory so do scandir on it */ + char hdrp2[MAXPATHLENGTH], + hdr822[MAXPATHLENGTH], + hdr_xtra[MAXPATHLENGTH]; + struct stat statbuf; + + if (mkdir(newfullname, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, newfullname, + ("Can't make directory")); + exit(-1); + } + dirlevel++; + if (dirlevel >= num_dir_flags) + resize_dir_flags(); + + sprintf(olddir, "%s", oldfullname); + sprintf(newdir, "%s", newfullname); + + /* deal with hdr.822 in this directory if there */ + if ((get_822_hdr(olddir,hdr822) == OK) + && (stat(hdr822, &statbuf) == OK)) { + sprintf(hdrp2,"%s/%s", + newdir, + (x40084 == TRUE) ? hdr_p2_bp : hdr_p22_bp); + sprintf(hdr_xtra,"%s/1.ia5",newdir); + + if (RFCtoP2(hdr822,hdrp2, + hdr_xtra,&linkerror,x40084) != OK) { + err_fatal = TRUE; + return 0; + } + + if (stat(hdr_xtra, &statbuf) == OK) + /* something in header xtra */ + dir_flags[dirlevel] = TRUE; + else + dir_flags[dirlevel] = FALSE; + + } else + PP_LOG(LLOG_EXCEPTIONS, + ("Format/RFCtoP2 : cannot find 822 hdr '%s'",hdr822)); + + num = _scandir(olddir,&namelist, do_link, NULL); + /* rewind newdir and olddir */ + ix = rindex(olddir,'/'); + *ix = '\0'; + ix = rindex(newdir,'/'); + *ix = '\0'; + dirlevel--; + + } else + /* just link */ + if (link(oldfullname, newfullname) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, "link", + ("Can't link from '%s' to '%s'",oldfullname,newfullname)); + exit(-1); + } + return 0; +} + +static int link_rest(orig, ep) +char *orig; +char **ep; +{ + int num; + struct dirent **namelist; + + dirlevel = 0; + num = _scandir(orig,&namelist, do_link, NULL); + if (linkerror != NULLCP) { + if (*ep == NULLCP) + *ep = linkerror; + else + free(linkerror); + linkerror = NULLCP; + } +} + +/* */ +/* auxilary routines to extract from lists */ +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc1148/f-P2toRFC.c b/Format/rfc1148/f-P2toRFC.c new file mode 100644 index 0000000..7d82b05 --- /dev/null +++ b/Format/rfc1148/f-P2toRFC.c @@ -0,0 +1,87 @@ +/* f-P2toRFC.c: P2 -> 822 filter */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/f-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/f-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: f-P2toRFC.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" + +extern void sys_init(), or_myinit(); + + + +/* ARGSUSED */ +main(argc, argv) +char **argv; +int argc; +{ + sys_init(argv[0]); + or_myinit (); + + if (P2toRFC (NULLCP, NULLCP, (Q_struct *) 0, NULLCP, NULLCP, 0) != OK) + { + fprintf (stderr, "P2 to RFC mapping failed\n"); + exit (-1); + } + +} + + + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc1148/f-RFCtoP2.c b/Format/rfc1148/f-RFCtoP2.c new file mode 100644 index 0000000..afbaf2e --- /dev/null +++ b/Format/rfc1148/f-RFCtoP2.c @@ -0,0 +1,83 @@ +/* f-RFCtoP2.c: 822 -> P2 filter */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/f-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/f-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: f-RFCtoP2.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" + + +/* ARGSUSED */ +main(argc, argv) +char **argv; +int argc; +{ + sys_init(argv[0]); + or_myinit (); + + if (RFCtoP2 (NULLCP, NULLCP, NULLCP) != OK) + { + fprintf (stderr, "RFC -> P2 failed\n"); + exit (-1); + } + +} + + + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc1148/make b/Format/rfc1148/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/rfc1148/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/rfc1148/oids.h b/Format/rfc1148/oids.h new file mode 100644 index 0000000..f35268a --- /dev/null +++ b/Format/rfc1148/oids.h @@ -0,0 +1,26 @@ +/* oids.h: the various oids needed for rfc1138 */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/oids.h,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: oids.h,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_RFC1148_OIDS +#define _H_RFC1148_OIDS + + +#define id_hex_incomplete_copy "2.6.1.5.0" +#define id_hex_languages "2.6.1.5.1" + +#define id_rfc_822_field "0.9.2342.234219200300.200.0" +#define id_rfc_822_field_list "0.9.2342.234219200300.200.1" + + +#endif diff --git a/Format/rfc1148/rfc-hdr.h b/Format/rfc1148/rfc-hdr.h new file mode 100644 index 0000000..0b3024f --- /dev/null +++ b/Format/rfc1148/rfc-hdr.h @@ -0,0 +1,48 @@ +/* rfc-hdr.h: Gives basic list of rfc header types */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/rfc-hdr.h,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: rfc-hdr.h,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_RFC1148_RFCHDR +#define _H_RFC1148_RFCHDR + +#include + + +/* --- generic values --- */ +#define HDR_ERROR -1 +#define HDR_EOH 0 +#define HDR_ILLEGAL 1 +#define HDR_IGNORE 2 + +/* --- 822 fields with specific mappings --- */ +#define HDR_MID 4 +#define HDR_FROM 5 +#define HDR_SENDER 6 +#define HDR_REPLY_TO 7 +#define HDR_TO 8 +#define HDR_CC 9 +#define HDR_BCC 10 +#define HDR_IN_REPLY_TO 11 +#define HDR_REFERENCES 12 +#define HDR_SUBJECT 13 +#define HDR_EXTENSIONS 14 +#define HDR_COMMENT 15 +#define HDR_INCOMPLETE_COPY 16 +#define HDR_LANGUAGE 17 +#define HDR_EXPIRY_DATE 18 +#define HDR_REPLY_BY 19 +#define HDR_OBSOLETES 20 +#define HDR_IMPORTANCE 21 +#define HDR_SENSITIVITY 22 +#define HDR_AUTOFORWARDED 23 +#endif diff --git a/Format/rfc1148/t-P2toRFC.c b/Format/rfc1148/t-P2toRFC.c new file mode 100644 index 0000000..16345a6 --- /dev/null +++ b/Format/rfc1148/t-P2toRFC.c @@ -0,0 +1,125 @@ +/* t-P2toRFC.c: P2 -> 822 test program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/t-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/t-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: t-P2toRFC.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "q.h" + +extern void sys_init(), or_myinit(); + +char *usage = "t-P2to822 <822> []\n"; +int order_pref = CH_USA_PREF; +char *rfc_out; +char *P2_in; +char *P2_ext_in; +char *ipn_body_out; + +main(argc, argv) +char **argv; +int argc; +{ + extern int optind, opterr; + extern char *optarg; + int opt; + char *error = NULLCP; + + sys_init(argv[0]); + or_myinit (); + + + fprintf (stderr, "Welcome to P2 -> RFC 822 \n"); + + opterr = 0; + while((opt = getopt(argc, argv, "d:s:")) != EOF) + switch(opt) + { + case 'd': + break; + default: + fprintf(stderr, "Unknown option %c\n", opt); + fputs(usage, stderr); + exit(1); + } + + if (argc - optind < 2 || + argc - optind > 3) + { + fprintf (stderr, usage); + exit (1); + } + + P2_in = argv[optind++]; + rfc_out = argv[optind++]; + if (argc > optind) + P2_ext_in = argv[optind]; + ipn_body_out = NULL; + fprintf (stderr, "Initialised\n"); + + if (P2toRFC (P2_in, P2_ext_in, (Q_struct *) 0, rfc_out, + ipn_body_out, &error, 1) != OK) + fprintf (stderr, "Blew it %s\n", + (error == NULLCP) ? "" : error ); + +} + + + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc1148/t-RFCtoP2.c b/Format/rfc1148/t-RFCtoP2.c new file mode 100644 index 0000000..d116890 --- /dev/null +++ b/Format/rfc1148/t-RFCtoP2.c @@ -0,0 +1,117 @@ +/* t-RFCtoP2.c: 822 -> P2 test program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/t-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/t-RFCtoP2.c,v 6.0 1991/12/18 20:20:34 jpo Rel $ + * + * $Log: t-RFCtoP2.c,v $ + * Revision 6.0 1991/12/18 20:20:34 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" + +extern void or_myinit(), sys_init(); + +char *usage = "t-822toP2 <822> []\n" ; + +char *rfc_in; +char *P2_out; +char *P2_ext_out; + +main(argc, argv) +char **argv; +int argc; +{ + extern int optind, opterr; + extern char *optarg; + int opt; + char *error = NULLCP; + sys_init(argv[0]); + or_myinit (); + + fprintf (stderr, "Welcome to RFC 822 -> P2\n"); + + opterr = 0; + while((opt = getopt(argc, argv, "d:s:")) != EOF) + switch(opt) + { + case 'd': + break; + default: + fprintf(stderr, "Unknown option %c\n", opt); + fputs(usage, stderr); + exit(1); + } + + if (argc - optind < 2 || + argc - optind > 3) + { + fprintf (stderr, usage); + exit (1); + } + rfc_in = argv[optind++]; + P2_out = argv[optind++]; + if (argc > optind) + P2_ext_out = argv[optind]; + + fprintf (stderr, "Initialised\n"); + + RFCtoP2 (rfc_in, P2_out, P2_ext_out, &error, 1); + +} + + + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "RFCtoP2 test"); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} + + +/* VARARGS 2 */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} diff --git a/Format/rfc822norm/Makefile b/Format/rfc822norm/Makefile new file mode 100644 index 0000000..c7cba06 --- /dev/null +++ b/Format/rfc822norm/Makefile @@ -0,0 +1,123 @@ +# Makefile for rfc822 normalizing filter +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/rfc822norm/RCS/Makefile,v 6.0 1991/12/18 20:20:54 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:20:54 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = rfc822norm.c +OBJS = rfc822norm.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) -DAP_DEBUG +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xrfc822norm + +default: $(PROGS) + +xrfc822norm: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LIBPP) $(LIBSYS) + +install: inst-dir inst-rfc822norm + +inst-rfc822norm: $(FORMDIR)/rfc822norm + +$(FORMDIR)/rfc822norm: xrfc822norm + -$(BACKUP) $@ zxrfc822norm + rm -f $@ + $(INSTALL) xrfc822norm $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "rfc822norm filter installed normally"; echo "" + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f $(PROGS) core a.out *.old *.BAK zxrfc822norm + + +lint: l-rfc822norm + +l-rfc822norm: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +rfc822norm.o: rfc822norm.c +rfc822norm.o: ../../h/util.h +rfc822norm.o: ../../h/config.h +rfc822norm.o: ../../h/ll_log.h +rfc822norm.o: ../../h/ap.h +rfc822norm.o: ../../h/util.h +rfc822norm.o: ../../h/alias.h +rfc822norm.o: ../../h/chan.h +rfc822norm.o: ../../h/table.h +rfc822norm.o: ../../h/list_bpt.h +rfc822norm.o: ../../h/retcode.h +rfc822norm.o: ../../h/adr.h +rfc822norm.o: ../../h/list_rchan.h +rfc822norm.o: ../../h/chan.h +rfc822norm.o: ../../h/auth.h +rfc822norm.o: ../../h/list_bpt.h +rfc822norm.o: ../../h/extension.h +rfc822norm.o: ../../h/mta.h +rfc822norm.o: ../../h/adr.h +rfc822norm.o: ../../h/list_bpt.h +rfc822norm.o: ../../h/aparse.h +rfc822norm.o: ../../h/ap.h +rfc822norm.o: ../../h/or.h +rfc822norm.o: ../../h/chan.h +rfc822norm.o: ../../h/auth.h +rfc822norm.o: ../../h/list_rchan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/rfc822norm/make b/Format/rfc822norm/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/rfc822norm/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/rfc822norm/rfc822norm.c b/Format/rfc822norm/rfc822norm.c new file mode 100644 index 0000000..d7de50f --- /dev/null +++ b/Format/rfc822norm/rfc822norm.c @@ -0,0 +1,1649 @@ +/* rfc822norm: program to 822norm stdin to stdout */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 6.0 1991/12/18 20:20:54 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 6.0 1991/12/18 20:20:54 jpo Rel $ + * + * $Log: rfc822norm.c,v $ + * Revision 6.0 1991/12/18 20:20:54 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include "ap.h" +#include "alias.h" +#include "chan.h" +#include "retcode.h" +#include "adr.h" + +#define OPT_822 1 +#define OPT_733 2 +#define OPT_JNT 3 +#define OPT_BIGEND 4 +#define OPT_LITTLEEND 5 +#define OPT_STRIPROUTES 6 +#define OPT_STRIPDOMAIN 7 +#define OPT_STRIPTRACE 8 +#define OPT_JNTSENDER 9 +#define OPT_FOLD 10 +#define OPT_MSGID 11 +#define OPT_PERCENT 12 +#define OPT_HIDELOCAL 13 +#define OPT_STRIPACK 14 +#define OPT_GENACK 15 +#define OPT_CHANGEDOMAIN 16 +#define OPT_FULL 17 +#define OPT_EXORDOM 18 +#define OPT_VALDOM 19 +#define OPT_EXORCISE 20 +#define OPT_EXTERNAL 21 +#define OPT_INTERNAL 22 + +CMD_TABLE tbl_options [] = { /* rfc822norm commandline options */ + "-822", OPT_822, + "-733", OPT_733, + "-jnt", OPT_JNT, + "-bigend", OPT_BIGEND, + "-littleend", OPT_LITTLEEND, + "-striproutes", OPT_STRIPROUTES, + "-stripdomain", OPT_STRIPDOMAIN, + "-changedomain", OPT_CHANGEDOMAIN, + "-striptrace", OPT_STRIPTRACE, + "-jntsender", OPT_JNTSENDER, + "-fold", OPT_FOLD, + "-msgid", OPT_MSGID, + "-percent", OPT_PERCENT, + "-full", OPT_FULL, + "-hidelocal", OPT_HIDELOCAL, + "-stripack", OPT_STRIPACK, + "-acks", OPT_GENACK, + "-exorcise", OPT_EXORCISE, + "-exorcise-domain", OPT_EXORDOM, + "-valid-domains", OPT_VALDOM, + "-external", OPT_EXTERNAL, + "-internal", OPT_INTERNAL, + 0, -1 + }; + +#define FLD_TO 1 +#define FLD_CC 2 +#define FLD_BCC 3 +#define FLD_FROM 4 +#define FLD_SENDER 5 +#define FLD_REPLY_TO 6 +#define FLD_RESENT_FROM 7 +#define FLD_RESENT_SENDER 8 +#define FLD_RESENT_TO 9 +#define FLD_RESENT_CC 10 +#define FLD_RESENT_BCC 11 +#define FLD_RESENT_BY 12 +#define FLD_REMAILED_FROM 13 +#define FLD_REMAILED_TO 14 +#define FLD_REMAILED_BY 15 +#define FLD_REDISTRIBUTED_FROM 16 +#define FLD_REDISTRIBUTED_TO 17 +#define FLD_REDISTRIBUTED_BY 18 +#define FLD_ORIG_SENDER 19 +/* RFC 987 extensions */ +#define FLD_RFC987 20 +/* RFC 987 (88) extensions - proposed */ +#define FLD_RFC987_88 21 +#define FLD_JNT_ACK 22 +/* misc */ +#define FLD_ERRORS_TO 23 +#define FLD_DATE 24 + +CMD_TABLE tbl_fields [] = {/* address field names */ +/* REAL RFC 822 */ + "Date", FLD_DATE, + "To", FLD_TO, + "CC", FLD_CC, + "bcc", FLD_BCC, + "From", FLD_FROM, + "Sender", FLD_SENDER, + "Reply-to", FLD_REPLY_TO, + "Resent-From", FLD_RESENT_FROM, + "Resent-Sender", FLD_RESENT_SENDER, + "Resent-To", FLD_RESENT_TO, + "Resent-Cc", FLD_RESENT_CC, + "Resent-Bcc", FLD_RESENT_BCC, + "Resent-By", FLD_RESENT_BY, +/* JNT stuff */ + "Original-Sender", FLD_ORIG_SENDER, + "Acknowledge-To", FLD_JNT_ACK, +/* RFC 733 & other misc stuff */ + "Remailed-From", FLD_REMAILED_FROM, + "Remailed-To", FLD_REMAILED_TO, + "Remailed-By", FLD_REMAILED_BY, + "Redistributed-From", FLD_REDISTRIBUTED_FROM, + "Redistributed-To", FLD_REDISTRIBUTED_TO, + "Redistributed-By", FLD_REDISTRIBUTED_BY, + "Errors-To", FLD_ERRORS_TO, +/* RFC 987 fields */ + "P1-Recipient", FLD_RFC987, +/* RFC 987 (88) fields */ + "X400-Originator", FLD_RFC987_88, + "X400-Recipients", FLD_RFC987_88, + "Notification-IPM-Originator", FLD_RFC987_88, + "Notification-Preferred-Recipients", FLD_RFC987_88, + "MTS-Originator", FLD_RFC987_88, + "MTS-Recipient", FLD_RFC987_88, + "Originally-Intended-Recipient", FLD_RFC987_88, + "Originator-Return-Address", FLD_RFC987_88, + "Report-Reporting-DL-Name", FLD_RFC987_88, + "Report-Originator-and-DL-Expansion-History", + FLD_RFC987_88, + 0, -1 + }; + +#define FOLD_SPACE 0 +#define FOLD_COMMA 1 +#define FOLD_SEMICOLON 2 +#define FOLD_RECIEVED 3 +#define FOLD_NONE 4 + +CMD_TABLE tbl_nonfields [] = {/* feilds dont deal with */ + "Received", FOLD_RECIEVED, + "X400-Received", FOLD_SEMICOLON, + "Via", FOLD_SEMICOLON, + "References", FOLD_COMMA, + "Keywords", FOLD_COMMA, + "X400-MTS-Identifier", FOLD_NONE, + "Message-ID", FOLD_NONE, + "In-Reply-To", FOLD_NONE, + "Obsoletes", FOLD_COMMA, + 0, -1 + }; + +#define TRACE_RECIEVED 1 +#define TRACE_VIA 2 +#define TRACE_X400 3 + +CMD_TABLE tbl_tracefields [] = {/* fields viable for strip trace */ + "Received", TRACE_RECIEVED, + "Via", TRACE_VIA, + "X400-Received", TRACE_X400, + 0, -1 +}; + +typedef struct dom_pair { + AP_ptr from; + AP_ptr to; +} DomPair; + +typedef enum {maj_none, rfc822, rfc733, jnt} Major_options; +typedef enum {min_none, bigend, littleend} Minor_options; + +extern void sys_init(), err_abrt(); +static void norm_sender(); +static int equalWithJntsender(); +#ifdef VAT +static int tidy_up(); +#endif +static getitm(), out_adr(); + +char *myname; +int nadrs; +int pcol; +int nonempty; +int fold_width; +int order_pref, percents; +int normalised = APARSE_NORM_NONE; +int striptrace = FALSE, + striproutes = FALSE, + stripacks = FALSE, + genacks = FALSE; +char **stripdomains = NULL; +char **hidedomains = NULL; +struct dom_pair *changedomains = NULL; +int num_domains = 0, + num_pairs = 0, + num_to_hide = 0, + message_id = 0, + acks = 0, + msgid_req = FALSE, + internal = FALSE; +char *jntsender = NULL, + *jntsendernorm = NULL; +AP_ptr jnttree, jntgroup, jntname, jntloc, jntdom, jntroute; +static int getach(); +static int getbufchar(); +static char *next_fold(); +static char *fold_recieved(); +extern AP_ptr ap_pinit(); +extern char *compress(); +extern char *rcmd_srch(); +extern int ap_outtype; +extern int ap_perlev; +extern char *loc_dom_site, + *loc_dom_mta; +char *rloc_dom_site, + *rloc_dom_mta; +static char *reverse(); +#ifndef BSD42 +#define random rand +#define srandom srand +#endif + +#define DEFAULT_FOLD_WIDTH 79 + +static char *fieldbuf = NULL, + *contbuf = NULL; +static int fieldsize = 0, + contsize = 0; +static int fieldlen = 0, + contlen = 0; +static char *contix = NULL; + +static int exorcise = FALSE; +static Table *exorciseTable; +static char *exorciseDomain; + +/* ARGSUSED */ +main(argc,argv) +int argc; +char **argv; +{ + /* parse flags */ + Major_options maj = maj_none; + Minor_options mino = min_none; + + myname = *argv++; + sys_init(myname); + or_myinit(); +/* malloc_debug(2);*/ + ap_outtype = AP_PARSE_822; + fold_width = DEFAULT_FOLD_WIDTH; + order_pref = CH_USA_PREF; + normalised = APARSE_NORM_NONE; + jntsendernorm = NULL; + percents = FALSE; + jntsender = NULL; + message_id = 0; + msgid_req = FALSE; + srandom(getpid()); + + exorcise = FALSE; + exorciseDomain = strdup(loc_dom_site); + exorciseTable = tb_nm2struct ("domain"); + + rloc_dom_site = reverse(loc_dom_site); + rloc_dom_mta = reverse(loc_dom_mta); + while (*argv != NULL) { + switch(cmd_srch(*argv,tbl_options)) { + case -1: + PP_LOG(LLOG_EXCEPTIONS, + ("unknown option '%s'",*argv)); + exit(1); + + case OPT_MSGID: + msgid_req = TRUE; + break; + + case OPT_PERCENT: + percents = TRUE; + ap_use_percent(); + break; + + case OPT_FULL: + normalised = APARSE_NORM_ALL; + break; + + case OPT_FOLD: + if (*(argv+1) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no fold width given with %s",*argv)); + else { + ++argv; + fold_width = atoi(*argv); + } + break; + + case OPT_822: + if ((maj == maj_none) || (maj == rfc822)) { + ap_outtype &= AP_TYPE_MASK; + ap_outtype |= AP_PARSE_822; + maj = rfc822; + } + break; + + case OPT_733: + if ((maj == maj_none) || (maj == rfc733)) { + ap_outtype &= AP_TYPE_MASK; + ap_outtype |= AP_PARSE_733; + maj = rfc733; + } + break; + + case OPT_JNT: + if ((maj == maj_none || maj == jnt) + && (mino == min_none || mino == bigend)) { + ap_outtype &= AP_TYPE_MASK; + ap_outtype |= AP_PARSE_733; + maj = jnt; + ap_outtype |= AP_PARSE_BIG; + mino = bigend; + order_pref = CH_UK_PREF; + break; + } + PP_LOG(LLOG_EXCEPTIONS, + ("multiple major parse options")); + exit(1); + + case OPT_BIGEND: + if (mino == min_none || mino == bigend) { + ap_outtype |= AP_PARSE_BIG; + mino = bigend; + order_pref = CH_UK_PREF; + } + break; + + case OPT_LITTLEEND: + if (mino == min_none || mino == littleend) { + mino = littleend; + break; + } + PP_LOG(LLOG_EXCEPTIONS, + ("multiple minor parse options")); + exit(1); + + case OPT_STRIPTRACE: + striptrace = TRUE; + break; + + case OPT_STRIPROUTES: + striproutes = TRUE; + break; + + case OPT_STRIPDOMAIN: + if (*(argv+1) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no domain specified with %s", *argv)); + else { + ++argv; + if (num_domains == 0) + stripdomains = (char **) calloc(1, + (unsigned int) sizeof(char *)); + else + stripdomains = (char **) realloc((char *) stripdomains, + (unsigned int) ((num_domains + 1) * sizeof(char *))); + stripdomains[num_domains++] = *argv; + } + break; + + case OPT_CHANGEDOMAIN: + if (*(argv+1) == NULL + || *(argv+2) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no domain pair specified with %s", + *argv)); + else { + if (num_pairs == 0) + changedomains = (struct dom_pair *) + calloc (1, + (unsigned int) sizeof(struct dom_pair)); + else + changedomains = (struct dom_pair *) + realloc ((char *) changedomains, + (unsigned int) ((num_pairs + 1) * sizeof (char *))); + argv++; + changedomains[num_pairs].from = ap_new(AP_DOMAIN, + *argv++); + changedomains[num_pairs++].to = ap_new(AP_DOMAIN, + *argv); + } + break; + + case OPT_JNTSENDER: + if (*(argv+1) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no sender specified with %s", *argv)); + else { + argv++; + jntsender = *argv; + } + break; + + case OPT_STRIPACK: + stripacks = TRUE; + break; + + case OPT_GENACK: + if (*(argv+1) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no flag specified with %s", *argv)); + else { + argv++; + if (lexequ(*argv, "yes") == 0) + genacks = TRUE; + } + break; + + case OPT_HIDELOCAL: + if (*(argv+1) == NULL) + PP_LOG(LLOG_EXCEPTIONS, + ("no domain specified with %s", *argv)); + else { + ++argv; + if (num_to_hide == 0) + hidedomains = (char **) calloc(1, + (unsigned int) sizeof(char *)); + else + hidedomains = (char **) realloc((char *) hidedomains, + (unsigned int) ((num_to_hide + 1) * sizeof(char *))); + hidedomains[num_to_hide++] = *argv; + } + break; + + case OPT_EXORCISE: + exorcise = TRUE; + break; + + case OPT_EXORDOM: + if (*(argv+1) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("no domain given with %s", *argv)); + exit(1); + } + ++argv; + free(exorciseDomain); + exorciseDomain = strdup(*argv); + exorcise = TRUE; + break; + + case OPT_VALDOM: + if (*(argv+1) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("no table given with %s", *argv)); + exit(1); + } else if ((exorciseTable = tb_nm2struct(*(argv+1))) == NULLTBL) { + PP_LOG(LLOG_EXCEPTIONS, + ("unknown table %s given with %s", + *(argv+1), *argv)); + exit(1); + } + ++argv; + exorcise = TRUE; + break; + + case OPT_EXTERNAL: + internal = FALSE; + break; + + case OPT_INTERNAL: + internal = TRUE; + break; + + default: + PP_LOG(LLOG_EXCEPTIONS, + ("unknown option '%s'")); + exit(1); + } + argv++; + } + + if (genacks == TRUE && !jntsender) + PP_LOG(LLOG_EXCEPTIONS, + ("Acknowledge-To required but no sender specified")); + if (jntsender) + norm_sender(); + /* ap_outtype set so now process */ + if (proc() != OK) + err_abrt( RP_LIO, "couldn't reformat it"); + free(rloc_dom_site); + free(rloc_dom_mta); + /* copy out rest of file */ + exit(0); +} + +/* */ + +static void norm_sender() +{ + Aparse_ptr aparse = aparse_new(); + aparse -> r822_str = strdup(jntsender); + aparse -> ad_type = AD_822_TYPE; + aparse -> dmnorder = order_pref; + aparse -> normalised = normalised; + aparse -> percents = percents; + aparse -> internal = internal; + + if (aparse_norm(aparse) == NOTOK) { + jnttree = ap_s2t(jntsender); + + jnttree = ap_t2p (jnttree, &jntgroup, &jntname, + &jntloc, &jntdom, &jntroute); + } else { + jnttree = aparse->ap_tree; + jntgroup = aparse->ap_group; + jntname = aparse->ap_name; + jntloc = aparse->ap_local; + jntdom = aparse->ap_domain; + jntroute = aparse->ap_route; + aparse -> ap_tree = NULLAP; + } + aparse_free(aparse); + free ((char *) aparse); + jntsendernorm = ap_p2s(jntgroup, jntname, jntloc, jntdom, jntroute); +} + +static int equalWithJntsender(tree) +AP_ptr tree; +{ + AP_ptr jix = tree, aix = jntloc; + + while (jix != NULLAP && + aix != NULLAP && + aix -> ap_obvalue != NULLCP && + jix -> ap_obvalue != NULLCP) { + if (jix -> ap_obtype == AP_COMMENT) + jix = jix -> ap_next; + else if (aix -> ap_obtype == AP_COMMENT) + aix = aix -> ap_next; + else if (strcmp(aix -> ap_obvalue, jix -> ap_obvalue) != 0) + return 0; + else { + aix = aix -> ap_next; + jix = jix -> ap_next; + } + } + while (jix != NULLAP && jix->ap_obvalue == NULLCP) + jix = jix -> ap_next; + + while (aix != NULLAP && aix->ap_obvalue == NULLCP) + aix = aix -> ap_next; + + if (aix == NULLAP && jix == NULLAP) + return 1; + return 0; +} + +/* */ + +int noFrom, from, gotDate; + +/* 822norm stdin to stdout */ +proc () +{ + int amp_fail; + int res; + int done; + register char *cp; + PP_TRACE(("outtype %o",ap_outtype)); + noFrom = 1; + gotDate = 0; + from = 0; + while ((getitm(&res) == OK) && (res == OK)) { + + ap_clear(); + nadrs = 0; + amp_fail = FALSE; + nonempty = FALSE; + done = FALSE; + + if (ap_pinit(getbufchar) == BADAP) { + PP_LOG(LLOG_EXCEPTIONS, + ("problem parsing message")); + return NOTOK; + } + + while (done == FALSE) { + res = ap_1adr(); /* Parse one adr */ + switch(res) { + case DONE: /* done */ + done = TRUE; + break; + case NOTOK: + /* pass the garbage and generate warning */ + amp_fail = TRUE; + break; + default: /* print it */ + ap_ppush (getbufchar); + if ((res = out_adr(ap_pstrt)) != OK) + return res; + ap_ppop(); + ap_pstrt = ap_pcur = ap_alloc (); + break; + } + } + putchar('\n'); + if (ap_perlev) { /* if still nested */ + PP_TRACE(("nested level %d",ap_perlev)); + amp_fail++; + } + if (amp_fail == TRUE) { + char *fold, *ix; + int nonempty = FALSE; + printf("PP-Warning: Parse error in original version of preceding line\n"); + printf("Original-%s: ", fieldbuf); + ix = &(contbuf[0]); + while (*ix != '\0') { + fold = next_fold(ix+1, FOLD_COMMA); + if ((fold_width != -1) + && (fold - ix + pcol > fold_width) + && nonempty == TRUE) { + /* fold */ + pcol = strlen(fieldbuf) + strlen("Original-: "); + printf("\n%*s", + strlen(fieldbuf) + strlen("Original-: "), + ""); + while (isspace(*ix)) + ix++; + } else + nonempty = TRUE; + pcol += fold - ix; + while (ix != fold) + putchar (*ix++); + } + putchar('\n'); + } + } + + if (gotDate == 0) { + /* no date so add one */ + UTC ut; + char buf[BUFSIZ], *cp; + strcpy (buf, "Date"); + cp = &buf[0]; + while (*cp != '\0') + putchar (*cp++); + putchar (':'); + putchar (' '); + + ut = utcnow(); + UTC2rfc(ut, buf); + + cp = &buf[0]; + while (*cp != '\0') + putchar (*cp++); + putchar('\n'); + } + + if (message_id == 0 && msgid_req == TRUE) { + /* output message id */ + MPDUid msgid; + char buf[BUFSIZ]; + strcpy(buf, "Message-ID"); + cp = &buf[0]; + while (*cp != '\0') + putchar (*cp++); + putchar (':'); + putchar (' '); + + MPDUid_new(&msgid); + (void) sprintf(buf, "<\"%s\"@%s>", + msgid.mpduid_string, loc_dom_site); + cp = buf; + while (*cp != '\0') + putchar (*cp++); + putchar ('\n'); + } + if (jntsendernorm != NULL) { + if (genacks == TRUE && acks == 0) { + /* output Acknowledge-To field */ + cp = rcmd_srch(FLD_JNT_ACK, tbl_fields); + while (*cp != '\0') + putchar (*cp++); + putchar(':'); + putchar(' '); + cp = jntsendernorm; + while (*cp != '\0') + putchar(*cp++); + putchar('\n'); + } + + if (noFrom) { + /* output Sender */ + cp = rcmd_srch(FLD_SENDER, tbl_fields); + while (*cp != '\0') + putchar(*cp++); + putchar(':'); + putchar(' '); + + cp = jntsendernorm; + while (*cp != '\0') + putchar(*cp++); + putchar('\n'); + } + + ap_sqdelete(jnttree, NULLAP); + free((char *)jnttree); + } + if (res == NOTOK) + return NOTOK; + +#ifdef VAT + tidy_up(); +#endif + + return (ferror(stdout) ? NOTOK : OK); +} + +/* */ +/* input routines */ + +#define INC 2 + +/* returns current pointer = *orig + olength */ +static char *resize_buf(orig, olength, size) +char **orig; +int olength, + *size; +{ + + *size += INC; + if (*orig == NULLCP) + *orig = calloc (1, (unsigned int) (*size)); + else + *orig = realloc (*orig, (unsigned int) (*size)); + return ((*orig)+olength); +} + +/* returns OK while still got more input to read */ +/* result == NOTOK if failed parsing */ +static int getitm(result) +int *result; +{ + register int c; + register char *cp, + *ix; + int gotitm = FALSE; + int fld; + + fieldlen = 0; + cp = fieldbuf; + *result = OK; + + while (gotitm == FALSE) { + if ((c = getach()) == EOF) + /* end of file */ + return NOTOK; + + switch (c) { + case '\n': + if (fieldlen != 0) + break; + case '\0': + /* end of input */ + return NOTOK; + } + + switch (c) { + case ':': + /* Field name collected */ + if ((fieldlen+1) >= fieldsize) + cp = resize_buf(&fieldbuf,fieldlen,&fieldsize); + *cp = '\0'; + PP_TRACE(("field '%s'",fieldbuf)); + ix = fieldbuf; + if (isspace(*ix) && *ix != '\n') { + while (isspace(*ix) && *ix != '\n') + ix++; + /* rewind back one to first nonspace */ + ix--; + } + + /* got field now get contents */ + cp = contbuf; + contlen = 0; + + while (((c = getach()) != 0) && (c != EOF)) { + if (++contlen >= contsize) + cp = resize_buf(&contbuf,(contlen-1),&contsize); + *cp++ = c; + } + + /* terminate with a null char */ + if ((contlen + 1) >= contsize) + cp = resize_buf(&contbuf,contlen,&contsize); + *cp ='\0'; + compress(fieldbuf, fieldbuf); + compress(contbuf, contbuf); + contix = contbuf; + + fld = cmd_srch(ix, tbl_tracefields); + + /* check if need to skip */ + if (striptrace == TRUE + && fld != -1) { + /* skip it */ + cp = fieldbuf; + fieldlen = 0; + break; + } + + if (fld != -1 + && valid_trace(fld, fieldbuf, contbuf) != OK) { + /* already output with error */ + cp = fieldbuf; + fieldlen = 0; + break; + } + + fld = cmd_srch(ix, tbl_fields); + + if (fld == FLD_JNT_ACK) { + if (stripacks == TRUE) { + /* skip it */ + cp = fieldbuf; + fieldlen = 0; + break; + } else + acks++; + } + + if (fld == FLD_FROM) + from = 1; + else + from = 0; + + if (jntsender != NULL + && (fld == FLD_SENDER)) + /* convert to Original-Sender */ + cp = rcmd_srch(FLD_ORIG_SENDER, tbl_fields); + else + cp = fieldbuf; + + if (fld == FLD_DATE) + gotDate++; + + pcol = strlen(cp)+2; + while (*cp != '\0') + putchar(*cp++); + putchar(':'); + /* put in jpo's space */ + putchar(' '); + + if (fld != -1 && fld != FLD_DATE) { + gotitm = TRUE; + + } else { + int fold_num; + /* copy rest of line out */ + nonempty = FALSE; + pcol = strlen(fieldbuf) + 1; + cp = contix; + if (lexequ(fieldbuf, "Message-ID") == 0) + message_id++; + + if ((fold_num = cmd_srch(fieldbuf,tbl_nonfields)) == -1) { + PP_DBG(("unknown non field %s folding on spaces",fieldbuf)); + fold_num = FOLD_SPACE; + } + while (*contix != '\0') { + /* go to next fold */ + cp = next_fold(contix+1,fold_num); + + if ((fold_width != -1) + && (cp - contix + pcol > fold_width) + && nonempty) { + /* new line */ + pcol = strlen(fieldbuf) + 2; + printf("\n%*s", strlen(fieldbuf) + 2, ""); + /* strip out white space */ + while (isspace(*contix)) + contix++; + } else + nonempty = TRUE; + pcol += cp - contix; + /* output line */ + while (contix != cp) + putchar(*contix++); + } + putchar('\n'); + if (c == EOF) + /* EOF */ + return NOTOK; + } + cp = fieldbuf; + fieldlen = 0; + break; + + default: + if (++fieldlen >= fieldsize) + cp = resize_buf(&fieldbuf,(fieldlen-1),&fieldsize); + *cp++ = c; + } + } + return OK; +} + +static int isblank(ch) +char ch; +{ + return (ch == ' ' || ch == '\t'); +} + +/* returns 0 when reach end of an item */ +/* returns EOF when reach EOF */ +static int getach() +{ + static unsigned char buf[MAXPATHLENGTH]; + static unsigned char *bufp = buf; + static int noInput = 0; + + if (noInput == 0) { /* buffer is empty */ + noInput = read(0, buf, MAXPATHLENGTH); + bufp = buf; + } + + if (*bufp == '\n') { + if (noInput == 1) { + /* last char in buffer */ + noInput = read(0, buf, MAXPATHLENGTH); + bufp = buf; + if (isblank(*bufp)) { + noInput--; + return *bufp++; + } else + return 0; + } else if (isblank(*(bufp+1))) { + /* skip newline */ + bufp++; + noInput--; + } + } + if (*bufp == '\n') { + bufp++; + noInput--; + return 0; + } + return ((--noInput >= 0) ? *bufp++ : EOF); +} + +static int getbufchar() +{ + char ret = *contix; + if (ret != 0) contix++; + return (ret == 0) ? EOF : ret; +} + +/* */ +/* output routine */ + +static char *next_fold(ix,fold) +char *ix; +int fold; +{ + char fold_ch; + + switch (fold) { + case FOLD_NONE: + fold_ch = '\0'; + break; + case FOLD_SPACE: + fold_ch = ' '; + break; + case FOLD_COMMA: + fold_ch = ','; + break; + case FOLD_SEMICOLON: + fold_ch = ';'; + break; + case FOLD_RECIEVED: + return fold_recieved(ix); + default: + PP_LOG(LLOG_EXCEPTIONS, + ("unknown fold number %d",fold)); + fold_ch = ' '; + } + + while (*ix != '\0' && *ix != fold_ch) + ix++; + if (*ix == '\0') + return ix; + else + return ++ix; +} + +static char *fold_recieved(chs) +char *chs; +{ + char *ix; + while (*chs != '\0' && *chs != ';' && *chs != ' ') + chs++; + if (*chs == '\0') + return chs; + if (*chs == ';') + return ++chs; + /* skip leading spaces */ + while (isspace(*chs)) + chs++; + + /* now check if have key words */ + ix = chs; + while (*ix != '\0' && + (ix - chs <= (int)strlen("from")+1)) { + + if (ix - chs == 3) { + if (strncmp(chs,"by ",3) == 0) + return chs; + else if (strncmp(chs,"id ",3) == 0) + return chs; + } + + if (ix - chs == 4) { + if (strncmp(chs,"via ",4) == 0) + return chs; + else if (strncmp(chs,"for ",4) == 0) + return chs; + } + + if (ix - chs == 5) { + if (strncmp(chs,"from ",5) == 0) + return chs; + else if (strncmp(chs, "with ", 5) == 0) + return chs; + + } + ix++; + } + if (*ix == '\0') + return ix; + return fold_recieved(chs); +} + +static int specifiedDomain(ptr) +AP_ptr ptr; +{ + int specified = FALSE, + i = 0; + + if (ptr->ap_obtype != AP_DOMAIN + && ptr -> ap_obtype != AP_DOMAIN_LITERAL) + return FALSE; + + while (specified != TRUE && i < num_domains) { + if ((ptr->ap_obvalue != NULL) + && (strcmp(stripdomains[i], ptr->ap_obvalue) == 0)) + specified = TRUE; + i++; + } + return specified; +} + + +static int hiddenDomain(ptr) +AP_ptr ptr; +{ + int hidden = FALSE, + i, nwild, nw; + char *bp, *cp; + + /* get to next domain */ + while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN)) + ptr = ptr->ap_next; + if (ptr == NULL) + return 0; + + if (ptr->ap_obvalue != NULL) + for (i = 0; hidden != TRUE && i < num_to_hide; i++) { + for (nwild = 0; hidedomains[i][nwild] == '.' || + hidedomains[i][nwild] == '*'; nwild ++) + continue; + nw = nwild; + nwild /= 2; + bp = cp = ptr->ap_obvalue; + if ( ! hidedomains[i][nw] ) { + PP_LOG (LLOG_EXCEPTIONS, + ("Format/rfc822norm/hiddenDomain: Too wild - Reality error")); + continue; + } + + while ( (nwild -- > 0) && (bp = index(bp, '.')) != NULL) + bp ++; + if ( !bp ) + continue; + while ((bp = index(bp,'.')) != NULL) { + if (++bp =='\0') + break; + cp = index(cp,'.'); + cp++; + if ((strcmp(&hidedomains[i][nw], bp) == 0)) { + hidden = TRUE; + strcpy(ptr->ap_obvalue, cp); + break; + } + } + } + return hidden; +} + +static int recognisedDomain(ptr) +AP_ptr ptr; +{ + if (ptr->ap_obtype != AP_DOMAIN + && ptr->ap_obtype != AP_DOMAIN_LITERAL) + return FALSE; + if (ptr->ap_normalised != TRUE) + rfc822_norm_dmn(ptr, order_pref); + return ptr->ap_recognised; +} + +static void changedomain (dom) +AP_ptr dom; +{ + int i; + for (i = 0; i < num_pairs; i++) { + if (changedomains[i].from->ap_normalised != TRUE) + rfc822_norm_dmn(changedomains[i].from, + order_pref); + if (lexequ(changedomains[i].from->ap_obvalue, + dom->ap_obvalue) == 0) + break; + } + if (i < num_pairs) { + if (dom->ap_obvalue) + free(dom->ap_obvalue); + if (changedomains[i].to->ap_normalised != TRUE) + rfc822_norm_dmn(changedomains[i].to, + order_pref); + dom->ap_obvalue = strdup(changedomains[i].to->ap_obvalue); + if (dom->ap_normalised == TRUE) { + if (dom->ap_localhub) { + free (dom->ap_localhub); + dom->ap_localhub = NULLCP; + } + if (dom->ap_chankey) { + free (dom->ap_chankey); + dom->ap_chankey = NULLCP; + } + if (dom->ap_error) { + free (dom->ap_error); + dom->ap_error = NULLCP; + } + } + } +} + +static void do_changedomains (tree) +AP_ptr tree; +{ + while (tree != NULLAP) { + if (tree -> ap_obtype == AP_DOMAIN + || tree -> ap_obtype == AP_DOMAIN_LITERAL) + changedomain(tree); + tree = tree->ap_next; + } +} + +static void do_stripdomains(pap, pgroup, pname, ploc, + pdom, proute) +AP_ptr *pap, + *pgroup, + *pname, + *ploc, + *pdom, + *proute; +{ + AP_ptr ix, hdr; + int cont = TRUE; + + if (*proute != NULLAP) { + /* go down tree removing specified domains */ + hdr = ap_new(AP_DOMAIN, "header"); + hdr->ap_next = *pap; + hdr->ap_ptrtype = AP_PTR_MORE; + ix = hdr; + + while ((ix->ap_next != NULL) + && cont == TRUE) { + switch (ix -> ap_next -> ap_obtype) { + case AP_DOMAIN: + case AP_DOMAIN_LITERAL: + if (specifiedDomain (ix->ap_next) == TRUE) + ap_delete (ix); + else + ix = ix -> ap_next; + break; + + case AP_MAILBOX: + case AP_GENERIC_WORD: + /* don't remove dom so stop here */ + cont = FALSE; + break; + + default: + ix = ix -> ap_next; + } + } + + /* reset all pointers */ + *pap = hdr->ap_next; + hdr->ap_next = NULLAP; + ap_free(hdr); + (void) ap_t2p(*pap, pgroup, pname, ploc, pdom, proute); + } +} + +static void do_striproutes(pap, pgroup, pname, ploc, + pdom, proute) +AP_ptr *pap, + *pgroup, + *pname, + *ploc, + *pdom, + *proute; +{ + int cont = TRUE; + char *tmp; + AP_ptr ix, + hdr; + + if (recognisedDomain(*pdom) == TRUE) { + /* recognised *pdom, remove all route */ + tmp = ap_p2s(*pgroup, *pname, *ploc, + *pdom, NULLAP); + ix = *pap; + ap_s2p(tmp, pap, pgroup, pname, ploc, pdom, proute); + ap_free(ix); + free(tmp); + } else { + /* go down tree removing recognised domains */ + hdr = ap_new(AP_DOMAIN, "header"); + hdr->ap_next = *pap; + hdr->ap_ptrtype = AP_PTR_MORE; + ix = hdr; + + while ((ix->ap_next != NULL) + && cont == TRUE) { + switch (ix -> ap_next -> ap_obtype) { + case AP_DOMAIN: + case AP_DOMAIN_LITERAL: + if (recognisedDomain (ix->ap_next) == TRUE) + ap_delete (ix); + else + cont = FALSE; + break; + + case AP_MAILBOX: + case AP_GENERIC_WORD: + cont = FALSE; + break; + + default: + ix = ix -> ap_next; + } + } + + /* reset all pointers */ + *pap = hdr->ap_next; + hdr->ap_next = NULLAP; + ap_free(hdr); + (void) ap_t2p(*pap, pgroup, pname, ploc, pdom, proute); + } +} + +static +do_hidedomains(dom_ptr, route_ptr) +AP_ptr dom_ptr, +route_ptr; +{ + int retval = 0; + AP_ptr ptr; + if ((ptr = route_ptr) != NULLAP ) + while ( ptr ) { + retval += hiddenDomain(ptr); + ptr = ptr->ap_next; + } + return retval += hiddenDomain(dom_ptr); +} + +#ifdef VAT +static int tidy_up() +{ + if (random() % 10000 != 42) + return; + /* lucky person gets a message */ + switch (random() % 4) { + case 0: + printf ("Checked-by: NSA, MI5, CIA, KGB\n"); + break; + case 1: + printf ("Green-Message: This message is stored on recycled memory\n"); + break; + case 2: + printf ("Best-Wishes-From: Steve, Julian, Pete, Alina et al\n"); + break; + default: + printf ("Congratulations: You are the recipient of our %d message\n", random() % 1000000); + break; + } +} +#endif + +static char *re_parse_ptr; +static int get_rp_char() +{ + char ret = *re_parse_ptr; + if (ret != 0) re_parse_ptr++; + return (ret == 0) ? EOF : ret; +} + +/* */ + +static int mustExorcise(domain) +char *domain; +{ + int retval = FALSE; + char chan[BUFSIZ], normalised[BUFSIZ]; + char *subdom; + + if (exorciseTable == NULLTBL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No table of valid addresses")); + return FALSE; + } + if (tb_getdomain_table(exorciseTable, domain, chan, normalised, + order_pref, &subdom) != OK) + retval = TRUE; + if (subdom) free(subdom); + return retval; +} + +AP_ptr exorciseAp; + +static void createExorciseAp () +{ + exorciseAp = ap_new(AP_DOMAIN, exorciseDomain); + rfc822_norm_dmn (exorciseAp, order_pref); +} + +static void do_exorcisedomain (pap, pgroup, pname, ploc, + pdom, proute) +AP_ptr *pap, *pgroup, *pname, *ploc, *pdom, *proute; +{ + AP_ptr ix; + if (*proute != NULLAP) { + for (ix = *proute; + ix != NULLAP && + ix -> ap_obtype != AP_DOMAIN + && ix -> ap_obtype != AP_DOMAIN_LITERAL; + ix = ix -> ap_next); + if (ix != NULLAP + && mustExorcise(ix->ap_obvalue) == TRUE) { + if (exorciseAp == NULLAP) + createExorciseAp(); + /* add exorciseAp immediately before ix */ + ap_insert(ix, AP_PTR_MORE, + ap_new(ix -> ap_obtype, + ix -> ap_obvalue)); + free(ix -> ap_obvalue); + ap_fllnode(ix, exorciseAp -> ap_obtype, + exorciseAp -> ap_obvalue); + } + } else if (*pdom != NULLAP) { + for (ix = *pdom; + ix != NULLAP && + ix -> ap_obtype != AP_DOMAIN + && ix -> ap_obtype != AP_DOMAIN_LITERAL; + ix = ix -> ap_next); + if (ix != NULLAP + && mustExorcise (ix->ap_obvalue) == TRUE) { + char *addrp; + if (exorciseAp == NULLAP) + createExorciseAp(); + /* add exorciseAp to route */ + addrp = ap_p2s(*pgroup, *pname, *ploc, + *pdom, exorciseAp); + ap_sqdelete (*pap, NULLAP); + ap_free(*pap); + ap_s2p(addrp, pap, pgroup, pname, ploc, pdom, proute); + free(addrp); + } + } +} + +/* */ +extern aliasList *aliases; + +static int out_adr(ap) +AP_ptr ap; +{ + AP_ptr loc_ptr, /* -- in case fake personal name needed -- */ + group_ptr, + name_ptr, + dom_ptr, + route_ptr, tmp; + char *addrp; + int len; + static rd = 0; + Aparse_ptr aparse = aparse_new(); + + if (ap->ap_obtype == AP_NIL) + return OK; + + rd++; + + aparse -> ad_type = AD_822_TYPE; + aparse -> dmnorder = order_pref; + aparse -> normalised = normalised; + aparse -> percents = percents; + aparse -> internal = internal; + + ap_t2s(ap, &(aparse->r822_str)); + if (aparse_norm(aparse) == NOTOK) { + ap = ap_t2p(ap, &group_ptr, &name_ptr, + &loc_ptr, &dom_ptr, &route_ptr); + } else { + tmp = ap; + ap = aparse->ap_tree; + aparse->ap_tree = tmp; + group_ptr = aparse->ap_group; + name_ptr = aparse->ap_name; + loc_ptr = aparse->ap_local; + dom_ptr = aparse->ap_domain; + route_ptr = aparse->ap_route; + } + aparse_free(aparse); + free ((char *) aparse); + + if (from && equalWithJntsender(loc_ptr)) + noFrom = 0; + + if (num_pairs != 0 + && changedomains != NULL) + do_changedomains (ap); + + /* do all stripping then create addrp */ + if ((dom_ptr != NULL) + && (num_to_hide != 0) + && do_hidedomains(dom_ptr, route_ptr)) { + + /* This might be local now, so go through the whole expansion + * process again. Remember though that we might be exremely + * silly, and cause `infinite' recursion. Hence the rd variable. + * + * If we are being silly we'll take what was demanded, and log an + * exception later + */ + + if (rd < 3) { + re_parse_ptr = addrp = ap_p2s(group_ptr, name_ptr, loc_ptr, + dom_ptr, route_ptr); + ap_sqdelete (ap, NULLAP); + ap_free (ap); + ap = ap_pstrt = ap_pcur = ap_alloc (); + ap_ppush(get_rp_char); + ap_clear(); + if (ap_1adr() == OK) + out_adr(ap); + ap_ppop(); + free(addrp); + rd--; + return OK; + /* NOTREACHED */ + } + } + if ((dom_ptr != NULL) + && (striproutes == TRUE)) + do_striproutes(&ap, &group_ptr, &name_ptr, &loc_ptr, + &dom_ptr, &route_ptr); + else if ((dom_ptr != NULL) + && (num_domains != 0)) + do_stripdomains(&ap, &group_ptr, &name_ptr, &loc_ptr, + &dom_ptr, &route_ptr); + + if (exorcise == TRUE) + do_exorcisedomain(&ap, &group_ptr, &name_ptr, &loc_ptr, + &dom_ptr, &route_ptr); + + addrp = ap_p2s(group_ptr, name_ptr, loc_ptr, + dom_ptr, route_ptr); + + + if (addrp == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/addr/ap_t2s: error from ap_p2s()")); + addrp = strdup ("(PP Error!)"); + } + if (rd == 3) { + PP_LOG (LLOG_EXCEPTIONS, + ("Format/rfc822norm: Excessive local hiding - lying about %s", addrp)); + } + + if (nadrs != 0) { + printf(", "); + pcol += 2; + } + + PP_TRACE(("output '%s'",addrp)); + + if ((len = strlen(addrp)) > 0) { /* print */ + pcol += len; + if (fold_width != -1 && pcol > fold_width && nonempty) { + pcol = strlen(fieldbuf) + 2 + len; + printf("\n%*s", strlen(fieldbuf) + 2, ""); + } else + nonempty = TRUE; + + printf("%s",addrp); + nadrs++; + } + free(addrp); +/* ap_sqdelete (ap, NULLAP); + ap_free (ap);*/ + rd--; + return OK; +} + +/* */ +static char *reverse(str) +char *str; +{ + char *ret = malloc((unsigned) strlen(str)+1), + *dup = strdup(str), + *ix; + ret[0] = '\0'; + while ((ix = rindex(dup,'.')) != NULL) { + if (ret[0] == '\0') + sprintf(ret, "%s", ix+1); + else + sprintf(ret,"%s.%s",ret,ix+1); + *ix = '\0'; + } + if (ret[0] == '\0') + sprintf(ret, "%s", dup); + else + sprintf(ret,"%s.%s",ret,dup); + free(dup); + return ret; +} + +/* */ + +static int valid_received (cont) +char *cont; +{ + if (index (cont, ';') == NULLCP) + return NOTOK; + return OK; +} + +static int valid_via(cont) +char *cont; +{ + char *sep, *ix; + if ((sep = index (cont, ';')) == NULLCP) + return NOTOK; + + for (ix = &(cont[0]); + ix != sep && isspace(*ix); + ix++); + + if (ix == sep) + return NOTOK; + + return OK; +} + +static int valid_x400(cont) +char *cont; +{ + char *sep; + /* at least two semi-colons */ + if ((sep = index(cont, ';')) == NULLCP + || index((sep+1), ';') == NULLCP) + return NOTOK; + return OK; +} + +int valid_trace(type, field, cont) +int type; +char *field; +char *cont; +{ + int retval = OK; + switch (type) { + case TRACE_RECIEVED: + retval = valid_received(cont); + break; + case TRACE_VIA: + retval = valid_via(cont); + break; + case TRACE_X400: + retval = valid_x400(cont); + break; + default: + break; + } + + if (retval == NOTOK) { + char *fold, *ix; + int nonempty = FALSE; + + printf("Original-%s: ", field); + ix = &(cont[0]); + while (*ix != '\0') { + fold = next_fold(ix+1, FOLD_SPACE); + if ((fold_width != -1) + && (fold - ix + pcol > fold_width) + && nonempty == TRUE) { + /* fold */ + pcol = strlen(field) + strlen("Original-: "); + printf("\n%*s", + strlen(field) + strlen("Original-: "), + ""); + while (isspace(*ix)) + ix++; + } else + nonempty = TRUE; + pcol += fold - ix; + while (ix != fold) + putchar (*ix++); + } + putchar('\n'); + + printf("PP-warning: Illegal %s field on preceding line\n", + rcmd_srch(type, tbl_tracefields)); + } + return retval; +} diff --git a/Format/rfc934/Makefile b/Format/rfc934/Makefile new file mode 100644 index 0000000..bd6576d --- /dev/null +++ b/Format/rfc934/Makefile @@ -0,0 +1,150 @@ +# Makefile for rfc934 filter channel +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Format/rfc934/RCS/Makefile,v 6.0 1991/12/18 20:21:02 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:21:02 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = do-rfc934.c rfc934.c +OBJS = do-rfc934.o rfc934.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +PROGS = xrfc934 + + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# rfc934 filter +# +############################################################ + +rfc934: xrfc934 + +xrfc934: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) \ + $(LIBPP) $(LIBSYS) + + + +############################################################ +# +# Misc stuff +# +############################################################ + +install: inst-dir inst-rfc934 + +inst-rfc934: $(CHANDIR)/rfc934 +$(CHANDIR)/rfc934: xrfc934 + -$(BACKUP) $@ zxrfc934 + rm -f $@ + $(INSTALL) xrfc934 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "rfc934 channel installed normally"; echo "" + +inst-dir: $(CHANDIR) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f $(PROGS) zxrfc934 core a.out *.old *.BAK + +lint: l-rfc934 + +l-rfc934: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +do-rfc934.o: do-rfc934.c +do-rfc934.o: ../../h/util.h +do-rfc934.o: ../../h/config.h +do-rfc934.o: ../../h/ll_log.h +do-rfc934.o: ../../h/retcode.h +do-rfc934.o: ../../h/tb_bpt84.h +rfc934.o: rfc934.c +rfc934.o: ../../h/util.h +rfc934.o: ../../h/config.h +rfc934.o: ../../h/ll_log.h +rfc934.o: ../../h/head.h +rfc934.o: ../../h/util.h +rfc934.o: ../../h/retcode.h +rfc934.o: ../../h/qmgr.h +rfc934.o: ../../h/Qmgr-types.h +rfc934.o: ../../h/Qmgr-ops.h +rfc934.o: ../../h/q.h +rfc934.o: ../../h/adr.h +rfc934.o: ../../h/list_rchan.h +rfc934.o: ../../h/chan.h +rfc934.o: ../../h/table.h +rfc934.o: ../../h/list_bpt.h +rfc934.o: ../../h/auth.h +rfc934.o: ../../h/list_bpt.h +rfc934.o: ../../h/extension.h +rfc934.o: ../../h/mta.h +rfc934.o: ../../h/adr.h +rfc934.o: ../../h/list_bpt.h +rfc934.o: ../../h/aparse.h +rfc934.o: ../../h/ap.h +rfc934.o: ../../h/util.h +rfc934.o: ../../h/or.h +rfc934.o: ../../h/chan.h +rfc934.o: ../../h/auth.h +rfc934.o: ../../h/list_rchan.h +rfc934.o: ../../h/mta.h +rfc934.o: ../../h/prm.h +rfc934.o: ../../h/chan.h +rfc934.o: ../../h/dr.h +rfc934.o: ../../h/extension.h +rfc934.o: ../../h/mta.h +rfc934.o: ../../h/sys.file.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Format/rfc934/do-rfc934.c b/Format/rfc934/do-rfc934.c new file mode 100644 index 0000000..38fe542 --- /dev/null +++ b/Format/rfc934/do-rfc934.c @@ -0,0 +1,585 @@ +/* do-rfc934.c: routines to carry out rfc934 conversion */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc934/RCS/do-rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc934/RCS/do-rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $ + * + * $Log: do-rfc934.c,v $ + * Revision 6.0 1991/12/18 20:21:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include +#include "retcode.h" +#include +#include "tb_bpt84.h" + + +extern CMD_TABLE bptbl_body_parts84[/* x400 84 body_parts */]; +extern char *hdr_822_bp; + +#define EBch '-' +#define Stuffing "- " + +char file[MAXPATHLENGTH], + line[LINESIZE]; +int fp; +int more = TRUE; +int start_depth = 0; +/* number of chars in buffer currently */ +int noInput = 0; +int err_fatal = FALSE; + +static int recursiveproc(); +static int ishdr(); +static int file_link(); +static void output_startmessage(); +static void output_endmessage(); +static int depth(); +static void output_stuffing(); +static void output_endbodypart(); +static void output_line(); +static int output_file(); +static int output_header(); +static void output_ia5(); +static int numBodyParts(); +static int bpFile(); +#define MaxCharPerInt 16 + +static char *itoa(i) +int i; +{ + char buf[MaxCharPerInt]; + + sprintf(buf,"%d",i); + + return strdup(buf); + +} + +int do_rfc934(from,to,perr) +char *from, /* original directory */ + *to, /* new directory */ + **perr; +{ + char hdr[MAXPATHLENGTH], + *stripped_hdr, + outfile[MAXPATHLENGTH], + buf[BUFSIZ], + wrkfile[MAXPATHLENGTH]; + int result = OK, + msgnum = 1, + fd_in, + first, + noBps, + bodynum; + noInput = 0; + msg_rinit(from); + start_depth = depth(from) + 1; + err_fatal = FALSE; + + noBps = numBodyParts(from); + + if (msg_rfile(hdr) != RP_OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 directory '%s' is empty",from)); + (void) sprintf (buf, + "directory '%s' is empty", + from); + *perr = strdup(buf); + return NOTOK; + } + if ((stripped_hdr = rindex(hdr,'/')) == NULL) + stripped_hdr = hdr; + else + stripped_hdr++; + + if (ishdr(stripped_hdr) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 cannot find hdr in '%s'",hdr)); + (void) sprintf (buf, + "Did not find valid header in message - unable to flatten"); + err_fatal = TRUE; + *perr = strdup(buf); + return NOTOK; + } + + if (result != OK) + return NOTOK; + if (msg_rfile(file) != RP_OK) { + /* empty body that's ok */ + result = file_link(from,to, + stripped_hdr); + return OK; + } + + more = TRUE; + first = TRUE; + + do { + if (depth(file) > start_depth) { + if (first == TRUE) { + result = put_out_header(hdr, to, stripped_hdr); + /* open output file */ + sprintf(outfile,"%s/1.ia5",to); + if ((fp = open(outfile, + O_WRONLY | O_CREAT | O_TRUNC, + 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, outfile, + ("Can't open file")); + (void) sprintf(buf, + "Unable to open output file '%s'", + outfile); + *perr = strdup(buf); + return NOTOK; + } + } + result = recursiveproc(msgnum++,perr); + } else { + strcpy(wrkfile, file); + if (msg_rfile(file) != RP_OK) + more = FALSE; + if (first == TRUE) { + if (more == FALSE) { + /* single body part */ + /* link hdr across */ + result = file_link(from,to, + stripped_hdr); + /* link single body part across */ + result = file_link(from, to, + rindex(wrkfile,'/')); + return result; + } else { + put_out_header(hdr, to, stripped_hdr); + /* open output file */ + sprintf(outfile,"%s/1.ia5",to); + if ((fp = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, outfile, + ("Can't open file")); + (void) sprintf(buf, + "Unable to open output file '%s'", + outfile); + *perr = strdup(buf); + return NOTOK; + } + + } + } + + if ((fd_in = open(wrkfile, O_RDONLY)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, wrkfile, + ("Can't open file")); + (void) sprintf (buf, + "Unable to open input file '%s'", + wrkfile); + *perr = strdup(buf); + result = NOTOK; + } + if (result == OK) { + result = output_file(fd_in,start_depth,wrkfile, noBps, &bodynum, perr); + if (more == FALSE) + output_endbodypart(fp, bodynum, start_depth); + close(fd_in); + } + } + first = FALSE; + } while (result == OK && more == TRUE); + close(fp); + return result; +} + +static int recursiveproc(num, perr) +int num; +char **perr; +/* uses external file */ +{ + int mydepth; + int fd_in; + int result = OK; + int bpnum, bodynum = 0; + char *dir_stub = NULL, buf[BUFSIZ], + *ix; + int cont, + msgnum = 1; + int noBps; + + mydepth = depth(file); + if ((ix = rindex(file,'/')) == NULL) + dir_stub = strdup(file); + else{ + while (*(ix-1) == '/') + ix--; + *ix = '\0'; + dir_stub = strdup(file); + *ix = '/'; + } + if ((ix = rindex(dir_stub, '/')) == NULL) + ix = dir_stub; + else + ix++; + bpnum = atoi(ix); + noBps = numBodyParts(dir_stub); + + output_startmessage(fp,num,bpnum,mydepth); + do { + /* output file with char stuffing */ + if ((fd_in = open(file, O_RDONLY)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, file, + ("Can't open file")); + (void) sprintf(buf, + "Unable to open input file '%s'", + file); + result = NOTOK; + } + if (result == OK) { + result = output_file(fd_in,mydepth,file,noBps, + &bodynum,perr); + close(fd_in); + } + + if (msg_rfile(file) != RP_OK) + more = FALSE; + else { + if (depth(file) > mydepth) + result = recursiveproc(msgnum++,perr); + bodynum = 0; + } + cont = FALSE; + if ((result == OK) + && (more == TRUE) + && (depth(file) == mydepth)) + cont = TRUE; + if ((ix = rindex(file,'/')) != NULL) { + while (*(ix-1) == '/') + ix--; + *ix = '\0'; + } + if ((cont == TRUE) + && (strcmp(dir_stub,file) != 0)) + cont = FALSE; + if (ix != NULL) + *ix = '/'; + } while ((result == OK) && (more == TRUE) && (cont == TRUE)); + if (dir_stub != NULL) free(dir_stub); + if (noBps > 1 && bodynum != 0) + output_endbodypart(fp, bodynum, mydepth); + output_endmessage(fp,num,bpnum,mydepth); + return result; +} + +static int ishdr(name) +char *name; +{ + +/* if (strcmp(name,rcmd_srch(BPT_HDR_P2,bptbl_body_parts84)) == 0) + return OK; + if (strcmp(name,rcmd_srch(BPT_HDR_822,bptbl_body_parts84)) == 0) + return OK;*/ + if (strncmp(name,hdr_822_bp,strlen(hdr_822_bp)) == 0) + return OK; + return NOTOK; +} + +/* */ +/* input and output routines */ +#define CMASK 0377 /* for making char's > 0 */ + +#define Start_message "------------------------------ Start of forwarded message " + +static void output_startmessage(fd, num, bpnum, deep) +int fd; +int num; +int bpnum; +int deep; +{ + char *cnum = itoa(num); + if (bpnum != 1) + write(fd,"\n",strlen("\n")); + output_stuffing(fd,deep-1); + write(fd,Start_message,strlen(Start_message)); + write(fd,cnum,strlen(cnum)); + free(cnum); +/* write(fd," (bodypart ",strlen("(bodypart ")); + cnum = itoa(bpnum); + write(fd,cnum,strlen(cnum));*/ + write(fd,"\n\n",strlen("\n\n")); + free(cnum); +} + +#define End_message "------------------------------ End of forwarded message " + +static void output_endmessage(fd,num,bpnum,deep) +int fd, + num, + bpnum, + deep; +{ + char *cnum = itoa(num); + write(fd,"\n",strlen("\n")); + output_stuffing(fd,deep-1); + write(fd,End_message,strlen(End_message)); + write(fd,cnum,strlen(cnum)); + free(cnum); +/* write(fd," (bodypart ",strlen("(bodypart ")); + cnum = itoa(bpnum); + write(fd,cnum,strlen(cnum));*/ + if (more == FALSE) + write(fd,"\n",strlen("\n")); + else + write(fd,"\n\n",strlen("\n\n")); + free(cnum); +} + +#define Bodypart_seperatorstart "------------------------------ Start of body part " +#define Bodypart_seperatorend "------------------------------ End of body part " + +static int output_startbodypart(fd, num, deep) +int fd; +int num; +int deep; +{ + char *cnum = itoa(num); + write(fd,"\n",strlen("\n")); + output_stuffing(fd,deep); + write(fd,Bodypart_seperatorstart,strlen(Bodypart_seperatorstart)); + write(fd,cnum,strlen(cnum)); + write(fd,"\n\n",strlen("\n\n")); + free(cnum); +} + +static void output_endbodypart(fd, num, deep) +int fd; +int num; +int deep; +{ + char *cnum = itoa(num); + + write(fd,"\n",strlen("\n")); + output_stuffing(fd,deep); + write(fd,Bodypart_seperatorend,strlen(Bodypart_seperatorend)); + write(fd,cnum,strlen(cnum)); + if (more == FALSE) + write(fd,"\n",strlen("\n")); + else + write(fd,"\n\n",strlen("\n\n")); + free(cnum); +} + + +static int mygetchar(fd) +int fd; +{ + static unsigned char buf[MAXPATHLENGTH]; + static unsigned char *bufp = buf; + + if (noInput == 0) { /* buffer is empty */ + noInput = read(fd, buf, MAXPATHLENGTH); + bufp = buf; + } + return ((--noInput >= 0) ? *bufp++ : EOF); +} + +static int getline(fd,linebuf) +int fd; +char linebuf[]; +{ + int i = 0; + int c; + while (i < LINESIZE && ((c = mygetchar(fd)) != EOF) && c != '\n') + linebuf[i++] = c; + if (c == '\n') + linebuf[i++] = c; + linebuf[i] = '\0'; + return i; +} + +static void output_stuffing(fd, deep) +int fd; +int deep; +{ + int i = 0; + while (i++ < (deep - start_depth)) + write(fd,Stuffing,strlen(Stuffing)); +} + +static void output_line(fd,buf) +int fd; +char buf[]; +{ + write(fd,buf,strlen(buf)); +} + +static int output_file(fd_in, deep, filename, noBps,pnum, perr) +int fd_in, + deep; +char *filename; +int noBps; +int *pnum; +char **perr; +{ + char *ix = NULL, buf[BUFSIZ], + *ix2; + /* reset input buffer */ + noInput = 0; + + if (((ix = rindex(filename,'/')) != NULL) + && (strncmp(++ix, hdr_822_bp, strlen(hdr_822_bp)) == 0)) { + output_header(fd_in, FALSE); + output_line(fp, "\n"); + return OK; + } else if (strcmp(ix,rcmd_srch(BPT_P2_DLIV_TXT, bptbl_body_parts84)) == 0) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 : illegal file type '%s' ignoring it",filename)); + return OK; + } + + if (((ix = rindex(filename,'.')) != NULL) && + (strcmp(++ix, rcmd_srch(BPT_IA5, bptbl_body_parts84)) == 0)) { + *(ix - 1) = '\0'; + ix2 = rindex(filename,'/'); + *ix2++ = '\0'; + *pnum = atoi(ix2); + output_ia5(fd_in, deep, *pnum, noBps); + *(ix - 1) = '.'; + *(ix2 - 1) ='/'; + return OK; + } + + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 : illegal file type '%s' BOMBING OUT",filename)); + (void) sprintf(buf, + "illegal file type '%s' unable to flatten", + filename); + *perr = strdup(buf); + err_fatal = TRUE; + return NOTOK; +} + +static int output_header(fd_in, first) +int fd_in; +int first; +{ + int msgtype; + + msgtype = FALSE; + while(getline(fd_in,line) != 0) { + if (first == TRUE + && line[0] == '\n' + && msgtype == FALSE) + output_line(fp, "Message-Type: Multiple Part"); + output_line(fp, line); + if (strncmp(line, "Message-Type", strlen("Message-Type")) == 0) + msgtype = TRUE; + } + return msgtype; +} + +static void output_ia5(fd_in, deep, bp_num, noBps) +int fd_in, + deep, + bp_num, + noBps; +{ + if (noBps > 1) + output_startbodypart(fp, bp_num, deep); + while (getline(fd_in,line) != 0) { + if (line[0] == EBch) + output_stuffing(fp, deep); + output_line(fp, line); + } +} + + +static int depth (filename) +char *filename; +{ + char *p; + int count = 0; + + for (p = filename; *p; p++) + if (*p == '/') { + count ++; + while(*p == '/') p++; + } + return count; +} + +static int file_link(orig,tmp,filename) +char *orig, /* original message directory */ + *tmp, /* new temporary directory */ + *filename; /* file to link across */ +{ + char old[MAXPATHLENGTH], /* old file */ + new[MAXPATHLENGTH]; /* new link */ + struct stat statbuf; + int result = OK; + + (void) sprintf(old, "%s/%s",orig,filename); + + (void) sprintf(new, "%s/%s",tmp,filename); + + if ((stat(old, &statbuf) == OK) + && (stat(new, &statbuf) != OK) + && (link(old, new) != -1)) { + result = OK; + } else + result = NOTOK; + + return result; +} + +put_out_header(old, to, stripped_hdr) +char *old, + *to, + *stripped_hdr; +{ + int fd_in; + char outfile[MAXPATHLENGTH]; + int gotMsgType = FALSE; + if ((fd_in = open(old, O_RDONLY)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, old, + ("Can't open file")); + return NOTOK; + } + + sprintf(outfile,"%s/%s",to, stripped_hdr); + if ((fp = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { + PP_SLOG(LLOG_EXCEPTIONS, outfile, + ("Can't open file")); + return NOTOK; + } + gotMsgType = output_header(fd_in, TRUE); + close(fd_in); + close(fp); + return OK; +} + +static int bpFile(entry) +struct dirent *entry; +{ + if (strcmp(entry->d_name, "..") == 0 + || strcmp(entry->d_name, ".") == 0 + || strncmp(entry->d_name, hdr_822_bp, strlen(hdr_822_bp)) == 0) + return 0; + return 1; +} + +static int numBodyParts(dir) +char *dir; +{ + struct dirent **namelist = NULL; + + int ret = _scandir(dir, &namelist, bpFile, NULLIFP); + + if (namelist) free ((char *) namelist); + return ret; +} diff --git a/Format/rfc934/make b/Format/rfc934/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Format/rfc934/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Format/rfc934/rfc934.c b/Format/rfc934/rfc934.c new file mode 100644 index 0000000..54eafb6 --- /dev/null +++ b/Format/rfc934/rfc934.c @@ -0,0 +1,332 @@ +/* rfc934.c: rfc934 filter channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc934/RCS/rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Format/rfc934/RCS/rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $ + * + * $Log: rfc934.c,v $ + * Revision 6.0 1991/12/18 20:21:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "head.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "chan.h" +#include "dr.h" +#include +#include "sys.file.h" + +extern char *quedfldir; +extern char *chndfldir; +extern void sys_init(), err_abrt(), rd_end(); +CHAN *mychan; +char *this_msg = NULL, *this_chan = NULL; +extern int err_fatal; +int first_failureDR; + +static struct type_Qmgr_DeliveryStatus *process (); +static int initialise (); +static int security_check (); +static void dirinit (); +static struct type_Qmgr_DeliveryStatus *new_DeliveryStatus(); +static ADDR *getnthrecip (); +static int filterMsg(); +static int doFilter(); +/* */ +/* main routine */ + +main (argc, argv) +int argc; +char **argv; +{ + sys_init(argv[0]); + dirinit (); +#ifdef PP_DEBUG + if (argc>1 && (strcmp(argv[1],"debug") == 0)) + debug_channel_control(argc,argv,initialise,process,NULLIFP); + else +#endif + channel_control (argc, argv, initialise, process,NULLIFP); +} + +/* */ +/* routine to move to correct place in file system */ + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, " Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialise routine */ + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + + name = qb2str(arg); + + if ((mychan = ch_nm2struct(name)) == NULLCHAN) { + PP_OPER(NULLCP, + ("Chans/rfc934 : Channel '%s' not known",name)); + if (name != NULL) free(name); + return NOTOK; + } + + /* check if a rfc934 channel */ + if (name != NULL) free(name); + return OK; +} + +/* */ +/* routine to check if allowed to rfc934 filter this message */ +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + char *msg_file = NULL, *msg_chan = NULL; + int result; + + result = TRUE; + msg_file = qb2str (msg->qid); + msg_chan = qb2str (msg->channel); + + if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 channel err: '%s'",msg_chan)); + result = FALSE; + } + if (msg_file != NULL) free(msg_file); + if (msg_chan != NULL) free(msg_chan); + return result; +} + +/* */ +/* routine called to do rfc934 filter */ + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + int retval; + struct type_Qmgr_UserList *ix; + ADDR *adr; + char *error; + bzero((char *)&prm,sizeof(prm)); + bzero((char *)&que,sizeof(que)); + first_failureDR = TRUE; + + delivery_init(arg->users); + delivery_setall(int_Qmgr_status_messageFailure); + + if (security_check(arg) != TRUE) + return deliverystate; + + if (this_msg != NULL) free(this_msg); + if (this_chan != NULL) free(this_chan); + + this_msg = qb2str(arg->qid); + this_chan = qb2str(arg->channel); + + PP_LOG(LLOG_NOTICE, + ("filtering msg '%s' through '%s'",this_msg, this_chan)); + + if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 rd_msg err: '%s'",this_msg)); + rd_end(); + return delivery_setallstate (int_Qmgr_status_messageFailure, + "Can't read message"); + } + + /* check each recipient for processing */ + for (ix = arg->users; ix; ix = ix->next) { + error = NULLCP; + if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 : failed to find recipient %d of msg '%s'",ix->RecipientId->parm, this_msg)); + + delivery_setstate(ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch (chan_acheck(adr, mychan, 1, NULL)) { + case OK: + if (filterMsg(this_msg,adr, &error) == NOTOK) { + if (err_fatal == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("failed to flatten msg '%s' (FATAL)", + this_msg)); + set_1dr(&que, adr->ad_no, this_msg, + DRR_CONVERSION_NOT_PERFORMED, + DRD_CONTENT_SYNTAX_ERROR, + (error == NULLCP) ? "Unable to flatten the message" : error); + delivery_set(adr->ad_no, + (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR); + first_failureDR = FALSE; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 : failed to filter msg '%s' for recip '%d' on channel '%s'",this_msg, adr->ad_no, this_chan)); + delivery_setstate(adr->ad_no, + int_Qmgr_status_messageFailure, + (error == NULLCP) ? "Failed to flatten message" : error); + } + } else { + /* CHANGE update adr->ad_rcnt in struct and in file */ + adr->ad_rcnt++; + wr_ad_rcntno(adr,adr->ad_rcnt); + delivery_set(adr->ad_no, + int_Qmgr_status_success); + } + break; + default: + break; + } + if (error != NULLCP) + free(error); + } + if (rp_isbad(retval = wr_q2dr(&que, this_msg))) { + PP_LOG(LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'",mychan->ch_name,retval)); + delivery_resetDRs(int_Qmgr_status_messageFailure); + } + rd_end(); + q_free (&que); + prm_free(&prm); + return deliverystate; +} + +/* */ +static int filterMsg (msg,recip,perr) +/* return OK if managed to filter msg through mychan for recip */ +char *msg; +ADDR *recip; +char **perr; +{ + char *origdir = NULL, + *newdir = NULL; + int result = OK; + struct stat statbuf; + + if (qid2dir(msg, recip, TRUE, &origdir) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 original directory not found for recipient %d of message '%s'",recip->ad_no, msg)); + *perr = strdup("Can't find source directory"); + result = NOTOK; + } + + /* temporary change to get new directory name */ + recip->ad_rcnt++; + if ((result == OK) + && (qid2dir(msg, recip, FALSE, &newdir) != OK)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Chans/rfc934 couldn't construct new directory for recipient '%d' of message '%s'",recip->ad_no, msg)); + *perr = strdup("Can't construct destination directory"); + result = NOTOK; + } + recip->ad_rcnt--; + + if ((result == OK) + && (stat(newdir, &statbuf) == OK) + && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) { + /* directory already exists and so filter already done */ + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return OK; + } + + if ((result == OK) && (doFilter(origdir,newdir,msg, perr) != OK)) + result = NOTOK; + + if (origdir != NULL) free(origdir); + if (newdir != NULL) free(newdir); + return result; +} + +/* */ +static doFilter (orig, new, msg, perr) +/* filters orig directory through mychan to new directory */ +char *orig, + *new, + *msg, + **perr; +{ + char tmpdir[MAXPATHLENGTH], buf[BUFSIZ]; + int result = OK; + struct stat statbuf; + + (void) sprintf(tmpdir, "%s/tmp.%s", + msg, mychan->ch_name); + + if (stat(tmpdir, &statbuf) == OK) { + char *cmd_line; + /* exists so remove it */ + cmd_line = malloc((unsigned) (strlen("rm -rf ") + + strlen(tmpdir) + 1)); + sprintf(cmd_line, "rm -rf %s", tmpdir); + system(cmd_line); + if (cmd_line != NULL) free(cmd_line); + } + + if (mkdir(tmpdir, 0777) != OK) { + PP_SLOG(LLOG_EXCEPTIONS, tmpdir, + ("Can't make directory")); + (void) sprintf (buf, + "Failed to make temporary directory '%s'", + tmpdir); + *perr = strdup(buf); + result = NOTOK; + } + + if (result == OK) { + /* filter from orig to tmpdir */ + result = do_rfc934(orig,tmpdir,perr); + /* if success rename tmpdir to new */ + if ((result == OK) && (rename(tmpdir,new) == -1)) { + PP_SLOG(LLOG_EXCEPTIONS, "rename", + ("Can't rename directory '%s' to '%s'", + tmpdir, new)); + (void) sprintf (buf, + "Failed to rename '%s' to '%s'", + tmpdir,new); + *perr = strdup(buf); + result = NOTOK; + } + + } + return result; +} + +/* */ +/* auxilary routines to extract from lists */ +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} + diff --git a/Lib/Makefile b/Lib/Makefile new file mode 100644 index 0000000..4a16e97 --- /dev/null +++ b/Lib/Makefile @@ -0,0 +1,68 @@ +# Library building Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/RCS/Makefile,v 6.0 1991/12/18 20:26:14 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:26:14 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = qmgr x400 addr format io or parse pp table tai charset util +SHADOW = ranlib-made +LIB = libpp.a +LINTLIB = llib-lpp.ln +CFLAGS = $(LIBCCOPTIONS) $(LCF) + +default: bits-made ${SHADOW} + +install: + @for x in ${SUBDIRS}; \ + do (echo "cd $$x; $(MAKE) $@";cd $$x; $(MAKE) $@); done + +bits-made: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x; $(MAKE)"; cd $$x ; $(MAKE) ) ; done + +${SHADOW}: $(LIB) + @$(MAKE) ppversion.o + $(AR) r$(ARFLAGS) $(LIB) ppversion.o + $(RANLIB) ${LIB} + touch $@ + +ppversion.c: $(LIB) version.major version.minor + @./version.sh pp > $@ + +lintlib: lint-bits concat-lint + +lint-bits: + @for x in ${SUBDIRS}; \ + do (echo "cd $$x; $(MAKE) lintlib"; cd $$x ; $(MAKE) lintlib); done + +concat-lint: + rm -f ${LINTLIB} + @for x in ${SUBDIRS}; \ + do cat $$x/*.ln >> ${LINTLIB}; done + +clean: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x; $(MAKE) $@"; cd $$x ; $(MAKE) $@ ); done + rm -f core *.old *.BAK ${SHADOW} *.o ${LIB} $(LINTLIB) + +tidy: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x; $(MAKE) $@"; cd $$x ; $(MAKE) $@ ); done + rm -f core *.old *.BAK ${SHADOW} *.o + +depend lint: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x; $(MAKE)"; cd $$x ; $(MAKE) $@ ); done diff --git a/Lib/addr/Makefile b/Lib/addr/Makefile new file mode 100644 index 0000000..0835650 --- /dev/null +++ b/Lib/addr/Makefile @@ -0,0 +1,214 @@ +# Makefile to build the 822 addressing stuff +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/addr/RCS/Makefile,v 6.0 1991/12/18 20:21:24 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:21:24 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ap_1adr.c ap_dmflip.c ap_file.c ap_lex.c ap_lex_tb.c ap_norm.c \ + ap_p2s.c ap_s2p.c ap_s2t.c ap_t2p.c ap_t2s.c ap_ut.c \ + ap_val2str.c ap_s2s.c ap_equ.c +OBJS = ap_1adr.o ap_dmflip.o ap_file.o ap_lex.o ap_lex_tb.o ap_norm.o \ + ap_p2s.o ap_s2p.o ap_s2t.o ap_t2p.o ap_t2s.o ap_ut.o \ + ap_val2str.o ap_s2s.o ap_equ.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -DAP_DEBUG -I$(HEADERS) $(LCF) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = addr-made +LINTLIBS = ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SHADOW) + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lintlib: llib-laddr.ln +llib-laddr.ln: $(SRCS) + $(LINT) $(LLFLAGS) -Caddr $(SRCS) + +install:; + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +clean: tidy + rm -f $(OBJS) llib-laddr.ln +tidy: + rm -f core $(SHADOW) *.old *.BAK + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ap_1adr.o: ap_1adr.c +ap_1adr.o: ../../h/util.h +ap_1adr.o: ../../h/config.h +ap_1adr.o: ../../h/ll_log.h +ap_1adr.o: ../../h/ap.h +ap_1adr.o: ../../h/util.h +ap_1adr.o: ../../h/ap_lex.h +ap_dmflip.o: ap_dmflip.c +ap_dmflip.o: ../../h/util.h +ap_dmflip.o: ../../h/config.h +ap_dmflip.o: ../../h/ll_log.h +ap_file.o: ap_file.c +ap_file.o: ../../h/util.h +ap_file.o: ../../h/config.h +ap_file.o: ../../h/ll_log.h +ap_file.o: ../../h/ap.h +ap_file.o: ../../h/util.h +ap_lex.o: ap_lex.c +ap_lex.o: ../../h/util.h +ap_lex.o: ../../h/config.h +ap_lex.o: ../../h/ll_log.h +ap_lex.o: ../../h/ap.h +ap_lex.o: ../../h/util.h +ap_lex.o: ../../h/ap_lex.h +ap_lex_tb.o: ap_lex_tb.c +ap_lex_tb.o: ../../h/util.h +ap_lex_tb.o: ../../h/config.h +ap_lex_tb.o: ../../h/ll_log.h +ap_lex_tb.o: ../../h/ap_lex.h +ap_lex_tb.o: ../../h/ap.h +ap_lex_tb.o: ../../h/util.h +ap_norm.o: ap_norm.c +ap_norm.o: ../../h/head.h +ap_norm.o: ../../h/util.h +ap_norm.o: ../../h/config.h +ap_norm.o: ../../h/ll_log.h +ap_norm.o: ../../h/retcode.h +ap_norm.o: ../../h/chan.h +ap_norm.o: ../../h/table.h +ap_norm.o: ../../h/list_bpt.h +ap_norm.o: ../../h/ap.h +ap_norm.o: ../../h/util.h +ap_p2s.o: ap_p2s.c +ap_p2s.o: ../../h/util.h +ap_p2s.o: ../../h/config.h +ap_p2s.o: ../../h/ll_log.h +ap_p2s.o: ../../h/chan.h +ap_p2s.o: ../../h/table.h +ap_p2s.o: ../../h/list_bpt.h +ap_p2s.o: ../../h/ap.h +ap_p2s.o: ../../h/util.h +ap_s2p.o: ap_s2p.c +ap_s2p.o: ../../h/util.h +ap_s2p.o: ../../h/config.h +ap_s2p.o: ../../h/ll_log.h +ap_s2p.o: ../../h/ap_lex.h +ap_s2p.o: ../../h/ap.h +ap_s2p.o: ../../h/util.h +ap_s2t.o: ap_s2t.c +ap_s2t.o: ../../h/util.h +ap_s2t.o: ../../h/config.h +ap_s2t.o: ../../h/ll_log.h +ap_s2t.o: ../../h/ap.h +ap_s2t.o: ../../h/util.h +ap_t2p.o: ap_t2p.c +ap_t2p.o: ../../h/util.h +ap_t2p.o: ../../h/config.h +ap_t2p.o: ../../h/ll_log.h +ap_t2p.o: ../../h/ap.h +ap_t2p.o: ../../h/util.h +ap_t2s.o: ap_t2s.c +ap_t2s.o: ../../h/util.h +ap_t2s.o: ../../h/config.h +ap_t2s.o: ../../h/ll_log.h +ap_t2s.o: ../../h/ap.h +ap_t2s.o: ../../h/util.h +ap_ut.o: ap_ut.c +ap_ut.o: ../../h/util.h +ap_ut.o: ../../h/config.h +ap_ut.o: ../../h/ll_log.h +ap_ut.o: ../../h/ap.h +ap_ut.o: ../../h/util.h +ap_val2str.o: ap_val2str.c +ap_val2str.o: ../../h/util.h +ap_val2str.o: ../../h/config.h +ap_val2str.o: ../../h/ll_log.h +ap_val2str.o: ../../h/ap.h +ap_val2str.o: ../../h/util.h +ap_s2s.o: ap_s2s.c +ap_s2s.o: ../../h/util.h +ap_s2s.o: ../../h/config.h +ap_s2s.o: ../../h/ll_log.h +ap_s2s.o: ../../h/ap.h +ap_s2s.o: ../../h/util.h +ap_equ.o: ap_equ.c +ap_equ.o: ../../h/util.h +ap_equ.o: ../../h/config.h +ap_equ.o: ../../h/ll_log.h +ap_equ.o: ../../h/ap.h +ap_equ.o: ../../h/util.h +ap_equ.o: ../../h/adr.h +ap_equ.o: ../../h/list_rchan.h +ap_equ.o: ../../h/chan.h +ap_equ.o: ../../h/table.h +ap_equ.o: ../../h/list_bpt.h +ap_equ.o: ../../h/auth.h +ap_equ.o: ../../h/list_bpt.h +ap_equ.o: ../../h/extension.h +ap_equ.o: ../../h/mta.h +ap_equ.o: ../../h/adr.h +ap_equ.o: ../../h/list_bpt.h +ap_equ.o: ../../h/aparse.h +ap_equ.o: ../../h/ap.h +ap_equ.o: ../../h/or.h +ap_equ.o: ../../h/chan.h +ap_equ.o: ../../h/auth.h +ap_equ.o: ../../h/list_rchan.h +ap_equ.o: ../../h/chan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/addr/ap_1adr.c b/Lib/addr/ap_1adr.c new file mode 100644 index 0000000..cfe7e19 --- /dev/null +++ b/Lib/addr/ap_1adr.c @@ -0,0 +1,670 @@ +/* ap_1adr.c: parse one address - the heart of the parser */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_1adr.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_1adr.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_1adr.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* ADDRESS PARSER, as per: + + "Standard for the Format of ARPA Network Text Messages", D. Crocker, + J. Vittal, K. Pogran & D. Henderson, in ARPANET PROTOCOL HANDBOOK, E. + Feinler & J. Postel (eds), NIC-7104-REV-1, Network Information Center, + SRI International: Menlo Park, Ca. (1978) (NTIS AD-A0038901). + + and + + "Standard for the Format of Arpa Internet Text Messages", Revised + by D. Crocker, RFC #822, in INTERNET PROTOCOL TRANSITION WORKBOOK, + Feinler & J. Postel (eds), Network Information Center, SRI + International: Menlo Park, Ca. (March 1982). + + A parsed address is normalized to have routing references placed + into rfc822-type positioning. + + History: + + Fall 1977 Bruce Borden: Initial Design & Coding + Summer 1979 Dave Crocker: Completed it & fixed bugs + Major reorganization & re-labeling + Minor changes to semantics + Documentation + Sept 81 Andy Knutsen case STPREND -> STPHRSE, to allow comments + afterwards + Sept 81 Dave Crocker generalized the use of STPHRSE, so that + STOKEND occurs only on comma or eof. + changed again, to cycle only accepting + comments + Nov 82 Dave Crocker Converted to accept 822 syntax, while + trying also to juggle 733... + Aug 83 Steve Kille Fix to STEPER + + This module is the real parser, tho it is intended to be co-routined + with a caller who has something specific to do with ap_1adr's output. + This is organized so as to make some attempt at limiting core + consumption. Fullparse(), however, simply causes a full parse tree to + be built up in core. + + The implementation deviates somewhat from the above specification. + Deviations and the use of the package are discussed in the companion + documentation. + + The parser's behavior is fairly straightforward. A singly-linked flat + list of labelled (lexical) nodes is built up. Ap_1adr() is used to get + the next "address segment", which consists of all of the lexical nodes + up to the end of the next host-phrase (i.e., usually that means up to + the next comma, semi-colon, or right-angle bracket). + + The caller is responsible for initializing state variables, via + ap_init(), and linking together or using ap_1adr's output segments. + + Note that ap_1adr does NOT interpret address text to cause re-directed + file input. The caller must do that. Ap_pshfil() and ap_popfil() can + be used to save and restore the parse state and acquire the named file. + The provision for this stacking, given the co-routining, is the reason + state information is chained through global variables, rather than + being saved on local (stack) variables. + + The amount of input processed on a single call may seem strange. The + idea is to try to guess the most common use of the routine. This is + presumed to be for address checking, in which acquisition of the MBOX + and DOMAIN text are most important, with the rest actually being thrown + away. It is, of course, possible for the core-limiting heuristic to + lose if a ridiculous number of groups and personal lists are specified + in a particular way. I am assuming that won't happen. + */ + + + +#include "util.h" +#include "ap.h" +#include "ap_lex.h" + + + +#define STDOMAIN 0 +#define STDTYPE 1 +#define STEBAD 2 +#define STECMNT 3 +#define STEDOMAIN 4 +#define STEDONE 5 /* Returned when addresses were NOT found */ +#define STEDTYPE 6 +#define STEGRP 7 +#define STEOK 8 /* Returned when addresses were found */ +#define STEPER 9 +#define STINIT 10 +#define STITER 11 +#define STPHRSE 12 +#define STSTPER 13 + + +int ap_intype = AP_PARSE_733; /* default to RFC #733 input */ +int ap_outtype = AP_PARSE_822; /* default to RFC #822 output */ + /* with little endian domains */ + +int ap_grplev = 0; /* Group nesting depth */ +int ap_perlev = 0; /* <> nesting depth */ +int ap_routing; /* parsing a route */ + + + +#ifdef AP_DEBUG + +extern AP_ptr ap_sqinsert (); +extern char *strdup(); +char ap_debug=TRUE; /* True if in debug mode */ + + +char *statnam[] = { + "Domain", "DTypNam", "BadEnd", "CmntEnd", + "DomainE", "DoneEnd", "DTypeE", "GrpEnd", + "OKEnd", "PersEnd", "Init", "Iterate", + "Phrase", "Persstrt", +}; + + +char *typtab[] = +{ + "Nil", "Comment", "DataType", "Domain", + "DomainLit", "Word", "GpEnd", "GpName", + "GpStart", "Mailbox", "PersonEnd", "PersonName", + "PersonStart" +}; +#endif +/* */ + + + +/* --------------------- Begin Routines -------------------------------- */ + + +int ap_1adr () +{ + struct ap_node base_node; + AP_ptr ap_sp = NULLAP, /* Saved ap node ptr */ + ap_noname, + r822_ptr = NULLAP, + r733_prefptr; + int got_822, + noname; + char buf[BUFSIZ]; + register int state; + + + ap_routing = DONE; + ap_noname = NULL; + ap_ninit (&base_node); + + (void) ap_sqinsert (&base_node, AP_PTR_MORE, ap_pstrt); + + for (state = STINIT, got_822 = FALSE, noname = FALSE, r733_prefptr = NULLAP; ; ) { + + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("=>%d (%s)", state, + (state >= 0 && state <= 13) ? + statnam[state] : "BOGUS!")); +#endif + + + switch (state) { + case STITER: + /* -- Iteration to get real address -- */ + ap_palloc (); + state = STINIT; + /* just drop on through -- */ + + case STINIT: + /* -- start of parse; empty node -- */ + ap_sp = ap_pcur; + switch (ap_lex (buf, sizeof(buf))) { + case LV_WORD: + ap_pfill (AP_GENERIC_WORD, buf); + if (noname == TRUE) { + /* no name before so copy buf into ap_noname */ + ap_noname->ap_obvalue = + (buf == NULLCP) ? NULLCP : strdup(buf); + ap_noname = NULL; + noname = FALSE; + } + state = STPHRSE; + break; + + case LV_AT: + if (!got_822) { + got_822 = TRUE; + r822_ptr = ap_pcur; + } + ap_routing = OK; +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(routing)")); +#endif + state = STDOMAIN; + break; + + case LV_COLON: + /* -- data type start -- */ + state = STDTYPE; + break; + + case LV_SEMI: + /* -- group list end -- */ + state = STEGRP; + break; + + case LV_GRTR: + /* -- personal list end -- */ + state = STEPER; + break; + + case LV_LESS: + /* -- allow one angle-bracket, here -- */ + ap_pfill (AP_GENERIC_WORD, ""); + noname = TRUE; + ap_noname = ap_pcur; + state = STSTPER; + break; + + case LV_FROM: + /* -- file source -- */ + ap_pfill (AP_DATA_TYPE, "Include"); + state = STITER; + break; + + case LV_COMMENT: + ap_pfill (AP_COMMENT, buf); + state = STITER; + break; + + case LV_COMMA: + /* -- ignore null addresses -- */ + break; + + case LV_EOD: + if (ap_perlev != 0 || ap_grplev != 0) + state = STEBAD; + else + state = STEDONE; + break; + + default: + state = STEBAD; + break; + } + + continue; + + +/* --------------------------- Ending --------------------------------- */ + + + case STECMNT: + /* -- accept comments until end -- */ + switch (ap_lex (buf, sizeof(buf))) { + case LV_COMMENT: + /* -- just cycle, accepting comments -- */ +/* ap_pfill (AP_COMMENT, buf);*/ + ap_pappend(AP_COMMENT, buf); + break; + + case LV_COMMA: + state = STEOK; + break; + + case LV_SEMI: + /* -- group list end -- */ + state = STEGRP; + break; + + case LV_EOD: + state = STEOK; + break; + + default: + state = STEBAD; + break; + } + + continue; + + + + case STEDONE: + /* -- end clean; no empty nodes? -- */ + ap_7to8 (r733_prefptr, r822_ptr); + return (DONE); + + + + case STEOK: + /* -- end clean -- */ + ap_7to8 (r733_prefptr, r822_ptr); + return (OK); + + + + case STEBAD: + /* -- end error -- */ + ap_clear(); /* Experimental, DPK, 7 Aug 84 */ + return (NOTOK); + + + + +/* ----------------------- Gather a phrase ------------------------------ */ + + + case STPHRSE: + /* -- phrase continuation; empty node -- */ + switch (ap_lex (buf, sizeof(buf))) { + case LV_WORD: + /* -- append word to phrase, maybe -- */ + ap_pappend (AP_GENERIC_WORD, buf); + break; + + case LV_AT: + /* -- mailbox (name) end -- */ + if (!got_822) { + r822_ptr = ap_sp; + got_822 = TRUE; + } + ap_sqtfix (ap_sp, ap_pcur, AP_MAILBOX); + ap_palloc (); + state = STDOMAIN; + break; + + case LV_LESS: + /* -- person name end -- */ + state = STSTPER; + break; + + case LV_COLON: + /* -- group name end -- */ + if (ap_grplev++ >= 1 && ap_intype == AP_PARSE_822) { + /* -- may not be nested -- */ + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(intype=%d,ap_grplev=%d)", + ap_intype, + ap_grplev)); +#endif + + state = STEBAD; + break; + } + ap_sqtfix (ap_sp, ap_pcur, AP_GROUP_START); + ap_sp -> ap_obtype = AP_GROUP_NAME; + state = STITER; + break; + + case LV_SEMI: + ap_sqtfix (ap_sp, ap_pcur, AP_MAILBOX); + ap_sp -> ap_obtype = AP_MAILBOX; + state = STEGRP; + break; + + case LV_GRTR: + state = STEPER; + break; + + case LV_COMMA: + ap_sqtfix (ap_sp, ap_pcur, AP_MAILBOX); + state = STEOK; + break; + case LV_EOD: + ap_sqtfix (ap_sp, ap_pcur, AP_MAILBOX); + state = STEOK; + break; + case LV_COMMENT: + ap_pappend (AP_COMMENT, buf); + break; + default: + state = STEBAD; + break; + } + + continue; + + +/* ------------------------- Address lists ---------------------------- */ + + + case STSTPER: + /* -- personal address list; no empty node -- */ + if (ap_perlev++ > 0 && ap_intype == AP_PARSE_822) { + /* -- may not be nested -- */ +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(intype=%d,ap_perlev=%d)", + ap_intype, + ap_perlev)); +#endif + state = STEBAD; + break; + } + ap_routing = OK; + ap_sqtfix (ap_sp, ap_pcur, AP_PERSON_START); + ap_sp -> ap_obtype = AP_PERSON_NAME; + state = STITER; + continue; + + + case STEPER: + if (--ap_perlev < 0) { + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(ap_perlev=%d)", ap_perlev)); +#endif + + state = STEBAD; + break; + } + ap_pappend (AP_PERSON_END, NULLCP); + ap_palloc (); /* SEK add storage */ + state = STECMNT; /* allow comments, etc */ + continue; + + + case STEGRP: + if (--ap_grplev < 0) { + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(ap_grplev=%d)", ap_grplev)); +#endif + + state = STEBAD; + break; + } + ap_pappend (AP_GROUP_END, NULLCP); + state = STECMNT; + continue; + + +/* -------------------------- Data type ---------------------------------- */ + + + case STDTYPE: + /* -- data type name; empty node -- */ + if (ap_intype == AP_PARSE_822) { + /* -- data types not legal in 822 -- */ + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(intype=%d)", ap_intype)); +#endif + + state = STEBAD; + break; + } + + if (ap_lex (buf, sizeof(buf)) != LV_WORD) { + state = STEBAD; + continue; + } + ap_pfill (AP_DATA_TYPE, buf); + state = STEDTYPE; + /* -- Just drop on through -- */ + + + case STEDTYPE: + /* -- data type name end; empty node -- */ + state = (ap_lex (buf, sizeof(buf)) == LV_COLON) ? STITER : STEBAD; + continue; + + + +/* --------------------------- domain ----------------------------------- */ + + + case STDOMAIN: + /* -- domain/host; no empty parse node -- */ + switch (ap_lex (buf, sizeof(buf))) { + default: + state = STEBAD; + continue; + case LV_COMMENT: + ap_pappend (AP_COMMENT, buf); + continue; + case LV_DLIT: + ap_pappend (AP_DOMAIN_LITERAL, buf); + state = STEDOMAIN; + continue; + case LV_WORD: + ap_pfill (AP_DOMAIN, buf); + state = STEDOMAIN; + } + + /* -- just drop on through -- */ + + + case STEDOMAIN: + /* -- domain end; no empty parse node -- */ + switch (ap_lex (buf, sizeof(buf))) { + case LV_AT: + /* -- sequence of HOST's => @ separation -- */ + if (r733_prefptr == NULLAP) + r733_prefptr = ap_pcur; + ap_palloc (); + /* -- node which points to first routing ref -- */ + state = STDOMAIN; + break; + + case LV_SEMI: + state = STEGRP; + break; + case LV_GRTR: + state = STEPER; + break; + case LV_COMMA: + if (ap_routing != DONE) + state = STITER; + else + state = STEOK; + break; + case LV_EOD: + if (ap_routing != DONE) + state = STEBAD; + else + state = STEOK; + break; + case LV_COMMENT: + ap_pappend (AP_COMMENT, buf); + break; + case LV_COLON: + if (ap_routing != DONE) { + ap_routing = DONE; + state = STITER; + continue; + } + /* else drop on through */ + default: + state = STEBAD; + break; + } + + continue; + } + } +} + + + +/* ------------------------------------------------------------------------ */ + + + +void ap_7to8 (r733_prefptr, r822_ptr) +AP_ptr r733_prefptr, + r822_ptr; +{ + AP_ptr routbase; + AP_ptr ap; + char *perneeded; + + + PP_DBG (("Lib/addr/ap_7to8()")); + + /* -- don't have to move it to 822 style -- */ + if (r733_prefptr == NULLAP) return; + + if (ap_pstrt -> ap_obtype == AP_MAILBOX) { + perneeded = strdup (r822_ptr -> ap_obvalue); + ap_pappend (AP_PERSON_END, NULLCP); + } + else + perneeded = NULLCP; + + /* -- move the sequence to newroute -- */ + routbase = ap_alloc (); + + while (r733_prefptr -> ap_ptrtype != AP_PTR_NIL && + r733_prefptr -> ap_ptrtype != AP_PTR_NXT && + r733_prefptr -> ap_next != NULLAP) { + + switch (r733_prefptr -> ap_next -> ap_obtype) { + default: + /* -- only move domain info -- */ + goto endit; + + case AP_COMMENT: + if (routbase -> ap_next != NULLAP) { + /* -- try to append, not prepend, cmnts -- */ + PP_DBG (("comment appended'%s'", + r733_prefptr->ap_next->ap_obvalue)); + (void) ap_move (routbase -> ap_next, + r733_prefptr); + continue; + } + /* else drop on through */ + + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + PP_DBG (("val='%s'", + r733_prefptr -> ap_next -> ap_obvalue)); + (void) ap_move (routbase, r733_prefptr); + continue; + } + } + + +endit: + /* + treatment here depends on whether we have an 822 route already. + Note that 822 pointer is NOT easy, as an easy pointer was + too hard! + There is a need to copy first part of route to r822_ptr + */ + + if (r822_ptr -> ap_obtype != AP_DOMAIN && + r822_ptr -> ap_obtype != AP_DOMAIN_LITERAL) { + + ap_insert (r822_ptr, AP_PTR_MORE, + ap_new (r822_ptr -> ap_obtype, + r822_ptr -> ap_obvalue)); + + free (r822_ptr -> ap_obvalue); + + ap_fllnode (r822_ptr, routbase -> ap_next -> ap_obtype, + routbase -> ap_next -> ap_obvalue); + + (void) ap_sqinsert (r822_ptr, AP_PTR_MORE, + routbase -> ap_next -> ap_next); + + /* -- add it before local-part -- */ + ap_free (routbase -> ap_next); + ap_free (routbase); + } + else { + ap = r822_ptr; + while (ap -> ap_next -> ap_obtype == AP_DOMAIN || + ap -> ap_next -> ap_obtype == AP_DOMAIN_LITERAL) + ap = ap -> ap_next; + (void) ap_sqinsert (ap, AP_PTR_MORE, routbase -> ap_next); + } + + + /* -- need to kludge person name -- */ + if (perneeded != 0) { + ap_insert (r822_ptr, AP_PTR_MORE, + ap_new (r822_ptr -> ap_obtype, + r822_ptr -> ap_obvalue)); + free (r822_ptr -> ap_obvalue); + ap_fllnode (r822_ptr, AP_PERSON_NAME, perneeded); + free (perneeded); + } +} diff --git a/Lib/addr/ap_dmflip.c b/Lib/addr/ap_dmflip.c new file mode 100644 index 0000000..7b2047a --- /dev/null +++ b/Lib/addr/ap_dmflip.c @@ -0,0 +1,50 @@ +/* ap_dmflip.c: flip domains around */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_dmflip.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_dmflip.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_dmflip.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + +/* --------------------- Begin Routines -------------------------------- */ + + +char *ap_dmflip(buf) +char *buf; +{ + char tbuf[LINESIZE]; + char *cp; + register char *p, + *q; + + /* -- don't flip if quoted or dlit -- */ + if (*buf == '"' || *buf == '[') + return (strdup (buf)); + + (void) strcpy (tbuf, buf); + + cp = smalloc (strlen (buf) + 1); + + for(q = cp; (p = rindex (tbuf, '.')) != NULLCP; *(q-1) = '.') { + *p++ = 0; + while((*q++ = *p++) != '\0') + continue; + } + + p = tbuf; + while((*q++ = *p++) != '\0') + continue; + return (cp); +} diff --git a/Lib/addr/ap_equ.c b/Lib/addr/ap_equ.c new file mode 100644 index 0000000..9c2668b --- /dev/null +++ b/Lib/addr/ap_equ.c @@ -0,0 +1,85 @@ +/* ap_equ: check to see if to strings represent same address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_equ.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_equ.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_equ.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap.h" +#include "adr.h" +#include "chan.h" + +extern char *loc_dom_site, *loc_dom_mta; +extern char *ad_getlocal(); + +ap_equ (one, two) +char *one, + *two; +{ + AP_ptr one_tree, two_tree, + loc1, dom1, loc2, dom2; + int equ = FALSE; + + one_tree = ap_s2t(one); +#ifdef UKORDER + one_tree = ap_normalize(one_tree, CH_UK_PREF); +#else + one_tree = ap_normalize(one_tree, CH_USA_PREF); +#endif + two_tree = ap_s2t(two); +#ifdef UKORDER + two_tree = ap_normalize(two_tree, CH_UK_PREF); +#else + two_tree = ap_normalize(two_tree, CH_USA_PREF); +#endif + + + (void) ap_t2p (one_tree, (AP_ptr *)0, (AP_ptr *)0, + &loc1, &dom1, (AP_ptr *)0); + (void) ap_t2p (two_tree, (AP_ptr *)0, (AP_ptr *)0, + &loc2, &dom2, (AP_ptr *)0); + + if (dom1 && dom2 && lexequ(dom1->ap_obvalue, dom2->ap_obvalue) ==0) { + /* same domains */ + if (dom1->ap_islocal == TRUE + || lexequ(dom1->ap_obvalue, loc_dom_site) == 0 + || lexequ(dom1->ap_obvalue, loc_dom_mta) == 0) { + /* local addresses */ + char *oneloc, *twoloc; + oneloc = ad_getlocal(one, AD_822_TYPE, YES); + twoloc = ad_getlocal(two, AD_822_TYPE, YES); + if (oneloc != NULLCP + && twoloc != NULLCP + && lexequ(oneloc, twoloc) == 0) + equ = TRUE; + if (oneloc == NULLCP + && twoloc == NULLCP + && loc1 && loc2 + && lexequ(loc1->ap_obvalue, loc2->ap_obvalue) == 0) + /* x400 encapsulated addrs */ + equ = TRUE; + if (oneloc != NULLCP) free(oneloc); + if (twoloc != NULLCP) free(twoloc); + } else if (loc1 && loc2 && + lexequ(loc1->ap_obvalue, loc2->ap_obvalue) == 0) + equ = TRUE; + + } + (void) ap_sqdelete(one_tree, NULLAP); + (void) ap_sqdelete(two_tree, NULLAP); + return equ; +} + + + diff --git a/Lib/addr/ap_file.c b/Lib/addr/ap_file.c new file mode 100644 index 0000000..b4507fb --- /dev/null +++ b/Lib/addr/ap_file.c @@ -0,0 +1,113 @@ +/* ap_file.c: ap file handling routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_file.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_file.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_file.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap.h" + +/* +parse state saving uses a linked list of state information, recorded in +ap_prevstruct structures. the list is manipulated as a simple stack. +*/ + +static struct ap_prevstruct *ap_file; /* -- parse state top of stack -- */ +extern int (*ap_gfunc)(); /* -- ptr to char get fn -- */ +extern int ap_peek; /* -- basic parse state info -- */ +extern int ap_perlev; +extern int ap_grplev; +extern AP_ptr ap_pstrt, + ap_pcur; + +int ap_ppush (gfunc) /* -- save parse context, ap_iinit -- */ +int (*gfunc)(); +{ + register struct ap_prevstruct *tfil; + + if ((tfil = (struct ap_prevstruct *) + malloc (sizeof (struct ap_prevstruct))) == + (struct ap_prevstruct *) NOTOK) + return (NOTOK); + + tfil -> ap_opeek = ap_peek; /* -- save regular parse info -- */ + tfil -> ap_ogroup = ap_grplev; + tfil -> ap_operson = ap_perlev; + tfil -> ap_prvgfunc = ap_gfunc; + tfil -> ap_next = ap_file; /* -- save previous stack entry -- */ + ap_file = tfil; /* -- save current stack entry -- */ + ap_iinit (gfunc); /* -- create new parse state -- */ + return (OK); +} + + + +void ap_ppop() /* -- restore previous parse state -- */ +{ + register struct ap_prevstruct *tfil; + + tfil = ap_file; + ap_peek = tfil -> ap_opeek; + ap_grplev = tfil -> ap_ogroup; + ap_perlev = tfil -> ap_operson; + ap_gfunc = tfil -> ap_prvgfunc; + ap_file = tfil -> ap_next; + free ((char *) tfil); +} + + + +/* +the next three routines handle most of the overhead for acquiring +the address list from a file. +*/ + + +int ap_flget() /* -- get character from included file -- */ +{ + register int c; + + c = getc (ap_file -> ap_curfp); + + if (c == '\n') + return (','); /* -- a minor convenience -- */ + + return (c); +} + + + +int ap_fpush (file) /* -- indirect input from file -- */ +char file[]; +{ + if (ap_ppush (ap_flget) == NOTOK) + /* -- save current & set for file input -- */ + return (NOTOK); + + if ((ap_file -> ap_curfp = fopen (file, "r")) == NULLFILE) { + /* -- couldn't get the file, tho -- */ + ap_ppop(); + return (NOTOK); + } + return (OK); +} + + + +void ap_fpop() /* -- pop the stack, if any input nested -- */ +{ + if (ap_file -> ap_curfp != NULLFILE) + (void) fclose (ap_file -> ap_curfp); + ap_ppop(); +} diff --git a/Lib/addr/ap_lex.c b/Lib/addr/ap_lex.c new file mode 100644 index 0000000..1cbf0f6 --- /dev/null +++ b/Lib/addr/ap_lex.c @@ -0,0 +1,381 @@ +/* ap_lex.c: lexical analyser for address parser */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_lex.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +Perform lexical analysis on input stream + +The stream is assumed to be "unfolded" and the / sequence +is NOT checked for. This must be done by the character-acquisition +routine, if necessary. In fact, space, tab and newline all return the +same lexical token. Due to a number of bagbiting mail systems on the +net which cannot handle having a space within a mailbox name, period +(.) has been equated with space. + +Letters, numbers, and other graphics, except specials, also all return +the same token. + +Note that only printable characters and format effectors are legal. +All others cause an error return. + +Only COMMENTs and WORDs have data associated with them. + +*/ + +/* +< 1978 B. Borden Wrote initial version of parser code +78-80 D. Crocker Reworked parser into current form +Apr 81 K. Harrenstein Hacked for SRI +Jun 81 D. Crocker Back in the fold. Finished v7 conversion + */ + + +#include "util.h" +#include "ap.h" +#include "ap_lex.h" + + +extern char ap_lxtable[], + ap_lxtable_per[]; /* ascii chars -> symbolic terminals */ +extern int ap_intype; +int ap_peek = -1; /* one-character look-ahead */ +char ap_llex; /* last lexeme returned by ap_lex() */ + +#ifdef AP_DEBUG +extern char ap_debug; +char *namtab[] = +{ + "eo-data", /* LV_EOD 0 */ + "error", /* LV_ERROR 1 */ + "comma", /* LV_COMMA 2 */ + "at", /* LV_AT 3 */ + "colon", /* LV_COLON 4 */ + "semi", /* LV_SEMI 5 */ + "comment", /* LV_COMMENT 6 */ + "less", /* LV_LESS 7 */ + "grtr", /* LV_GRTR 8 */ + "word", /* LV_WORD 9 */ + "from", /* LV_FROM 10 */ + "domain-literal" /* LV_DLIT 11 */ +}; +#endif + + + +/* --------------------- Begin Routines -------------------------------- */ + +static int ap_char (); +int ap_lex_percent = FALSE; + +void ap_use_percent() +{ + ap_lex_percent = TRUE; +} + +int ap_lex (lexval, siz) +char lexval[]; +int siz; +{ + register char c, + *lexptr; + register int retval; + char *lex_table = (ap_lex_percent == FALSE) ? ap_lxtable : ap_lxtable_per; + + siz--; /* need one for terminating '\0' */ + /* -- Skips space, tab and newline -- */ + while ((retval = lex_table[c = ap_char()]) == LT_SPC) + continue; + + lexptr = lexval; + *lexptr++ = c; + + switch (retval) { + case LT_ERR: + /* -- bad character -- */ + retval = LV_ERROR; + break; + + case LT_EOD: + /* -- end of data stream -- */ + retval = LV_EOD; + break; + + case LT_COM: + /* -- comma "," the addr list separator -- */ + retval = LV_COMMA; + break; + + case LT_AT: + /* -- At sign "@" the node separator -- */ + retval = LV_AT; + break; + + +/* --------------------- data types and group list -------------------- */ + + case LT_COL: + /* -- colon ":" the data type / group -- */ + retval = LV_COLON; + break; + + case LT_SEM: + /* -- semicolon ";" the group end -- */ + retval = LV_SEMI; + break; + + + +/* ----------------------- person address list ------------------------ */ + + case LT_LES: + /* -- less-than-sign "<" the person list -- */ + + if (lex_table[c = ap_char()] == LT_LES) + /* -- << implies redirection -- */ + retval = LV_FROM; + else { + /* -- restore xtra char -- */ + ap_peek = c; + retval = LV_LESS; + } + break; + + + case LT_GTR: + /* -- greater-than-sign ">" the end person -- */ + retval = LV_GRTR; + break; + + +/* --------------------- quoted & unquoted words ------------------------ */ + + case LT_SQT: + /* -- back slash at start of atom - illegal -- */ + retval = LV_ERROR; + break; + + case LT_LTR: + /* -- letters -- */ + case LT_RPR: + /* -- right paren ")" its just char, here -- */ + + for (;;) { + if ((int) (lexptr - &(lexval[0])) >= siz) + /* too long */ + retval = LV_ERROR; + else { + switch (lex_table[*lexptr++ = c = ap_char()]) { + case LT_LTR: + case LT_SQT: + case LT_RPR: + continue; + + case LT_ERR: + retval = LV_ERROR; + break; + + case LT_EOD: + /* -- permit eod to end string -- */ + default: + /* -- non-member character -- */ + ap_peek = c; + lexptr--; +#ifdef AP_733_AT + if (ap_lex_percent == TRUE && + lexptr == &lexval[2] && + uptolow (lexval[0]) == 'a' && + uptolow (lexval[1]) == 't' ) + retval = LV_AT; + else +#endif + retval = LV_WORD; + } + } + break; + }; + break; + + + case LT_QOT: + /* -- double quote "\"" => string -- */ + retval = LV_WORD; + + /* -- don't put quotes into obvalue -- */ + --lexptr; + + for (;;) { + if ((int) (lexptr - &(lexval[0])) >= siz) + /* too long */ + retval = LV_ERROR; + else { + switch (lex_table[*lexptr++ = c = ap_char()]) { + case LT_QOT: + --lexptr; + break; + + case LT_SQT: + /* -- include next char w/out interpeting --*/ + /* -- and drop on through -- */ + --lexptr; + *lexptr++ = ap_char(); + + case LT_RPR: + case LT_LPR: + case LT_ERR: + default: + continue; + + case LT_EOD: + retval = LV_ERROR; + } + } + break; + } + + break; + + +/* --------------------------- comment ---------------------------------- */ + + + case LT_LPR: + /* -- left paren "(" -- comment start -- */ + + /* -- remove left-most paren -- */ + lexptr--; + + for (retval = 0;;) { + /* -- retval is count of comment nesting -- */ + if ((int) (lexptr - &(lexval[0])) >= siz) { + /* too long */ + retval = LV_ERROR; + } else { + switch (lex_table[*lexptr++ = c = ap_char()]) { + case LT_LPR: + /* -- nested comments -- */ + /* -- just drop on through -- */ + retval++; + + default: + continue; + + case LT_SQT: + /* -- include next char w/out interpeting --*/ + --lexptr; + *lexptr++ = ap_char(); + continue; + + case LT_RPR: + if (retval-- > 0) + continue; + /* -- remove right-most paren -- */ + lexptr--; + retval = LV_COMMENT; + break; + + case LT_EOD: + case LT_ERR: + retval = LV_ERROR; + break; + } + } + break; + } + + break; + + + +/* ------------------------ domain literal ------------------------------- */ + + + + case LT_LSQ: + /* -- left squar bracket "[" -- */ + + for(;;) { + if ((int) (lexptr - &(lexval[0])) >= siz) + /* too long */ + retval = LV_ERROR; + else { + switch (lex_table[*lexptr++ = c = ap_char()]) { + default: + continue; + case LT_SQT: + /* -- include next char w/out interpeting --*/ + --lexptr; + *lexptr++ = ap_char(); + continue; + case LT_RSQ: + retval = LV_DLIT; + break; + case LT_EOD: + case LT_ERR: + retval = LV_ERROR; + break; + } + } + break; + } + + break; + } + + + + +/* ----------------------- cleanup and return --------------------------- */ + + *lexptr = '\0'; + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG ((" %s", namtab[retval])); +#endif + + return (ap_llex = retval); +} + + +/* --------------------- Static Routines -------------------------------- */ + + +/* +get next input character +*/ + +static int ap_char() +{ + /* -- handle lookahead and 8th bit -- */ + + extern int (*ap_gfunc)(); /* -- ptr to character get fn -- */ + register int i; + + if (ap_peek == 0) + return (0); + + if ((i = ap_peek) > 0) { + ap_peek = -1; + return (i); + } + + /* -- EOD -- */ + if ((i = ((*ap_gfunc)())) == -1) + return (0); + + /* -- force error, if eighth bit is on -- */ + return ((isascii (i)) ? i : '\177'); +} diff --git a/Lib/addr/ap_lex_tb.c b/Lib/addr/ap_lex_tb.c new file mode 100644 index 0000000..8c3f914 --- /dev/null +++ b/Lib/addr/ap_lex_tb.c @@ -0,0 +1,101 @@ +/* ap_lex_tb.c: lexical table for address parser */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex_tb.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex_tb.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_lex_tb.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap_lex.h" +#include "ap.h" + +/* +mappings of lexical symbols to ascii values for address parser +*/ + +char ap_lxtable_per[] = +{ + LT_EOD, LT_ERR, LT_ERR, LT_ERR, /* 000-003 nul */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 004-007 */ + LT_LTR, LT_SPC, LT_SPC, LT_ERR, /* 010-013 bs tab lf */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 014-017 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 020-023 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 024-027 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 030-033 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 034-037 */ + LT_SPC, LT_XTR, LT_QOT, LT_XTR, /* 040-043 sp ! " # */ + + /* In JNT domain treat % as @ */ + LT_XTR, LT_AT, LT_XTR, LT_XTR, /* 044-047 $ % & ' */ + + LT_LPR, LT_RPR, LT_XTR, LT_XTR, /* 050-053 ( ) * + */ + LT_COM, LT_XTR, LT_XTR, LT_XTR, /* 054-057 , - . / */ + LT_NUM, LT_NUM, LT_NUM, LT_NUM, /* 060-063 0 1 2 3 */ + LT_NUM, LT_NUM, LT_NUM, LT_NUM, /* 014-067 4 5 6 7 */ + LT_NUM, LT_NUM, LT_COL, LT_SEM, /* 070-073 8 9 : ; */ + LT_LES, LT_XTR, LT_GTR, LT_XTR, /* 074-077 < = > ? */ + LT_AT, LT_LTR, LT_LTR, LT_LTR, /* 100-103 @ A B C */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 014-107 D E F G */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 110-114 H I J K */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 115-117 L M N O */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 120-123 P Q R S */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 124-127 T U V W */ + LT_LTR, LT_LTR, LT_LTR, LT_LSQ, /* 130-133 X Y Z [ */ + LT_SQT, LT_RSQ, LT_XTR, LT_XTR, /* 134-137 \ ] ^ _ */ + LT_XTR, LT_LTR, LT_LTR, LT_LTR, /* 140-143 ` a b c */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 144-147 d e f g */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 150-153 h i j k */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 154-157 l m n o */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 160-163 p q r s */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 164-167 t u v w */ + LT_LTR, LT_LTR, LT_LTR, LT_XTR, /* 170-173 x y z { */ + LT_XTR, LT_XTR, LT_XTR, LT_ERR, /* 174-177 | } ~ del */ +}; + +char ap_lxtable[] = +{ + LT_EOD, LT_ERR, LT_ERR, LT_ERR, /* 000-003 nul */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 004-007 */ + LT_LTR, LT_SPC, LT_SPC, LT_ERR, /* 010-013 bs tab lf */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 014-017 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 020-023 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 024-027 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 030-033 */ + LT_ERR, LT_ERR, LT_ERR, LT_ERR, /* 034-037 */ + LT_SPC, LT_XTR, LT_QOT, LT_XTR, /* 040-043 sp ! " # */ + + LT_XTR, LT_XTR, LT_XTR, LT_XTR, /* 044-047 $ % & ' */ + + LT_LPR, LT_RPR, LT_XTR, LT_XTR, /* 050-053 ( ) * + */ + LT_COM, LT_XTR, LT_XTR, LT_XTR, /* 054-057 , - . / */ + LT_NUM, LT_NUM, LT_NUM, LT_NUM, /* 060-063 0 1 2 3 */ + LT_NUM, LT_NUM, LT_NUM, LT_NUM, /* 014-067 4 5 6 7 */ + LT_NUM, LT_NUM, LT_COL, LT_SEM, /* 070-073 8 9 : ; */ + LT_LES, LT_XTR, LT_GTR, LT_XTR, /* 074-077 < = > ? */ + LT_AT, LT_LTR, LT_LTR, LT_LTR, /* 100-103 @ A B C */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 014-107 D E F G */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 110-114 H I J K */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 115-117 L M N O */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 120-123 P Q R S */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 124-127 T U V W */ + LT_LTR, LT_LTR, LT_LTR, LT_LSQ, /* 130-133 X Y Z [ */ + LT_SQT, LT_RSQ, LT_XTR, LT_XTR, /* 134-137 \ ] ^ _ */ + LT_XTR, LT_LTR, LT_LTR, LT_LTR, /* 140-143 ` a b c */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 144-147 d e f g */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 150-153 h i j k */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 154-157 l m n o */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 160-163 p q r s */ + LT_LTR, LT_LTR, LT_LTR, LT_LTR, /* 164-167 t u v w */ + LT_LTR, LT_LTR, LT_LTR, LT_XTR, /* 170-173 x y z { */ + LT_XTR, LT_XTR, LT_XTR, LT_ERR, /* 174-177 | } ~ del */ +}; diff --git a/Lib/addr/ap_norm.c b/Lib/addr/ap_norm.c new file mode 100644 index 0000000..c8178b1 --- /dev/null +++ b/Lib/addr/ap_norm.c @@ -0,0 +1,399 @@ +/* ap_norm.c: normali[zs]e an address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_norm.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_norm.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_norm.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "chan.h" +#include "ap.h" + +extern char *loc_dom_site; +extern int ap_lex_percent; + +static void ap_ptinit (); +/* --------------------- Begin Routines -------------------------------- */ + + +/* +Normalize a parse tree, to fill-in host references, etc. + Returns: + 0 if ok + -1 if error +*/ + +int all_domain_norm = FALSE; + +ap_norm_all_domains() +{ + all_domain_norm = TRUE; +} + +ap_norm_first_domain() +{ + all_domain_norm = FALSE; +} + +AP_ptr ap_normalize (thetree, order_pref) + AP_ptr thetree; /* the parse tree */ + int order_pref; +{ + struct ap_node base_node; /* first node in routing chain */ + AP_ptr r822_prefptr, + person_ptr, + mbx_prefptr, + dom_prefptr, + lst_comment_prefptr, + last_ptr, + group_ptr, + ap; + int oneNorm = FALSE; + + ap_ninit (&base_node); + + (void) ap_sqinsert (&base_node, AP_PTR_MORE, thetree); + + ap_ptinit (&base_node, &person_ptr, &r822_prefptr, &mbx_prefptr, + &dom_prefptr, &lst_comment_prefptr, &last_ptr, &group_ptr); + + /* + Remember "list: ;"... + */ + + if (mbx_prefptr == NULLAP) { + PP_DBG (("Lib/addr/ap_normalize/No mailbox found!")); + return (base_node.ap_next); + } + + + /* + Normalize all refs in source route + */ + + if (r822_prefptr != NULLAP) { + ap = r822_prefptr; + for(;;) { + switch (ap -> ap_ptrtype) { + case AP_PTR_NIL: + break; + case AP_PTR_NXT: + break; + case AP_PTR_MORE: + /* -- next is part of this address -- */ + ap = ap -> ap_next; + + switch (ap -> ap_obtype) { + case AP_DOMAIN: + (void) ap_dmnormalize (ap, order_pref); + if (all_domain_norm == TRUE) + continue; + oneNorm = TRUE; + break; + case AP_DOMAIN_LITERAL: + case AP_COMMENT: + continue; + } + } + break; + } + } + + + + if (ap_lex_percent != TRUE) { + /* + if JNT mail, % is treated as lexically equivalent + to @, and CSNET style routes ignored. Might accept + CSNET routes if someone wants this... + */ + + if (dom_prefptr == NULLAP) { + /* -- no domain, so add default and leave -- */ + PP_DBG (("Lib/addr/ap_normalize/no domain")); + ap_locnormalize (&base_node, &r822_prefptr, + &mbx_prefptr, &dom_prefptr); + } + } + + + if ((dom_prefptr != NULLAP) && + (oneNorm == FALSE) && + (ap_dmnormalize (dom_prefptr -> ap_next, order_pref) == OK)) { + PP_DBG (("Lib/addr/ap_normali/Local reference")); + if (ap_lex_percent != TRUE) + ap_locnormalize (&base_node, &r822_prefptr, + &mbx_prefptr, &dom_prefptr); + } + + + if (dom_prefptr == NULLAP && r822_prefptr == NULLAP) { + /* -- no host references anywhere -- */ + + if (mbx_prefptr == NULLAP || + mbx_prefptr -> ap_next -> ap_obtype == AP_GROUP_NAME || + mbx_prefptr -> ap_next -> ap_obtype == AP_GROUP_START) + return (base_node.ap_next); + + (void) ap_append (mbx_prefptr -> ap_next, AP_DOMAIN, loc_dom_site); + + PP_DBG (("Lib/addr/ap_normalize/appending %s domain", + loc_dom_site)); + + (void) ap_dmnormalize (mbx_prefptr -> ap_next -> ap_next, + order_pref); + } + + return (base_node.ap_next); +} + + + +int ap_dmnormalize (ap, order_pref) +AP_ptr ap; +int order_pref; +{ + char official[LINESIZE], *subdom; + int retval; + + + if (ap == NULL) + return NOTOK; + + retval = tb_getdomain (ap->ap_obvalue, NULLCP, official, + order_pref, &subdom); + if (subdom != NULLCP) free(subdom); + + if (retval == OK) { + if (official[0]) { + free (ap -> ap_obvalue); + ap -> ap_obvalue = strdup (official); + PP_DBG (("Lib/addr/ap_dmnormalize/Official = '%s'", + official)); + } + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("%s is not a known domain reference", + ap -> ap_obvalue)); + + return (OK); + /* This is not worth choking on */ + /* SEK */ + } + + + return (retval); + +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static void ap_ptinit (base_prefptr, person_ptr, r822_prefptr, mbx_prefptr, + dom_prefptr, lst_comment_prefptr, last_ptr, group_ptr) + + AP_ptr base_prefptr, + *person_ptr, + *r822_prefptr, + *mbx_prefptr, + *dom_prefptr, + *lst_comment_prefptr, + *last_ptr, + *group_ptr; +{ + AP_ptr ap; + + + *person_ptr = NULLAP; + *r822_prefptr = NULLAP; + *mbx_prefptr = NULLAP; + *dom_prefptr = NULLAP; + *lst_comment_prefptr = NULLAP; + *last_ptr = NULLAP; + *group_ptr = NULLAP; + + + /* + Need switch here to catch leading mbox or domain + */ + if (base_prefptr == NULLAP + || base_prefptr -> ap_next == NULLAP) + return; + switch (base_prefptr -> ap_next -> ap_obtype) { + case AP_MAILBOX: + *mbx_prefptr = base_prefptr; + break; + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + *r822_prefptr = base_prefptr; + break; + } + + + for (ap = base_prefptr -> ap_next; ap -> ap_obtype != AP_NIL; + ap = ap -> ap_next) { + + *last_ptr = ap; + + PP_DBG (("Lib/addr/ap_ptinit/val '%s'", ap -> ap_obvalue)); + + switch (ap -> ap_obtype) { + case AP_PERSON_NAME: + PP_DBG (("Lib/addr/ap_ptinit/person_ptr")); + *person_ptr = ap; + break; + case AP_GROUP_NAME: + PP_DBG (("Lib/addr/ap_ptinit/group_ptr")); + *group_ptr = ap; + break; + } + + + if (ap -> ap_ptrtype == AP_PTR_NXT) break; + if (ap -> ap_ptrtype == AP_PTR_NIL) break; + if (ap -> ap_next == NULLAP) break; + + + switch (ap -> ap_next -> ap_obtype) { + case AP_COMMENT: + PP_DBG (("Lib/addr/ap_ptinit/got comment")); + *lst_comment_prefptr = ap; + break; + + case AP_GENERIC_WORD: + PP_DBG (("Lib/addr/ap_ptinit/got word")); + if (*mbx_prefptr != NULLAP) + break; + + case AP_MAILBOX: + PP_DBG (("Lib/addr/ap_ptinit/got mbox pref")); + /* -- one before the mbox -- */ + *mbx_prefptr = ap; + break; + + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + if(*r822_prefptr == NULLAP && *mbx_prefptr == NULLAP){ + PP_DBG (("Lib/addr/ap_ptinit/got r822_prefptr" + )); + *r822_prefptr = ap; + } + else if ((*dom_prefptr == NULLAP) && + (*mbx_prefptr != NULLAP)) { + /* -- need mailbox befor domain -- */ + PP_DBG (("%s%s", + "Lib/addr/ap_ptinit/", + "got dom_prefptr")); + *dom_prefptr = ap; + } + + break; + } + } + + + + if (*last_ptr == NULLAP) + PP_DBG (("Lib/addr/ap_ptinit/no last_ptr")); + else + PP_DBG (("Lib/addr/ap_ptinit/last_ptr '%s'", + (*last_ptr) -> ap_obvalue)); +} + + + +/* --------------------- Not JNTMAIL ----------------------------------- */ + + +ap_locnormalize (obase_ptr, or822_prefptr, ombx_prefptr, odom_prefptr) +AP_ptr obase_ptr, + *or822_prefptr, + *ombx_prefptr, + *odom_prefptr; +{ + /* -- tear local-part apart -- */ + + struct ap_node base_node; + AP_ptr cur_ptr; + AP_ptr r822_prefptr, + person_ptr, + mbx_prefptr, + dom_prefptr, + lst_comment_prefptr, + last_ptr, + group_ptr; + + PP_DBG (("Lib/addr/ap_locnormalize/parsing '%s'", + (*ombx_prefptr) -> ap_next -> ap_obvalue)); + + ap_ninit (&base_node); + + (void) ap_sqinsert (&base_node, AP_PTR_MORE, + ap_s2t ((*ombx_prefptr) -> ap_next -> ap_obvalue)); + + ap_ptinit (&base_node, &person_ptr, &r822_prefptr, + &mbx_prefptr, &dom_prefptr, &lst_comment_prefptr, + &last_ptr, &group_ptr); + + + if (dom_prefptr != NULLAP) { + /* -- actually have some stuff -- */ + + /* -- replace old reference -- */ + free ((*ombx_prefptr) -> ap_next -> ap_obvalue); + + (*ombx_prefptr) -> ap_next -> ap_obvalue = + strdup (mbx_prefptr -> ap_next -> ap_obvalue); + + PP_DBG (("Lib/addr/ap_locnormalize/newlocal '%s'", + (*ombx_prefptr) -> ap_next -> ap_obvalue)); + + if (r822_prefptr != NULLAP || *odom_prefptr != NULLAP) + if (*or822_prefptr == NULLAP) + /* -- initialize route pointer -- */ + *or822_prefptr = obase_ptr; + + + if (*odom_prefptr == NULLAP) + *odom_prefptr = mbx_prefptr -> ap_next; + else + /* -- get rid of old domain reference -- */ + (void) ap_move (*or822_prefptr, *odom_prefptr); + + + if (r822_prefptr != NULLAP) { + /* -- put new chain at end of old -- */ + PP_DBG (("%s%s", + "Lib/addr/ap_locnormalize/", + "adding new routing to end info")); + + for (cur_ptr = *or822_prefptr; + cur_ptr -> ap_next -> ap_obtype + == AP_DOMAIN || + cur_ptr -> ap_next -> ap_obtype + == AP_DOMAIN_LITERAL || + cur_ptr -> ap_next -> ap_obtype + == AP_COMMENT; + cur_ptr = cur_ptr -> ap_next) + continue; + + (void) ap_sqmove (cur_ptr, r822_prefptr, AP_DOMAIN); + } + + (void) ap_move (*odom_prefptr, dom_prefptr); + } +} diff --git a/Lib/addr/ap_p2s.c b/Lib/addr/ap_p2s.c new file mode 100644 index 0000000..593221f --- /dev/null +++ b/Lib/addr/ap_p2s.c @@ -0,0 +1,684 @@ +/* ap_p2s.c: convert parts to a string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_p2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_p2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_p2s.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +Format one address from pointers to constitutents, in a tree + Returns: pointer to string if successful or + NOTOK if error + + Using ap_p2s as output for ap_t2s has the general problem + of losing comments. Perhaps ap_t2s should be separate? +*/ + + + +#include "util.h" +#include "chan.h" +#include "ap.h" + +static ap_compress_local(); + +extern int ap_outtype; + +extern void ad_val2str (); + +/* --------------------- Begin Routines -------------------------------- */ + +static char *ap_p2s_aux(); + +char *ap_p2s(group, name, local, domain, route) +AP_ptr group, + name, + local, + domain, + route; +{ + return ap_p2s_aux (group, name, local, domain, route, TRUE); +} + +char *ap_p2s_nc(group, name, local, domain, route) +AP_ptr group, + name, + local, + domain, + route; +{ + return ap_p2s_aux (group, name, local, domain, route, FALSE); +} + + +static char *ap_p2s_aux (group, name, local, domain, route, comments) +AP_ptr group, /* -- start of group name -- */ + name, /* -- start of person name -- */ + local, /* -- start of local-part -- */ + domain, /* -- basic domain ref -- */ + route; /* -- start of 733 forw routing -- */ +int comments; +{ + + AP_ptr last_ptr; + char *route_ptr, /* -- 822 -> 733 route ptr */ + *flip_ptr, *subdom = NULLCP, + *dref_ptr, /* -- ptr to output str -- */ + tmpbuf [BUFSIZ], + buf[BUFSIZ]; /* -- buf for tb_getdomain -- */ + int in_person, + in_group, + last, + after_comment; + register AP_ptr cur_ptr = NULLAP; + register char *s_ptr, /* -- the str we are building -- */ + *c_ptr; + + + PP_DBG (("Lib/adr/ap_p2s()")); + + PP_DBG (("Lib/addr/ap_p2s/AP_PARSE_822 %s", + ap_outtype & AP_PARSE_822?"on":"off")); + + PP_DBG (((ap_outtype & AP_PARSE_BIG) ? + "AP_PARSE_BIG on" : "AP_PARSE_LITTLE on")); + + + in_person = FALSE; + in_group = FALSE; + s_ptr = strdup (""); + route_ptr = strdup (""); + last = AP_NIL; + after_comment = FALSE; + + if (!comments) + ap_compress_local(group,name,local,domain,route,comments); + + if (group != NULLAP) { + + PP_DBG (("Lib/addr/ap_p2s: group is '%s'", + group -> ap_obvalue)); + + for (cur_ptr = group; cur_ptr != NULLAP; + cur_ptr = cur_ptr->ap_next) { + + if (cur_ptr == name || cur_ptr == local || + cur_ptr == domain || cur_ptr == route) + break; + + /* -- print munged addr -- */ + + switch (cur_ptr -> ap_obtype) { + default: + case AP_NIL: + break; + + case AP_COMMENT: + if (comments == TRUE) { + /* -- output value as comment -- */ + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_COMMENT); + + c_ptr = multcat (s_ptr, + (s_ptr[0]?" ":""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = TRUE; + } + continue; + + case AP_GROUP_NAME: + in_group = TRUE; + + case AP_GROUP_START: + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_GROUP_START); + c_ptr = multcat (s_ptr, + (((s_ptr[0]&&last==AP_GROUP_START) || after_comment == TRUE)?" ":""), + tmpbuf, NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + last = AP_GROUP_START; + after_comment = FALSE; + continue; + } + + break; + } + + + if (in_group) { + c_ptr = multcat (s_ptr, ":", NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + /* need space after this yuch */ + after_comment = TRUE; + } + } + + + + if (name != NULLAP) { + PP_DBG (("LIb/addr/ap_p2s: name is '%s'", + name -> ap_obvalue)); + + for (cur_ptr = name; cur_ptr != NULLAP; + cur_ptr = cur_ptr -> ap_next) { + + if (cur_ptr == group || cur_ptr == local || + cur_ptr == domain || cur_ptr == route) + break; + + /* -- print munged addr -- */ + switch (cur_ptr -> ap_obtype) { + default: + case AP_NIL: + break; + + case AP_COMMENT: + if (comments == TRUE) { + /* -- output value as comment -- */ + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_COMMENT); + + c_ptr = multcat (s_ptr, + (s_ptr[0]?" " : ""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = TRUE; + } + continue; + + case AP_PERSON_NAME: + in_person = TRUE; + + case AP_PERSON_START: + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_PERSON_START); + c_ptr = multcat (s_ptr, + (((s_ptr[0] && last == AP_PERSON_START) || after_comment == TRUE)?" ":""), + tmpbuf, NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + last = AP_PERSON_START; + after_comment = FALSE; + continue; + } + + break; + } + } + + + + if (in_person) { + c_ptr = multcat (s_ptr, " <", NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = FALSE; + } + + + + if (route != NULLAP) { + /* -- routing info exits -- */ + PP_DBG (("Lib/addr/ap_p2s: route is '%s'", + route -> ap_obvalue)); + + for (last_ptr = cur_ptr = route; ; + cur_ptr = cur_ptr -> ap_next) { + + /* -- grot grot !!!!!!! -- */ + if (cur_ptr == NULLAP) + goto defcase1; + + switch (cur_ptr -> ap_obtype) { + case AP_PERSON_END: + continue; + + defcase1:; + /* yeuch !! */ + default: + + case AP_NIL: + if ((ap_outtype & AP_PARSE_822) == + AP_PARSE_822) { + /* -- piece of cake -- */ + c_ptr = multcat (s_ptr, ":", NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + } + break; + + case AP_COMMENT: + if (comments == TRUE) { + /* -- output value as comment -- */ + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_COMMENT); + after_comment = TRUE; + c_ptr = multcat (s_ptr, + (s_ptr[0]?" ":""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + } + continue; + + + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + cur_ptr -> ap_obtype); + flip_ptr = NULLCP; + dref_ptr = tmpbuf; + + /* -- only flip valid domains -- */ + if ((ap_outtype & AP_PARSE_BIG) == + AP_PARSE_BIG && + tb_getdomain (tmpbuf, NULLCP, + buf, +#ifdef UKORDER + CH_UK_PREF, +#else + CH_USA_PREF, +#endif + &subdom) == OK) { + /* -- usa ordering preferred -- */ + flip_ptr = ap_dmflip (buf); + dref_ptr = flip_ptr; + } + if (subdom != NULLCP) { + free(subdom);subdom=NULLCP; + } + if ((ap_outtype & AP_PARSE_822) == + AP_PARSE_822) { + /* -- piece of cake -- */ + c_ptr = multcat ( + s_ptr, +/* (((s_ptr[0] && last == AP_DOMAIN) || after_comment == TRUE)?" ":""),*/ + ((after_comment == TRUE)?" ":""), + (cur_ptr!=last_ptr?",@":"@"), + dref_ptr, + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + last = AP_DOMAIN; + after_comment = FALSE; + s_ptr = c_ptr; + } + else { + if (route_ptr[0] == '\0') + c_ptr = multcat ( + "@", + dref_ptr, + NULLCP); + else + c_ptr = multcat ( + "%", + dref_ptr, + route_ptr, + NULLCP); + free (route_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + route_ptr = c_ptr; + } + + if (flip_ptr != NULLCP) + free (flip_ptr); + continue; + } + + break; + } + } + + + if (local != NULLAP) { + PP_DBG (("LIb/addr/ap_p2s: local is '%s'", + local -> ap_obvalue)); + + for (cur_ptr = local; cur_ptr != NULLAP; + cur_ptr = cur_ptr -> ap_next) { + + if (cur_ptr == group || cur_ptr == name || + cur_ptr == domain || cur_ptr == route) + break; + /* -- print munged addr -- */ + switch (cur_ptr -> ap_obtype) { + default: + case AP_NIL: + break; + + case AP_COMMENT: + if (comments == TRUE) { + /* -- don't skip these -- */ + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_COMMENT); + + c_ptr = multcat (s_ptr, + (s_ptr[0]?" ":""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = TRUE; + } + continue; + + case AP_GENERIC_WORD: + case AP_MAILBOX: + /* -- yuk -- */ + ap_val2str (tmpbuf, + cur_ptr -> ap_obvalue, + AP_MAILBOX); + c_ptr = multcat (s_ptr, + (((s_ptr[0]&&last==AP_MAILBOX) || after_comment == TRUE)?" ":""), + tmpbuf, NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + last = AP_MAILBOX; + after_comment = FALSE; + continue; + } + + break; + } + } + + + + if (domain != NULLAP) { + PP_DBG (("Lib/addr/ap_p2s: domain is '%s'", + domain -> ap_obvalue)); + + for (cur_ptr = domain; cur_ptr != NULLAP; + cur_ptr = cur_ptr->ap_next) { + + if (cur_ptr == group || cur_ptr == name || + cur_ptr == local || cur_ptr == route) + break; + switch (cur_ptr->ap_obtype) { + default: + case AP_NIL: + break; + + case AP_COMMENT: + if (comments == TRUE) { + ap_val2str(tmpbuf, + cur_ptr->ap_obvalue, + AP_COMMENT); + c_ptr = multcat (s_ptr, + (s_ptr[0]?" ":""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = TRUE; + } + continue; + + case AP_DOMAIN: + ap_val2str (tmpbuf, domain -> ap_obvalue, domain -> ap_obtype); + flip_ptr = NULLCP; + dref_ptr = tmpbuf; + + /* -- only flip valid domains -- */ + if ((ap_outtype & AP_PARSE_BIG) == AP_PARSE_BIG && + tb_getdomain (tmpbuf, + NULLCP, buf, +#ifdef UKORDER + CH_UK_PREF, +#else + CH_USA_PREF, +#endif + &subdom) == OK) { + /* -- usa ordering preferred -- */ + flip_ptr = ap_dmflip (buf); + dref_ptr = flip_ptr; + } + if (subdom != NULLCP) { + free(subdom);subdom=NULLCP; + } + + if ((ap_outtype & AP_PARSE_822) == AP_PARSE_822 || + route_ptr[0] == '\0') + /* -- easy -- */ + c_ptr = multcat (s_ptr, + "@", + dref_ptr, + route_ptr, + NULLCP); + else + c_ptr = multcat (s_ptr, + "%", + dref_ptr, + route_ptr, + NULLCP); + + if (c_ptr == NULLCP) + return (c_ptr); + free (s_ptr); + s_ptr = c_ptr; + if (flip_ptr != NULLCP) + free (flip_ptr); + after_comment = FALSE; + continue; + } + break; + } + } else if (route_ptr[0] != '\0') { + c_ptr = multcat (s_ptr, + route_ptr, + NULLCP); + + if (c_ptr == NULLCP) + return (c_ptr); + free (s_ptr); + s_ptr = c_ptr; + after_comment = FALSE; + } + + + free (route_ptr); + + if (in_person) { + c_ptr = multcat (s_ptr, ">", NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + after_comment = FALSE; + if (cur_ptr != NULL && cur_ptr->ap_obtype == AP_PERSON_END) + cur_ptr = cur_ptr->ap_next; + } + + if (cur_ptr != NULL + && cur_ptr->ap_obtype == AP_GROUP_END) { + c_ptr = multcat (s_ptr, ";", NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *)NOTOK); + s_ptr = c_ptr; + in_group = FALSE; + cur_ptr = cur_ptr -> ap_next; + } + + if (comments == TRUE && + cur_ptr != NULL && cur_ptr->ap_obtype == AP_COMMENT) { + while (cur_ptr != NULL + && cur_ptr->ap_obtype == AP_COMMENT) { + /* trailing comments */ + ap_val2str(tmpbuf, + cur_ptr->ap_obvalue, + AP_COMMENT); + c_ptr = multcat (s_ptr, + (s_ptr[0]?" ":""), + "(", + tmpbuf, + ")", + NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return ((char *) NOTOK); + s_ptr = c_ptr; + after_comment = TRUE; + cur_ptr = cur_ptr->ap_next; + } + } + + return (s_ptr); +} + + +static ap_compress_local (group, name, local, domain, route, comments) +AP_ptr group, /* -- start of group name -- */ + name, /* -- start of person name -- */ + local, /* -- start of local-part -- */ + domain, /* -- basic domain ref -- */ + route; /* -- start of 733 forw routing -- */ +int comments; +{ + /* compress local into one AP_ptr */ + AP_ptr ix, trc; + register char *s_ptr, + *c_ptr; + char tmpbuf [BUFSIZ]; + + if (local == NULLAP) + return; + s_ptr = strdup(""); + for (ix = local; ix != NULLAP; ix = ix -> ap_next) { + if (ix == group || ix == name || + ix == domain || ix == route) + break; + switch (ix -> ap_obtype) { + default: + case AP_NIL: + break; + + case AP_COMMENT: + if (comments == TRUE) { + ap_val2str (tmpbuf, + ix -> ap_obvalue, + AP_COMMENT); + c_ptr = multcat (s_ptr, + (s_ptr[0] ? " " : ""), + "(", + tmpbuf, + ")", + NULLCP); + free(s_ptr); + if (c_ptr == NULLCP) + return; + s_ptr = c_ptr; + } + continue; + + case AP_GENERIC_WORD: + case AP_MAILBOX: + /* -- yuk -- */ + ap_val2str (tmpbuf, + ix -> ap_obvalue, + AP_MAILBOX); + c_ptr = multcat (s_ptr, + ((s_ptr[0] && + s_ptr[(strlen(s_ptr) -1)] != '"') + ?" ":""), + tmpbuf, NULLCP); + free (s_ptr); + if (c_ptr == NULLCP) + return; + s_ptr = c_ptr; + continue; + } + break; + } + + if (ix == local -> ap_next) { + /* no need to compress */ + free(s_ptr); + return; + } + + for (trc = local; trc -> ap_next && trc -> ap_next != ix; ) { + switch (trc -> ap_next -> ap_obtype) { + case AP_GENERIC_WORD: + case AP_MAILBOX: + ap_delete (trc); + break; + default: + trc = trc -> ap_next; + break; + } + } + + switch (local -> ap_obtype) { + case AP_GENERIC_WORD: + case AP_MAILBOX: + free(local -> ap_obvalue); + local -> ap_obvalue = s_ptr; + break; + default: + trc = ap_alloc (); + trc -> ap_obvalue = s_ptr; + trc -> ap_obtype = AP_MAILBOX; + ap_insert (local, AP_PTR_MORE, trc); + break; + } +} diff --git a/Lib/addr/ap_s2p.c b/Lib/addr/ap_s2p.c new file mode 100644 index 0000000..2147305 --- /dev/null +++ b/Lib/addr/ap_s2p.c @@ -0,0 +1,83 @@ +/* ap_s2p.c: convert string into major address parts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2p.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2p.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_s2p.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap_lex.h" +#include "ap.h" + + +static char *s2p_txt; /* -- hdr_in() passes to alst() -- */ + + + + +/* --------------------- Static Routines ------------------------------- */ + + +/* -- adrs extracted from component text -- */ + +static int s2p_in() +{ + /* -- nothing to give it -- */ + + if (s2p_txt == NULLCP) + return (EOF); + + switch (*s2p_txt) { + case '\0': + case '\n': + /* -- end of string, drop on through -- */ + s2p_txt = NULLCP; + return (0); + } + + return (*(s2p_txt++)); +} + + + + +/* --------------------- Begin Routines -------------------------------- */ + + +/* -- One of the main uses of this routine is to replace adrparse.c -- */ + + +char *ap_s2p (str_ptr, tree, group, name, local, domain, route) +char *str_ptr; +AP_ptr *tree, + *group, + *name, + *local, + *domain, + *route; +{ + s2p_txt = str_ptr; + + *tree = ap_pinit (s2p_in); + + switch (ap_1adr()) { + case DONE: + return ((char *) DONE); + case OK: + (void) ap_t2p (*tree, group, name, local, domain, route); + /* -- so they can parse the next chunk -- */ + return (s2p_txt); + } + + return ((char *) NOTOK); +} diff --git a/Lib/addr/ap_s2s.c b/Lib/addr/ap_s2s.c new file mode 100644 index 0000000..e0b7ddf --- /dev/null +++ b/Lib/addr/ap_s2s.c @@ -0,0 +1,35 @@ +/* ap_s2s: converts a string into a normalise string with given order pref */ +/* ap_s2t + ap_normalise + ap_t2s */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_s2s.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap.h" + +ap_s2s (orig, str_pptr, order_pref) +char *orig, + **str_pptr; +int order_pref; +{ + AP_ptr tree, + rettree; + + tree = ap_s2t(orig); + tree = ap_normalize(tree, order_pref); + rettree = ap_t2s(tree, str_pptr); + ap_free(tree); + ap_free(rettree); +} diff --git a/Lib/addr/ap_s2t.c b/Lib/addr/ap_s2t.c new file mode 100644 index 0000000..7e9e30a --- /dev/null +++ b/Lib/addr/ap_s2t.c @@ -0,0 +1,88 @@ +/* ap_s2t.c: convert a string into an address tree */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2t.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_s2t.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_s2t.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap.h" + + +static char *ap_str_ptr; + + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int get_a_char() /* -- get next character from string -- */ +{ + + if (*ap_str_ptr == '\0') + /* -- end of the string -- */ + return (-1); + + return (*ap_str_ptr++); +} + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +/* -- parse a string into an address tree -- */ + +AP_ptr ap_s2t (thestr) +char *thestr; +{ + int got_one; + AP_ptr thetree; + + + PP_DBG (("Lib/addr/ap_s2t (%s)", thestr)); + + ap_str_ptr = thestr; + + if ((thetree = ap_pinit (get_a_char)) == BADAP) + return( NULLAP); + + ap_clear(); + + got_one = 0; + + for (;;) + switch (ap_1adr()) { + case NOTOK: + (void) ap_sqdelete (thetree, NULLAP); + ap_free (thetree); + return (NULLAP); + + case OK: + /* -- more to process -- */ + got_one++; + continue; + + case DONE: + if (got_one != 1){ + (void) ap_sqdelete(thetree, NULLAP); + ap_free(thetree); + thetree = BADAP; + } + return (thetree); + } +} diff --git a/Lib/addr/ap_t2p.c b/Lib/addr/ap_t2p.c new file mode 100644 index 0000000..e5a4de3 --- /dev/null +++ b/Lib/addr/ap_t2p.c @@ -0,0 +1,179 @@ +/* ap_t2p.c: split tree into major address parts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_t2p.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_t2p.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_t2p.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +Record beginnings of major sections of an address + + Returns: pointer to next node, after address + 0 if end of tree + -1 if error + +if both rroute and nroute are requested, and the tree has routing +in reverse-path form, then these will point to the same node. +*/ + + + +#include "util.h" +#include "ap.h" + + +static int person_level, + group_level; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +AP_ptr ap_t2p (tree, group, name, local, domain, route) +register AP_ptr tree; /* -- the parse tree -- */ +AP_ptr *group, /* -- start of group name -- */ + *name, /* -- start of person name -- */ + *local, /* -- start of local-part -- */ + *domain, /* -- basic domain reference -- */ + *route; /* -- start of 822 reverse route -- */ +{ + AP_ptr return_ptr, + start_ptr = tree; + int got_local, got_first; + + PP_DBG (("Lib/addr/ap_t2p()")); + + group_level = 0; + person_level = 0; + + if (group != (AP_ptr *) 0) *group = NULLAP; + if (name != (AP_ptr *) 0) *name = NULLAP; + if (local != (AP_ptr *) 0) *local = NULLAP; + if (domain != (AP_ptr *) 0) *domain = NULLAP; + if (route != (AP_ptr *) 0) *route = NULLAP; + + /* -- ignore null stuff -- */ + if (tree == NULLAP || tree -> ap_obtype == AP_NIL) + return ((AP_ptr) OK); + + got_first = FALSE; + + for (got_local = FALSE; ; tree = tree -> ap_next) { + /* -- print munged addr -- */ + switch (tree -> ap_obtype) { + case AP_NIL: + return_ptr = NULLAP; + goto endit; + + case AP_PERSON_NAME: + person_level++; + if (name != (AP_ptr *) 0 && *name == NULLAP) { + *name = start_ptr; + got_first = TRUE; + } + start_ptr = tree -> ap_next; + break; + + case AP_PERSON_START: + start_ptr = tree -> ap_next; + break; + + case AP_PERSON_END: + person_level--; + start_ptr = tree -> ap_next; + break; + + case AP_GROUP_NAME: + group_level++; + if (group != (AP_ptr *) 0 && *group == NULLAP) { + *group = start_ptr; + got_first = TRUE; + } + start_ptr = tree -> ap_next; + break; + + case AP_GROUP_START: + start_ptr = tree -> ap_next; + break; + + case AP_GROUP_END: + group_level--; + start_ptr = tree -> ap_next; + break; + + case AP_GENERIC_WORD: + case AP_MAILBOX: + if (local != (AP_ptr *) 0 && *local == NULLAP) { + *local = start_ptr; + got_first = TRUE; + } + got_local = TRUE; + start_ptr = tree -> ap_next; + + break; + + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + if (got_local) { + /* -- reference after local -- */ + if (domain != (AP_ptr *) 0 && + *domain == NULLAP) { + *domain = start_ptr; + got_first = TRUE; + } + } + else { + /* -- must be 822 route -- */ + /* -- domain precedes local-part -- */ + if (route != (AP_ptr *) 0 && *route == NULLAP) { + *route = start_ptr; + got_first = TRUE; + } + } + start_ptr = tree -> ap_next; + + break; + + case AP_COMMENT: + /* -- output value as comment -- */ + if (got_first == FALSE) + /* cannot lose preceding comments */ + break; + default: + start_ptr = tree -> ap_next; + break; + } + + + + switch (tree -> ap_ptrtype) { + case AP_PTR_NXT: + if (tree -> ap_next -> ap_obtype != AP_NIL) { + return_ptr = (AP_ptr) tree -> ap_next; + goto endit; + } + + /* -- else drop on through -- */ + + case AP_PTR_NIL: + return_ptr = (AP_ptr) OK; + goto endit; + } + } + +endit: + + return (return_ptr); +} diff --git a/Lib/addr/ap_t2s.c b/Lib/addr/ap_t2s.c new file mode 100644 index 0000000..72e8a0d --- /dev/null +++ b/Lib/addr/ap_t2s.c @@ -0,0 +1,67 @@ +/* ap_t2s.c: Address tree to String */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_t2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_t2s.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_t2s.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +Format one address from parse tree, into a string + + Returns: pointer to next node, after address + 0 if end of tree + NOTOK if error +*/ + + +#include "util.h" +#include "ap.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + +AP_ptr ap_t2s (thetree, str_pptr) +AP_ptr thetree; /* -- the parse tree -- */ +char **str_pptr; /* -- where to stuff the string -- */ +{ + AP_ptr loc_ptr, /* -- in case fake personal name needed -- */ + group_ptr, + name_ptr, + dom_ptr, + route_ptr, + return_tree; + + return_tree = ap_t2p (thetree, &group_ptr, &name_ptr, + &loc_ptr, &dom_ptr, &route_ptr); + + if (return_tree == BADAP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/addr/ap_t2s: error from ap_t2p()")); + *str_pptr = strdup ("(PP Error!)"); + return (BADAP); + } + + *str_pptr = ap_p2s (group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); + + if (*str_pptr == (char *)NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/addr/ap_t2s: error from ap_p2s()")); + *str_pptr = strdup ("(PP Error!)"); + return (BADAP); + } + + return (return_tree); +} diff --git a/Lib/addr/ap_ut.c b/Lib/addr/ap_ut.c new file mode 100644 index 0000000..d7004b3 --- /dev/null +++ b/Lib/addr/ap_ut.c @@ -0,0 +1,487 @@ +/* ap_ut.c: address parser utility routines. */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_ut.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_ut.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_ut.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +Standard routines for handling address list element nodes +*/ + + +/* +< 1978 B. Borden Wrote initial version of parser code +78-80 D. Crocker Reworked parser into current form +Apr 81 K. Harrenstein Hacked for SRI +Jun 81 D. Crocker Back in the fold. Finished v7 conversion + minor cleanups. + repackaging into more complete set of calls +Jul 81 D. Crocker ap_free & _alloc check for not 0 or -1 + malloc() error causes jump to ap_init error +*/ + + + +#include "util.h" +#include "ap.h" + + +#ifdef AP_DEBUG +extern char ap_debug; +extern char *typtab[]; +#endif + + +int (*ap_gfunc)(); /* -- ptr to char get fn -- */ +int ap_peek; /* -- basic parse state info -- */ +extern int ap_perlev; +extern int ap_grplev; +AP_ptr ap_pstrt, + ap_pcur; + + +/* --------------------- Begin Routines -------------------------------- */ + + + +AP_ptr ap_alloc() /* -- create node, return pointer to it -- */ +{ + AP_ptr ap; + + ap = (AP_ptr) malloc (sizeof (struct ap_node)); + + if (ap == BADAP) + return (BADAP); + + ap_ninit (ap); + return (ap); +} + + + +void ap_ninit (ap) +register AP_ptr ap; +{ + bzero((char *)ap, sizeof(*ap)); + ap -> ap_obtype = AP_NIL; + ap -> ap_ptrtype = AP_PTR_NIL; +} + + + +void ap_free (ap) +register AP_ptr ap; +{ + register char *obvalue; + + /* -- get rid of node, if have one -- */ + switch ((int)ap) { + case OK: + case NOTOK: + /* -- nothing to free -- */ + break; + + default: + if (ap->ap_normalised == TRUE) { + if (ap->ap_localhub) + free(ap->ap_localhub); + if (ap->ap_chankey) + free(ap->ap_chankey); + if (ap->ap_error) + free(ap->ap_error); + } + /* -- get rid of its data string -- */ + switch ((int)(obvalue = ap -> ap_obvalue)) { + case OK: + case NOTOK: + /* -- nothing to free -- */ + break; + + default: + free (obvalue); + } + + free ((char *) ap); + } +} + + + +/* -- add data to node at end of chain -- */ +void ap_fllnode (ap, obtype, obvalue) +register AP_ptr ap; +char obtype; +register char *obvalue; +{ + + ap -> ap_obtype = obtype; + ap -> ap_obvalue = (obvalue == NULLCP) ? NULLCP : strdup (obvalue); + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(%s/'%s')", typtab[obtype], obvalue)); +#endif +} + + + +AP_ptr ap_new (obtype, obvalue) /* -- alloc & fill node -- */ +char obtype; +char *obvalue; +{ + register AP_ptr nap; + + nap = ap_alloc(); + ap_fllnode (nap, obtype, obvalue); + return (nap); +} + + + +void ap_insert (cur, ptrtype, new) /* -- create, fill or insert node in list -- */ +register AP_ptr cur; /* -- where to insert after -- */ +char ptrtype; /* -- more or new address ? -- */ +register AP_ptr new; /* -- where to insert after -- */ +{ + + /* -- Now copy linkages from current node -- */ + + new -> ap_ptrtype = cur -> ap_ptrtype; + new -> ap_next = cur -> ap_next; + + /* -- now point current node at inserted node -- */ + + cur -> ap_ptrtype = ptrtype; + cur -> ap_next = new; +} + + + +AP_ptr ap_sqinsert (cur, type, new) /* -- insert in sequence -- */ +register AP_ptr cur; +int type; +register AP_ptr new; +{ + AP_ptr oldptr; + int otype; + + switch ((int)new) { + case OK: + case NOTOK: + return (NULLAP); + } + + oldptr = cur -> ap_next; + otype = cur -> ap_ptrtype; + cur -> ap_next = new; + cur -> ap_ptrtype = type; + + while (new -> ap_ptrtype != AP_PTR_NIL && + new -> ap_next != NULLAP && + new -> ap_next -> ap_obtype != AP_NIL) + new = new -> ap_next; + + if (new -> ap_next && new -> ap_next -> ap_obtype == AP_NIL) + ap_delete (new); + + new -> ap_next = oldptr; + new -> ap_ptrtype = otype; + return (new); +} + + + +void ap_delete (ap) /* -- remove next node in sequence -- */ +register AP_ptr ap; +{ + register AP_ptr next; + + if (ap != NULLAP && ap -> ap_ptrtype != AP_PTR_NIL + && ap -> ap_next != NULLAP) { + /* -- only if there is something there -- */ + /* -- link around one to be removed -- */ + next = ap -> ap_next; + ap -> ap_ptrtype = next -> ap_ptrtype; + ap -> ap_next = next -> ap_next; + ap_free (next); + } +} + + + +AP_ptr ap_append (ap, obtype, obvalue) /* -- alloc, fill or insert node -- */ +register AP_ptr ap; /* -- node to insert after -- */ +char obtype; +char *obvalue; +{ + register AP_ptr nap; + + nap = ap_alloc(); + ap_fllnode (nap, obtype, obvalue); + ap_insert (ap, AP_PTR_MORE, nap); + return (nap); +} + + + +AP_ptr ap_add (ap, obtype, obvalue) /* -- append data to current node -- */ +register AP_ptr ap; +char obtype; +register char *obvalue; +{ + register char *ovalue; + + if (ap -> ap_obtype != obtype) + return (ap_append (ap, obtype, obvalue)); + else { + /* -- same type or empty => can append -- */ + + /* -- no data to add -- */ + if (obvalue == NULLCP) + return (OK); + + if ((ovalue = ap -> ap_obvalue) == NULLCP) + ap_fllnode (ap, obtype, obvalue); + else { + /* -- add to existing data -- */ + ovalue = ap -> ap_obvalue; + ap -> ap_obvalue = multcat (ovalue, " ", + obvalue, NULLCP); + free (ovalue); + } + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(%d/'%s')", obtype, obvalue)); +#endif + } + + return (OK); +} + + + +AP_ptr ap_sqdelete (strt_node, end_node) +register AP_ptr strt_node; +register AP_ptr end_node; +{ + /* -- remove nodes, through end node -- */ + + switch ((int)strt_node) { + case OK: + case NOTOK: + return (NULLAP); + } + + while (strt_node -> ap_ptrtype != AP_PTR_NIL) { + if (strt_node -> ap_next == end_node) { + /* -- last one requested -- */ + ap_delete (strt_node); + return (strt_node -> ap_next); + } + + ap_delete (strt_node); + } + + /* -- end of chain -- */ + return (NULLAP); +} + + + +AP_ptr ap_1delete (ap) /* -- remove all nodes of address to NXT -- */ +register AP_ptr ap; /* -- starting node -- */ +{ + while (ap -> ap_ptrtype != AP_PTR_NIL) { + if (ap -> ap_ptrtype == AP_PTR_NXT) + return (ap -> ap_next); + + ap_delete (ap); + } + + /* -- end of chain -- */ + return (NULLAP); +} + + + +void ap_sqtfix (strt, end, obtype) /* -- alter obtype of a node subsequence -- */ +register AP_ptr strt; +register AP_ptr end; +register char obtype; +{ + for ( ; ; strt = strt -> ap_next) { + if (strt -> ap_obtype != AP_COMMENT) + strt -> ap_obtype = obtype; + + if (strt == end || strt -> ap_ptrtype == AP_PTR_NIL) + break; + } +} + + + +AP_ptr ap_move (to, from) /* -- move node after from to be after to -- */ +register AP_ptr to, + from; +{ + register AP_ptr nodeptr; + + /* -- quiet failure -- */ + if (from -> ap_ptrtype == AP_PTR_NIL || from -> ap_next == NULLAP) + return (from); + + nodeptr = from -> ap_next; + + from -> ap_next = nodeptr -> ap_next; + from -> ap_ptrtype = nodeptr -> ap_ptrtype; + + ap_insert (to, AP_PTR_MORE, nodeptr); + + /* -- next in chain, now -- */ + return (from); +} + + + +AP_ptr ap_sqmove (to, from, endtype) /* -- move sequence -- */ +register AP_ptr to, + from; +register char endtype; /* -- copy only COMMENT and this -- */ +{ + switch ((int)from) { + case OK: + case NOTOK: + return (NULLAP); + } + + while (from -> ap_ptrtype != AP_PTR_NIL && + from -> ap_next != NULLAP) { + + if (endtype != (char) AP_NIL) + if (from -> ap_obtype != AP_COMMENT && + from -> ap_obtype != endtype) + break; + to = ap_move (to, from); + } + + /* -- end of chain -- */ + return (to); +} + + + +void ap_iinit (gfunc) /* -- input function initialization -- */ +int (*gfunc)(); +{ + ap_gfunc = gfunc; /* -- set character fetch func -- */ + ap_peek = -1; /* -- no lex peek char -- */ +} + + + +void ap_clear() /* -- clear out the parser state -- */ +{ + ap_grplev = 0; /* -- zero group nesting depth -- */ + ap_perlev = 0; /* -- zero <> nesting depth -- */ +} + + + +AP_ptr ap_pinit (gfunc) /* -- init, alloc & set start node -- */ +int (*gfunc)(); +{ + ap_iinit (gfunc); + return (ap_pstrt = ap_pcur = ap_alloc()); +} + + + + + + +/* +These echo the basic list manipuation primitives, but use ap_pcur +for the pointer and any insert will cause ap_pcur to be updated +to point to the new node. +*/ + + +void ap_palloc() /* -- alloc, insert after pcur -- */ +{ + ap_pnsrt (ap_alloc(), AP_PTR_MORE); +} + + + +void ap_pfill (obtype, obvalue) /* -- add data to node at end of chain -- */ +char obtype; +register char *obvalue; +{ + ap_pcur -> ap_obtype = obtype; + ap_pcur -> ap_obvalue = + (obvalue == NULLCP) ? NULLCP : strdup (obvalue); + +#ifdef AP_DEBUG + if (ap_debug) + PP_DBG (("(%s/'%s')", typtab[obtype], obvalue)); +#endif +} + + + +void ap_pnsrt (ap, ptrtype) /* -- add node to end of parse chain -- */ +register AP_ptr ap; +char ptrtype; +{ + register AP_ptr rap_pcur; + + if ((rap_pcur = ap_pcur) -> ap_obtype == AP_NIL) { + /* -- current one can be used -- */ + rap_pcur -> ap_obtype = ap -> ap_obtype; + rap_pcur -> ap_obvalue = ap -> ap_obvalue; + ap -> ap_obvalue = NULLCP; + ap_free (ap); + } + else { + /* -- really do the insert -- */ + rap_pcur -> ap_ptrtype = ptrtype; + rap_pcur -> ap_next = ap; + ap_pcur = ap; + } +} + + + +void ap_pappend (obtype, obvalue) /* -- alloc, fill, append at end -- */ +char obtype; +char *obvalue; +{ + ap_palloc(); /* -- will update pcur -- */ + ap_fllnode (ap_pcur, obtype, obvalue); +} + + + +void ap_padd (obtype, obvalue) /* -- try to append data to current node -- */ +char obtype; +char *obvalue; +{ + register AP_ptr nap; + + nap = ap_add (ap_pcur, obtype, obvalue); + + if (nap != OK) /* -- created new node -- */ + ap_pcur = nap; +} diff --git a/Lib/addr/ap_val2str.c b/Lib/addr/ap_val2str.c new file mode 100644 index 0000000..fa0b7f5 --- /dev/null +++ b/Lib/addr/ap_val2str.c @@ -0,0 +1,189 @@ +/* ap_val2str: converts values to strings */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_val2str.c,v 6.0 1991/12/18 20:21:24 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_val2str.c,v 6.0 1991/12/18 20:21:24 jpo Rel $ + * + * $Log: ap_val2str.c,v $ + * Revision 6.0 1991/12/18 20:21:24 jpo + * Release 6.0 + * + */ + + + +/* +This function is just barely usable. The hole problem of +quoted strings is hard to get right especially when the +mail system is trying to make up for human forgetfulness. + -DPK- + +SEK - have improved this somewhat by giving knowledge of +various object types. Does not handle strings of spaces. +*/ + +#include "util.h" +#include "ap.h" + +void ap_val2str (buf, value, obtype) /* -- convert to canonical str -- */ +char *buf, + *value, + obtype; +{ + int got_spcl; + int in_quote; + register char *from_ptr, + *to_ptr; + + PP_DBG (("Lib/addr/ap_val2str ('%s', '%d')", value, obtype)); + + if (obtype == AP_COMMENT) { + for (from_ptr = value, to_ptr = buf; *from_ptr != '\0'; + *to_ptr++ = *from_ptr++) + + switch (*from_ptr) { + case '\r': + case '\n': + case '\\': + case '(': + case ')': + *to_ptr++ = '\\'; + } + + *to_ptr = '\0'; + return; + } + + + if (obtype == AP_DOMAIN_LITERAL) { + for (from_ptr = value, to_ptr = buf; *from_ptr != '\0'; + *to_ptr++ = *from_ptr++) + + switch (*from_ptr) { + case '\r': + case '\n': + case '\\': + *to_ptr++ = '\\'; + continue; + case '[': + if (from_ptr != value) + *to_ptr++ = '\\'; + continue; + case ']': + if (*(from_ptr + 1) != (char) 0) + *to_ptr++ = '\\'; + } + + *to_ptr = '\0'; + return; + } + + + in_quote = FALSE; + + for (got_spcl = FALSE, from_ptr = value; *from_ptr != '\0'; + from_ptr++) { + switch (*from_ptr) { + case '"': + /* -- flip-flop -- */ + in_quote = (in_quote == TRUE ? FALSE : TRUE); + break; + + case '\\': + case '\r': + case '\n': + if (in_quote == FALSE) { + got_spcl = TRUE; + goto copyit; + } + break; + + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\t': + case '[': + case ']': + case '(': + case ')': + if (in_quote == FALSE) { + got_spcl = TRUE; + goto copyit; + } + break; + + case ' ': + if (in_quote == FALSE) + if ((obtype == AP_DOMAIN) || + (obtype == AP_MAILBOX)) { + got_spcl = TRUE; + goto copyit; + } + else { + /* -- hacked to handle " at " -- */ + /* -- this really is needed -- */ + + if ((uptolow (*(from_ptr + 1)) + == 'a') && + (uptolow (*(from_ptr + 2)) + == 't') && + (*(from_ptr + 3) + == ' ')) { + got_spcl = TRUE; + goto copyit; + } + } + break; + + + case '.': + if (in_quote == FALSE && + ((obtype == AP_GROUP_START) || + (obtype == AP_PERSON_START))) { + got_spcl = TRUE; + goto copyit; + } + break; + default: + if (!isascii(*from_ptr) || iscntrl(*from_ptr)) + if (in_quote == FALSE) { + got_spcl = TRUE; + goto copyit; + } + break; + } + } + + + + /* -- if were in a quote, something's wrong -- */ + got_spcl = in_quote; + +copyit: + to_ptr = buf; + + if (got_spcl) + *to_ptr++ = '"'; + + for (from_ptr = value; *from_ptr != '\0'; *to_ptr++ = *from_ptr++) + switch (*from_ptr) { + case '\r': + case '\n': + case '\\': + case '"': + if (got_spcl) + *to_ptr++ = '\\'; + } + + if (got_spcl) + *to_ptr++ = '"'; + + *to_ptr = '\0'; + +} diff --git a/Lib/addr/make b/Lib/addr/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/addr/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/charset/Make.defs b/Lib/charset/Make.defs new file mode 100644 index 0000000..57852df --- /dev/null +++ b/Lib/charset/Make.defs @@ -0,0 +1,40 @@ +# Make.defs exclusively for characer set conversions +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + + +# +# This file is used by both Lib/charset & Format/charset +# + + +# +# The directory holding the generated character set tables. +# +CSDIR = $(FORMDIR)/charset_tables + + +# +# generated character set files for charset_conf.c +# +FILE_CHARSETS = CHARSETS +FILE_CHARDEFS = CHARDEFS +FILE_CHARMAP = CHARMAP.10646 +FILE_CHARMNEM = CHARMNEM + + +# +# character set files for the table database. +# +MASTER_CHARSETS = master/$(FILE_CHARSETS) master/CHARSETS_PP +MASTER_CHARDEFS = master/ISO_10646 master/CONTROL master/OTHER diff --git a/Lib/charset/Makefile b/Lib/charset/Makefile new file mode 100644 index 0000000..23c931b --- /dev/null +++ b/Lib/charset/Makefile @@ -0,0 +1,143 @@ +# Character Set specific routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/charset/RCS/Makefile,v 6.0 1991/12/18 20:21:39 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:21:39 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = charset_conf.c gc.c strcnv.c +OBJS = charset_conf.o gc.o strcnv.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +LIBSRCS = charset_conf.c strcnv.c +LIBOBJS = charset_conf.o strcnv.o +HEADERS = ../../h + +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = charset-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + + +############################################################ +# +# Building Rules +# +############################################################ + + + +default: ${SHADOW} xgc + +${SHADOW}: $(LIBOBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + + + + +charset_conf.o: charset_conf.c ../../Make.defs Make.defs + $(CC) $(CFLAGS) -c \ + '-DFILE_CHARSETS="$(FILE_CHARSETS)"' \ + '-DFILE_CHARDEFS="$(FILE_CHARDEFS)"' \ + '-DFILE_CHARMAP="$(FILE_CHARMAP)"' \ + '-DFILE_CHARMNEM="$(FILE_CHARMNEM)"' \ + '-DCSDIR="$(CSDIR)"' \ + charset_conf.c + +gc: xgc +xgc: charset_conf.o gc.o + $(CC) $(CCFLAGS) charset_conf.o gc.o -o $@ + + +lintlib:llib-lcs.ln +llib-lcs.ln: ${LIBSRCS} + $(LINT) -Ccs $(LLFLAGS) ${LIBSRCS} + +lint: $(LIBSRCS) + $(LINT) $(LLFLAGS) $(LIBSRCS) $(LINTLIBS) $(LINTISODE) + +install: $(CSDIR) $(CSDIR)/$(FILE_CHARSETS) \ + $(CSDIR)/$(FILE_CHARDEFS) inst-gc $(CSDIR)/LATIN1 + @echo "All installed" + +inst-gc: $(CSDIR)/gc +$(CSDIR)/gc: xgc + -$(BACKUP) $@ zxgc + rm -f $@ + $(INSTALL) xgc $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "gc program installed normally"; echo "" + +$(CSDIR)/LATIN1: $(CSDIR)/$(FILE_CHARSETS) + (cd $(CSDIR); ./gc) + (cd $(CSDIR); $(CHOWN) $(PPUSER) * ) + +$(CSDIR): + mkdir $(CSDIR) + $(CHOWN) $(PPUSER) $(CSDIR) + +$(CSDIR)/$(FILE_CHARSETS): $(MASTER_CHARSETS) + cat $(MASTER_CHARSETS) > $(CSDIR)/$(FILE_CHARSETS) + +$(CSDIR)/$(FILE_CHARDEFS): $(MASTER_CHARDEFS) + cat $(MASTER_CHARDEFS) > $(CSDIR)/$(FILE_CHARDEFS) + +clean: tidy + rm -f $(OBJS) llib-lcs.ln + +tidy: + rm -f core ${SHADOW} charset-table-made xgc *.old a.out *.BAK + +depend: + $(DEPEND) $(SRCS) + +define: + $(DEFINE) Makefile + + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +charset_conf.o: charset_conf.c +gc.o: gc.c +gc.o: ../../h/charset.h +strcnv.o: strcnv.c +strcnv.o: ../../h/charset.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/charset/README b/Lib/charset/README new file mode 100644 index 0000000..48f4a8a --- /dev/null +++ b/Lib/charset/README @@ -0,0 +1,16 @@ +******************************************************************************** + + + This code needs to be geared for compatibility on all m/cs. + To use the code effectively you may wish to update the + following files: + Lib/charset/charset_conf.c + ../../h/charset.h + + For more information please read: + The PP Documentation Vol 1 + And the copyright and design documents. + + + +******************************************************************************** diff --git a/Lib/charset/charset_conf.c b/Lib/charset/charset_conf.c new file mode 100644 index 0000000..56bfbbf --- /dev/null +++ b/Lib/charset/charset_conf.c @@ -0,0 +1,43 @@ +/* conf.c: configuration information for body part filters */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/charset/RCS/charset_conf.c,v 6.0 1991/12/18 20:21:39 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/charset/RCS/charset_conf.c,v 6.0 1991/12/18 20:21:39 jpo Rel $ + * + * $Log: charset_conf.c,v $ + * Revision 6.0 1991/12/18 20:21:39 jpo + * Release 6.0 + * + */ + + + +#ifndef FILE_CHARSETS +#define FILE_CHARSETS "CHARSETS" +#endif + +#ifndef FILE_CHARDEFS +#define FILE_CHARDEFS "CHARDEFS" +#endif + +#ifndef FILE_CHARMAP +#define FILE_CHARMAP "CHARMAP.10646" +#endif + +#ifndef FILE_CHARMNEM +#define FILE_CHARMNEM "CHARMNEM" +#endif + +#ifndef CSDIR +#define CSDIR "." +#endif + + +char *charset_dir = CSDIR; +char *charset_sets = FILE_CHARSETS; +char *charset_defs = FILE_CHARDEFS; +char *charset_map = FILE_CHARMAP; +char *charset_mnem = FILE_CHARMNEM; diff --git a/Lib/charset/copyright b/Lib/charset/copyright new file mode 100644 index 0000000..ce08262 --- /dev/null +++ b/Lib/charset/copyright @@ -0,0 +1,20 @@ +The material provided here is copyright Keld Simonsen 1990, 1991. +The material is allowed for copying, also for commercial products, +as long as the following 3 rules are obeyed: + +1. The character and character set codes and names in the material + may not be changed. +2 You are allowed to change the programming code as long as + it is backwards compatible. +3. Due credit must be given to "Keld Simonsen, RAP, Sct. Joergens Alle 8, + DK-1615 Copenhagen V, Denmark". + +The restriction on altering of names is done so that all versons +of the code have a chance of being compatible. If you want alterations +or additions, please mail me (preferably email to keld@dkuug.dk) +and I will consider it for future releases. + +If the material is included in commercial products, donations +will be most appreciated. + +Keld Simonsen diff --git a/Lib/charset/design b/Lib/charset/design new file mode 100644 index 0000000..39c5109 --- /dev/null +++ b/Lib/charset/design @@ -0,0 +1,161 @@ +Guidelines for character mnemonics in a minimal character set. + +By Keld Simonsen, Danish UNIX User Group (DKUUG) +Representative to SC22 WG on Character Set Usage +for Danish Standards Association (DS), Denmark. + +Draft January 1991. + +Aim of Character Mnemonics + +The aim of the mnemonics is to be able to represent all characters +in all standard coded character sets in any standard coded +character set. Thus all standard coded character sets will be +related, and a conversion can take place. + +The usage of the character mnemonics is primarily intended +within computer operating systems, programming languages and +applications, and this work with character mnemonics is the current +state of work which has been presented to the ISO working group +responsible for these computer related issues, namely the +ISO/IEC JTC1/SC22 special working group on character set usage. + +Covered Coded Character Sets + +Almost all characters in the standard coded character sets have been +given a mnemonic name in the minimal character set. +The minimal character set is defined as the basic character set +of ISO 646, where 12 positions are left undefined. +The standard coded character sets are taken as the sum of +all ISO defined or ISO registered character sets. + +The most significant ISO coded character set is the 10646 coded character +set, whose aim is to code in 32 bits all characters in the world. +These guidelines can be seen as assigning mnemonic attributes +to most characters in 10646, currently at DIS stage. + +Other ISO coded character sets covered include all parts of +ISO 8859, ISO 6937-2 and all ISO 646 conforming coded character +sets in the ISO character set registry managed by ECMA +according to ISO 4873. +Some non-ISO character sets are also covered for convenience. + +The Character Mnemonics Classes + +The character mnemonics are classified into two groups: + +1. A group with two-character mnemonics + - Primarily intended for alphabetic scripts like Latin, Greek, + Cyrillian, Hebrew and Arabic, and special characters. +2. A group with variable-length mnemonics + - primarily intended for non-alphabetic scripts like Japanese + and Chinese. + +All mnemonics are given a long descriptive name, written in the +reference character set and taken from ISO 10646, if possible. + + +The Two-Character mnemonics + +The two-character mnemonics include various accented Latin letters, +Greek, Cyrillic, Hebrew, Arabic, Hiragana, Katakana and Bopomofo. +Also quite some special characters are included. +Almost all ISO or ISO registered 7- and 8-bit coded +character sets are covered with these two-character mnemonics. +Thus conversions between these character sets can be done via a +two-character conversion table. + +The two characters are chosen so the graphical appearence in the +reference set resembles as much as possible (within the posibilities +available) the graphical appearance of the character. The basic character +set of ISO 646 is used as the reference set, as mentioned above. + +The characters in the reference character set are chosen to represent +themselves. You may consider them as two-character mnemonics where +the second char is a space. + +Control characters mnemonics are chosen according to ISO 2047 and ISO 6429 . + +Letters, including Greek, Cyrillic, Arabic and Hebrew, are represented +with the base letter as the first letter, and the second letter +represents an accent or relation to a non-Latin script. +Non-Latin letters are translitterated to Latin letters, +following translitteration standards as closely as possible. + +After a letter, the second character signifies the following: + + Exclamation mark ! Grave + Apostrophe ' Acute accent + Greater-Than sign > Circumflex accent + Question Mark ? tilde + Hyphen-Minus - Macron + Left parenthesis ( Breve + Full Stop . Dot Above/Ring above + Colon : Diaeresis + Comma , Cedilla + Underline _ Underline + Solidus / Stroke + Quotation mark " Double acute accent + Semicolon ; Ogonek + Less-Than sign < Caron + + Equals = Cyrillian + Asterisk * Greek + Percent sign % Greek/Cyrillian special + Plus + smalls: Arabic, capitals: Hebrew + Four 4 Bopomofo + Five 5 Hiragana + Six 6 Katakana + +The ampersand & is reserved as an intro character, indicating that the +following string is in the mnemonic character set. This character +could also be another character, e.g. in the control character set. +One common choice in the control character set is decimal 29, +which seems to have no effect on almost all current equipment. +The intro character can be negotiated between the communicating parties, +but the default is the ampersand "&". Two intro characters in a row +signifies the intro character itself. + +The underscore is reserved for the variable-length mnemonics. +This use does not eliminate usage as an accent or language identifier. +The right-pointing parenthesis ")" is not in use at the moment +for accent or language identifying. +This is also the case for some digits. + +Special characters are encoded with some mnemonic value. +These are not systematic thruout, but most mnemonics start +with a special character of the reference set. +Special chars with some sort of reference to the reference +character set normally have this character as the first character +in the mnemonic. + + +The Variable-length Character Mnemonics + +The Variable-length Character Mnemonics are primarily meant for the +ideographic characters in larger Asian character sets. +To have the mnemonics as short as possible, which both saves storage +and is easier to type in, a quite short name is preferred. +Considering the Chinese standard GB 2312-1980 and the Japanese standards +JIS X0208 and JIS X0212, they are all given by row and column +numbers between 1 and 99. So two positions for row and column and +a character set identifier of one character would be almost as short +as possible. The following character set identifiers are defined: + + c GB 2312-1980 + j JIS X0208-1990 + J JIS X0212-1990 + k KS C 5601-1987 + +The first idea was to have a name in Latin describing the pronunciation +but that is not possible according to Asian sources. + +One prominent character in the reference character set is reserved +for identifying variable-length mnemonics, namely the underscore "_". This character +is intended as a delimiter both in the front and in the end +of the mnemonic. An example of its use would be: (&=intro): + + &_j3210_ &_j4436_&_j6530_ + +The Variable-Length Character Mnemonics can also be used for less-used +Latin letters with more than one accent or other less-used special characters. diff --git a/Lib/charset/gc.c b/Lib/charset/gc.c new file mode 100644 index 0000000..4c60e0d --- /dev/null +++ b/Lib/charset/gc.c @@ -0,0 +1,184 @@ +/* gc.c - generates the required mappings */ + + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/charset/RCS/gc.c,v 6.0 1991/12/18 20:21:39 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/charset/RCS/gc.c,v 6.0 1991/12/18 20:21:39 jpo Rel $ + * + * $Log: gc.c,v $ + * Revision 6.0 1991/12/18 20:21:39 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "charset.h" + +#define AMAX 2000 + +extern char *charset_sets, *charset_defs, *charset_map, *charset_mnem; +extern char *charset_dir; +/* char charset_sets[] = "CHARSETS"; */ +/* char charset_defs[] = "CHARDEFS"; */ +/* char charset_map[] = "CHARMAP.10646"; */ +/* char charset_mnem[] = "MNEM"; */ +/* char charset_dir[] = "cs"; */ + +FILE *f,*g,*h; +CHAR8U s[LSIZE], c[AMAX], ref[C256], cmd[LSIZE]; +INT16S v[AMAX], l[AMAX], codetable[C256]; +int i,mx,a,cv,val,cod,dupl,ecma,line,group,plane,row,cell,num; + +gwrite() { + if (g) { + for (i= 0; i < C256; i++) + if (c[codetable[i]] == NULL) + c[codetable[i]] = i; + fwrite (codetable,2,C256,g); + fwrite (c,1,mx,g); + fclose (g); + } +} + +FILE * +fopener (file,mode) +char *file, *mode; +{ + FILE *f; + f= fopen (file,mode); + if (f == (FILE *)NULL) { + (void) fprintf (stderr,"*** Error: unable to open %s\n", file); + exit (1); + } + return f; +} + +main (argc,argv) int argc; char **argv; { + CHAR8U defname[LSIZE], linkname[LSIZE], *p; + + mx= 0; line= 0; + + f= fopener (charset_defs,"r"); + h= fopener (charset_map,"w"); + + v[mx++]= '?' * C256 +'?'; + while (fgets ((char *)s,LSIZE,f)) { + line++; + if (mx > AMAX) perror ("Warning: too many chars\n"); + if (s[0] != ' ' && strlen (s) > 2) { + v[mx++]= s[0]* C256 + s[1]; l[mx]= line; + for (i=0; i < mx-1; i++) if (v[mx-1] == v[i]) + (void) fprintf (stderr, + "Warning: char %2.2s occurs in line %d and %d\n", + s,l[i+1],line); + (void) fprintf (h,"%2.2s\t,,,%.3d,,,%.3d,,,%.3d,,,%.3d\t%s", + s,group,plane,row,cell,s+3); + cell++; + } + else if (strlen (s) >3 ){ + sscanf ((char *)s," %s %d", cmd, &num); + for (p=cmd; *p; p++) if (isupper (*p)) *p= tolower (*p); + /* printf ("command %s %d\n",cmd,num); */ + if (strcmp (cmd,"group") == 0) group=num; + else if (strcmp (cmd,"plane") == 0) plane=num; + else if (strcmp (cmd,"row") == 0) row=num; + else if (strcmp (cmd,"cell") == 0) cell=num; + } + } + + (void) fprintf (stdout,"%d chars defined\n",mx); + fclose (f); fclose (h); + + v[0]= mx; + g= fopener (charset_mnem,"w"); + + fwrite (v,2,mx,g); + v[0]= '?' * C256 +'?'; + + f= fopener (charset_sets,"r"); + + if (chdir (charset_dir)) + (void) fprintf (stderr,"Warning: cannot cd to %s\n",charset_dir); + + while (fscanf (f,"%s",s) != EOF) { + if (strlen (s) == 1) { s[1]= ' '; s[2]= '\0'; } + cv= s[0]* C256 + s[1]; + if (strlen (s) != 2) { + if (strcmp ((char *)s,"referenceset") == 0) { + fgets ((char *)ref+32,40,f); /* skip rest of line */ + fgets ((char *)ref+32,40,f); + fgets ((char *)ref+64,40,f); + fgets ((char *)ref+96,40,f); + for (i=0; i< 32; i++) ref[i]= 0; + for (i=33; i< C256; i++) + if (ref[i] <= ref[32]) ref[i]= 0; + fwrite (ref,1,C256,g); + fclose (g); g= NULL; + } else if (strcmp ((char *)s,"charset") == 0) { + fscanf (f,"%s",defname); + gwrite(); + for (p= defname; *p; p++) + if (islower (*p)) *p= toupper (*p); + g= fopener (defname,"w"); + cod= 0; ecma= 0; + for (i= 0; i < mx; i++) c[i] = 0; + for (i=0; i< C256; i++) codetable[i]= 0; + } else if (strcmp ((char *)s,"alias") == 0) { + fscanf (f,"%s",linkname); + for (p= linkname; *p; p++) + if (islower (*p)) *p= toupper (*p); + unlink (linkname); + link (defname,linkname); + } else if (strcmp ((char *)s,"ecma") == 0) { + ecma= fscanf (f,"%s",s); + if (s[0] == 'o') sscanf ((char *)s+1,"%o",&ecma); + else if (s[0] == 'x') sscanf ((char *)s+1,"%x",&ecma); + else sscanf ((char *)s,"%d",&ecma); + } else if (strcmp ((char *)s,"code") == 0) { + cod= fscanf (f,"%s",s); + if (s[0] == 'o') sscanf ((char *)s+1,"%o",&cod); + else if (s[0] == 'x') sscanf ((char *)s+1,"%x",&cod); + else sscanf ((char *)s,"%d",&cod); + } else if (strcmp ((char *)s,"comment:") == 0) { + char c; + while ((c = fgetc (f)) != EOF && c != '\n'); + } else if (strcmp ((char *)s,"duplicate") == 0) { + dupl= fscanf (f,"%s",s); + if (s[0] == 'o') sscanf ((char *)s+1,"%o",&dupl); + else if (s[0] == 'x') sscanf ((char *)s+1,"%x",&dupl); + else sscanf ((char *)s,"%d",&dupl); + if (dupl <0 || dupl >= C256 || + ! codetable[dupl]) + (void) fprintf (stderr, "Warning: charset %s has duplicate %d but no original\n",defname,dupl); + fscanf (f,"%s",s); + if (strlen (s) == 1) { s[1]= ' '; s[2]= '\0'; } + cv= s[0]* C256 + s[1]; + for (i= 0; i < mx && cv != v[i]; i++); + if (i >= mx) + (void) fprintf (stderr, "Warning: charset %s duplicate %d %s unknown\n",defname,dupl,s); + c[i] = dupl; + } else + (void) fprintf (stderr, "Warning: charset %s unknown command '%s'\n",defname,s); + } else { + for (i= 0; i < mx && cv != v[i]; i++); + if (i >= mx) + (void) fprintf (stderr, "charset %s char %s %d not defined\n",defname,s,cod++); + else { + val= i; + if (val) for (i=0; i <= cod && codetable[i] != val; i++); + if (val && codetable[i] == val) + (void) fprintf (stderr, "Warning: charset %s char %s occurs twice %d %d\n",defname,s,i,cod); + codetable[cod++]= val; + } + } + } + fclose (f); + gwrite(); + exit (0); +} diff --git a/Lib/charset/make b/Lib/charset/make new file mode 100755 index 0000000..f5727a2 --- /dev/null +++ b/Lib/charset/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f ./Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/charset/master/CHARSETS b/Lib/charset/master/CHARSETS new file mode 100644 index 0000000..9cee4ac --- /dev/null +++ b/Lib/charset/master/CHARSETS @@ -0,0 +1,1630 @@ +referenceset + !" %&'()*+,-./0123456789:;<=>? + ABCDEFGHIJKLMNOPQRSTUVWXYZ _ + abcdefghijklmnopqrstuvwxyz + +charset ISO_646.basic:1983 +alias ref +code 32 +SP ! " ?? ?? % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +?? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ?? ?? ?? ?? _ +?? a b c d e f g h i j k l m n o p q r s t u v w x y z + +charset ISO_646.irv:1983 +alias iso-ir-2 +alias irv +ecma x40 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT + +charset BS_4730 +alias iso-ir-4 +ecma x41 +alias gb +alias uk +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT + +charset ANSI_X3.4-1968 +alias iso-ir-6 +ecma x42 +alias ASCII +alias us +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT + +charset NATS-SEFI +alias iso-ir-8-1 +ecma x43 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +UA A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: AA fS _ +UB a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: aa -N DT + +charset NATS-SEFI-ADD +alias iso-ir-8-2 +ecma x44 +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A! ?? ?? D/ E' ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +TH ?? ?? ?? ?? U: ?? ?? ?? ?? ?? AE O/ ?? ?? ?? +?? a! ?? ?? d/ e' ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +th ?? ?? ?? ?? u: ?? ?? ?? ?? ?? ae o/ ?? ?? ?? + +charset NATS-DANO +alias iso-ir-9-1 +ecma x45 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! << >> DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +UA A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AE O/ AA fS _ +UB a b c d e f g h i j k l m n o p q r s t u v w x y z ae o/ aa -N DT + +charset NATS-DANO-ADD +alias iso-ir-9-2 +ecma x46 +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A! ?? ?? D/ E' ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +TH ?? ?? ?? ?? U: ?? ?? ?? ?? ?? A: O: ?? ?? ?? +?? a! ?? ?? d/ e' ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +th ?? ?? ?? ?? u: ?? ?? ?? ?? ?? a: o: ?? ?? ?? + +charset SEN_850200_B +alias iso-ir-10 +ecma x47 +alias se +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: aa '- DT + +charset SEN_850200_C +alias iso-ir-11 +ecma x48 +alias se2 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +E' A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: AA U: _ +e' a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: aa u: DT + +charset JIS_C_6220-1969 +alias iso-ir-13 +alias katakana +alias x0201-7 +ecma x49 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP .6 <6 >6 ,6 &6 Wo a6 i6 u6 e6 o6 YA YU YO TU +-6 A6 I6 U6 E6 O6 Ka Ki Ku Ke Ko Sa Si Su Se So +Ta Ti Tu Te To Na Ni Nu Ne No Ha Hi Hu He Ho Ma +Mi Mu Me Mo Ya Yu Yo Ra Ri Ru Re Ro Wa N6 "5 05 +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT + +charset JIS_C_6220-1969 +alias iso-ir-14 +ecma x4a +alias jp +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( Ye )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT + +charset IT +alias iso-ir-15 +ecma x59 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +SE A B C D E F G H I J K L M N O P Q R S T U V W X Y Z DG c, e' '> _ +u! a b c d e f g h i j k l m n o p q r s t u v w x y z a! o! e! i! DT + +charset PT +alias iso-ir-16 +ecma x4c +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +SE A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A? C, O? '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a? c, o? DG DT + +charset ES +alias iso-ir-17 +ecma x5a +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +SE A B C D E F G H I J K L M N O P Q R S T U V W X Y Z !I N? ?I '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z DG n? c, '? DT + +charset greek7 +alias iso-ir-18 +ecma x5b +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +'' a* b* q* d* e* f* g* y* i* c* k* l* m* n* o* +p* i3 r* s* t* h* w* *s x* u* z* ?, ,, ,' '? _ +'! A* B* Q* D* E* F* G* Y* I* C* K* L* M* N* O* +P* ?? R* S* T* H* W* .M X* U* Z* ?; ;; ;' ': DT + +charset latin-greek +alias iso-ir-19 +ecma x5c +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O +P Q R S T U V W X Y Z <( // )> '> _ +'! A* B* Q* D* E* F* G* Y* I* C* K* L* M* N* O* +P* ?? R* S* T* H* W* .M X* U* Z* (! !! !) ': DT + +charset DIN_66003 +alias iso-ir-21 +ecma x4b +alias de +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +SE A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: U: '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: u: ss DT + +charset NF_Z_62-010_(1973) +alias iso-ir-25 +ecma x52 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +a! A B C D E F G H I J K L M N O P Q R S T U V W X Y Z DG c, SE '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z e' u! e! ': DT + +charset Latin-greek-1 +alias iso-ir-27 +ecma x55 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP C* " G* Cu % & ' ( ) * + , - . / +0 1 2 3 4 5 6 7 8 9 Q* ; < = > P* +D* A B C D E F G H I J K L M N O +P Q R S T U V W X Y Z W* H* F* L* S* +'! a b c d e f g h i j k l m n o +p q r s t u v w x y z (! !! !) '- DT + +charset ISO_5428 +alias iso-ir-31 +ecma x58 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP "! "' ?? "? ?? ?? ?? ?? ': ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A* B* G* D* E* Z* Y* H* I* K* L* M* N* C* O* +P* R* S* T* U* F* X* Q* W* .M << >> ?? ?? ?? ?? +?? a* b* g* d* e* z* y* h* i* k* l* m* n* c* o* +p* r* s* t* u* f* x* q* w* *s ?? ?? ?? ?? ?? ?? +__ + +charset ISO_5427 +alias iso-ir-37 +ecma x4e +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +ju a= b= c= d= e= f= g= h= i= j= k= l= m= n= o= +p= ja r= s= t= u= z% v= %' y= z= s% je sc c% =' +JU A= B= C= D= E= F= G= H= I= J= K= L= M= N= O= +P= JA R= S= T= U= Z% V= %" Y= Z= S% JE Sc C% DT + +charset DIN_31624 +alias iso-ir-38 +ecma x4f +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +SE A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: U: '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: u: ss DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I ?? Pd Cu %0 /- At DE <( (! << Mb Co Po Rg +?? ?? ?? ?? // !! /= .M -> )> !) >> MX ?? ?? ?I +?? "! "' "> "? "- "( ". ": "2 "0 ?? ?? "" ?? "< +"; ?? ?? ?? ?? ?? ?? ?? "_ "= ?? ?? ?? ?? ?? ?? +?? AE D/ ?? ?? ?? ?? ?? L/ O/ OE ?? TH ?? ?? ?? +?? ae d/ d- ?? i. ?? ?? l/ o/ oe yr th ?? ?? ?? +__ + +charset DIN_31625 +alias iso-ir-39 +ecma x4d +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP +__ + +charset BS_viewdata +alias iso-ir-47 +ecma x56 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <- 12 -> -! OS +'! a b c d e f g h i j k l m n o p q r s t u v w x y z 14 PP 34 -: DT + +charset INIS +alias iso-ir-49 +ecma x57 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? DO % ?? ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?? +?? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( ?? )> ?? ?? +?? a b c d e f g h i j k l m n o p q r s t u v w x y z ?? !! ?? ?? DT + +charset INIS-8 +alias iso-ir-50 +ecma x5d +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? a* b* g* d* C* ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -> In +0S 1S 2S 3S 4S 5S 6S 7S 8S 9S +S -S Ru D* L* W* +0s 1s 2s 3s 4s 5s 6s 7s 8s 9s S* m* n* w* p* DT + +charset INIS-cyrillic +alias iso-ir-51 +ecma x5e +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? RT ?? -> In +a* b* g* d* S* m* n* w* p* C* D* L* W* =" -S +S +ju a= b= c= d= e= f= g= h= i= j= k= l= m= n= o= +p= ja r= s= t= u= z% v= %' y= z= s% je sc c% =' +JU A= B= C= D= E= F= G= H= I= J= K= L= M= N= O= +P= JA R= S= T= U= Z% V= %" Y= Z= S% JE Sc C% DT + +charset ISO_5426:1980 +alias iso-ir-53 +ecma x50 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I :9 Pd DO Ye /- SE '1 '6 "6 << Mb Co Po Rg +?? ?? .9 ?? ?? ?? /= .M '2 '9 "9 >> MX '' '" ?I +?? "! "' "> "? "- "( ". ": "2 "0 ?? ?? "" ?? '< +"; ?? ?? ?? ?? ?? ?? ?? "_ "= ?? ?? ?? ?? ?? ?? +?? AE D/ ?? ?? ?? IJ ?? L/ O/ OE ?? TH ?? ?? ?? +?? ae d/ d- ?? i. ij ?? l/ o/ oe ss th ?? __ + +charset ISO_5427:1981 +alias iso-ir-54 +ecma x51 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? d% g% ie io ds ii yi j% lj nj ts kj v% dz ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? <( ?? )> ?? _ +?? D% G% IE IO DS II YI J% LJ NJ Ts KJ V% DZ =" +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT +__ + +charset ISO_5428:1980 +alias iso-ir-55 +ecma x53 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP '! '' ': '? ,, ;; i3 ?? ?? ?? ?? ?? ?? ?? ?? +<< >> 9" ?? '1 ?? ?? ?? ?? ?? ?? .M ?? ?? ?? ; +?? A* B* ?? G* D* E* ?? ?? Z* Y* H* I* K* L* M* +N* C* O* P* ?? R* S* ?? T* U* F* X* Q* W* ?? ?? +?? a* b* ?? g* d* e* ?? ?? z* y* h* i* k* l* m* +n* c* o* p* ?? r* s* *s t* u* f* x* q* w* ?? ?? +__ + +charset GB_1988-80 +alias iso-ir-57 +ecma x54 +alias cn +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Ye % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT + +charset codar-u +alias iso-ir-59 +ecma x5f +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + ,+ - . / 0 1 2 3 4 5 6 7 8 9 : ;+ < = > ?+ +At ?? ?? ?? ?? ?? ?? ?? /+ :+ ?? '+ "+ ?? 1+ =+ +?? 0+ ?? 3+ aH aM wH ?? yH ah yf p+ v+ gf H' a+ +b+ tm t+ tk g+ hk x+ d+ dk r+ z+ s+ sn c+ dd tj +zH e+ i+ f+ q+ k+ l+ m+ n+ h+ w+ y+ !! j+ NO DT +__ + +charset NS_4551-1 +alias iso-ir-60 +ecma x60 +alias no +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AE O/ AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z ae o/ aa '- DT + +charset NS_4551-2 +alias iso-ir-61 +ecma x61 +alias no2 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " PI DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AE O/ AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z ae o/ aa !! DT + +charset APL +alias iso-ir-68 +ecma x65 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ': ) < <= = > )> OR AN != -: , + . / +0 1 2 3 4 5 6 7 8 9 ( <( ; ?? : // +'- ?? ?? ?? ?? ?? _ ?? ?? i* ?? ' OS !! ?? ?? +* ? r* ?? ?? ?? ?? w* ?? -! ?? <- ?? -> >= - +OL A B C D E F G H I J K L M N O P Q R S T U V W X Y Z (! ?? !) DO DT +__ + +charset NF_Z_62-010 +alias iso-ir-69 +ecma x66 +alias fr +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +a! A B C D E F G H I J K L M N O P Q R S T U V W X Y Z DG c, SE '> _ +My a b c d e f g h i j k l m n o p q r s t u v w x y z e' u! e! ': DT + +charset videotex-suppl +alias iso-ir-70 +ecma x62 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " ?? ?? % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye Nb SE Cu '6 "6 << <- -! -> -v +DG +- 2S 3S *X My PI .M -: '9 "9 >> 14 12 34 ?I +"1 "! "' "> "? "- "( ". ": ?? "0 ", ?? "" "; "< +-M 1S Rg Co TM Md ?? ?? ?? ?? ?? ?? 18 38 58 78 +Om AE D- -a H/ ?? IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng ?? + +charset mosaic-2 +alias iso-ir-71 +ecma x63 +__ + +charset mosaic-3 +alias iso-ir-72 +ecma x64 +__ + +charset PT2 +alias iso-ir-84 +ecma x67 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +'' A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A? C, O? '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a? c, o? '- DT + +charset ES2 +alias iso-ir-85 +ecma x68 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +Sb A B C D E F G H I J K L M N O P Q R S T U V W X Y Z !I N? C, ?I _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z '' n? c, ': DT + +charset MSZ_7795.3 +alias iso-ir-86 +ecma x69 +alias hu +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +A' A B C D E F G H I J K L M N O P Q R S T U V W X Y Z E' O: U: '> _ +a' a b c d e f g h i j k l m n o p q r s t u v w x y z e' o: u: '" DT + +charset greek7 +alias iso-ir-88 +ecma x6a +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A* B* G* D* E* Z* Y* H* I* ?? K* L* M* N* C* +O* P* R* S* T* U* F* ?? X* Q* W* <( // )> '> _ +'! a* b* g* d* e* z* y* h* i* ?? k* l* m* n* c* +o* p* r* s* t* u* f* *s x* q* w* (! !! !) '- DT + +charset ASMO_449 +alias ISO_9036 +alias arabic7 +alias iso-ir-89 +ecma x6b +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + ,+ - . / 0 1 2 3 4 5 6 7 8 9 : ;+ < = > ?+ +At H' aM aH wH ah yH a+ b+ tm t+ tk g+ hk x+ d+ +dk r+ z+ s+ sn c+ dd tj zH e+ i+ <( // )> '> _ +++ f+ q+ k+ l+ m+ n+ h+ w+ j+ y+ :+ "+ =+ /+ '+ +1+ 3+ 0+ ?? ?? ?? ?? ?? ?? ?? ?? (! !! !) '- DT + +charset iso-ir-90 +ecma x6c +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye ?? SE ?? '6 "6 << <- -! -> -v +DG +- 2S 3S *X My PI .M -: '9 "9 >> 14 12 34 ?I +?? "! "' "> "? "- "( ". ": ?? "0 ", "_ "" "; "< +-M 1S Rg Co TM Md ?? ?? ?? ?? ?? ?? 18 38 58 78 +Om AE D- -a H/ ?? IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng ?? + +charset JIS_C_6229-1984-a +alias iso-ir-91 +ecma x6d +alias jp-ocr-a +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? " Pd DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; 1h = 3h ? +?? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ?? Ye 2h '> _ +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 4h ?? ?? DT + +charset JIS_C_6229-1984-b +alias iso-ir-92 +ecma x6e +alias jp-ocr-b +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z '> _ +?? a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) ?? DT + +charset JIS_C_6229-1984-b-add +alias iso-ir-93 +ecma x6f +alias jp-ocr-a +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? Pd Cu // ?? SE ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT + +charset JIS_C_6229-1984-hand +alias iso-ir-94 +ecma x70 +alias jp-ocr-hand +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z '> _ +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? !! ?? ?? DT + +charset JIS_C_6229-1984-hand-add +alias iso-ir-95 +ecma x71 +alias jp-ocr-hand-add +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? ?? // ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT + +charset JIS_C_6229-1984-kana +alias iso-ir-96 +ecma x72 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? <6 >6 ?? ?? Wo ?? ?? ?? ?? ?? ?? ?? ?? ?? +-6 A6 I6 U6 E6 O6 Ka Ki Ku Ke Ko Sa Si Su Se So +Ta Ti Tu Te To Na Ni Nu Ne No Ha Hi Hu He Ho Ma +Mi Mu Me Mo Ya Yu Yo Ra Ri Ru Re Ro Wa N6 "5 05 +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT + +charset ISO_2033-1983 +alias iso-ir-98 +alias e13b +ecma x73 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 1j 2j 3j 4j ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? DT + +charset ANSI_X3.110-1983 +alias iso-ir-99 +alias CSA_T500-1983 +alias NAPLPS +ecma x74 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " ?? ?? % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye Nb SE Cu '6 "6 << <- -! -> -v +DG +- 2S 3S *X My PI .M -: '9 "9 >> 14 12 34 ?I +?? "! "' "> "? "- "( ". ": "/ "0 ", "_ "" "; "< +-M 1S Rg Co TM Md HH VV FD BD Fd Bd 18 38 58 78 +Om AE D- -a H/ VH IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng ?? + +charset ISO_8859-1:1987 +alias iso-ir-100 +ecma x141 +alias ISO_8859-1 +alias latin1 +alias l1 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd Cu Ye BB SE ': Co -a << NO -- Rg '- +DG +- 2S 3S '' My PI .M ', 1S -o >> 14 12 34 ?I +A! A' A> A? A: AA AE C, E! E' E> E: I! I' I> I: +D- N? O! O' O> O? O: *X O/ U! U' U> U: Y' TH ss +a! a' a> a? a: aa ae c, e! e' e> e: i! i' i> i: +d- n? o! o' o> o? o: -: o/ u! u' u> u: y' th y: + +charset ISO_8859-2:1987 +alias iso-ir-101 +ecma x142 +alias ISO_8859-2 +alias latin2 +alias l2 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS A; '( L/ Cu L< S' SE ': S< S, T< Z' -- Z< Z. +DG a; '; l/ '' l< s' '< ', s< s, t< z' '" z< z. +R' A' A> A( A: L' C' C, C< E' E; E: E< I' I> D< +D/ N' N< O' O> O" O: *X R< U0 U' U" U: Y' T, ss +r' a' a> a( a: l' c' c, c< e' e; e: e< i' i> d< +d/ n' n< o' o> o" o: -: r< u0 u' u" u: y' t, '. + +charset T.61 +alias iso-ir-102 +ecma x75 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( ?? )> ?? _ +?? a b c d e f g h i j k l m n o p q r s t u v w x y z ?? !! ?? ?? DT + +charset T.61-8bit +alias iso-ir-103 +ecma x76 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " ?? ?? % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( ?? )> ?? _ +?? a b c d e f g h i j k l m n o p q r s t u v w x y z ?? !! ?? ?? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye Nb SE Cu ?? ?? << ?? ?? ?? ?? +DG +- 2S 3S *X My PI .M -: ?? ?? >> 14 12 34 ?I +?? "! "' "> "? "- "( ". ": ?? "0 ", "_ "" "; "< +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +Om AE D- -a H/ ?? IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng ?? + +charset ISO_8859-3:1988 +alias iso-ir-109 +ecma x143 +alias ISO_8859-3 +alias latin3 +alias l3 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS H/ '( Pd Cu ?? H> SE ': I. S, G( J> -- ?? Z. +DG h/ 2S 3S '' My h> .M ', i. s, g( j> 12 ?? z. +A! A' A> ?? A: C. C> C, E! E' E> E: I! I' I> I: +?? N? O! O' O> G. O: *X G> U! U' U> U: U( S> ss +a! a' a> ?? a: c. c> c, e! e' e> e: i! i' i> i: +?? n? o! o' o> g. o: -: g> u! u' u> u: u( s> '. + +charset ISO_8859-4:1988 +alias iso-ir-110 +ecma x144 +alias ISO_8859-4 +alias latin4 +alias l4 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS A; kk R, Cu I? L, SE ': S< E- G, T/ -- Z< '- +DG a; '; r, '' i? l, '< ', s< e- g, t/ NG z< ng +A- A' A> A? A: AA AE I; C< E' E; E: E. I' I> I- +D/ N, O- K, O> O? O: *X O/ U; U' U> U: U? U- ss +a- a' a> a? a: aa ae i; c< e' e; e: e. i' i> i- +d/ n, o- k, o> o? o: -: o/ u; u' u> u: u? u- '. + +charset ECMA-cyrillic +alias iso-ir-111 +ecma x40 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS IO D% G% IE DS II YI J% LJ NJ Ts KJ -- V% DZ +N0 io d% g% ie ds ii yi j% lj nj ts kj Cu v% dz +A= B= V= G= D= E= Z% Z= I= J= K= L= M= N= O= P= +R= S= T= U= F= H= C= C% S% Sc =" Y= %" JE JU JA +a= b= v= g= d= e= z% z= i= j= k= l= m= n= o= p= +r= s= t= u= f= h= c= c% s% sc =' y= %' je ju ja + +charset CSA_Z243.4-1985-1 +alias iso-ir-121 +ecma x77 +alias csa7-1 +alias ca +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +a! A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a> c, e> i> _ +o> a b c d e f g h i j k l m n o p q r s t u v w x y z e' u! e! u> DT + +charset CSA_Z243.4-1985-2 +alias iso-ir-122 +ecma x78 +alias csa7-2 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +a! A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a> c, e> E' _ +o> a b c d e f g h i j k l m n o p q r s t u v w x y z e' u! e! u> DT + +charset CSA_Z243.4-1985-gr +alias iso-ir-123 +ecma x45 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I ': Pd Ct Ye +- '' (S )S 12 +S ', -- .M -S +0S 1S 2S 3S 4S 5S 6S 7S 8S 9S 14 34 <= != >= ?I +A! A' A> C, E! E' E> E: I' I> I: N? O' O> U! U' +U> U: Rg SE PI m* -a -o '6 '9 "6 "9 << >> DG BB +a! a' a> c, e! e' e> e: i' i> i: n? o' o> u! u' +u> u: Co hh vv ur ul dl dr vr uh vl dh vh NO FB + +charset ISO_8859-7:1987 +alias iso-ir-126 +ecma x146 +alias ISO_8859-7 +alias ELOT_928 +alias greek +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS 9' '9 Pd ?? ?? BB SE ': Co ?? << NO -- ?? -M +DG +- 2S 3S '% '' A% .M E% Y% I% >> O% 12 U% W% +j% A* B* G* D* E* Z* Y* H* I* K* L* M* N* C* O* +P* R* ?? S* T* U* F* X* Q* W* J* V* a% e% y% i% +v% a* b* g* d* e* z* y* h* i* k* l* m* n* c* o* +p* r* *s s* t* u* f* x* q* w* j* v* o% u% w% ?? + +charset ISO_8859-6:1987 +alias iso-ir-127 +ecma x147 +alias ISO_8859-6 +alias arabic +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS ?? ?? ?? Cu ?? ?? ?? ?? ?? ?? ?? ,+ -- ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ;+ ?? ?? ?? ?+ +?? H' aM aH wH ah yH a+ b+ tm t+ tk g+ hk x+ d+ +dk r+ z+ s+ sn c+ dd tj zH e+ i+ ?? ?? ?? ?? ?? +++ f+ q+ k+ l+ m+ n+ h+ w+ j+ y+ :+ "+ =+ /+ '+ +1+ 3+ 0+ ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? + +charset T.101-G2 +alias iso-ir-128 +ecma x7c +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " ?? ?? % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye Nb SE Cu '6 "6 << <- -! -> -v +DG +- 2S 3S *X My PI .M -: '9 "9 >> 14 12 34 ?I +?? "! "' "> "? "- "( ". ": "/ "0 ", "_ "" "; "< +-M 1S Rg Co TM Md HH VV FD BD Fd Bd 18 38 58 78 +Om AE D- -a H/ VH IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng ?? + +charset T.101-G3 +alias iso-ir-129 +ecma x7d +__ + +charset T.101-DS1 +alias iso-ir-137 +ecma x79 +__ + +charset ISO_8859-8:1988 +alias iso-ir-138 +ecma x148 +alias ISO_8859-8 +alias hebrew +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS ?? Ct Pd Cu Ye BB SE ': Co *X << NO -- Rg '- +DG +- 2S 3S '' My PI .M ', 1S -: >> 14 12 34 ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? =2 +A+ B+ G+ D+ H+ W+ Z+ X+ Tj J+ K% K+ L+ M% M+ N% +N+ S+ E+ P% P+ Zj ZJ Q+ R+ Sh T+ ?? ?? ?? ?? ?? + +charset CSN_369103 +alias iso-ir-139 +ecma x49 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS A; '( L/ DO L< S' SE ': S< S, T< Z' -- Z< Z. +DG a; '; l/ '' l< s' '< ', s< s, t< z' '" z< z. +R' A' A> A( A: L' C' C, C< E' E; E: E< I' I> D< +D/ N' N< O' O> O" O: *X R< U0 U' U" U: Y' T, ss +r' a' a> a( a: l' c' c, c< e' e; e: e< i' i> d< +d/ n' n< o' o> o" o: -: r< u0 u' u" u: y' t, '. + +charset JUS_I.B1.002 +alias iso-ir-141 +ecma x7a +alias js +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +Z< A B C D E F G H I J K L M N O P Q R S T U V W X Y Z S< D/ C' C< _ +z< a b c d e f g h i j k l m n o p q r s t u v w x y z s< d/ c' c< DT + +charset ISO_6937-2-add +alias iso-ir-142 +ecma x4a +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd DO Ye ?? SE ?? '6 "6 << <- -! -> -v +DG +- 2S 3S *X My PI .M -: '9 "9 >> 14 12 34 ?I +?? "! "' "> "? "- "( ". ": ?? "0 ", "_ "" "; "< +-M 1S Rg Co TM Md NO BB ?? ?? ?? ?? 18 38 58 78 +Om AE D- -a H/ ?? IJ L. L/ O/ OE -o TH T/ NG 'n +kk ae d/ d- h/ i. ij l. l/ o/ oe ss th t/ ng -- + +charset IEC_P27-1 +alias iso-ir-143 +ecma x4b +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +'< =3 AN OR (U )U (C )C <= => .: :. (- -) (_ )_ +In Io 00 NB dP ?1 ?2 ?- ?= =< != >= <> NO FA TE +A+ OS PP G* D* -T -V -L H* L* '1 '2 C* -+ +P* 2S S* *X 3S U* F* .M Q* W* /0 >V RT f( 0( +- +DG a* b* g* d* e* z* y* h* i* k* l* m* n* c* %0 +p* r* s* -: t* u* f* x* q* w* /- <- -! -> -v '- + +charset ISO_8859-5:1988 +alias iso-ir-144 +ecma x4c +alias ISO_8859-5 +alias cyrillic +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS IO D% G% IE DS II YI J% LJ NJ Ts KJ -- V% DZ +A= B= V= G= D= E= Z% Z= I= J= K= L= M= N= O= P= +R= S= T= U= F= H= C= C% S% Sc =" Y= %" JE JU JA +a= b= v= g= d= e= z% z= i= j= k= l= m= n= o= p= +r= s= t= u= f= h= c= c% s% sc =' y= %' je ju ja +N0 io d% g% ie ds ii yi j% lj nj ts kj SE v% dz + +charset JUS_I.B1.003-serb +alias iso-ir-146 +ecma x7b +alias serbian +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +Z% A= B= C= D= E= F= G= H= I= J% K= L= M= N= O= +P= LJ R= S= T= U= V= NJ DZ DS Z= S% D% Ts C% _ +z% a= b= c= d= e= f= g= h= i= j% k= l= m= n= o= +p= lj r= s= t= u= v= nj dz ds z= s% d% ts c% DT + +charset JUS_I.B1.003-mac +alias macedonian +alias iso-ir-147 +ecma x7d +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +Z% A= B= C= D= E= F= G= H= I= J% K= L= M= N= O= +P= LJ R= S= T= U= V= NJ DZ DS Z= S% G% KJ C% _ +z% a= b= c= d= e= f= g= h= i= j% k= l= m= n= o= +p= lj r= s= t= u= v= nj dz ds z= s% g% kj c% DT + +charset ISO_8859-9:1989 +alias iso-ir-148 +ecma x14d +alias ISO_8859-9 +alias latin5 +alias l5 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS !I Ct Pd Cu Ye BB SE ': Co -a << NO -- Rg '- +DG +- 2S 3S '' My PI .M ', 1S -o >> 14 12 34 ?I +A! A' A> A? A: AA AE C, E! E' E> E: I! I' I> I: +G( N? O! O' O> O? O: *X O/ U! U' U> U: I. S, ss +a! a' a> a? a: aa ae c, e! e' e; e: e. i' i> i- +g( n? o! o' o> o? o: -: o/ u! u' u> u: i. s, y: + +charset greek-ccitt +alias iso-ir-150 +ecma x140 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A* B* G* D* E* Z* Y* H* I* K* L* M* N* C* O* +P* R* ?? S* T* U* F* X* Q* W* ?? <( // )> '> _ +?? a* b* g* d* e* z* y* h* i* k* l* m* n* c* o* +p* r* *s s* t* u* f* x* q* w* ?? (! !! !) '- DT + +charset NC_NC00-10:81 +alias cuba +alias iso-ir-151 +ecma x141 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O +P Q R S T U V W X Y Z !I N? )> ?I _ +'! a b c d e f g h i j k l m n o +p q r s t u v w x y z '' n? <( ': DT + +charset ISO_6937-2-25 +alias iso-ir-152 +ecma x4e +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS ?? ?? ?? ?? ?? ?? ?? ?? ?? "6 ?? <- -! -> -v +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? "9 ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? TM Md ?? ?? ?? ?? ?? ?? 18 38 58 78 +Om ?? ?? ?? ?? ?? IJ L. ?? ?? OE ?? W> Y> Y: 'n +?? ?? ?? ?? ?? ?? ij l. ?? ?? oe ?? w> y> ?? ?? + +charset GOST_19768-74 +alias ST_SEV_358-88 +alias iso-ir-153 +ecma x4f +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS IO ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -- ?? ?? +A= B= V= G= D= E= Z% Z= I= J= K= L= M= N= O= P= +R= S= T= U= F= H= C= C% S% Sc =" Y= %" JE JU JA +a= b= v= g= d= e= z% z= i= j= k= l= m= n= o= p= +r= s= t= u= f= h= c= c% s% sc =' y= %' je ju ja +?? io ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? + +charset ISO_8859-supp +alias iso-ir-154 +alias latin1-2-5 +ecma x50 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +?? ?? A- C> C. ?? E. E- G> '6 "6 TM <- -! -> -v +?? ?? a- c> c. d- e. e- g> '9 "9 Md 18 38 58 78 +?? G( G. G, H> H/ I? I. I- I; IJ J> K, L, L. N, +-M NG O- OE R, S> T/ TH U? U( U- U; W> Y' Y> Y: +Om g( g. g, h> h/ i? i. i- i; ij j> k, l, l. n, +kk ng o- oe r, s> t/ th u? u( u- u; w> y' y> 'n + +charset ISO_8859-supp +alias iso-ir-155 +ecma x51 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +VV HH DR LD UR UL VR VL DH UH VH UB LB FB sB ?? +vv hh dr dl ur ul vr vl dh uh vh .S :S ?S ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? + +charset latin6 +alias iso-ir-157 +alias l6 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS A; E- G, I- I? K, L, N' R, S< T/ Z< -- kk NG +d/ a; e- g, i- i? k, l, n' r, s< t/ z< SE ss ng +A- A' A> A? A: AA AE I; C< E' E; E: E. I' I> I: +D/ N, O- O' O> O? O: U? O/ U; U' U> U: Y' TH U- +a- a' a> a? a: aa ae i; c< e' e; e: e. i' i> i: +d- n, o- o' o> o? o: u? o/ u; u' u> u: y' th u- + +charset latin-lap +alias lap +alias iso-ir-158 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +'' ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +;S ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +A( A> A! A- A1 A2 A3 E( E! E- G/ G< K< O( O! O; +O1 U- ED EZ ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +a( a> a! a- a1 a2 a3 e( e! e- g/ g< k< o( o! o; +o1 u- ed ez ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? + +charset DS_2089 +alias DS2089 +alias dk +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AE O/ AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z ae o/ aa '? DT + +charset us-dk +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +duplicate 91 AE +duplicate 92 O/ +duplicate 93 AA +duplicate 123 ae +duplicate 124 o/ +duplicate 125 aa + +charset dk-us +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AE O/ AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z ae o/ aa '? DT +duplicate 91 <( +duplicate 92 // +duplicate 93 )> +duplicate 123 (! +duplicate 124 !! +duplicate 125 !) + +charset FI +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A: O: AA '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z a: o: aa '? DT + +charset JIS_X0201 +alias X0201 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( Ye )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS .6 <6 >6 ,6 &6 Wo a6 i6 u6 e6 o6 YA YU YO TU +-6 A6 I6 U6 E6 O6 Ka Ki Ku Ke Ko Sa Si Su Se So +Ta Ti Tu Te To Na Ni Nu Ne No Ha Hi Hu He Ho Ma +Mi Mu Me Mo Ya Yu Yo Ra Ri Ru Re Ro Wa N6 "5 05 +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? + +charset cp437 +alias 437 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +C, u: e' a> a: a! aa c, e> e: e! i: i> i! A: AA +E' ae AE o> o: o! u> u! y: O: U: Ct Pd Ye Pt Fl +a' i' o' u' n? N? -a -o ?I NI NO 12 14 !I << >> +.S :S ?S vv vl vL Vl Dl dL VL VV LD UL Ul uL dl +ur uh dh vr hh vh vR Vr UR DR UH DH VR HH VH uH +Uh dH Dh Ur uR dR Dr Vh vH ul dr FB LB lB RB TB +a* b* G* p* S* s* m* t* F* H* W* d* 00 /0 e* (U +=3 +- >= =< Iu Il -: ?2 Ob .M Sb RT nS 2S fS NS + +charset cp850 +alias 850 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +C, u: e' a> a: a! aa c, e> e: e! i: i> i! A: AA +E' ae AE o> o: o! u> u! y: O: U: o/ Pd O/ *X Fl +a' i' o' u' n? N? -a -o ?I Rg NO 12 14 !I << >> +.S :S ?S vv vl A' A> A! Co VL VV LD UL Ct Ye dl +ur uh dh vr hh vh a? A? UR DR UH DH VR HH VH Cu +d- D- E> E: E! i. I' I> I: ul dr FB LB BB I! TB +O' ss O> O! o? O? m* TH th U' U> U! y' Y' -M '' +-- +- == 34 PI SE -: '; DG ': '. 1S 3S 2S fS NS + +charset cp860 +alias 860 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +C, u: e' a> a? a! A' c, e> E> e! I> O> i! A? A> +E' A! E! o> o? o! U' u! I! O? U: Ct Pd U! Pt O! +a' i' o' u' n? N? -a -o ?I O' NO 12 14 !I << >> +.S :S ?S vv vl vL Vl Dl dL VL VV LD UL Ul uL dl +ur uh dh vr hh vh vR Vr UR DR UH DH VR HH VH uH +Uh dH Dh Ur uR dR Dr Vh vH ul dr FB LB lB RB TB +a* b* G* p* S* s* m* t* F* H* W* d* 00 /0 e* (U +=3 +- >= =< Iu Il -: ?2 Ob .M Sb RT nS 2S fS NS + +charset cp863 +alias 863 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +C, u: e' a> A> a! PI c, e> e: e! i: i> i! A! SE +E' E! E> o> E: I: u> u! Cu O> U: Ct Pd U! U> Fl +BB '' o' u' ': ', 3S '- I> NI NO 12 14 34 << >> +.S :S ?S vv vl vL Vl Dl dL VL VV LD UL Ul uL dl +ur uh dh vr hh vh vR Vr UR DR UH DH VR HH VH uH +Uh dH Dh Ur uR dR Dr Vh vH ul dr FB LB lB RB TB +a* b* G* p* S* s* m* t* F* H* W* d* 00 /0 e* (U +=3 +- >= =< Iu Il -: ?2 Ob .M Sb RT nS 2S fS NS + +charset cp865 +alias 865 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +C, u: e' a> a: a! aa c, e> e: e! i: i> i! A: AA +E' ae AE o> o: o! u> u! y: O: U: o/ Pd O/ Pt Fl +a' i' o' u' n? N? -a -o ?I NI NO 12 14 !I << >> +.S :S ?S vv vl vL Vl Dl dL VL VV LD UL Ul uL dl +ur uh dh vr hh vh vR Vr UR DR UH DH VR HH VH uH +Uh dH Dh Ur uR dR Dr Vh vH ul dr FB LB lB RB TB +a* b* G* p* S* s* m* t* F* H* W* d* 00 /0 e* (U +=3 +- >= =< Iu Il -: ?2 Ob .M Sb RT nS 2S fS NS + +charset DEC-MCS +alias dec +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +?? !I Ct Pd ?? Ye ?? SE Cu Co -a << ?? ?? ?? ?? +DG +- 2S 3S ?? My PI .M ?? 1S -o >> 14 12 ?? ?I +A! A' A> A? A: AA AE C, E! E' E> E: I! I' I> I: +?? N? O! O' O> O? O: OE O/ U! U' U> U: Y: ?? ss +a! a' a> a? a: aa ae c, e! e' e; e: e. i' i> i: +?? n? o! o' o> o? o: oe o/ u! u' u> u: y: ?? ?? + +charset roman8 +alias r8 +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +PA HO BH NH IN NL SA ES HS HJ VS PD PU RI S2 S3 +DC P1 P2 TS CC MW SG EG SS GC SC CI ST OC PM AC +NS A! A> E! E> E: I> I: '' ?? ?? ': ?? U! U> Li +'- Y' y' DG C, c, N? n? !I ?I Cu Pd Ye SE Fl Ct +a> e> o> u> a' e' o' u' a! e! o! u! a: e: o: u: +AA i> O/ AE aa i' o/ ae A: i! O: U: E' i: ss O> +A' A? a? D- d- I' I! O' O! O? o? S< s< U' Y: y: +TH th .M My PI 34 -M 14 12 -a -o << fS >> +- ?? + +charset macintosh +alias mac +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb DO % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '? DT +A: AA C, E' N? O: U: a' a! a> a: a? aa c, e' e! +e> e: i' i! i> i: n? o' o! o> o: o? u' u! u> u: +/- DG Ct Pd SE Sb PI ss Rg Co TM '' ': != AE O/ +00 +- =< >= Ye My dP +Z *P p* In -a -o W* ae o/ +?I !I NO RT Fl ?2 D* << >> .3 NS A! A? O? OE oe +-M -N "6 "9 '6 '9 -: OL y: Y: /f Cu <1 >1 fi fl +/= .M .9 :9 %0 A> E> A' E: E! I' I> I: I! O' O> +?? O! U' U> U! i. ?? ?? '- '( '. '0 ', '" '; '< + +charset EBCDIC-AT-DL +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? A: . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? U: DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? o: , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb SE ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ss s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +a: A B C D E F G H I ?? ?? ?? ?? ?? ?? +u: J K L M N O P Q R ?? ?? ?? ?? ?? ?? +O: ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-AT-DL-A +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? o: . < ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? u: U: * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? ss , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? : A: O: ' = a: +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ?? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A B C D E F G H I ?? ?? ?? ?? ?? ?? +?? J K L M N O P Q R ?? ?? ?? ?? ?? ?? +?? ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-BE +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? <( . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? )> DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? u! , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb a! ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ': s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +e' A B C D E F G H I ?? ?? ?? ?? ?? ?? +e! J K L M N O P Q R ?? ?? ?? ?? ?? ?? +c, ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-BR +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? E' . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? DO C, * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? c, , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? a? : O? A? ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? '? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +o? A B C D E F G H I ?? ?? ?? ?? ?? ?? +e' J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-CA-FR +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? a> ?? ?? ?? ?? ?? c, ?? a! . < ( + ! +& ?? e> e: ?? ?? i> i: ?? ?? '' DO * ) ; '> +- / A> ?? A! ?? ?? ?? C, ?? u! , % _ > ? +?? E' E> E: ?? I> I: ?? ?? '! : Nb At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ': s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +e' A B C D E F G H I ?? o> ?? ?? ?? ?? +e! J K L M N O P Q R ?? u> u: ?? ?? ?? +', ?? S T U V W X Y Z ?? O> ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? U> U: U! ?? ?? + +charset EBCDIC-DK-NO +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? Nb . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? Cu AA * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? o/ , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : AE O/ ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? u: s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +ae A B C D E F G H I ?? ?? ?? ?? ?? ?? +aa J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-DK-NO-A +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? o/ . < ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? aa AA * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? : AE O/ ' = ae +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ?? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A B C D E F G H I ?? ?? ?? ?? ?? ?? +?? J K L M N O P Q R ?? ?? ?? ?? ?? ?? +?? ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-FI-SE +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? SE . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? Cu AA * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? o: , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? e' : A: O: ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? u: s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +a: A B C D E F G H I ?? ?? ?? ?? ?? ?? +aa J K L M N O P Q R ?? ?? ?? ?? ?? ?? +E' ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-FI-SE-A +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? o: . < ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? aa AA * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? : A: O: ' = a: +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ?? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A B C D E F G H I ?? ?? ?? ?? ?? ?? +?? J K L M N O P Q R ?? ?? ?? ?? ?? ?? +?? ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-FR +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? DG . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? SE DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? u! , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Pd a! ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ': s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +e' A B C D E F G H I ?? ?? ?? ?? ?? ?? +e! J K L M N O P Q R ?? ?? ?? ?? ?? ?? +c, ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-IT +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? DG . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? e' DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? o! , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? u! : Pd SE ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? i! s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +a! A B C D E F G H I ?? ?? ?? ?? ?? ?? +e! J K L M N O P Q R ?? ?? ?? ?? ?? ?? +c, ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-INT +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? <( . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? )> DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? '? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-JP-E +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? Pd . < ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? ! Ye * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? '- s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +Do ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-PT +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? <( . < ( + ! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? )> DO * ) ; '> +- / ?? ?? ?? ?? ?? ?? ?? ?? o? , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : A? O? ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? c, s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +a? A B C D E F G H I ?? ?? ?? ?? ?? ?? +'' J K L M N O P Q R ?? ?? ?? ?? ?? ?? +C, ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-ES +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? <( . C, ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? )> Pt * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? n? , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : N? At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ': s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-ES-A +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? Ct . C, ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? ! Pt * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? : N? At ' = n? +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ?? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? A B C D E F G H I ?? ?? ?? ?? ?? ?? +?? J K L M N O P Q R ?? ?? ?? ?? ?? ?? +?? ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-ES-S +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? <( . C, ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? )> DO * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? n? , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : N? At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? ': s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-UK +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? DO . C, ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? ! Pd * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? '- s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? + +charset EBCDIC-US +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +SP ?? ?? ?? ?? ?? ?? ?? ?? ?? Ct . C, ( + !! +& ?? ?? ?? ?? ?? ?? ?? ?? ?? ! DO * ) ; NO +- / ?? ?? ?? ?? ?? ?? ?? ?? BB , % _ > ? +?? ?? ?? ?? ?? ?? ?? ?? ?? '! : Nb At ' = " +?? a b c d e f g h i ?? ?? ?? ?? ?? ?? +?? j k l m n o p q r ?? ?? ?? ?? ?? ?? +?? '? s t u v w x y z ?? ?? ?? ?? ?? ?? +?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? +(! A B C D E F G H I ?? ?? ?? ?? ?? ?? +!) J K L M N O P Q R ?? ?? ?? ?? ?? ?? +// ?? S T U V W X Y Z ?? ?? ?? ?? ?? ?? +0 1 2 3 4 5 6 7 8 9 ?? ?? ?? ?? ?? ?? diff --git a/Lib/charset/master/CHARSETS_PP b/Lib/charset/master/CHARSETS_PP new file mode 100644 index 0000000..7bc919b --- /dev/null +++ b/Lib/charset/master/CHARSETS_PP @@ -0,0 +1,22 @@ +charset CCITT_T.50.irv:1988 +alias ccitt_x.408_ia5irv +NU SH SX EX ET EQ AK BL BS HT LF VT FF CR SO SI +DL D1 D2 D3 D4 NK SY EB CN EM SB EC FS GS RS US +SP ! " Nb Cu % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +At A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <( // )> '> _ +'! a b c d e f g h i j k l m n o p q r s t u v w x y z (! !! !) '- DT + +comment: /* replace with Cu. */ +duplicate 36 Ct +duplicate 36 Pd +duplicate 36 DO +duplicate 36 Ye + +comment: /* replace with < and > */ +duplicate 60 << +duplicate 62 >> + +comment: /* replace with FS */ +duplicate 28 S2 +duplicate 28 S3 +duplicate 28 CI diff --git a/Lib/charset/master/CONTROL b/Lib/charset/master/CONTROL new file mode 100644 index 0000000..33e3ac3 --- /dev/null +++ b/Lib/charset/master/CONTROL @@ -0,0 +1,204 @@ + + Control characters + Names according to ISO 2047 and ISO 6429:1988 + Acronyms for the 7-bit control codes taken from ISO 2047 + Acronyms for the 8-bit control codes taken if possible from 6429, + else an abbrevation of the 6429 names not conflicting + with other 6429 names. + group 000 + plane 128 + row 128 + cell 128 +NU NULL (NUL) + group 001 + cell 128 +SH START OF HEADING (SOH) + group 002 + cell 128 +SX START OF TEXT (STX) + group 003 + cell 128 +EX END OF TEXT (ETX) + group 004 + cell 128 +ET END OF TRANSMISSION (EOT) + group 005 + cell 128 +EQ ENQUIRY (ENQ) + group 006 + cell 128 +AK ACKNOWLEDGE (ACK) + group 007 + cell 128 +BL BELL (BEL) + group 008 + cell 128 +BS BACKSPACE (BS) + group 009 + cell 128 +HT CHARACTER TABULATION (HT) + group 010 + cell 128 +LF LINE FEED (LF) + group 011 + cell 128 +VT LINE TABULATION (VT) + group 012 + cell 128 +FF FORM FEED (FF) + group 013 + cell 128 +CR CARRIAGE RETURN (CR) + group 014 + cell 128 +SO SHIFT OUT (SO) + group 015 + cell 128 +SI SHIFT IN (SI) + group 016 + cell 128 +DL DATALINK ESCAPE (DLE) + group 017 + cell 128 +D1 DEVICE CONTROL ONE (DC1) + group 018 + cell 128 +D2 DEVICE CONTROL TWO (DC2) + group 019 + cell 128 +D3 DEVICE CONTROL THREE (DC3) + group 020 + cell 128 +D4 DEVICE CONTROL FOUR (DC4) + group 021 + cell 128 +NK NEGATIVE ACKNOWLEDGE (NAK) + group 022 + cell 128 +SY SYNCRONOUS IDLE (SYN) + group 023 + cell 128 +EB END OF TRANSMISSION BLOCK (ETB) + group 024 + cell 128 +CN CANCEL (CAN) + group 025 + cell 128 +EM END OF MEDIUM (EM) + group 026 + cell 128 +SB SUBSTITUTE (SUB) + group 027 + cell 128 +EC ESCAPE (ESC) + group 028 + cell 128 +FS FILE SEPARATOR (IS4) + group 029 + cell 128 +GS GROUP SEPARATOR (IS3) + group 030 + cell 128 +RS RECORD SEPARATOR (IS2) + group 031 + cell 128 +US UNIT SEPARATOR (IS1) + group 127 + cell 128 +DT DELETE (DEL) + group 128 + cell 128 +PA PADDING CHARACTER (PAD) + group 129 + cell 128 +HO HIGH OCTET PRESET (HOP) + group 130 + cell 128 +BH BREAK PERMITTED HERE (BPH) + group 131 + cell 128 +NH NO BREAK HERE (NBH) + group 132 + cell 128 +IN INDEX (IND) + group 133 + cell 128 +NL NEXT LINE (NEL) + group 134 + cell 128 +SA START OF SELECTED AREA (SSA) + group 135 + cell 128 +ES END OF SELECTED AREA (ESA) + group 136 + cell 128 +HS CHARACTER TABULATION SET (HTS) + group 137 + cell 128 +HJ CHARACTER TABULATION WITH JUSTIFICATION (HTJ) + group 138 + cell 128 +VS LINE TABULATION SET (VTS) + group 139 + cell 128 +PD PARTIAL LINE FORWARD (PLD) + group 140 + cell 128 +PU PARTIAL LINE BACKWARD (PLU) + group 141 + cell 128 +RI REVERSE LINE FEED (RI) + group 142 + cell 128 +S2 SINGLE-SHIFT TWO (SS2) + group 143 + cell 128 +S3 SINGLE-SHIFT THREE (SS3) + group 144 + cell 128 +DC DEVICE CONTROL STRING (DCS) + group 145 + cell 128 +P1 PRIVATE USE ONE (PU1) + group 146 + cell 128 +P2 PRIVATE USE TWO (PU2) + group 147 + cell 128 +TS SET TRANSMIT STATE (STS) + group 148 + cell 128 +CC CANCEL CHARACTER (CCH) + group 149 + cell 128 +MW MESSAGE WAITING (MW) + group 150 + cell 128 +SG START OF GUARDED AREA (SPA) + group 151 + cell 128 +EG END OF GUARDED AREA (EPA) + group 152 + cell 128 +SS START OF STRING (SOS) + group 153 + cell 128 +GC SINGLE GRAPHIC CHARACTER INTRODUCER (SGCI) + group 154 + cell 128 +SC SINGLE CHARACTER INTRODUCER (SCI) + group 155 + cell 128 +CI CONTROL SEQUENCE INTRODUCER (CSI) + group 156 + cell 128 +ST STRING TERMINATOR (ST) + group 157 + cell 128 +OC OPERATING SYSTEM COMMAND (OSC) + group 158 + cell 128 +PM PRIVACY MESSAGE (PM) + group 159 + cell 128 +AC APPLICATION PROGRAM COMMAND (APC) diff --git a/Lib/charset/master/ISO_10646 b/Lib/charset/master/ISO_10646 new file mode 100644 index 0000000..8e10656 --- /dev/null +++ b/Lib/charset/master/ISO_10646 @@ -0,0 +1,1507 @@ + Repertoire according to ISO/IEC DIS 10646 JTC1/SC2/WG2 N666 19901104 + keld@dkuug.dk 1990-12-26 + group 032 + Plane 032 + row 032 + cell 032 +SP SPACE +! EXCLAMATION MARK +" QUOTATION MARK +Nb NUMBER SIGN +DO DOLLAR SIGN +% PERCENT SIGN +& AMPERSAND +' APOSTROPHE +( LEFT PARENTHESIS +) RIGHT PARENTHESIS +* ASTERISK ++ PLUS SIGN +, COMMA +- HYPHEN-MINUS +. FULL STOP +/ SOLIDUS +0 DIGIT ZERO +1 DIGIT ONE +2 DIGIT TWO +3 DIGIT THREE +4 DIGIT FOUR +5 DIGIT FIVE +6 DIGIT SIX +7 DIGIT SEVEN +8 DIGIT EIGHT +9 DIGIT NINE +: COLON +; SEMICOLON +< LESS-THAN SIGN += EQUALS SIGN +> GREATER-THAN SIGN +? QUESTION MARK +At COMMERCIAL AT +A LATIN CAPITAL LETTER A +B LATIN CAPITAL LETTER B +C LATIN CAPITAL LETTER C +D LATIN CAPITAL LETTER D +E LATIN CAPITAL LETTER E +F LATIN CAPITAL LETTER F +G LATIN CAPITAL LETTER G +H LATIN CAPITAL LETTER H +I LATIN CAPITAL LETTER I +J LATIN CAPITAL LETTER J +K LATIN CAPITAL LETTER K +L LATIN CAPITAL LETTER L +M LATIN CAPITAL LETTER M +N LATIN CAPITAL LETTER N +O LATIN CAPITAL LETTER O +P LATIN CAPITAL LETTER P +Q LATIN CAPITAL LETTER Q +R LATIN CAPITAL LETTER R +S LATIN CAPITAL LETTER S +T LATIN CAPITAL LETTER T +U LATIN CAPITAL LETTER U +V LATIN CAPITAL LETTER V +W LATIN CAPITAL LETTER W +X LATIN CAPITAL LETTER X +Y LATIN CAPITAL LETTER Y +Z LATIN CAPITAL LETTER Z +<( LEFT SQUARE BRACKET +// REVERSE SOLIDUS +)> RIGHT SQUARE BRACKET +'> CIRCUMFLEX ACCENT +_ LOW LINE +'! GRAVE ACCENT +a LATIN SMALL LETTER A +b LATIN SMALL LETTER B +c LATIN SMALL LETTER C +d LATIN SMALL LETTER D +e LATIN SMALL LETTER E +f LATIN SMALL LETTER F +g LATIN SMALL LETTER G +h LATIN SMALL LETTER H +i LATIN SMALL LETTER I +j LATIN SMALL LETTER J +k LATIN SMALL LETTER K +l LATIN SMALL LETTER L +m LATIN SMALL LETTER M +n LATIN SMALL LETTER N +o LATIN SMALL LETTER O +p LATIN SMALL LETTER P +q LATIN SMALL LETTER Q +r LATIN SMALL LETTER R +s LATIN SMALL LETTER S +t LATIN SMALL LETTER T +u LATIN SMALL LETTER U +v LATIN SMALL LETTER V +w LATIN SMALL LETTER W +x LATIN SMALL LETTER X +y LATIN SMALL LETTER Y +z LATIN SMALL LETTER Z +(! LEFT CURLY BRACKET +!! VERTICAL LINE +!) RIGHT CURLY BRACKET +'? TILDE + cell 160 +NS NO-BREAK SPACE +!I INVERTED EXCLAMATION MARK +Ct CENT SIGN +Pd POUND SIGN +Cu CURRENCY SIGN +Ye YEN SIGN +BB BROKEN BAR +SE SECTION SIGN +': DIAERESIS +Co COPYRIGHT SIGN +-a FEMININE ORDINAL INDICATOR +<< LEFT POINTING DOUBLE ANGLE QUOTATION MARK +NO NOT SIGN +-- SOFT HYPHEN +Rg REGISTERED SIGN +'- MACRON +DG DEGREE SIGN ++- PLUS-MINUS SIGN +2S SUPERSCRIPT TWO +3S SUPERSCRIPT THREE +'' ACUTE ACCENT +My MICRO SIGN +PI PILCROW SIGN +.M MIDDLE DOT +', CEDILLA +1S SUPERSCRIPT ONE +-o MASCULINE ORDINAL INDICATOR +>> RIGHT POINTING DOUBLE ANGLE QUOTATION MARK +14 VULGAR FRACTION ONE QUARTER +12 VULGAR FRACTION ONE HALF +34 VULGAR FRACTION THREE QUARTERS +?I INVERTED QUESTION MARK +A! LATIN CAPITAL LETTER A WITH GRAVE +A' LATIN CAPITAL LETTER A WITH ACUTE +A> LATIN CAPITAL LETTER A WITH CIRCUMFLEX +A? LATIN CAPITAL LETTER A WITH TILDE +A: LATIN CAPITAL LETTER A WITH DIAERESIS +AA LATIN CAPITAL LETTER A WITH RING ABOVE +AE LATIN CAPITAL LETTER AE +C, LATIN CAPITAL LETTER C WITH CEDILLA +E! LATIN CAPITAL LETTER E WITH GRAVE +E' LATIN CAPITAL LETTER E WITH ACUTE +E> LATIN CAPITAL LETTER E WITH CIRCUMFLEX +E: LATIN CAPITAL LETTER E WITH DIAERESIS +I! LATIN CAPITAL LETTER I WITH GRAVE +I' LATIN CAPITAL LETTER I WITH ACUTE +I> LATIN CAPITAL LETTER I WITH CIRCUMFLEX +I: LATIN CAPITAL LETTER I WITH DIAERESIS +D- LATIN CAPITAL LETTER ETH (Icelandic) +N? LATIN CAPITAL LETTER N WITH TILDE +O! LATIN CAPITAL LETTER O WITH GRAVE +O' LATIN CAPITAL LETTER O WITH ACUTE +O> LATIN CAPITAL LETTER O WITH CIRCUMFLEX +O? LATIN CAPITAL LETTER O WITH TILDE +O: LATIN CAPITAL LETTER O WITH DIAERESIS +*X MULTIPLICATION SIGN +O/ LATIN CAPITAL LETTER O WITH STROKE +U! LATIN CAPITAL LETTER U WITH GRAVE +U' LATIN CAPITAL LETTER U WITH ACUTE +U> LATIN CAPITAL LETTER U WITH CIRCUMFLEX +U: LATIN CAPITAL LETTER U WITH DIAERESIS +Y' LATIN CAPITAL LETTER Y WITH ACUTE +TH LATIN CAPITAL LETTER THORN (Icelandic) +ss LATIN SMALL LETTER SHARP S (German) +a! LATIN SMALL LETTER A WITH GRAVE +a' LATIN SMALL LETTER A WITH ACUTE +a> LATIN SMALL LETTER A WITH CIRCUMFLEX +a? LATIN SMALL LETTER A WITH TILDE +a: LATIN SMALL LETTER A WITH DIAERESIS +aa LATIN SMALL LETTER A WITH RING ABOVE +ae LATIN SMALL LETTER AE +c, LATIN SMALL LETTER C WITH CEDILLA +e! LATIN SMALL LETTER E WITH GRAVE +e' LATIN SMALL LETTER E WITH ACUTE +e> LATIN SMALL LETTER E WITH CIRCUMFLEX +e: LATIN SMALL LETTER E WITH DIAERESIS +i! LATIN SMALL LETTER I WITH GRAVE +i' LATIN SMALL LETTER I WITH ACUTE +i> LATIN SMALL LETTER I WITH CIRCUMFLEX +i: LATIN SMALL LETTER I WITH DIAERESIS +d- LATIN SMALL LETTER ETH (Icelandic) +n? LATIN SMALL LETTER N WITH TILDE +o! LATIN SMALL LETTER O WITH GRAVE +o' LATIN SMALL LETTER O WITH ACUTE +o> LATIN SMALL LETTER O WITH CIRCUMFLEX +o? LATIN SMALL LETTER O WITH TILDE +o: LATIN SMALL LETTER O WITH DIAERESIS +-: DIVISION SIGN +o/ LATIN SMALL LETTER O WITH STROKE +u! LATIN SMALL LETTER U WITH GRAVE +u' LATIN SMALL LETTER U WITH ACUTE +u> LATIN SMALL LETTER U WITH CIRCUMFLEX +u: LATIN SMALL LETTER U WITH DIAERESIS +y' LATIN SMALL LETTER Y WITH ACUTE +th LATIN SMALL LETTER THORN (Icelandic) +y: LATIN SMALL LETTER Y WITH DIAERESIS + + row 033 + cell 033 +A- LATIN CAPITAL LETTER A WITH MACRON +C> LATIN CAPITAL LETTER C WITH CIRCUMFLEX +C. LATIN CAPITAL LETTER C WITH DOT ABOVE +E- LATIN CAPITAL LETTER E WITH MACRON +E. LATIN CAPITAL LETTER E WITH DOT ABOVE + cell 039 +G> LATIN CAPITAL LETTER G WITH CIRCUMFLEX + cell 041 +'6 LEFT SINGLE QUOTATION MARK +"6 LEFT DOUBLE QUOTATION MARK +G( LATIN CAPITAL LETTER G WITH BREVE +<- LEFTWARD ARROW +-! UPWARD ARROW +-> RIGHTWARD ARROW +-v DOWNWARD ARROW + cell 049 +a- LATIN SMALL LETTER A WITH MACRON +c> LATIN SMALL LETTER C WITH CIRCUMFLEX +c. LATIN SMALL LETTER C WITH DOT ABOVE +e- LATIN SMALL LETTER E WITH MACRON +e. LATIN SMALL LETTER E WITH DOT ABOVE + cell 055 +g> LATIN SMALL LETTER G WITH CIRCUMFLEX + cell 057 +'9 RIGHT SINGLE QUOTATION MARK +"9 RIGHT DOUBLE QUOTATION MARK +g( LATIN SMALL LETTER G WITH BREVE + cell 065 +G. LATIN CAPITAL LETTER G WITH DOT ABOVE +G, LATIN CAPITAL LETTER G WITH CEDILLA +H> LATIN CAPITAL LETTER H WITH CIRCUMFLEX + cell 070 +I? LATIN CAPITAL LETTER I WITH TILDE +I- LATIN CAPITAL LETTER I WITH MACRON +I. LATIN CAPITAL LETTER I WITH DOT ABOVE + cell 074 +'0 RING ABOVE + cell 080 +HB HORIZONTAL BAR +g. LATIN SMALL LETTER G WITH DOT ABOVE +g, LATIN SMALL LETTER G WITH CEDILLA +h> LATIN SMALL LETTER H WITH CIRCUMFLEX +TM TRADE MARK SIGN +Md MUSIC NOTE +i? LATIN SMALL LETTER I WITH TILDE +i- LATIN SMALL LETTER I WITH MACRON + cell 092 +18 VULGAR FRACTION ONE EIGHTH +38 VULGAR FRACTION THREE EIGHTHS +58 VULGAR FRACTION FIVE EIGHTHS +78 VULGAR FRACTION SEVEN EIGHTHS +Om OHM SIGN +I; LATIN CAPITAL LETTER I WITH OGONEK +J> LATIN CAPITAL LETTER J WITH CIRCUMFLEX +K, LATIN CAPITAL LETTER K WITH CEDILLA +H/ LATIN CAPITAL LETTER H WITH STROKE + cell 102 +IJ LATIN CAPITAL LIGATURE IJ +L. LATIN CAPITAL LETTER L WITH MIDDLE DOT +L, LATIN CAPITAL LETTER L WITH CEDILLA +N, LATIN CAPITAL LETTER N WITH CEDILLA +OE LATIN CAPITAL LIGATURE OE +O- LATIN CAPITAL LETTER O WITH MACRON + cell 109 +T/ LATIN CAPITAL LETTER T WITH STROKE +NG LATIN CAPITAL LETTER ENG (Lappish) +'n LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +kk LATIN SMALL LETTER KRA (Greenlandic) +i; LATIN SMALL LETTER I WITH OGONEK +j> LATIN SMALL LETTER J WITH CIRCUMFLEX +k, LATIN SMALL LETTER K WITH CEDILLA +h/ LATIN SMALL LETTER H WITH STROKE +i. LATIN SMALL LETTER I WITH NO DOT +ij LATIN SMALL LIGATURE IJ +l. LATIN SMALL LETTER L WITH MIDDLE DOT +l, LATIN SMALL LETTER L WITH CEDILLA +n, LATIN SMALL LETTER N WITH CEDILLA +oe LATIN SMALL LIGATURE OE +o- LATIN SMALL LETTER O WITH MACRON + cell 125 +t/ LATIN SMALL LETTER T WITH STROKE +ng LATIN SMALL LETTER ENG + cell 161 +A; LATIN CAPITAL LETTER A WITH OGONEK +'( BREVE +L/ LATIN CAPITAL LETTER L WITH STROKE + cell 165 +L< LATIN CAPITAL LETTER L WITH CARON +S' LATIN CAPITAL LETTER S WITH ACUTE + cell 168 +S> LATIN CAPITAL LETTER S WITH CIRCUMFLEX +S< LATIN CAPITAL LETTER S WITH CARON +S, LATIN CAPITAL LETTER S WITH CEDILLA +T< LATIN CAPITAL LETTER T WITH CARON +Z' LATIN CAPITAL LETTER Z WITH ACUTE + cell 174 +Z< LATIN CAPITAL LETTER Z WITH CARON +Z. LATIN CAPITAL LETTER Z WITH DOT ABOVE + cell 177 +a; LATIN SMALL LETTER A WITH OGONEK +'; OGONEK +l/ LATIN SMALL LETTER L WITH STROKE + cell 181 +l< LATIN SMALL LETTER L WITH CARON +s' LATIN SMALL LETTER S WITH ACUTE +'< CARON +s> LATIN SMALL LETTER S WITH CIRCUMFLEX +s< LATIN SMALL LETTER S WITH CARON +s, LATIN SMALL LETTER S WITH CEDILLA +t< LATIN SMALL LETTER T WITH CARON +z' LATIN SMALL LETTER Z WITH ACUTE +'" DOUBLE ACUTE ACCENT +z< LATIN SMALL LETTER Z WITH CARON +z. LATIN SMALL LETTER Z WITH DOT ABOVE +R' LATIN CAPITAL LETTER R WITH ACUTE +R, LATIN CAPITAL LETTER R WITH CEDILLA + cell 195 +A( LATIN CAPITAL LETTER A WITH BREVE + cell 197 +L' LATIN CAPITAL LETTER L WITH ACUTE +C' LATIN CAPITAL LETTER C WITH ACUTE + cell 200 +C< LATIN CAPITAL LETTER C WITH CARON + cell 202 +E; LATIN CAPITAL LETTER E WITH OGONEK + cell 204 +E< LATIN CAPITAL LETTER E WITH CARON + cell 207 +D< LATIN CAPITAL LETTER D WITH CARON +D/ LATIN CAPITAL LETTER D WITH STROKE +N' LATIN CAPITAL LETTER N WITH ACUTE +N< LATIN CAPITAL LETTER N WITH CARON + cell 212 +U? LATIN CAPITAL LETTER U WITH TILDE +O" LATIN CAPITAL LETTER O WITH DOUBLE ACUTE +U- LATIN CAPITAL LETTER U WITH MACRON +U( LATIN CAPITAL LETTER U WITH BREVE +R< LATIN CAPITAL LETTER R WITH CARON +U0 LATIN CAPITAL LETTER U WITH RING ABOVE +U; LATIN CAPITAL LETTER U WITH OGONEK +U" LATIN CAPITAL LETTER U WITH DOUBLE ACUTE +W> LATIN CAPITAL LETTER W WITH CIRCUMFLEX +Y> LATIN CAPITAL LETTER Y WITH CIRCUMFLEX +T, LATIN CAPITAL LETTER T WITH CEDILLA +Y: LATIN CAPITAL LETTER Y WITH DIAERESIS +r' LATIN SMALL LETTER R WITH ACUTE +r, LATIN SMALL LETTER R WITH CEDILLA + cell 227 +a( LATIN SMALL LETTER A WITH BREVE + cell 229 +l' LATIN SMALL LETTER L WITH ACUTE +c' LATIN SMALL LETTER C WITH ACUTE + cell 232 +c< LATIN SMALL LETTER C WITH CARON + cell 234 +e; LATIN SMALL LETTER E WITH OGONEK + cell 236 +e< LATIN SMALL LETTER E WITH CARON + cell 239 +d< LATIN SMALL LETTER D WITH CARON +d/ LATIN SMALL LETTER D WITH STROKE +n' LATIN SMALL LETTER N WITH ACUTE +n< LATIN SMALL LETTER N WITH CARON + cell 244 +u? LATIN SMALL LETTER U WITH TILDE +o" LATIN SMALL LETTER O WITH DOUBLE ACUTE +u- LATIN SMALL LETTER U WITH MACRON +u( LATIN SMALL LETTER U WITH BREVE +r< LATIN SMALL LETTER R WITH CARON +u0 LATIN SMALL LETTER U WITH RING ABOVE +u; LATIN SMALL LETTER U WITH OGONEK +u" LATIN SMALL LETTER U WITH DOUBLE ACUTE +w> LATIN SMALL LETTER W WITH CIRCUMFLEX +y> LATIN SMALL LETTER Y WITH CIRCUMFLEX +t, LATIN SMALL LETTER T WITH CEDILLA +'. DOT ABOVE + + row 034 + cell 032 +a< LATIN SMALL LETTER A WITH CARON +A< LATIN CAPITAL LETTER A WITH CARON +a_ LATIN SMALL LETTER A WITH LINE BELOW +A_ LATIN CAPITAL LETTER A WITH LINE BELOW + LATIN SMALL LETTER A WITH DOT BELOW + LATIN CAPITAL LETTER A WITH DOT BELOW + LATIN SMALL LETTER A WITH MACRON AND LINE BELOW + LATIN CAPITAL LETTER A WITH MACRON AND LINE BELOW + LATIN SMALL LETTER A WITH RING BELOW + LATIN CAPITAL LETTER A WITH RING BELOW + LATIN SMALL LETTER A WITH VERTICAL BAR ABOVE + LATIN CAPITAL LETTER A WITH VERTICAL BAR ABOVE + LATIN SMALL LETTER A WITH DOUBLE VERTICAL BAR ABOVE + LATIN CAPITAL LETTER A WITH DOUBLE VERTICAL BAR ABOVE + LATIN SMALL LETTER A WITH APOSTROPHE + LATIN CAPITAL LETTER A WITH APOSTROPHE + cell 048 +'a LATIN SMALL LETTER A PRECEDED BY APOSTROPHE +'A LATIN CAPITAL LETTER A PRECEDED BY APOSTROPHE + LATIN SMALL LETTER A WITH ACUTE AND APOSTROPHE + LATIN CAPITAL LETTER A WITH ACUTE AND APOSTROPHE + cell 052 +a1 LATIN SMALL LETTER A WITH MACRON AND DIAERESIS +A1 LATIN CAPITAL LETTER A WITH MACRON AND DIAERESIS +a2 LATIN SMALL LETTER A WITH MACRON AND DOT ABOVE +A2 LATIN CAPITAL LETTER A WITH MACRON AND DOT ABOVE +a3 LATIN SMALL LETTER AE WITH MACRON +A3 LATIN CAPITAL LETTER AE WITH MACRON + ae' LATIN SMALL LETTER AE WITH ACUTE + AE' LATIN CAPITAL LETTER AE WITH ACUTE + aa' LATIN SMALL LETTER A WITH ACUTE AND RING ABOVE + AA' LATIN CAPITAL LETTER A WITH ACUTE AND RING ABOVE + LATIN SMALL LETTER A WITH VERTICAL TILDE + LATIN CAPITAL LETTER A WITH VERTICAL TILDE + a'< LATIN SMALL LETTER A WITH ACUTE AND CIRCUMFLEX + A'< LATIN CAPITAL LETTER A WITH ACUTE AND CIRCUMFLEX + a LATIN SMALL LETTER Z WITH CIRCUMFLEX +Z> LATIN CAPITAL LETTER Z WITH CIRCUMFLEX +z( LATIN SMALL LETTER Z WITH BREVE +Z( LATIN CAPITAL LETTER Z WITH BREVE +z_ LATIN SMALL LETTER Z WITH LINE BELOW +Z_ LATIN CAPITAL LETTER Z WITH LINE BELOW + LATIN SMALL LETTER Z WITH DOT BELOW + LATIN CAPITAL LETTER Z WITH DOT BELOW + cell 252 +z/ LATIN SMALL LETTER Z WITH STROKE +Z/ LATIN CAPITAL LETTER Z WITH STROKE +ez LATIN SMALL LETTER EZH WITH CARON +EZ LATIN CAPITAL LETTER EZH WITH CARON + + row 036 + cell 033 +g' LATIN SMALL LETTER G WITH ACUTE +G' LATIN CAPITAL LETTER G WITH ACUTE + ..... + cell 084 +'b LATIN SMALL LETTER B PRECEDED BY APOSTROPHE +'B LATIN CAPITAL LETTER B PRECEDED BY APOSTROPHE + ...... + cell 096 +'d LATIN SMALL LETTER D PRECEDED BY APOSTROPHE +'D LATIN CAPITAL LETTER D PRECEDED BY APOSTROPHE + ...... + cell 162 +'g LATIN SMALL LETTER G PRECEDED BY APOSTROPHE +'G LATIN CAPITAL LETTER G PRECEDED BY APOSTROPHE + ...... + cell 174 +'j LATIN SMALL LETTER J PRECEDED BY APOSTROPHE +'J LATIN CAPITAL LETTER J PRECEDED BY APOSTROPHE + ...... + cell 235 +'y LATIN SMALL LETTER Y PRECEDED BY APOSTROPHE +'Y LATIN CAPITAL LETTER Y PRECEDED BY APOSTROPHE + ..... + cell 239 +ed LATIN SMALL LETTER EDZ +ED LATIN CAPITAL LETTER EDZ + .... + + row 037 + cell 032 +Vs SPACE SYMBOL +1M EM-SPACE +1N EN-SPACE +3M THREE-PER-EM SPACE +4M FOUR-PER-EM SPACE +6M SIX-PER-EM SPACE +1H HAIR SPACE +1T THIN SPACE +-1 HYPHEN +-N EN-DASH +-2 MINUS SIGN +-M EM-DASH +-3 QUOTATION DASH +'1 SINGLE PRIME +'2 DOUBLE PRIME +'3 TRIPLE PRIME +9' SINGLE HIGH-REVERSED-9 QUOTATION MARK +9" DOUBLE HIGH-REVERSED-9 QUOTATION MARK +.9 SINGLE LOW-9 QUOTATION MARK +:9 DOUBLE LOW-9 QUOTATION MARK +<1 SINGLE LEFT-POINTING ANGLE QUOTATION MARK +>1 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + RIGHT-POINTING ANGLE BRACKET +15 VULGAR FRACTION ONE FIFTH +25 VULGAR FRACTION TWO FIFTHS +35 VULGAR FRACTION THREE FIFTHS +45 VULGAR FRACTION FOUR FIFTHS +16 VULGAR FRACTION ONE SIXTH +13 VULGAR FRACTION ONE THIRD +23 VULGAR FRACTION TWO THIRDS +56 VULGAR FRACTION FIVE SIXTHS +*- MIDDLE ASTERISK +/- DAGGER +/= DOUBLE-DAGGER +-X MALTESE CROSS +%0 PER-MILLE SIGN +co CARE-OF SIGN +PO SOUND RECORDING COPYRIGHT SIGN +Rx PRESCRIPTION SIGN +AO ANGSTROEM SIGN +oC CENTIGRADE DEGREE SIGN +Ml MALE SIGN +Fm FEMALE SIGN +Tl TELEPHONE SIGN +TR TELEPHONE RECORDER SIGN +MX MUSICAL SHARP SIGN +Mb MUSICAL FLAT SIGN +Mx MUSICAL NATURAL SIGN +XX BALLOT CROSS SIGN +OK CHECK MARK +M2 DOUBLE MUSICAL NOTES +!2 DOUBLE EXCLAMATION MARKS +=2 DOUBLE LOW LINE +Ca CARET +.. TWO-DOT LEADER +.3 HORIZONTAL ELLIPSIS +:3 VERTICAL ELLIPSIS +.: THEREFORE SIGN +:. BECAUSE SIGN +-+ MINUS-PLUS SIGN +!= NOT EQUAL-TO SIGN +=3 IDENTICAL-TO SIGN +?1 DIFFERENCE-BETWEEN SIGN +?2 ALMOST-EQUALS SIGN +?- ASYMTOTICALLY-EQUALS SIGN +?= SIMILAR-TO SIGN +=< LESS-THAN OR EQUAL-TO SIGN +>= GREATER-THAN OR EQUAL-TO SIGN +0( PROPORTIONAL-TO SIGN +00 INFINITY SIGN +PP PARALLEL-TO SIGN +-T ORTHOGONAL-TO SIGN +-L RIGHT ANGLE SIGN +-V ANGLE SIGN +AN LOGICAL-AND SIGN +OR LOGICAL-OR SIGN +.P PRODUCT DOT SIGN +nS SUPERSCRIPT LATIN SMALL LETTER N +dP PARTIAL DIFFERENTIAL SIGN +f( FUNCTION SIGN +In INTEGRAL SIGN +Io CONTOUR INTEGRAL SIGN + OVERLINE + DOUBLE CIRCLE + cell 117 +RT RADICAL SIGN +*P REPEATED PRODUCT SIGN ++Z SUMMATION SIGN +FA FOR-ALL SIGN +TE THERE-EXISTS SIGN +GF GAMMA FUNCTION SIGN +DE INCREMENT SIGN +NB NABLA +(U INTERSECTION SIGN +)U UNION SIGN + cell 160 +(C PROPER SUBSET SIGN +)C PROPER SUPERSET SIGN +(_ SUBSET SIGN +)_ SUPERSET SIGN +(- ELEMENT-OF SIGN +-) HAS AN ELEMENT SIGN +<> LEFT AND RIGHT-POINTING ARROW +UD UP AND DOWN-POINTING ARROW +Ub UP AND DOWN-POINTING ARROW WITH LINE BELOW +<= IMPLIED-BY SIGN +=> IMPLIES SIGN +== IF-AND-ONLY-IF SIGN +/0 EMPTY SIGN +OL SOLID LOZENGE + PLACE OF INTEREST SIGN + END OF LINE SYMBOL + cell 176 +0u SMILING FACE WHITE +0U SMILING FACE BLACK +SU RADIANT SUN +0: DOTTED CIRCLE +OS SQUARE EMPTY +fS SQUARE SOLID +Or RECTANGLE EMPTY +SR RECTANGLE SOLID +uT UPWARDS-POINTING TRIANGLE EMPTY +UT UPWARDS-POINTING TRIANGLE SOLID +dT DOWNWARDS-POINTING TRIANGLE EMPTY +Dt DOWNWARDS-POINTING TRIANGLE SOLID +PL LEFTWARDS POINTER SOLID +PR RIGHTWARDS POINTER SOLID +*1 STAR EMPTY +*2 STAR SOLID +VV BOX DRAWINGS HEAVY VERTICAL +HH BOX DRAWINGS HEAVY HORIZONTAL +DR BOX DRAWINGS HEAVY DOWN AND RIGHT +LD BOX DRAWINGS HEAVY DOWN AND LEFT +UR BOX DRAWINGS HEAVY UP AND RIGHT +UL BOX DRAWINGS HEAVY UP AND LEFT +VR BOX DRAWINGS HEAVY VERTICAL AND RIGHT +VL BOX DRAWINGS HEAVY VERTICAL AND LEFT +DH BOX DRAWINGS HEAVY HORIZONTAL AND DOWN +UH BOX DRAWINGS HEAVY HORIZONTAL AND UP +VH BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL +TB BOX DRAWING SOLID UPPER HALF BLOCK +LB BOX DRAWING SOLID LOWER HALF BLOCK +FB BOX DRAWING SOLID FULL BLOCK +sB BOX DRAWING SOLID SMALL SQUARE +EH EMPTY HOUSE SIGN + cell 208 +vv BOX DRAWINGS LIGHT VERTICAL +hh BOX DRAWINGS LIGHT HORIZONTAL +dr BOX DRAWINGS LIGHT DOWN AND RIGHT +dl BOX DRAWINGS LIGHT DOWN AND LEFT +ur BOX DRAWINGS LIGHT UP AND RIGHT +ul BOX DRAWINGS LIGHT UP AND LEFT +vr BOX DRAWINGS LIGHT VERTICAL AND RIGHT +vl BOX DRAWINGS LIGHT VERTICAL AND LEFT +dh BOX DRAWINGS LIGHT HORIZONTAL AND DOWN +uh BOX DRAWINGS LIGHT HORIZONTAL AND UP +vh BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL +.S BOX DRAWING LIGHT SHADE (25%) +:S BOX DRAWING MEDIUM SHADE (50%) +?S BOX DRAWING DARK SHADE (75%) +lB BOX DRAWING SOLID LEFT HALF BLOCK +RB BOX DRAWING SOLID RIGHT HALF BLOCK +cC CLUB SYMBOL +cD DIAMOND SYMBOL +Dr BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT +Dl BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT +Ur BOX DRAWINGS UP HEAVY AND RIGHT LIGHT +Ul BOX DRAWINGS UP HEAVY AND LEFT LIGHT +Vr BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT +Vl BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT +dH BOX DRAWINGS HORIZONTAL HEAVY AND DOWN LIGHT +uH BOX DRAWINGS HORIZONTAL HEAVY AND UP LIGHT +vH BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY +Ob CIRCLE BULLET EMPTY +Sb CIRCLE BULLET SOLID +Sn CIRCLE BULLET NEGATIVE +Pt PESETA SYMBOL +NI REVERSED NOT SIGN +cH HEART SYMBOL +cS SPADE SYMBOL +dR BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY +dL BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY +uR BOX DRAWINGS UP LIGHT AND RIGHT HEAVY +uL BOX DRAWINGS UP LIGHT AND LEFT HEAVY +vR BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY +vL BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY +Dh BOX DRAWINGS HORIZONTAL LIGHT AND DOWN HEAVY +Uh BOX DRAWINGS HORIZONTAL LIGHT AND UP HEAVY +Vh BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT +0m MEDIUM CIRCLE EMPTY +0M MEDIUM CIRCLE SOLID +Ic MEDIUM CIRCLE NEGATIVE +SM SERVICE MARK SIGN +CG CONGRUENCE SIGN + + row 038 + .... + cell 037 +Ci CIRCLE + .... + cell 041 +(A ARC SIGN + .... + cell 046 +>V RIGHTWARDS VECTOR ABOVE + .... + cell 049 +!< NOT LESS-THAN SIGN + .... + cell 056 +<* MUCH-LESS-THAN SIGN + .... + cell 065 +!> NOT GREATER-THAN SIGN + .... + cell 072 +*> MUCH-GREATER-THAN SIGN + .... + cell 094 +<7 CEILING SIGN LEFT +7< FLOOR SIGN LEFT + .... + cell 110 +>7 CEILING SIGN RIGHT +7> FLOOR SIGN RIGHT + .... + cell 121 +I2 DOUBLE INTEGRAL SIGN + .... + cell 164 +0. DOT IN RING + .... + cell 177 +HI HAS-AN-IMAGE SIGN + .... + cell 193 +:: PROPORTION SIGN + .... + cell 209 +FD FORWARD DIAGONAL + .... + cell 223 +LZ LOZENGE + cell 225 +BD BACKWARD DIAGONAL + .... + row 039 + cell 032 +1R ROMAN NUMERAL ONE +2R ROMAN NUMERAL TWO +3R ROMAN NUMERAL THREE +4R ROMAN NUMERAL FOUR +5R ROMAN NUMERAL FIVE +6R ROMAN NUMERAL SIX +7R ROMAN NUMERAL SEVEN +8R ROMAN NUMERAL EIGHT +9R ROMAN NUMERAL NINE +aR ROMAN NUMERAL TEN +bR ROMAN NUMERAL ELEVEN +cR ROMAN NUMERAL TWELVE + cell 064 + MATHEMATICAL PHI SYMBOL + MATHEMATICAL THETA SYMBOL + MATHEMATICAL OMEGA SYMBOL + MATHEMATICAL EPSILON SYMBOL + MATHEMATICAL KAPPA SYMBOL + + row 040 - transliteration according to ISO 9-1986 + cell 096 + a'= CYRILLIC SMALL LETTER A WITH ACUTE + A'= CYRILLIC CAPITAL LETTER A WITH ACUTE + a(= CYRILLIC SMALL LETTER A WITH CARON + A(= CYRILLIC CAPITAL LETTER A WITH CARON + a:= CYRILLIC SMALL LETTER A WITH DIAERESIS + A:= CYRILLIC CAPITAL LETTER A WITH DIAERESIS + ae= CYRILLIC SMALL LETTER A WITH IE + AE= CYRILLIC CAPITAL LETTER A WITH IE + cell 108 + g/= CYRILLIC SMALL LETTER GHE WITH STROKE + G/= CYRILLIC CAPITAL LETTER GHE WITH STROKE + cell 114 + CYRILLIC SMALL LETTER GHE HVOSTIKOM + CYRILLIC CAPITAL LETTER GHE HVOSTIKOM + cell 120 + e'= CYRILLIC SMALL LETTER IE WITH ACUTE + E'= CYRILLIC CAPITAL LETTER IE WITH ACUTE + e(= CYRILLIC SMALL LETTER IE WITH BREVE + E(= CYRILLIC CAPITAL LETTER IE WITH BREVE + e':= CYRILLIC SMALL LETTER IE WITH ACUTE AND DIAERESIS + E':= CYRILLIC CAPITAL LETTER IE WITH ACUTE AND DIAERESIS + + cell 161 +IO CYRILLIC CAPITAL LETTER IO +D% CYRILLIC CAPITAL LETTER DJE (Serbocroatian) +G% CYRILLIC CAPITAL LETTER GJE (Macedonian) +IE CYRILLIC CAPITAL LETTER UKRAINIAN IE +DS CYRILLIC CAPITAL LETTER DZE (Macedonian) +II CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +YI CYRILLIC CAPITAL LETTER YI (Ukrainian) +J% CYRILLIC CAPITAL LETTER JE +LJ CYRILLIC CAPITAL LETTER LJE +NJ CYRILLIC CAPITAL LETTER NJE +Ts CYRILLIC CAPITAL LETTER TSHE (Serbocroatian) +KJ CYRILLIC CAPITAL LETTER KJE (Macedonian) + cell 174 +V% CYRILLIC CAPITAL LETTER SHORT U (Byelorussian) +DZ CYRILLIC CAPITAL LETTER DZHE +A= CYRILLIC CAPITAL LETTER A +B= CYRILLIC CAPITAL LETTER BE +V= CYRILLIC CAPITAL LETTER VE +G= CYRILLIC CAPITAL LETTER GHE +D= CYRILLIC CAPITAL LETTER DE +E= CYRILLIC CAPITAL LETTER IE +Z% CYRILLIC CAPITAL LETTER ZHE +Z= CYRILLIC CAPITAL LETTER ZE +I= CYRILLIC CAPITAL LETTER I +J= CYRILLIC CAPITAL LETTER SHORT I +K= CYRILLIC CAPITAL LETTER KA +L= CYRILLIC CAPITAL LETTER EL +M= CYRILLIC CAPITAL LETTER EM +N= CYRILLIC CAPITAL LETTER EN +O= CYRILLIC CAPITAL LETTER O +P= CYRILLIC CAPITAL LETTER PE +R= CYRILLIC CAPITAL LETTER ER +S= CYRILLIC CAPITAL LETTER ES +T= CYRILLIC CAPITAL LETTER TE +U= CYRILLIC CAPITAL LETTER U +F= CYRILLIC CAPITAL LETTER EF +H= CYRILLIC CAPITAL LETTER HA +C= CYRILLIC CAPITAL LETTER TSE +C% CYRILLIC CAPITAL LETTER CHE +S% CYRILLIC CAPITAL LETTER SHA +Sc CYRILLIC CAPITAL LETTER SHCHA +=" CYRILLIC CAPITAL HARD SIGN +Y= CYRILLIC CAPITAL LETTER YERU +%" CYRILLIC CAPITAL SOFT SIGN +JE CYRILLIC CAPITAL LETTER E +JU CYRILLIC CAPITAL LETTER YU +JA CYRILLIC CAPITAL LETTER YA +a= CYRILLIC SMALL LETTER A +b= CYRILLIC SMALL LETTER BE +v= CYRILLIC SMALL LETTER VE +g= CYRILLIC SMALL LETTER GHE +d= CYRILLIC SMALL LETTER DE +e= CYRILLIC SMALL LETTER IE +z% CYRILLIC SMALL LETTER ZHE +z= CYRILLIC SMALL LETTER ZE +i= CYRILLIC SMALL LETTER I +j= CYRILLIC SMALL LETTER SHORT I +k= CYRILLIC SMALL LETTER KA +l= CYRILLIC SMALL LETTER EL +m= CYRILLIC SMALL LETTER EM +n= CYRILLIC SMALL LETTER EN +o= CYRILLIC SMALL LETTER O +p= CYRILLIC SMALL LETTER PE +r= CYRILLIC SMALL LETTER ER +s= CYRILLIC SMALL LETTER ES +t= CYRILLIC SMALL LETTER TE +u= CYRILLIC SMALL LETTER U +f= CYRILLIC SMALL LETTER EF +h= CYRILLIC SMALL LETTER HA +c= CYRILLIC SMALL LETTER TSE +c% CYRILLIC SMALL LETTER CHE +s% CYRILLIC SMALL LETTER SHA +sc CYRILLIC SMALL LETTER SHCHA +=' CYRILLIC SMALL HARD SIGN +y= CYRILLIC SMALL LETTER YERU +%' CYRILLIC SMALL SOFT SIGN +je CYRILLIC SMALL LETTER E +ju CYRILLIC SMALL LETTER YU +ja CYRILLIC SMALL LETTER YA +N0 NUMERO SIGN +io CYRILLIC SMALL LETTER IO +d% CYRILLIC SMALL LETTER DJE (Serbocroatian) +g% CYRILLIC SMALL LETTER GJE (Macedonian) +ie CYRILLIC SMALL LETTER UKRAINIAN IE +ds CYRILLIC SMALL LETTER DZE (Macedonian) +ii CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +yi CYRILLIC SMALL LETTER YI (Ukrainian) +j% CYRILLIC SMALL LETTER JE +lj CYRILLIC SMALL LETTER LJE +nj CYRILLIC SMALL LETTER NJE +ts CYRILLIC SMALL LETTER TSHE (Serbocroatian) +kj CYRILLIC SMALL LETTER KJE (Macedonian) + cell 254 +v% CYRILLIC SMALL LETTER SHORT U (Byelorussian) +dz CYRILLIC SMALL LETTER DZHE + + row 041 + ..... + + row 042 + ..... + cell 160 +i3 GREEK IOTA BELOW + cell 161 +;; GREEK DAISA PNEUMATA (rough) +,, GREEK PSILI PNEUMATA (smooth) + cell 164 +!* GREEK VARIA +?* GREEK PERISPOMENI + cell 166 +;' GREEK DAISA AND ACUTE ACCENT +,' GREEK PSILI AND ACUTE ACCENT +;! GREEK DAISA AND VARIA +,! GREEK PSILI AND VARIA +?; GREEK PERISPOMENI AND DAISA +?, GREEK PERISPOMENI AND PSILI + cell 174 +!: GREEK VARIA AND DIAERESIS +?: GREEK PERISPOMENI AND DIAERESIS +I3 GREEK CAPITAL LETTER IOTA WITH PERISPOMENI AND PSILI + cell 181 +'% ACUTE ACCENT AND DIAERESIS (Tonos and Dialytica) +A% GREEK CAPITAL LETTER ALPHA WITH ACUTE + cell 184 +E% GREEK CAPITAL LETTER EPSILON WITH ACUTE +Y% GREEK CAPITAL LETTER ETA WITH ACUTE +I% GREEK CAPITAL LETTER IOTA WITH ACUTE + cell 188 +O% GREEK CAPITAL LETTER OMICRON WITH ACUTE + cell 190 +U% GREEK CAPITAL LETTER UPSILON WITH ACUTE +W% GREEK CAPITAL LETTER OMEGA WITH ACUTE + GREEK SMALL LETTER IOTA WITH ACUTE AND DIAERESIS + cell 193 +A* GREEK CAPITAL LETTER ALPHA +B* GREEK CAPITAL LETTER BETA +G* GREEK CAPITAL LETTER GAMMA +D* GREEK CAPITAL LETTER DELTA +E* GREEK CAPITAL LETTER EPSILON +Z* GREEK CAPITAL LETTER ZETA +Y* GREEK CAPITAL LETTER ETA +H* GREEK CAPITAL LETTER THETA +I* GREEK CAPITAL LETTER IOTA +K* GREEK CAPITAL LETTER KAPPA +L* GREEK CAPITAL LETTER LAMDA +M* GREEK CAPITAL LETTER MU +N* GREEK CAPITAL LETTER NU +C* GREEK CAPITAL LETTER XI +O* GREEK CAPITAL LETTER OMICRON +P* GREEK CAPITAL LETTER PI +R* GREEK CAPITAL LETTER RHO + cell 211 +S* GREEK CAPITAL LETTER SIGMA +T* GREEK CAPITAL LETTER TAU +U* GREEK CAPITAL LETTER UPSILON +F* GREEK CAPITAL LETTER PHI +X* GREEK CAPITAL LETTER CHI +Q* GREEK CAPITAL LETTER PSI +W* GREEK CAPITAL LETTER OMEGA +J* GREEK CAPITAL LETTER IOTA WITH DIAERESIS +V* GREEK CAPITAL LETTER UPSILON WITH DIAERESIS +a% GREEK SMALL LETTER ALPHA WITH ACUTE +e% GREEK SMALL LETTER EPSILON WITH ACUTE +y% GREEK SMALL LETTER ETA WITH ACUTE +i% GREEK SMALL LETTER IOTA WITH ACUTE + GREEK SMALL LETTER UPSILON WITH ACUTE AND DIAERESIS + cell 225 +a* GREEK SMALL LETTER ALPHA +b* GREEK SMALL LETTER BETA +g* GREEK SMALL LETTER GAMMA +d* GREEK SMALL LETTER DELTA +e* GREEK SMALL LETTER EPSILON +z* GREEK SMALL LETTER ZETA +y* GREEK SMALL LETTER ETA +h* GREEK SMALL LETTER THETA +i* GREEK SMALL LETTER IOTA +k* GREEK SMALL LETTER KAPPA +l* GREEK SMALL LETTER LAMDA +m* GREEK SMALL LETTER MU +n* GREEK SMALL LETTER NU +c* GREEK SMALL LETTER XI +o* GREEK SMALL LETTER OMICRON +p* GREEK SMALL LETTER PI +r* GREEK SMALL LETTER RHO +*s GREEK SMALL LETTER FINAL SIGMA +s* GREEK SMALL LETTER SIGMA +t* GREEK SMALL LETTER TAU +u* GREEK SMALL LETTER UPSILON +f* GREEK SMALL LETTER PHI +x* GREEK SMALL LETTER CHI +q* GREEK SMALL LETTER PSI +w* GREEK SMALL LETTER OMEGA +j* GREEK SMALL LETTER IOTA WITH DIAERESIS +v* GREEK SMALL LETTER UPSILON WITH DIAERESIS +o% GREEK SMALL LETTER OMICRON WITH ACUTE +u% GREEK SMALL LETTER UPSILON WITH ACUTE +w% GREEK SMALL LETTER OMEGA WITH ACUTE + + row 043 + .... + + row 044 + ..... + cell 035 +p+ ARABIC LETTER PEH + ... + cell 040 +v+ ARABIC LETTER VEH + ... + cell 052 +gf ARABIC LETTER GAF + ... + cell 172 +,+ ARABIC COMMA + cell 187 +;+ ARABIC SEMICOLON + cell 191 +?+ ARABIC QUESTION MARK + cell 193 +H' ARABIC LETTER HAMZA +aM ARABIC LETTER ALEF WITH MADDA ABOVE +aH ARABIC LETTER ALEF WITH HAMZA ABOVE +wH ARABIC LETTER WAW WITH HAMZA ABOVE +ah ARABIC LETTER ALEF WITH HAMZA BELOW +yH ARABIC LETTER YEH WITH HAMZA ABOVE +a+ ARABIC LETTER ALEF +b+ ARABIC LETTER BEH +tm ARABIC LETTER TEH MARBUTA +t+ ARABIC LETTER TEH +tk ARABIC LETTER THEH +g+ ARABIC LETTER JEEM +hk ARABIC LETTER HAH +x+ ARABIC LETTER KHAH +d+ ARABIC LETTER DAL +dk ARABIC LETTER THAL +r+ ARABIC LETTER RA +z+ ARABIC LETTER ZAIN +s+ ARABIC LETTER SEEN +sn ARABIC LETTER SHEEN +c+ ARABIC LETTER SAD +dd ARABIC LETTER DAD +tj ARABIC LETTER TAH +zH ARABIC LETTER ZAH +e+ ARABIC LETTER AIN +i+ ARABIC LETTER GHAIN + cell 224 +++ ARABIC TATWEEL +f+ ARABIC LETTER FEH +q+ ARABIC LETTER QAF +k+ ARABIC LETTER KAF +l+ ARABIC LETTER LAM +m+ ARABIC LETTER MEEM +n+ ARABIC LETTER NOON +h+ ARABIC LETTER HEH +w+ ARABIC LETTER WAW +j+ ARABIC LETTER ALEF MAKSURA +y+ ARABIC LETTER YEH +:+ ARABIC FATHATAN +"+ ARABIC DAMMATAN +=+ ARABIC KASRATAN +/+ ARABIC FATHA +'+ ARABIC DAMMA +1+ ARABIC KASRA +3+ ARABIC SHADDA +0+ ARABIC SUKUN + + row 045 + ..... + cell 224 +A+ HEBREW LETTER ALEF +B+ HEBREW LETTER BET +G+ HEBREW LETTER GIMEL +D+ HEBREW LETTER DALET +H+ HEBREW LETTER HE +W+ HEBREW LETTER VAV +Z+ HEBREW LETTER ZAYIN +X+ HEBREW LETTER HET +Tj HEBREW LETTER TET +J+ HEBREW LETTER YOD +K% HEBREW LETTER FINAL KAF +K+ HEBREW LETTER KAF +L+ HEBREW LETTER LAMED +M% HEBREW LETTER FINAL MEM +M+ HEBREW LETTER MEM +N% HEBREW LETTER FINAL NUN +N+ HEBREW LETTER NUN +S+ HEBREW LETTER SAMEKH +E+ HEBREW LETTER AYIN +P% HEBREW LETTER FINAL PE +P+ HEBREW LETTER PE +Zj HEBREW LETTER FINAL TSADI +ZJ HEBREW LETTER TSADI +Q+ HEBREW LETTER QOF +R+ HEBREW LETTER RESH +Sh HEBREW LETTER SIN +T+ HEBREW LETTER TAV + + row 046 + cell 032 +IS IDEOGRAPHIC SPACE +,_ IDEOGRAPHIC COMMA +._ IDEOGRAPHIC FULL STOP ++" DITTO MARK ++_ IDEOGRAPHIC DITTO MARK +*_ IDEOGRAPHIC REPETITION MARK +;_ IDEOGRAPHIC CLOSING MARK +0_ IDEOGRAPHIC NUMBER ZERO + cell 042 +<+ LEFT-POINTING DOUBLE ANGLE BRACKET +>+ RIGHT-POINTING DOUBLE ANGLE BRACKET +<' IDEOGRAPHIC LEFT BRACKET +>' IDEOGRAPHIC RIGHT BRACKET +<" IDEOGRAPHIC LEFT DOUBLE BRACKET +>" IDEOGRAPHIC RIGHT DOUBLE BRACKET +(" LEFT BOLDFACE SQUARE BRACKET +)" RIGHT BOLDFACE SQUARE BRACKET +=/ POSTAL MARK +=_ GETA MARK +(' LEFT TORTOISE-SHELL BRACKET +)' RIGHT TORTOISE-SHELL BRACKET +KM KOME MARK + cell 069 +b4 BOPOMOFO LETTER B +p4 BOPOMOFO LETTER P +m4 BOPOMOFO LETTER M +f4 BOPOMOFO LETTER F +d4 BOPOMOFO LETTER D +t4 BOPOMOFO LETTER T +n4 BOPOMOFO LETTER N +l4 BOPOMOFO LETTER L +g4 BOPOMOFO LETTER G +k4 BOPOMOFO LETTER K +h4 BOPOMOFO LETTER H +j4 BOPOMOFO LETTER J +q4 BOPOMOFO LETTER Q +x4 BOPOMOFO LETTER X +zh BOPOMOFO LETTER ZH +ch BOPOMOFO LETTER CH +sh BOPOMOFO LETTER SH +r4 BOPOMOFO LETTER R +z4 BOPOMOFO LETTER Z +c4 BOPOMOFO LETTER C +s4 BOPOMOFO LETTER S +a4 BOPOMOFO LETTER A +o4 BOPOMOFO LETTER O +e4 BOPOMOFO LETTER E +eh BOPOMOFO LETTER EH +ai BOPOMOFO LETTER AI +ei BOPOMOFO LETTER EI +au BOPOMOFO LETTER AU +ou BOPOMOFO LETTER OU +an BOPOMOFO LETTER AN +en BOPOMOFO LETTER EN +aN BOPOMOFO LETTER ANG +eN BOPOMOFO LETTER ENG +er BOPOMOFO LETTER ER +i4 BOPOMOFO LETTER I +u4 BOPOMOFO LETTER U +iu BOPOMOFO LETTER IU + BOPOMOFO SOFT TONE MARK + BOPOMOFO FIRST TONE MARK + BOPOMOFO SECOND TONE MARK + BOPOMOFO THIRD TONE MARK + BOPOMOFO FOURTH TONE MARK + + cell 161 + .... + row 047 + cell 033 +A5 HIRAGANA LETTER SMALL A +a5 HIRAGANA LETTER A +I5 HIRAGANA LETTER SMALL I +i5 HIRAGANA LETTER I +U5 HIRAGANA LETTER SMALL U +u5 HIRAGANA LETTER U +E5 HIRAGANA LETTER SMALL E +e5 HIRAGANA LETTER E +O5 HIRAGANA LETTER SMALL O +o5 HIRAGANA LETTER O +ka HIRAGANA LETTER KA +ga HIRAGANA LETTER GA +ki HIRAGANA LETTER KI +gi HIRAGANA LETTER GI +ku HIRAGANA LETTER KU +gu HIRAGANA LETTER GU +ke HIRAGANA LETTER KE +ge HIRAGANA LETTER GE +ko HIRAGANA LETTER KO +go HIRAGANA LETTER GO +sa HIRAGANA LETTER SA +za HIRAGANA LETTER ZA +si HIRAGANA LETTER SI +zi HIRAGANA LETTER ZI +su HIRAGANA LETTER SU +zu HIRAGANA LETTER ZU +se HIRAGANA LETTER SE +ze HIRAGANA LETTER ZE +so HIRAGANA LETTER SO +zo HIRAGANA LETTER ZO +ta HIRAGANA LETTER TA +da HIRAGANA LETTER DA +ti HIRAGANA LETTER TI +di HIRAGANA LETTER DI +tU HIRAGANA LETTER SMALL TU +tu HIRAGANA LETTER TU +du HIRAGANA LETTER DU +te HIRAGANA LETTER TE +de HIRAGANA LETTER DE +to HIRAGANA LETTER TO +do HIRAGANA LETTER DO +na HIRAGANA LETTER NA +ni HIRAGANA LETTER NI +nu HIRAGANA LETTER NU +ne HIRAGANA LETTER NE +no HIRAGANA LETTER NO +ha HIRAGANA LETTER HA +ba HIRAGANA LETTER BA +pa HIRAGANA LETTER PA +hi HIRAGANA LETTER HI +bi HIRAGANA LETTER BI +pi HIRAGANA LETTER PI +hu HIRAGANA LETTER HU +bu HIRAGANA LETTER BU +pu HIRAGANA LETTER PU +he HIRAGANA LETTER HE +be HIRAGANA LETTER BE +pe HIRAGANA LETTER PE +ho HIRAGANA LETTER HO +bo HIRAGANA LETTER BO +po HIRAGANA LETTER PO +ma HIRAGANA LETTER MA +mi HIRAGANA LETTER MI +mu HIRAGANA LETTER MU +me HIRAGANA LETTER ME +mo HIRAGANA LETTER MO +yA HIRAGANA LETTER SMALL YA +ya HIRAGANA LETTER YA +yU HIRAGANA LETTER SMALL YU +yu HIRAGANA LETTER YU +yO HIRAGANA LETTER SMALL YO +yo HIRAGANA LETTER YO +ra HIRAGANA LETTER RA +ri HIRAGANA LETTER RI +ru HIRAGANA LETTER RU +re HIRAGANA LETTER RE +ro HIRAGANA LETTER RO +wA HIRAGANA LETTER SMALL WA +wa HIRAGANA LETTER WA +wi HIRAGANA LETTER WI +we HIRAGANA LETTER WE +wo HIRAGANA LETTER WO +n5 HIRAGANA LETTER N + cell 122 +"5 HIRAGANA-KATAKANA VOICED SOUND MARK +05 HIRAGANA-KATAKANA SEMI-VOICED SOUND MARK +*5 HIRAGANA ITERATION MARK ++5 HIRAGANA VOICED ITERATION MARK + + cell 161 +a6 KATAKANA LETTER SMALL A +A6 KATAKANA LETTER A +i6 KATAKANA LETTER SMALL I +I6 KATAKANA LETTER I +u6 KATAKANA LETTER SMALL U +U6 KATAKANA LETTER U +e6 KATAKANA LETTER SMALL E +E6 KATAKANA LETTER E +o6 KATAKANA LETTER SMALL O +O6 KATAKANA LETTER O +Ka KATAKANA LETTER KA +Ga KATAKANA LETTER GA +Ki KATAKANA LETTER KI +Gi KATAKANA LETTER GI +Ku KATAKANA LETTER KU +Gu KATAKANA LETTER GU +Ke KATAKANA LETTER KE +Ge KATAKANA LETTER GE +Ko KATAKANA LETTER KO +Go KATAKANA LETTER GO +Sa KATAKANA LETTER SA +Za KATAKANA LETTER ZA +Si KATAKANA LETTER SI +Zi KATAKANA LETTER ZI +Su KATAKANA LETTER SU +Zu KATAKANA LETTER ZU +Se KATAKANA LETTER SE +Ze KATAKANA LETTER ZE +So KATAKANA LETTER SO +Zo KATAKANA LETTER ZO +Ta KATAKANA LETTER TA +Da KATAKANA LETTER DA +Ti KATAKANA LETTER TI +Di KATAKANA LETTER DI +TU KATAKANA LETTER SMALL TU +Tu KATAKANA LETTER TU +Du KATAKANA LETTER DU +Te KATAKANA LETTER TE +De KATAKANA LETTER DE +To KATAKANA LETTER TO +Do KATAKANA LETTER DO +Na KATAKANA LETTER NA +Ni KATAKANA LETTER NI +Nu KATAKANA LETTER NU +Ne KATAKANA LETTER NE +No KATAKANA LETTER NO +Ha KATAKANA LETTER HA +Ba KATAKANA LETTER BA +Pa KATAKANA LETTER PA +Hi KATAKANA LETTER HI +Bi KATAKANA LETTER BI +Pi KATAKANA LETTER PI +Hu KATAKANA LETTER HU +Bu KATAKANA LETTER BU +Pu KATAKANA LETTER PU +He KATAKANA LETTER HE +Be KATAKANA LETTER BE +Pe KATAKANA LETTER PE +Ho KATAKANA LETTER HO +Bo KATAKANA LETTER BO +Po KATAKANA LETTER PO +Ma KATAKANA LETTER MA +Mi KATAKANA LETTER MI +Mu KATAKANA LETTER MU +Me KATAKANA LETTER ME +Mo KATAKANA LETTER MO +YA KATAKANA LETTER SMALL YA +Ya KATAKANA LETTER YA +YU KATAKANA LETTER SMALL YU +Yu KATAKANA LETTER YU +YO KATAKANA LETTER SMALL YO +Yo KATAKANA LETTER YO +Ra KATAKANA LETTER RA +Ri KATAKANA LETTER RI +Ru KATAKANA LETTER RU +Re KATAKANA LETTER RE +Ro KATAKANA LETTER RO +WA KATAKANA LETTER SMALL WA +Wa KATAKANA LETTER WA +Wi KATAKANA LETTER WI +We KATAKANA LETTER WE +Wo KATAKANA LETTER WO +N6 KATAKANA LETTER N +Vu KATAKANA LETTER VU +KA KATAKANA LETTER SMALL KA +KE KATAKANA LETTER SMALL KE + cell 252 +-6 HIRAGANA-KATAKANA PROLONGED SOUND MARK +*6 KATAKANA ITERATION MARK ++6 KATAKANA VOICED ITERATION MARK + + Presentation forms + row 060 + cell 040 +ff LATIN SMALL LIGATURE FF +fi LATIN SMALL LIGATURE FI +fl LATIN SMALL LIGATURE FL + ffi LATIN SMALL LIGATURE FFI + ffl LATIN SMALL LIGATURE FFL + cell 045 +ft LATIN SMALL LIGATURE FT +st LATIN SMALL LIGATURE ST + cell 048 +Iu INTEGRAL SIGN UPPER PART +Il INTEGRAL SIGN LOWER PART + .... diff --git a/Lib/charset/master/OTHER b/Lib/charset/master/OTHER new file mode 100644 index 0000000..bdb9042 --- /dev/null +++ b/Lib/charset/master/OTHER @@ -0,0 +1,68 @@ + Private use + group 032 + plane 032 + row 052 + cell 032 + +__ indicates unfinished +"! NON-SPACING GRAVE ACCENT (ISO IR 70 193) +"' NON-SPACING ACUTE ACCENT (ISO IR 70 194) +"> NON-SPACING CIRCUMFLEX ACCENT (ISO IR 70 195) +"? NON-SPACING TILDE (ISO IR 70 196) +"- NON-SPACING MACRON (ISO IR 70 197) +"( NON-SPACING BREVE (ISO IR 70 198) +". NON-SPACING DOT ABOVE (ISO IR 70 199) +": NON-SPACING DIAERESIS (ISO IR 70 200) +"/ NON-SPACING SOLIDUS (ISO IR 99 201) +"0 NON-SPACING RING ABOVE (ISO IR 70 202) +", NON-SPACING CEDILLA (ISO IR 70 203) +"_ NON-SPACING UNDERLINE (ISO IR 99 216) +"" NON-SPACING DOUBLE ACCUTE ACCENT (ISO IR 70 205) +"< NON-SPACING CARON (ISO IR 70 207) +"; NON-SPACING OGONEK (ISO IR 53 208) +"= NON-SPACING DOUBLE UNDERLINE (ISO IR 53 217) +"1 NON-SPACING DIAERESIS WITH ACCENT (ISO IR 70 192) +"2 NON-SPACING UMLAUT (ISO 5426 201) +Fd FILLED FORWARD DIAGONAL (ANSI X3.110-1983 218) +Bd FILLED BACKWARD DIAGONAL (ANSI X3.110-1983 219) +Fl Dutch guilder sign (IBM CP 437 159) +Li Italian Lira sign (HP ROMAN 8 175) +/f VULGAR FRACTION BAR (MacIntosh 218) +0s SUBSCRIPT ZERO (ISO IR 50 096) +1s SUBSCRIPT ONE (ISO IR 50 097) +2s SUBSCRIPT TWO (ISO IR 50 098) +3s SUBSCRIPT THREE (ISO IR 50 099) +4s SUBSCRIPT FOUR (ISO IR 50 100) +5s SUBSCRIPT FIVE (ISO IR 50 101) +6s SUBSCRIPT SIX (ISO IR 50 102) +7s SUBSCRIPT SEVEN (ISO IR 50 103) +8s SUBSCRIPT EIGHT (ISO IR 50 104) +9s SUBSCRIPT NINE (ISO IR 50 105) +0S SUPERSCRIPT ZERO (ISO IR 50 112) +4S SUPERSCRIPT FOUR (ISO IR 50 116) +5S SUPERSCRIPT FIVE (ISO IR 50 117) +6S SUPERSCRIPT SIX (ISO IR 50 118) +7S SUPERSCRIPT SEVEN (ISO IR 50 119) +8S SUPERSCRIPT EIGHT (ISO IR 50 120) +9S SUPERSCRIPT NINE (ISO IR 50 121) ++S SUPERSCRIPT PLUS (ISO IR 50 106) +-S SUPERSCRIPT MINUS (ISO IR 50 107) +1h ABSTRACT SYMBOL H ONE (HOOK) (JIS C 6229-1984 060) +2h ABSTRACT SYMBOL H TWO (FORK) (JIS C 6229-1984 093) +3h ABSTRACT SYMBOL H THREE (CHAIR) (JIS C 6229-1984 062) +4h ABSTRACT SYMBOL H FOUR (LONG VERTICAL MARK) (JIS C 6229-1984 125) +1j SYMBOL ONE (ISO 2033-1983 058) +2j SYMBOL TWO (ISO 2033-1983 059) +3j SYMBOL THREE (ISO 2033-1983 060) +4j SYMBOL FOUR (ISO 2033-1983 061) +UA Unit space A (ISO IR 8-1 064) +UB Unit space B (ISO IR 8-1 096) +yf ARABIC LETTER YEH FINAL (CODAR U 090) +yr OLD NORSE YR (DIN 31624 251) +.6 KATAKANA FULL STOP (JIS C 6220 033) +<6 KATAKANA OPENING BRACKET (JIS C 6220 034) +>6 KATAKANA CLOSING BRACKET (JIS C 6220 035) +,6 KATAKANA COMMA (JIS C 6220 036) +&6 KATAKANA CONJUNCTION SYMBOL (JIS C 6220 037) +(S LEFT PARENTHESIS SUPERSCRIPT (CSA Z243.4-1985-gr 168) +)S RIGHT PARENTHESIS SUPERSCRIPT (CSA Z243.4-1985-gr 169) diff --git a/Lib/charset/strcnv.c b/Lib/charset/strcnv.c new file mode 100644 index 0000000..34e2133 --- /dev/null +++ b/Lib/charset/strcnv.c @@ -0,0 +1,431 @@ +/* strcnv.c 1.4 901228 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/charset/RCS/strcnv.c,v 6.0 1991/12/18 20:21:39 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/charset/RCS/strcnv.c,v 6.0 1991/12/18 20:21:39 jpo Rel $ + * + * $Log: strcnv.c,v $ + * Revision 6.0 1991/12/18 20:21:39 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include "charset.h" + + +extern char *charset_dir, *charset_mnem; + +static IN_CH *chset = NULL; +static CHARSET *charsets = NULL; + + + +/* -- local routines -- */ +static CHAR8U *getoutch(); +static INT16S *getinch(); +static int findc(); +static int getchbas(); +static int openfile(); +extern off_t lseek (); + +static int strcnv_mnemonics(), strncnv_mnemonics(), + strncnv_x408(); + + + +/* -------------------- Begin Routines ------------------------------------ */ + + + + +int strcnv (r_chset, s_chset, result, source, MnemonicsRequired) +CHARSET *r_chset; +CHARSET *s_chset; +CHAR8U *result; +CHAR8U *source; +int MnemonicsRequired; +{ + switch (MnemonicsRequired) { + case TRUE: + return (strcnv_mnemonics (r_chset, s_chset, result, source)); + default: + return (-1); + } +} + + + + +int strncnv (r_chset, s_chset, result, source, n, MnemonicsRequired) +CHARSET *r_chset; +CHARSET *s_chset; +CHAR8U *result; +CHAR8U *source; +int n; +int MnemonicsRequired; +{ + switch (MnemonicsRequired) { + case TRUE: + return (strncnv_mnemonics + (r_chset, s_chset, result, source, n)); + default: + return (strncnv_x408 + (r_chset, s_chset, result, source, n)); + } +} + + + + +CHARSET *getchset (s, esc) +char *s; +INT16S esc; +{ + register CHARSET *c, *c1; + register char *p; + + for (p = s; *p; p++) + if (isascii (*p) && islower (*p)) + *p = toupper (*p); + if (getchbas() == 0) + return NULL; + for (c = charsets; c && strcmp (c->name, s); c = c->next) + c1 = c; + if (!c) { + c = (CHARSET * ) malloc (sizeof (CHARSET)); + if (!c) + return NULL; + c->next = NULL; + c->out = getoutch (s, (CHAR8U)0); + if (c->out) { + c->name = (char *) strdup (s); + c->in = getinch (s, (CHAR8U)0); + c->esc = esc; + } else { + free ((char *)c); + c = NULL; + } + if (charsets) + c1->next = c; + else + charsets = c; + } + return c; +} + + + + +/* ------------------------- Static Routines ---------------------------- */ + + + + +static int strcnv_mnemonics (r_chset, s_chset, result, source) +CHARSET *r_chset; +CHARSET *s_chset; +CHAR8U *result; +CHAR8U *source; +{ + register CHAR8U *p, *q; + register CHAR8U *out; + register INT16S *in; + register int o; /* intermediate binary value */ + register int c; + register INT16S esc, esco, mnem; + + p = result; + q = source; + out = r_chset->out; + in = s_chset->in; + esco = r_chset->esc; + esc = s_chset->esc; + + while (c = *q++) { + /* printf (" %c %c %c",c,*q,esc); */ + if (c == esc) { + /* two esc in a row -> one escape */ + /* if esc followed by defined mnemonic + next char is mnemonic. */ + + if (*q == esc) { + o = in[esc]; + q++; + } else { + o = findc (q[0] * C256 + q[1]); + q += 2; + } + } else + o = in[c]; + if (!o) + o = LOW_LINE; /* if illegal input replace with '_' */ + + /* printf (" %d %d %c",o,esco,esco); */ + if (out[o] == esco) { + *p++ = esco; + *p++ = esco; + } else if (out[o]) + *p++ = out[o]; + else { + mnem = chset[o]; + *p++ = esco; + *p++ = out [in [mnem / C256 ]]; + *p++ = out [in [mnem % C256 ]]; + } + } + *p = '\0'; + return p - result; +} + + + + +static int strncnv_mnemonics (r_chset, s_chset, result, source, n) +CHARSET *r_chset; +CHARSET *s_chset; +CHAR8U *result, *source; +int n; +{ + register CHAR8U *p, *q, *e; + register CHAR8U *out; + register INT16S *in; + register int o; /* intermediate binary value */ + register int c; + register INT16S esc, esco, mnem; + + p = result; + q = source; + e = p + n - 4; /* 4 chars for ending: esc two-char nul */ + out = r_chset->out; + in = s_chset->in; + esco = r_chset->esc; + esc = s_chset->esc; + + while ((c = *q++) && p < e) { + /* printf (" %c %c %c",c,*q,esc); */ + if (c == esc) { + /* two esc in a row -> one escape */ + /* if esc followed by defined mnemonic + next char is mnemonic. */ + + if (*q == esc) { + o = in[esc]; + q++; + } else { + o = findc (q[0] * C256 + q[1]); + q += 2; + } + } else + o = in[c]; + if (!o) + o = LOW_LINE; /* if illegal input replace with '_' */ + + /* printf (" %d %d %c",o,esco,esco); */ + if (out[o] == esco) { + *p++ = esco; + *p++ = esco; + } else if (out[o]) + *p++ = out[o]; + else { + mnem = chset[o]; + *p++ = esco; + *p++ = out [in [mnem / C256 ]]; + *p++ = out [in [mnem % C256 ]]; + } + } + *p = '\0'; + return p - result; +} + + + + +static int strncnv_x408 (r_chset, s_chset, result, source, n) +CHARSET *r_chset; +CHARSET *s_chset; +CHAR8U *result, *source; +int n; +{ + register CHAR8U *p, *q, *e; + register CHAR8U *out; + register INT16S *in; + register int o; /* intermediate binary value */ + register int c; + + p = result; + q = source; + e = q + n; + out = r_chset->out; + in = s_chset->in; + + /* --- *** --- + 1) No mnemonics are used for unknown symbols. + They are just replaced with '?'. Provided they are NOT + accented letters or umlauts. + 2) Accented letters or umlauts are 2 bit combinations: + the first is a a mark, the second a basic Latin character. + In this case only the character is printed. + --- *** --- */ + + for (c = *q++; q <= e; c = *q++) { + o = in[c]; + if (!o) + o = QUESTION_MARK; + /* if illegal input replace with '?' */ + + if (out[o]) + *p++ = out[o]; + else if (c >= 192 && c <= 207) /* an accent ? */ + if ((q[0] >= 'A' && q[0] <= 'Z') || + (q[0] >= 'a' && q[0] <= 'z')) + continue; + else + *p++ = out[QUESTION_MARK]; + else + *p++ = out[QUESTION_MARK]; + } + + *p = '\0'; + return p - result; +} + + + + +static int findc (c) +register unsigned int c; /* c is ascii value of two-byte char mnem */ +{ + register INT16S *cs; + register int i; + + i = chset[0] + 1; + cs = &chset[i]; + while (--i > 0 && c != *--cs) + ; + + /* printf (" %d ",i); */ + return i; /* zero == not found */ +} + + + + +static int openfile (dir, file, mode) +char *dir, *file; +int mode; +{ + char fn[LSIZE]; + register char *p, *q; + register int f; + + (void) strcpy (fn, dir); + (void) strcat (fn, "/"); + + q = fn + strlen (fn); + for (p = file; *p; p++) + *q++ = (isascii (*p) && islower (*p)) + ? toupper (*p) : *p; + *q = 0; + + f = open (fn, mode); + if (f < 0) + (void) fprintf (stderr, "\n\n*** Error: opening file %s\n", fn); + return f; +} + + + + +static int getchbas() +{ + INT16S sz[2]; + register int f; + unsigned sz1; + + if (!chset) { + f = openfile (charset_dir, charset_mnem, O_RDONLY); + if (f < 0) + return NULL; + if (read (f, (char *)sz, sizeof (INT16S)) != sizeof (INT16S)) + goto err; + sz1 = sz[0] * sizeof (INT16S); + (void) lseek (f, 0L, 0); + if ((chset = (IN_CH * ) malloc (sz1)) == NULL) + goto err; + if (read (f, (char *)chset, (int)sz1) != sz1) + goto err; + /* printf ("charsz %d chars %22.22s\n",sz1,chset); */ + (void) close (f); + } + return 1; + +err: + (void) close (f); + return NULL; +} + + + + +static INT16S *getinch (charset, c) +char *charset; +CHAR8U c; +{ + int f, sz; + IN_CH * in; + + sz = C256 * sizeof (IN_CH); + in = (IN_CH * ) malloc ((unsigned)sz); + if (!in) + return NULL; + f = openfile (charset_dir, charset, O_RDONLY); + if (f < 0) + return NULL; + if (read (f, (char *)in, sz) != sz) { + (void) close (f); + return NULL; + } + (void) close (f); + in[0] = c; + /* printf (" %c %d ",c,in[0]); */ + return in; +} + + + + +static CHAR8U *getoutch (charset, c) +char *charset; +CHAR8U c; +{ + int f; + unsigned sz1; + OUT_CH * out; + + if (getchbas() == 0) + return NULL; + sz1 = chset[0]; + f = openfile (charset_dir, charset, O_RDONLY); + if (f < 0) + return NULL; + (void) lseek (f, C256L * sizeof (INT16S), 0); + out = (OUT_CH * ) malloc (sz1); + if (!out) + goto err; + if (read (f, (char *)out, (int)sz1) != sz1) + goto err; + (void) close (f); + out[0] = c; + return out; +err: + (void) close (f); + return NULL; +} diff --git a/Lib/format/Makefile b/Lib/format/Makefile new file mode 100644 index 0000000..3ab9300 --- /dev/null +++ b/Lib/format/Makefile @@ -0,0 +1,438 @@ +# format lib Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/format/RCS/Makefile,v 6.0 1991/12/18 20:22:06 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:22:06 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = UTC2rfc.c adr2rfc.c domsinfo2rfc.c globalid2rfc.c \ + msgid2rfc.c reprecip2rfc.c rfc2UTC.c rfc2domsinfo.c rfc2encinfo.c \ + rfc2globalid.c rfc2msgid.c rfc2reprecip.c rfc2trace.c \ + rfctxtfold.c trace2rfc.c x400trc2rfc.c rfc2x400trc.c +OBJS = UTC2rfc.o adr2rfc.o domsinfo2rfc.o globalid2rfc.o \ + msgid2rfc.o reprecip2rfc.o rfc2UTC.o rfc2domsinfo.o rfc2encinfo.o \ + rfc2globalid.o rfc2msgid.o rfc2reprecip.o rfc2trace.o \ + rfctxtfold.o trace2rfc.o x400trc2rfc.o rfc2x400trc.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = fmt-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SHADOW) + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +lintlib:llib-lfmt.ln +llib-lfmt.ln: $(SRCS) + $(LINT) -Cfmt $(LLFLAGS) $(SRCS) + +clean: tidy + rm -f $(OBJS) llib-lfmt.ln +tidy: + rm -f core $(SHADOW) *.old *.BAK + +install: + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of building rules +# +############################################################ + + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +UTC2rfc.o: UTC2rfc.c +UTC2rfc.o: ../../h/util.h +UTC2rfc.o: ../../h/config.h +UTC2rfc.o: ../../h/ll_log.h +adr2rfc.o: adr2rfc.c +adr2rfc.o: ../../h/util.h +adr2rfc.o: ../../h/config.h +adr2rfc.o: ../../h/ll_log.h +adr2rfc.o: ../../h/or.h +adr2rfc.o: ../../h/adr.h +adr2rfc.o: ../../h/list_rchan.h +adr2rfc.o: ../../h/chan.h +adr2rfc.o: ../../h/table.h +adr2rfc.o: ../../h/list_bpt.h +adr2rfc.o: ../../h/auth.h +adr2rfc.o: ../../h/list_bpt.h +adr2rfc.o: ../../h/extension.h +adr2rfc.o: ../../h/mta.h +adr2rfc.o: ../../h/adr.h +adr2rfc.o: ../../h/list_bpt.h +adr2rfc.o: ../../h/aparse.h +adr2rfc.o: ../../h/ap.h +adr2rfc.o: ../../h/util.h +adr2rfc.o: ../../h/or.h +adr2rfc.o: ../../h/chan.h +adr2rfc.o: ../../h/auth.h +adr2rfc.o: ../../h/list_rchan.h +domsinfo2rfc.o: domsinfo2rfc.c +domsinfo2rfc.o: ../../h/util.h +domsinfo2rfc.o: ../../h/config.h +domsinfo2rfc.o: ../../h/ll_log.h +domsinfo2rfc.o: ../../h/mta.h +domsinfo2rfc.o: ../../h/adr.h +domsinfo2rfc.o: ../../h/list_rchan.h +domsinfo2rfc.o: ../../h/chan.h +domsinfo2rfc.o: ../../h/table.h +domsinfo2rfc.o: ../../h/list_bpt.h +domsinfo2rfc.o: ../../h/auth.h +domsinfo2rfc.o: ../../h/list_bpt.h +domsinfo2rfc.o: ../../h/extension.h +domsinfo2rfc.o: ../../h/mta.h +domsinfo2rfc.o: ../../h/aparse.h +domsinfo2rfc.o: ../../h/ap.h +domsinfo2rfc.o: ../../h/util.h +domsinfo2rfc.o: ../../h/or.h +domsinfo2rfc.o: ../../h/chan.h +domsinfo2rfc.o: ../../h/auth.h +domsinfo2rfc.o: ../../h/list_rchan.h +domsinfo2rfc.o: ../../h/list_bpt.h +domsinfo2rfc.o: ../../h/tb_p1.h +globalid2rfc.o: globalid2rfc.c +globalid2rfc.o: ../../h/util.h +globalid2rfc.o: ../../h/config.h +globalid2rfc.o: ../../h/ll_log.h +globalid2rfc.o: ../../h/mta.h +globalid2rfc.o: ../../h/adr.h +globalid2rfc.o: ../../h/list_rchan.h +globalid2rfc.o: ../../h/chan.h +globalid2rfc.o: ../../h/table.h +globalid2rfc.o: ../../h/list_bpt.h +globalid2rfc.o: ../../h/auth.h +globalid2rfc.o: ../../h/list_bpt.h +globalid2rfc.o: ../../h/extension.h +globalid2rfc.o: ../../h/mta.h +globalid2rfc.o: ../../h/aparse.h +globalid2rfc.o: ../../h/ap.h +globalid2rfc.o: ../../h/util.h +globalid2rfc.o: ../../h/or.h +globalid2rfc.o: ../../h/chan.h +globalid2rfc.o: ../../h/auth.h +globalid2rfc.o: ../../h/list_rchan.h +globalid2rfc.o: ../../h/list_bpt.h +msgid2rfc.o: msgid2rfc.c +msgid2rfc.o: ../../h/util.h +msgid2rfc.o: ../../h/config.h +msgid2rfc.o: ../../h/ll_log.h +msgid2rfc.o: ../../h/mta.h +msgid2rfc.o: ../../h/adr.h +msgid2rfc.o: ../../h/list_rchan.h +msgid2rfc.o: ../../h/chan.h +msgid2rfc.o: ../../h/table.h +msgid2rfc.o: ../../h/list_bpt.h +msgid2rfc.o: ../../h/auth.h +msgid2rfc.o: ../../h/list_bpt.h +msgid2rfc.o: ../../h/extension.h +msgid2rfc.o: ../../h/mta.h +msgid2rfc.o: ../../h/aparse.h +msgid2rfc.o: ../../h/ap.h +msgid2rfc.o: ../../h/util.h +msgid2rfc.o: ../../h/or.h +msgid2rfc.o: ../../h/chan.h +msgid2rfc.o: ../../h/auth.h +msgid2rfc.o: ../../h/list_rchan.h +msgid2rfc.o: ../../h/list_bpt.h +reprecip2rfc.o: reprecip2rfc.c +reprecip2rfc.o: ../../h/util.h +reprecip2rfc.o: ../../h/config.h +reprecip2rfc.o: ../../h/ll_log.h +reprecip2rfc.o: ../../h/dr.h +reprecip2rfc.o: ../../h/extension.h +reprecip2rfc.o: ../../h/mta.h +reprecip2rfc.o: ../../h/adr.h +reprecip2rfc.o: ../../h/list_rchan.h +reprecip2rfc.o: ../../h/chan.h +reprecip2rfc.o: ../../h/table.h +reprecip2rfc.o: ../../h/list_bpt.h +reprecip2rfc.o: ../../h/auth.h +reprecip2rfc.o: ../../h/list_bpt.h +reprecip2rfc.o: ../../h/extension.h +reprecip2rfc.o: ../../h/mta.h +reprecip2rfc.o: ../../h/aparse.h +reprecip2rfc.o: ../../h/ap.h +reprecip2rfc.o: ../../h/util.h +reprecip2rfc.o: ../../h/or.h +reprecip2rfc.o: ../../h/chan.h +reprecip2rfc.o: ../../h/auth.h +reprecip2rfc.o: ../../h/list_rchan.h +reprecip2rfc.o: ../../h/list_bpt.h +rfc2UTC.o: rfc2UTC.c +rfc2UTC.o: ../../h/util.h +rfc2UTC.o: ../../h/config.h +rfc2UTC.o: ../../h/ll_log.h +rfc2UTC.o: ../../h/mta.h +rfc2UTC.o: ../../h/adr.h +rfc2UTC.o: ../../h/list_rchan.h +rfc2UTC.o: ../../h/chan.h +rfc2UTC.o: ../../h/table.h +rfc2UTC.o: ../../h/list_bpt.h +rfc2UTC.o: ../../h/auth.h +rfc2UTC.o: ../../h/list_bpt.h +rfc2UTC.o: ../../h/extension.h +rfc2UTC.o: ../../h/mta.h +rfc2UTC.o: ../../h/aparse.h +rfc2UTC.o: ../../h/ap.h +rfc2UTC.o: ../../h/util.h +rfc2UTC.o: ../../h/or.h +rfc2UTC.o: ../../h/chan.h +rfc2UTC.o: ../../h/auth.h +rfc2UTC.o: ../../h/list_rchan.h +rfc2UTC.o: ../../h/list_bpt.h +rfc2domsinfo.o: rfc2domsinfo.c +rfc2domsinfo.o: ../../h/util.h +rfc2domsinfo.o: ../../h/config.h +rfc2domsinfo.o: ../../h/ll_log.h +rfc2domsinfo.o: ../../h/mta.h +rfc2domsinfo.o: ../../h/adr.h +rfc2domsinfo.o: ../../h/list_rchan.h +rfc2domsinfo.o: ../../h/chan.h +rfc2domsinfo.o: ../../h/table.h +rfc2domsinfo.o: ../../h/list_bpt.h +rfc2domsinfo.o: ../../h/auth.h +rfc2domsinfo.o: ../../h/list_bpt.h +rfc2domsinfo.o: ../../h/extension.h +rfc2domsinfo.o: ../../h/mta.h +rfc2domsinfo.o: ../../h/aparse.h +rfc2domsinfo.o: ../../h/ap.h +rfc2domsinfo.o: ../../h/util.h +rfc2domsinfo.o: ../../h/or.h +rfc2domsinfo.o: ../../h/chan.h +rfc2domsinfo.o: ../../h/auth.h +rfc2domsinfo.o: ../../h/list_rchan.h +rfc2domsinfo.o: ../../h/list_bpt.h +rfc2domsinfo.o: ../../h/tb_p1.h +rfc2encinfo.o: rfc2encinfo.c +rfc2encinfo.o: ../../h/util.h +rfc2encinfo.o: ../../h/config.h +rfc2encinfo.o: ../../h/ll_log.h +rfc2encinfo.o: ../../h/mta.h +rfc2encinfo.o: ../../h/adr.h +rfc2encinfo.o: ../../h/list_rchan.h +rfc2encinfo.o: ../../h/chan.h +rfc2encinfo.o: ../../h/table.h +rfc2encinfo.o: ../../h/list_bpt.h +rfc2encinfo.o: ../../h/auth.h +rfc2encinfo.o: ../../h/list_bpt.h +rfc2encinfo.o: ../../h/extension.h +rfc2encinfo.o: ../../h/mta.h +rfc2encinfo.o: ../../h/aparse.h +rfc2encinfo.o: ../../h/ap.h +rfc2encinfo.o: ../../h/util.h +rfc2encinfo.o: ../../h/or.h +rfc2encinfo.o: ../../h/chan.h +rfc2encinfo.o: ../../h/auth.h +rfc2encinfo.o: ../../h/list_rchan.h +rfc2encinfo.o: ../../h/list_bpt.h +rfc2encinfo.o: ../../h/list_bpt.h +rfc2globalid.o: rfc2globalid.c +rfc2globalid.o: ../../h/util.h +rfc2globalid.o: ../../h/config.h +rfc2globalid.o: ../../h/ll_log.h +rfc2globalid.o: ../../h/mta.h +rfc2globalid.o: ../../h/adr.h +rfc2globalid.o: ../../h/list_rchan.h +rfc2globalid.o: ../../h/chan.h +rfc2globalid.o: ../../h/table.h +rfc2globalid.o: ../../h/list_bpt.h +rfc2globalid.o: ../../h/auth.h +rfc2globalid.o: ../../h/list_bpt.h +rfc2globalid.o: ../../h/extension.h +rfc2globalid.o: ../../h/mta.h +rfc2globalid.o: ../../h/aparse.h +rfc2globalid.o: ../../h/ap.h +rfc2globalid.o: ../../h/util.h +rfc2globalid.o: ../../h/or.h +rfc2globalid.o: ../../h/chan.h +rfc2globalid.o: ../../h/auth.h +rfc2globalid.o: ../../h/list_rchan.h +rfc2globalid.o: ../../h/list_bpt.h +rfc2msgid.o: rfc2msgid.c +rfc2msgid.o: ../../h/util.h +rfc2msgid.o: ../../h/config.h +rfc2msgid.o: ../../h/ll_log.h +rfc2msgid.o: ../../h/mta.h +rfc2msgid.o: ../../h/adr.h +rfc2msgid.o: ../../h/list_rchan.h +rfc2msgid.o: ../../h/chan.h +rfc2msgid.o: ../../h/table.h +rfc2msgid.o: ../../h/list_bpt.h +rfc2msgid.o: ../../h/auth.h +rfc2msgid.o: ../../h/list_bpt.h +rfc2msgid.o: ../../h/extension.h +rfc2msgid.o: ../../h/mta.h +rfc2msgid.o: ../../h/aparse.h +rfc2msgid.o: ../../h/ap.h +rfc2msgid.o: ../../h/util.h +rfc2msgid.o: ../../h/or.h +rfc2msgid.o: ../../h/chan.h +rfc2msgid.o: ../../h/auth.h +rfc2msgid.o: ../../h/list_rchan.h +rfc2msgid.o: ../../h/list_bpt.h +rfc2reprecip.o: rfc2reprecip.c +rfc2reprecip.o: ../../h/util.h +rfc2reprecip.o: ../../h/config.h +rfc2reprecip.o: ../../h/ll_log.h +rfc2reprecip.o: ../../h/dr.h +rfc2reprecip.o: ../../h/extension.h +rfc2reprecip.o: ../../h/mta.h +rfc2reprecip.o: ../../h/adr.h +rfc2reprecip.o: ../../h/list_rchan.h +rfc2reprecip.o: ../../h/chan.h +rfc2reprecip.o: ../../h/table.h +rfc2reprecip.o: ../../h/list_bpt.h +rfc2reprecip.o: ../../h/auth.h +rfc2reprecip.o: ../../h/list_bpt.h +rfc2reprecip.o: ../../h/extension.h +rfc2reprecip.o: ../../h/mta.h +rfc2reprecip.o: ../../h/aparse.h +rfc2reprecip.o: ../../h/ap.h +rfc2reprecip.o: ../../h/util.h +rfc2reprecip.o: ../../h/or.h +rfc2reprecip.o: ../../h/chan.h +rfc2reprecip.o: ../../h/auth.h +rfc2reprecip.o: ../../h/list_rchan.h +rfc2reprecip.o: ../../h/list_bpt.h +rfc2trace.o: rfc2trace.c +rfc2trace.o: ../../h/util.h +rfc2trace.o: ../../h/config.h +rfc2trace.o: ../../h/ll_log.h +rfc2trace.o: ../../h/mta.h +rfc2trace.o: ../../h/adr.h +rfc2trace.o: ../../h/list_rchan.h +rfc2trace.o: ../../h/chan.h +rfc2trace.o: ../../h/table.h +rfc2trace.o: ../../h/list_bpt.h +rfc2trace.o: ../../h/auth.h +rfc2trace.o: ../../h/list_bpt.h +rfc2trace.o: ../../h/extension.h +rfc2trace.o: ../../h/mta.h +rfc2trace.o: ../../h/aparse.h +rfc2trace.o: ../../h/ap.h +rfc2trace.o: ../../h/util.h +rfc2trace.o: ../../h/or.h +rfc2trace.o: ../../h/chan.h +rfc2trace.o: ../../h/auth.h +rfc2trace.o: ../../h/list_rchan.h +rfc2trace.o: ../../h/list_bpt.h +rfctxtfold.o: rfctxtfold.c +rfctxtfold.o: ../../h/util.h +rfctxtfold.o: ../../h/config.h +rfctxtfold.o: ../../h/ll_log.h +trace2rfc.o: trace2rfc.c +trace2rfc.o: ../../h/util.h +trace2rfc.o: ../../h/config.h +trace2rfc.o: ../../h/ll_log.h +trace2rfc.o: ../../h/mta.h +trace2rfc.o: ../../h/adr.h +trace2rfc.o: ../../h/list_rchan.h +trace2rfc.o: ../../h/chan.h +trace2rfc.o: ../../h/table.h +trace2rfc.o: ../../h/list_bpt.h +trace2rfc.o: ../../h/auth.h +trace2rfc.o: ../../h/list_bpt.h +trace2rfc.o: ../../h/extension.h +trace2rfc.o: ../../h/mta.h +trace2rfc.o: ../../h/aparse.h +trace2rfc.o: ../../h/ap.h +trace2rfc.o: ../../h/util.h +trace2rfc.o: ../../h/or.h +trace2rfc.o: ../../h/chan.h +trace2rfc.o: ../../h/auth.h +trace2rfc.o: ../../h/list_rchan.h +trace2rfc.o: ../../h/list_bpt.h +x400trc2rfc.o: x400trc2rfc.c +x400trc2rfc.o: ../../h/util.h +x400trc2rfc.o: ../../h/config.h +x400trc2rfc.o: ../../h/ll_log.h +x400trc2rfc.o: ../../h/mta.h +x400trc2rfc.o: ../../h/adr.h +x400trc2rfc.o: ../../h/list_rchan.h +x400trc2rfc.o: ../../h/chan.h +x400trc2rfc.o: ../../h/table.h +x400trc2rfc.o: ../../h/list_bpt.h +x400trc2rfc.o: ../../h/auth.h +x400trc2rfc.o: ../../h/list_bpt.h +x400trc2rfc.o: ../../h/extension.h +x400trc2rfc.o: ../../h/mta.h +x400trc2rfc.o: ../../h/aparse.h +x400trc2rfc.o: ../../h/ap.h +x400trc2rfc.o: ../../h/util.h +x400trc2rfc.o: ../../h/or.h +x400trc2rfc.o: ../../h/chan.h +x400trc2rfc.o: ../../h/auth.h +x400trc2rfc.o: ../../h/list_rchan.h +x400trc2rfc.o: ../../h/list_bpt.h +rfc2x400trc.o: rfc2x400trc.c +rfc2x400trc.o: ../../h/util.h +rfc2x400trc.o: ../../h/config.h +rfc2x400trc.o: ../../h/ll_log.h +rfc2x400trc.o: ../../h/mta.h +rfc2x400trc.o: ../../h/adr.h +rfc2x400trc.o: ../../h/list_rchan.h +rfc2x400trc.o: ../../h/chan.h +rfc2x400trc.o: ../../h/table.h +rfc2x400trc.o: ../../h/list_bpt.h +rfc2x400trc.o: ../../h/auth.h +rfc2x400trc.o: ../../h/list_bpt.h +rfc2x400trc.o: ../../h/extension.h +rfc2x400trc.o: ../../h/mta.h +rfc2x400trc.o: ../../h/aparse.h +rfc2x400trc.o: ../../h/ap.h +rfc2x400trc.o: ../../h/util.h +rfc2x400trc.o: ../../h/or.h +rfc2x400trc.o: ../../h/chan.h +rfc2x400trc.o: ../../h/auth.h +rfc2x400trc.o: ../../h/list_rchan.h +rfc2x400trc.o: ../../h/list_bpt.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/format/UTC2rfc.c b/Lib/format/UTC2rfc.c new file mode 100644 index 0000000..3f3feb9 --- /dev/null +++ b/Lib/format/UTC2rfc.c @@ -0,0 +1,132 @@ +/* UTC2rfc.c - Converts a UTC struct into an RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/UTC2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/UTC2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: UTC2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include + + +#define UYEAR(x) ((x) >= 100 ? (x) - 1900 : (x)) +#define YEAR(x) ((x) >= 100 ? (x) : (x) + 1900) +#define dysize(x) (((x) % 4) ? 365 : (((x) % 100) ? 366 : \ + (((x) % 400) ? 365 : 366))) + +static char *Day [] = { + "Sat", + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri" + }; + +extern int dmsize[]; +extern CMD_TABLE tbl_month[]; +extern time_t time (); +extern int abs (); +static int makewkday (); + + +/* --------------------- Begin Routines -------------------------------- */ + + + +/* +This routine produces a RFC 822 standard time string like: + "Tue, 16 Aug 88 10:23:21 BST" +from a UTC structure. +*/ + + +int UTC2rfc (utc, buffer) +UTC utc; +char *buffer; +{ + char zone[10]; + char secs[10]; + int wday; + + *buffer = '\0'; + + if (utc == NULLUTC) { + PP_LOG (LLOG_EXCEPTIONS, ("NULL UTC time")); + return NOTOK; + } + + if (utc -> ut_mon <= 0 || utc -> ut_mon > 12) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/UTC2rfc zero UTC specified")); + return NOTOK; + } + + if (utc -> ut_flags & UT_ZONE) + (void) sprintf (zone, "%c%02d%02d", + utc -> ut_zone < 0 ? '-' : '+', + abs(utc -> ut_zone / 60), + abs(utc -> ut_zone % 60)); + else + (void) strcpy (zone, "+0000"); + + if (utc -> ut_flags & UT_SEC) + (void) sprintf (secs, ":%02d", utc -> ut_sec); + else secs[0] = 0; + + wday = makewkday (utc); + if (wday < 0 || wday > 6) { + PP_LOG (LLOG_EXCEPTIONS, ("Bad weekday calculated %d", wday)); + return NOTOK; + } + + (void) sprintf (buffer, "%s, %d %s %d %02d:%02d%s %s", + Day [wday], + utc -> ut_mday, + rcmd_srch (utc -> ut_mon - 1, tbl_month), + YEAR(utc -> ut_year), + utc -> ut_hour, + utc -> ut_min, + secs, + zone); + + PP_DBG (("Lib/UTC2rfc returns (%s)", buffer)); + + return OK; +} + +static int makewkday (ut) +UTC ut; +{ + int year; + int mon; + int d; + + mon = ut -> ut_mon; + year = YEAR (ut -> ut_year); + d = 4 + year + (year+3)/4; + + if (year > 1800) { + d -= (year - 1701)/100; + d += (year - 1601)/400; + } + if (year > 1752) + d += 3; + if (dysize (year) == 366 && ut -> ut_mon >= 3) + d ++; + while (--mon) + d += dmsize[mon - 1]; + d += ut -> ut_mday; + return (d % 7); +} diff --git a/Lib/format/adr2rfc.c b/Lib/format/adr2rfc.c new file mode 100644 index 0000000..4693b41 --- /dev/null +++ b/Lib/format/adr2rfc.c @@ -0,0 +1,193 @@ +/* adr2rfc.c - Converts an X400 address into an RFC one */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/adr2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/adr2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: adr2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "or.h" +#include "adr.h" +#include + + +/* -------------------- Begin Routines ----------------------------------- */ + +extern char *oid2lstr(); + +extern CMD_TABLE atbl_rdm[], atbl_pd_modes[], atbl_reg_mail[]; + +int adr2rfc (ap, buffer, order_pref) +ADDR *ap; +char *buffer; +int order_pref; +{ + OR_ptr or; + char lbuf[LINESIZE]; + char *str = NULLCP; + + /* -- RFC or X400 address ? -- */ + + if (ap->ad_r822adr) + (void) strcpy (buffer, ap->ad_r822adr); + else if (ap->ad_type == AD_822_TYPE) + return NOTOK; + + else if (ap->ad_r400adr) { + if ((or = or_std2or (ap->ad_r400adr)) == NULLOR) + return NOTOK; + if (or_or2rfc (or, lbuf) == NOTOK) + return NOTOK; + or_free (or); + (void) strcpy (buffer, lbuf); + } + else + return NOTOK; + + + ap_s2s(buffer, &str, order_pref); + if (str != NULLCP) { + (void) strcpy (buffer, str); + free (str); + } + if (ap -> ad_no != 0) /* don't do for Originator */ + return adr2comments(ap, buffer); + return OK; +} + +int adr2comments(ap, buffer) +ADDR *ap; +char *buffer; +{ + char lbuf[LINESIZE]; + char *type; + + /* do 1148 stuff */ + if (ap -> ad_redirection_history != NULL) { + char *reason; + Redirection *ix = ap -> ad_redirection_history; + (void) strcat(buffer, " ("); + while (ix != NULL) { + switch (ix->rd_reason) { + case RDR_RECIP_ASSIGNED: + reason = "Recipient Assigned Alternate Recipient"; + break; + case RDR_ORIG_ASSIGNED: + reason = "Originator Requested Alternate Recipient"; + break; + case RDR_MD_ASSIGNED: + reason = "Recipient MD Assigned Alternate Recipient"; + break; + default: + reason = NULLCP; + break; + } + + if (ix->rd_addr != NULLCP + || ix->rd_dn != NULLCP) { + if (ix == ap->ad_redirection_history) + (void) strcat(buffer, "Originally To: "); + else + (void) strcat (buffer, " "); + (void) strcat (buffer, + (ix -> rd_addr != NULLCP) ? + ix -> rd_addr : ix -> rd_dn); + } + if (ix == ap->ad_redirection_history) + (void) strcat (buffer, " Redirected on "); + else + (void) strcat (buffer, " Redirected Again on "); + + if (UTC2rfc (ix->rd_time, lbuf) != OK) + return NOTOK; + (void) strcat (buffer, lbuf); + (void) strcat (buffer, " To: "); + if (reason != NULLCP) + (void) strcat (buffer, reason); + ix = ix -> rd_next; + } + (void) strcat (buffer, ")"); + } + + if (ap -> ad_req_del[0] != AD_RDM_NOTUSED + && ap -> ad_req_del[0] != AD_RDM_ANY) { + int ix = 0, first = OK; + + (void) sprintf (buffer, + "%s (Requested Delivery Methods ", + buffer); + while (ix < AD_RDM_MAX + && ap -> ad_req_del[ix] != AD_RDM_NOTUSED + && ap -> ad_req_del[ix] != AD_RDM_ANY) { + if ((type = rcmd_srch(ap -> ad_req_del[ix], + atbl_rdm)) != NULLCP) + (void) sprintf(buffer, + "%s%s%s", + buffer, + (first == OK) ? "" : ", ", + type); + ix++; + first = NOTOK; + } + (void) sprintf (buffer, "%s)", buffer); + } + + if (ap -> ad_phys_forward) + (void) sprintf (buffer, + "%s (Physical Forwarding Prohibited)", + buffer); + + if (ap -> ad_phys_fw_ad_req) + (void) sprintf (buffer, + "%s (Physical Forwarding Address Requested)", + buffer); + + if (ap -> ad_phys_modes + && ap -> ad_phys_modes != AD_PM_ORD + && (type = rcmd_srch (ap -> ad_phys_modes, atbl_pd_modes)) != NULLCP) + (void) sprintf (buffer, + "%s (Physical Delivery Mode %s)", + buffer, type); + + if (ap -> ad_reg_mail_type + && ap -> ad_reg_mail_type != AD_RMT_UNSPECIFIED + && (type = rcmd_srch (ap -> ad_reg_mail_type, atbl_reg_mail)) != NULLCP) + (void) sprintf (buffer, + "%s (Registered Mail Type %s)", + buffer, type); + + if (ap -> ad_recip_number_for_advice != NULLCP) + (void) sprintf (buffer, + "%s (Recipient Number For Advice %s)", + buffer, + ap -> ad_recip_number_for_advice); + + if (ap -> ad_phys_rendition_attribs != NULL) + (void) sprintf (buffer, + "%s (Physical Rendition Attributes %s)", + buffer, + oid2lstr(ap -> ad_phys_rendition_attribs)); + + if (ap -> ad_pd_report_request) + (void) sprintf (buffer, + "%s (Physical Delivery Report Requested)", + buffer); + + if (ap -> ad_proof_delivery) + (void) sprintf (buffer, + "%s (Proof of Delivery Requested)", + buffer); + + PP_DBG (("Lib/adr2rfc returns (%s)", buffer)); + return OK; +} diff --git a/Lib/format/domsinfo2rfc.c b/Lib/format/domsinfo2rfc.c new file mode 100644 index 0000000..05e72c0 --- /dev/null +++ b/Lib/format/domsinfo2rfc.c @@ -0,0 +1,132 @@ +/* domsinfo2rfc.c - Converts a DomSupInfo struct into a RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/domsinfo2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/domsinfo2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: domsinfo2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" +#include "tb_p1.h" + + +extern CMD_TABLE p1tbl_domsinfo[]; + +extern int x400eits2rfc (); +extern int globalid2rfc (); +extern UTC utclocalise (); + +static int action2rfc (); +/* -------------------- Begin Routines ---------------------------------- */ + + + + +int domsinfo2rfc (dominfo, buffer) /* DomainSuppliedInfo -> RFC */ +DomSupInfo *dominfo; +char *buffer; +{ + char tbuf [LINESIZE]; + UTC lut; + char *cp, *p; + + cp = buffer; + + /* -- arrival -- */ + if (dominfo -> dsi_time != NULLUTC && + (lut = utclocalise(dominfo -> dsi_time)) != NULLUTC && + UTC2rfc (lut, tbuf) == OK && + (p = rcmd_srch (DSI_TIME, p1tbl_domsinfo)) != NULLCP) { + (void) sprintf (cp, "%s %s", p, tbuf); + free ((char *) lut); + + cp += strlen (cp); + } + else + return NOTOK; + + + /* -- deferred -- */ + if (dominfo -> dsi_deferred != NULLUTC) { + if ((lut = utclocalise(dominfo -> dsi_deferred)) != NULLUTC && + UTC2rfc (lut, tbuf) == OK && + (p = rcmd_srch (DSI_DEFERRED, p1tbl_domsinfo)) != NULLCP) { + (void) sprintf (cp, " %s %s", p, tbuf); + free ((char *) lut); + + cp += strlen(cp); + } + else return NOTOK; + } + + + /* -- action -- */ + if (action2rfc (dominfo -> dsi_action, tbuf) == OK && + (p = rcmd_srch (DSI_ACTION, p1tbl_domsinfo)) != NULLCP) + (void) sprintf (cp, " %s %s", p, tbuf); + else return NOTOK; + + /* -- converted -- */ + if (dominfo -> dsi_converted.eit_types) { + if (x400eits2rfc (&dominfo -> dsi_converted, tbuf) == NOTOK) + return NOTOK; + (void) sprintf (cp, " %s (%s)", + rcmd_srch (DSI_CONVERTED, p1tbl_domsinfo), + tbuf); + cp += strlen (cp); + } + + + /* -- attempted/previous -- */ + if (dominfo -> dsi_attempted_md.global_Country != NULLCP || + dominfo -> dsi_attempted_md.global_Admin != NULLCP || + dominfo -> dsi_attempted_md.global_Private != NULLCP) { + if (globalid2rfc (&dominfo -> dsi_attempted_md, tbuf) == NOTOK) + return NOTOK; + (void) sprintf (cp, " %s %s", + rcmd_srch (DSI_ATTEMPTED, p1tbl_domsinfo), + tbuf); + } + PP_DBG (("Lib/domsinfo2rfc returns (%s)", buffer)); + + return OK; +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static int action2rfc (action, buffer) /* DomainSuppliedInfo(action) -> RFC */ +int action; +char *buffer; +{ + PP_DBG (("Lib/action2rfc(%d)", action)); + + switch (action) { + case ACTION_RELAYED: + (void) strcpy (buffer, "Relayed"); + break; + case ACTION_ROUTED: + (void) strcpy (buffer, "Routed"); + break; + default: + *buffer = '\0'; + return NOTOK; + } + return OK; +} diff --git a/Lib/format/globalid2rfc.c b/Lib/format/globalid2rfc.c new file mode 100644 index 0000000..4c68e75 --- /dev/null +++ b/Lib/format/globalid2rfc.c @@ -0,0 +1,49 @@ +/* globalid2rfc.c - Converts a GlobalDomId struct into a RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/globalid2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/globalid2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: globalid2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +int globalid2rfc (gp, buffer) /* GlobalDomainIdentifier -> RFC */ +GlobalDomId *gp; +char *buffer; +{ + char *cp = buffer; + + if (gp -> global_Private) { + (void) sprintf (cp, "/PRMD=%s", gp -> global_Private); + cp += strlen(cp); + } + + if (gp -> global_Admin) { + (void) sprintf(cp,"/ADMD=%s", gp -> global_Admin); + cp += strlen(cp); + } + + if (gp -> global_Country) { + (void) sprintf(cp, "/C=%s",gp -> global_Country); + cp += strlen(cp); + } + if (cp != buffer) { + *cp++ = '/'; + *cp = NULL; + } + + PP_DBG (("Lib/globalid2rfc returns (%s)", buffer)); + + return OK; +} diff --git a/Lib/format/make b/Lib/format/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/format/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/format/msgid2rfc.c b/Lib/format/msgid2rfc.c new file mode 100644 index 0000000..3985cac --- /dev/null +++ b/Lib/format/msgid2rfc.c @@ -0,0 +1,57 @@ +/* msgid2rfc - Converts a MPDUid struct into a RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/msgid2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/msgid2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: msgid2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +extern int globalid2rfc (); +int msgid2rfc_aux(); + +/* --------------------- Begin Routines -------------------------------- */ + +int msgid2rfc (msgid, buffer) +MPDUid *msgid; +char *buffer; +{ + return msgid2rfc_aux (msgid, buffer, FALSE); +} + +int msgid2rfc_aux (msgid, buffer, angled) +MPDUid *msgid; +char *buffer; +int angled; +{ + char tbuf[LINESIZE]; + + if (globalid2rfc (&msgid -> mpduid_DomId, tbuf) == NOTOK) + return NOTOK; + + if (msgid -> mpduid_string) + (void) sprintf(buffer, "%c%s;%s%c", + (angled == TRUE) ? '<' : '[', + tbuf, msgid -> mpduid_string, + (angled == TRUE) ? '>' : ']'); + else + (void) sprintf(buffer, "%c%s%c", + (angled == TRUE) ? '<' : '[', + tbuf, + (angled == TRUE) ? '>' : ']'); + + PP_DBG (("Lib/msgid2rfc returns (%s)", buffer)); + + return OK; +} diff --git a/Lib/format/reprecip2rfc.c b/Lib/format/reprecip2rfc.c new file mode 100644 index 0000000..ebfd47c --- /dev/null +++ b/Lib/format/reprecip2rfc.c @@ -0,0 +1,163 @@ +/* reprecip2rfc.c - Converts a Rrseq struct into a RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/reprecip2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/reprecip2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: reprecip2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "dr.h" + + +extern CMD_TABLE + rr_rcode [/* reason-codes */], + rr_dcode [/* diagnostic-codes */]; + +extern UTC utclocalise(); +extern int x400eits2rfc(); +static int lastrace2rfc (); + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int reprecip2rfc (rp, ap, buffer) /* ReportedRecipientInfo -> RFC */ +Rrinfo *rp; +ADDR *ap; +char *buffer; +{ + int i; + char *cp; + + if (rp == NULL) + return OK; + + cp = buffer; + + if (rp -> rr_recip) { + (void) sprintf (cp, "%s; ", ap -> ad_r822adr); + cp += strlen(cp); + } + else { + *buffer = '\0'; + return OK; + } + + if (lastrace2rfc (rp, cp) == NOTOK) + return NOTOK; + + cp += strlen(cp); + + (void) sprintf (cp, "ext %d ", ap -> ad_extension); + cp += strlen(cp); + + i = mem2prf (ap -> ad_resp, ap -> ad_mtarreq, ap -> ad_usrreq); + (void) sprintf (cp, "flags %02d", i); + cp += strlen(cp); + + if (rp -> rr_originally_intended_recip && + rp -> rr_originally_intended_recip->fn_addr) { + (void) sprintf (cp, " intended %s", + rp -> rr_originally_intended_recip -> fn_addr); + cp += strlen(cp); + } + + if (rp -> rr_supplementary) { + (void) sprintf (cp, " info %s", rp->rr_supplementary); + cp += strlen(cp); + } + else if (rp -> rr_report.rep_type == DR_REP_FAILURE) { + (void) sprintf (cp, " info %s", + "Extra information on the failure was not supplied"); + cp += strlen(cp); + } + PP_DBG (("Lib/rri2rfc returns (%s)", buffer)); + + return OK; +} + +static int lastrace2rfc (rp, buffer) /* LastTraceInformation -> RFC */ +Rrinfo *rp; +char *buffer; +{ + Delinfo *dliv; + NonDelinfo *ndliv; + char tbuf [BUFSIZ]; + UTC lut; + char *cp = buffer; + + switch (rp -> rr_report.rep_type) { + case DR_REP_SUCCESS: + dliv = &rp -> rr_report.rep.rep_dinfo; + if (dliv->del_time == NULLUTC) { + PP_LOG(LLOG_EXCEPTIONS, + ("lastrace2rfc: missing deliv time")); + return NOTOK; + } + lut = utclocalise(dliv -> del_time); + if(UTC2rfc (lut, tbuf) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("lastrace2rfc: bad deliv time")); + return NOTOK; + } + free((char *) lut); + (void) sprintf (cp, "SUCCESS %s; %d; ", + tbuf, dliv -> del_type); + break; + case DR_REP_FAILURE: + ndliv = &rp -> rr_report.rep.rep_ndinfo; + (void) sprintf (cp, "FAILURE %d (%s); %d (%s); ", + ndliv -> nd_rcode, + rcmd_srch (ndliv -> nd_rcode, rr_rcode), + ndliv -> nd_dcode, + rcmd_srch (ndliv -> nd_dcode, rr_dcode)); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/lastrace2rfc/Unknown report type %d", + rp -> rr_report.rep_type)); + *buffer = '\0'; + return NOTOK; + } + cp += strlen(cp); + + + if (rp -> rr_arrival == NULLUTC) { + PP_LOG(LLOG_EXCEPTIONS, + ("lastrace2rfc: missing arrival time")); + return NOTOK; + } + lut = utclocalise (rp -> rr_arrival); + if(UTC2rfc (lut, tbuf) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("lastrace2rfc: bad arrival time")); + return NOTOK; + } + free ((char *) lut); + + (void) sprintf (cp, "%s;", tbuf); + cp += strlen(cp); + + if (rp -> rr_converted) { + tbuf[0] = NULL; + if (x400eits2rfc (rp -> rr_converted, + tbuf) == NOTOK) + return NOTOK; + if (tbuf[0]) + (void) sprintf (cp, " converted(%s);", tbuf); + } + PP_DBG (("Lib/lastrace2rfc returns (%s)", buffer)); + + return OK; +} diff --git a/Lib/format/rfc2UTC.c b/Lib/format/rfc2UTC.c new file mode 100644 index 0000000..72b7b59 --- /dev/null +++ b/Lib/format/rfc2UTC.c @@ -0,0 +1,261 @@ +/* rfc2UTC.c - Converts an RFC string into UTC structure */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2UTC.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2UTC.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2UTC.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" + + +extern CMD_TABLE tbl_month[]; + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* +This routine converts a RFC 822 standard time string like: + "Tue, 16 Aug 88 10:23:21 BST" +into a UTC structure. Where "Tue," is optional. +*/ + +static void getzone (); + +int rfc2UTC (str, utc) +char *str; +UTC *utc; +{ + UTC ut; + char *cp, *cp2; + char tbuf[LINESIZE]; + int n; + + + PP_DBG (("Lib/rfc2UTC (%s)", str)); + + ut = (UTC) smalloc (sizeof *ut); + bzero ((char *)ut, sizeof *ut); + *utc = NULL; + + cp = str; +#define skips(c) while (isspace (*c)) c++ +#define skipsp(c) while (isspace (*c) || ispunct(*c)) c++; + + skips (cp); + + if (isalpha (*cp)) { + while(isalpha (*cp)) + cp ++; + skipsp (cp); + } + + + /* month day */ + if (isdigit (*cp)) { + n = 0; + while (isdigit (*cp)) + n = n * 10 + (*cp++ - '0'); + ut -> ut_mday = n; + skips (cp); + } + else { + PP_LOG (LLOG_EXCEPTIONS, ("Bad month day '%s'", str)); + free((char *)ut); + return NOTOK; + } + + /* Month */ + if (isalpha (*cp)) { + for (cp2 = tbuf; isalpha(*cp); *cp2 ++ = *cp++) + continue; + *cp2 = NULL; + if (cp2 - tbuf > 3) + tbuf[3] = NULL; + ut -> ut_mon = cmd_srch (tbuf, tbl_month); + if (ut -> ut_mon == -1) { + free ((char *)ut); + return NOTOK; + } + ut -> ut_mon ++; + skips (cp); + } + else { + free((char*)ut); + return NOTOK; + } + + /* -- Year -- */ + if (isdigit (*cp)) { + n = 0; + while (isdigit (*cp)) + n = n * 10 + (*cp ++ - '0'); + if (n < 100) + ut -> ut_year = 1900 + n; + else + ut -> ut_year = n; + skips (cp); + } + else { + free ((char *)ut); + return NOTOK; + } + + if (isdigit (*cp)) { + n = 0; + while (isdigit(*cp)) + n = n * 10 + (*cp++ - '0'); + ut -> ut_hour = n; + skips (cp); + } + + /* -- Minute & Secs -- */ + if (*cp == ':') { + cp ++; + n = 0; + while (isdigit (*cp)) + n = n * 10 + (*cp++ - '0'); + ut -> ut_min = n; + skips (cp); + } + if (*cp == ':') { + cp ++; + n = 0; + while (isdigit (*cp)) + n = n * 10 + (*cp ++ - '0'); + ut -> ut_sec = n; + ut -> ut_flags |= UT_SEC; + skips (cp); + } + + getzone (cp, ut); + + *utc = ut; + PP_DBG (("Lib/rfc2UTC returns (%.22s)", utct2str (ut))); + + return OK; +} + + + +static CMD_TABLE zone_tbl[] = { /* some of the more popular zones... */ + "A", -100, + "AHST", -1000, /* Alaska-Hawaii Std Time */ + "AT", -200, /* Azores Time */ + "AST", -400, /* Atlantic Std Time */ + "B", -200, + "BST", 100, /* British Summer Time, also Brasil Std Time (-300) and Bering Strait Time (-1100) */ + "BT", -1100, /* Bering Time also Baghdad Time (+200) */ + "C", -300, + "CAT", -1000, /* Central Alaska Time */ + "CCT", 800, /* China Coast Time, USSR Zone 7 */ + "CDT", -500, + "CET", 100, /* Central European Time */ + "CST", -600, /* Central Std Time */ + "D", -400, + "E", -500, + "EDT", -400, + "EET", 200, /* Eastern European Time, USSR Zone 1 */ + "EST", -500, /* Eastern Std Time */ + "F", -600, + "G", -700, + "GMT", 0, + "GST", 1000, /* Guam Std Time, USSR Zone 9 */ + "H", -800, + "HST", -1030, /* Hawaiian Std Time */ + "I", -900, + "IDLE", 1200, /* International Date Line, East */ + "IDLW", -1200, /* International Date Line, West */ + "IST", 530, /* Indian Standard Time */ + "IT", 300, /* Iran Time */ + "JST", 900, /* Japan Std Time, USSR Zone 8 */ + "JT", 730, /* Java Time */ + "K", -1000, + "L", -1100, + "M", -1200, + "MDT", -600, + "MET", 100, /* Middle European Time */ + "MST", -700, /* Mountain Std Time */ + "MT", 830, /* Moluccas Time */ + "N", 100, + "NT", -1100, /* Nome Time */ + "NFT", -330, /* Newfoundland Time */ + "NST", 630, /* North Sumatra Time */ + "NZT", 1130, /* New Zealand Time */ + "O", 200, + "P", 300, + "PDT", -700, + "PST", -800, /* Paciific Std Time */ + "Q", 400, + "R", 500, + "S", 600, + "SAST", 930, /* South Australia Std Time */ + "SST", 700, /* South Sumatra Time */ + "T", 700, + "U", 800, + "UT", 0, + "V", 900, + "W", 1000, + "WAT", -100, /* West Africa Time */ + "WDT", 100, + "WET", 0, /* Western European Time */ + "X", 1100, + "Y", 1200, + "YST", -900, /* Yukon Std Time */ + "Z", 0, + 0, -99 +}; +#define N_ZONES ((sizeof(zone_tbl)/sizeof(CMD_TABLE)) - 1) + +static void getzone (bp, ut) +char *bp; +UTC ut; +{ + int hours, mins; + char *cp, zbuf[64]; + + while (isspace (*bp)) + bp ++; + + if (*bp == '+' || *bp == '-') { /* offset TZ */ + hours = (bp[1] - '0') * 10 + (bp[2] - '0'); + mins = (bp[3] - '0') * 10 + (bp[4] - '0'); + ut -> ut_zone = 60 * hours + mins; + if (*bp == '-') + ut -> ut_zone = - ut -> ut_zone; + + ut -> ut_flags |= UT_ZONE; + return; + } + if (isalpha(*bp)) { /* 'real' TZ (e.g. BST) */ + for (cp = zbuf; isalpha(*bp); ) + *cp++ = *bp ++; + *cp = 0; + if ((hours = cmdbsrch (zbuf, zone_tbl, N_ZONES)) != -99) { + ut -> ut_flags |= UT_ZONE; + ut -> ut_zone = ((hours/100) * 60); + /* add minutes */ + if (hours >= 0) + ut -> ut_zone += (hours%100); + else + ut -> ut_zone -= (hours%100); + return; + } + PP_LOG (LLOG_EXCEPTIONS, ("Unknown timezone syntax %s", zbuf)); + } + if (*bp != '\0') + PP_LOG (LLOG_EXCEPTIONS, ("Unknown timezone syntax %s", bp)); +} diff --git a/Lib/format/rfc2domsinfo.c b/Lib/format/rfc2domsinfo.c new file mode 100644 index 0000000..846cb31 --- /dev/null +++ b/Lib/format/rfc2domsinfo.c @@ -0,0 +1,162 @@ +/* rfc2domsinfo.c - Converts a RFC string to a DomSupInfo struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2domsinfo.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2domsinfo.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2domsinfo.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" +#include "tb_p1.h" + + +extern CMD_TABLE p1tbl_domsinfo[], + p1tbl_action[]; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rfc2domsinfo (dp, str) +DomSupInfo *dp; +char *str; +{ + char *cp = str, + *bp = str, + *ptr; + + PP_DBG (("Lib/rfc2domsinfo (%s)", str)); + + if ((cp = index (str, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + + + /* -- arrival -- */ + if (lexequ (bp, rcmd_srch (DSI_TIME, p1tbl_domsinfo)) == 0) { + bp = cp; + if ((cp = rindex (cp, ':')) == NULLCP) + return NOTOK; + if ((ptr = index (cp, '+')) == NULLCP) + ptr = index (cp, '-'); + if (ptr) + cp = ptr; + if ((cp = index (cp, ' ')) != NULLCP) + *cp++ = '\0'; + if (rfc2UTC (bp, &dp->dsi_time) == NOTOK) + return NOTOK; + } + else + return NOTOK; + + + /* -- optional stuff now follows -- */ + if ((bp = cp) == NULLCP) + return OK; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + + + + /* -- deferred -- */ + if (lexequ (bp, rcmd_srch (DSI_DEFERRED, p1tbl_domsinfo)) == 0) { + bp = cp; + if ((cp = rindex (cp, ':')) == NULLCP) + return NOTOK; + if ((ptr = index (cp, '+')) == NULLCP) + ptr = index (cp, '-'); + if (ptr) + cp = ptr; + if ((cp = index (bp, ' ')) != NULLCP) + *cp++ = '\0'; + if (rfc2UTC (bp, &dp->dsi_deferred) == NOTOK) + return NOTOK; + if ((bp = cp) == NULLCP) + return OK; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + } + + + + /* -- action -- */ + if (lexequ (bp, rcmd_srch (DSI_ACTION, p1tbl_domsinfo)) == 0) { + bp = cp; + + if ((cp = index (bp, ' ')) != NULLCP) + *cp++ = '\0'; + + switch (cmd_srch (bp, p1tbl_action)) { + case ACTION_RELAYED: + dp->dsi_action = ACTION_RELAYED; + break; + default: + dp->dsi_action = ACTION_ROUTED; + break; + } + + if ((bp = cp) == NULLCP) + return OK; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + } + + + + /* -- converted -- */ + if (lexequ (bp, rcmd_srch (DSI_CONVERTED, p1tbl_domsinfo)) == 0) { + if ((cp = index (cp, '(')) == NULLCP) + return NOTOK; + else + bp = ++cp; + + if ((cp = index (bp, ')')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + + if (rfc2encinfo (&dp->dsi_converted, bp) == NOTOK) + return NOTOK; + + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return OK; + else + *cp++ = '\0'; + } + + + + /* -- attempted -- */ + if (lexequ (bp, rcmd_srch (DSI_ATTEMPTED, p1tbl_domsinfo)) == 0) { + bp = cp; + if (rfc2globalid (&dp->dsi_attempted_md, bp) == NOTOK) + return NOTOK; + } + + + return OK; + +} diff --git a/Lib/format/rfc2encinfo.c b/Lib/format/rfc2encinfo.c new file mode 100644 index 0000000..a5b13b9 --- /dev/null +++ b/Lib/format/rfc2encinfo.c @@ -0,0 +1,52 @@ +/* rfc2encinfo.c - Converts a RFC string into a EncodedIT struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2encinfo.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2encinfo.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2encinfo.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include "list_bpt.h" + + + +/* --------------------- Begin Routines -------------------------------- */ + +int rfc2encinfo (ep, str) +EncodedIT *ep; +char *str; +{ + LIST_BPT *base = NULLIST_BPT, + *new; + char *cp = str, + *bp = str; + + + PP_DBG (("Lib/rfc2listbpt (%s)", str)); + + /* -- read string which delimitted by ',' and an optional ' ' -- */ + while (cp != NULLCP) { + if (cp = index (bp, ',')) { + *cp++ = '\0'; + if (*cp == ' ') cp++; + } + new = list_bpt_new (bp); + list_bpt_add (&base, new); + bp = cp; + } + + ep -> eit_types = base; + + return OK; +} diff --git a/Lib/format/rfc2globalid.c b/Lib/format/rfc2globalid.c new file mode 100644 index 0000000..e96ee2f --- /dev/null +++ b/Lib/format/rfc2globalid.c @@ -0,0 +1,120 @@ +/* rfc2globalid.c - Converts a RFC string into a GlobalDomId struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2globalid.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2globalid.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2globalid.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + +#define PRMD "/PRMD=" +#define ADMD "/ADMD=" +#define COUNTRY "/C=" + +int rfc2x400globalid (gp, str) +GlobalDomId *gp; +char *str; +{ + char *start, *end; + int len; + + len = strlen(PRMD); + if (lexnequ (str, PRMD, len) == 0) { + start = str + len; + if ((end = index(start, '/')) == NULLCP) + return NOTOK; + *end = '\0'; + gp -> global_Private = strdup(start); + *end = '/'; + str = end; + } + len = strlen (ADMD); + if (lexnequ (str, ADMD, len) == 0) { + start = str + len; + if ((end = index(start, '/')) == NULLCP) { + if (gp -> global_Private != NULLCP) { + free (gp -> global_Private); + gp -> global_Private = NULLCP; + } + return NOTOK; + } + *end = '\0'; + gp -> global_Admin = strdup(start); + *end = '/'; + str = end; + } + len = strlen(COUNTRY); + if (lexnequ (str, COUNTRY, strlen(COUNTRY)) == 0) { + start = str + len; + if ((end = index(start, '/')) == NULLCP) { + if (gp -> global_Private != NULLCP) { + free (gp -> global_Private); + gp -> global_Private = NULLCP; + } + if (gp -> global_Admin != NULLCP) { + free (gp -> global_Admin); + gp -> global_Admin = NULLCP; + } + return NOTOK; + } + *end = '\0'; + gp -> global_Country = strdup(start); + *end = '/'; + str = end; + } + return OK; +} + + +int rfc2globalid (gp, str) +GlobalDomId *gp; +char *str; +{ + + char *cp = str, + *bp = str; + + PP_DBG (("Lib/rfc2globalid (%s)", str)); + + + if (*cp == '*') + return NOTOK; + + /* -- Country -- */ + cp = index (bp, '*'); + if (cp == NULLCP) + return NOTOK; + *cp++ = '\0'; + gp->global_Country = strdup (bp); + bp = cp; + + /* -- Admin -- */ + cp = index (bp, '*'); + if (cp != NULLCP) + *cp++ = '\0'; + gp->global_Admin = strdup (bp); + bp = cp; + + /* -- Prmd -- */ + if (cp == NULLCP) + return OK; + gp->global_Private = strdup (bp); + + return OK; +} diff --git a/Lib/format/rfc2msgid.c b/Lib/format/rfc2msgid.c new file mode 100644 index 0000000..b2de2df --- /dev/null +++ b/Lib/format/rfc2msgid.c @@ -0,0 +1,70 @@ +/* rfc2msgid - Converts a RFC string into a MPDUid struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2msgid.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2msgid.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2msgid.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include "x400_ub.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rfc2msgid (mp, str) +register MPDUid *mp; +char *str; +{ + char *cp, *start, *end, *temp; + + PP_DBG (("Lib/rfc2msgid (%s)", str)); + + temp = strdup(str); + start = temp; + if (*start == '[') { + start++; + end = str+strlen(str); + if (*end == ']') + *end = '\0'; + } + + /* try parsing as dom;string */ + cp = rindex (start, ';'); + if (cp != NULLCP) { + *cp++ = '\0'; + if (rfc2globalid (&mp->mpduid_DomId, start) == OK) { + mp->mpduid_string = strdup (cp); + free(temp); + return OK; + } + } + free(temp); + GlobalDomId_free(&mp->mpduid_DomId); + /* put in loc dom and string */ + if ((int) strlen(str) > UB_LOCAL_ID_LENGTH) { + char tbuf[UB_LOCAL_ID_LENGTH + 1]; + (void) strncap (tbuf, str, UB_LOCAL_ID_LENGTH); + tbuf[UB_LOCAL_ID_LENGTH] = 0; + mp->mpduid_string = strdup (tbuf); + } + else + mp->mpduid_string = strdup (str); + GlobalDomId_new (&mp->mpduid_DomId); + return OK; +} diff --git a/Lib/format/rfc2reprecip.c b/Lib/format/rfc2reprecip.c new file mode 100644 index 0000000..4d2f11b --- /dev/null +++ b/Lib/format/rfc2reprecip.c @@ -0,0 +1,316 @@ +/* rfc2reprecip.c - Converts a RFC string into a Rrseq struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2reprecip.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2reprecip.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2reprecip.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "dr.h" + + + +extern CMD_TABLE drtbl_rep[]; + + +extern void encodedinfo_free (); + +static char *rfc2lastrace(), + *rfc2report(); + +#define txt2int(n) atoi(n) + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rfc2reprecip (rp, ap, str) +Rrinfo *rp; +ADDR *ap; +char *str; +{ + char *cp = str, + *bp = str; + + + PP_DBG (("Lib/pp/rfc2reprecip(%s)", str)); + + + /* -- OR address -- */ + if ((cp = index (str, ';')) == NULLCP) + return NOTOK; + else { + *cp++ = '\0'; + rp -> rr_recip = ap -> ad_no; + } + + + /* -- last-trace -- */ + if (*cp == ' ') + cp++; + bp = cp; + cp = rfc2lastrace (rp, bp); + if (cp == NULLCP) + return NOTOK; + if (*++cp != ';') + return NOTOK; + else + cp++; + + + /* -- ext -- */ + if (*cp == ' ') + cp++; + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else { + *cp++ = '\0'; + if (lexequ (bp, "ext") != 0) + return NOTOK; + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else { + *cp++ = '\0'; + rp->rr_recip = txt2int (bp); + } + } + + + /* -- flags -- */ + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else { + *cp++ = '\0'; + if (lexequ (bp, "flags") != 0) + return NOTOK; + bp = cp; + if ((cp = index (bp, ' ')) != NULLCP) + *cp++ = '\0'; + } + + + /* -- the rest is optional -- */ + if (cp == NULLCP) + return OK; + + + /* -- intended -- */ + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + + if (lexequ (bp, "intended") == 0) { + bp = cp; + if ((cp = index (bp, ' ')) != NULLCP) + *cp++ = '\0'; + if (rp -> rr_originally_intended_recip == NULL) { + rp -> rr_originally_intended_recip = + (FullName *) smalloc (sizeof (FullName)); + bzero ((char *)rp -> rr_originally_intended_recip, + sizeof (FullName)); + } + rp->rr_originally_intended_recip -> fn_addr = strdup (bp); + if (cp == NULLCP) + return OK; + bp = cp; + if ((cp = index (bp, ' ')) == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + } + + + /* -- info -- */ + if (lexequ (bp, "info") == 0) { + bp = cp; + rp->rr_supplementary = strdup (bp); + } + else + return NOTOK; + + + return OK; +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static char *rfc2lastrace (rp, str) +Rrinfo *rp; +char *str; +{ + EncodedIT *new; + char *cp = str, + *bp = str; + + + PP_DBG (("Lib/rfc2lastrace (%s)", str)); + + + /* -- drc-report -- */ + cp = rfc2report (&rp -> rr_report, str); + if (cp == NULLCP) + return NULLCP; + if (*++cp != ';') + return NULLCP; + else + cp++; + + + + /* -- date-time -- */ + if (*cp == ' ') + cp++; + bp = cp; + if ((cp = index (bp, ';')) == NULLCP) + return NULLCP; + else { + *cp++ = '\0'; + if (rfc2UTC (bp, &rp->rr_arrival) == NOTOK) + rp -> rr_arrival = utcnow (); + } + + + /* -- converted (optional) -- */ + bp = cp; + if (*bp == ' ') + bp++; + + if ((cp = index (bp, '(')) == NULLCP) + return --bp; + else { + *cp = '\0'; + if (lexequ (bp, "converted") != 0) { + *cp = '('; + return --bp; + } + else + bp = ++cp; + } + if ((cp = index (bp, ')')) == NULLCP) + return NULLCP; + else + *cp = '\0'; + + /* -- create a new Encoded struct -- */ + new = (EncodedIT *) smalloc (sizeof (*new)); + bzero ((char*)new, sizeof (*new)); + if (rfc2encinfo (new, bp) == NOTOK) { + encodedinfo_free (new); + return NULLCP; + } + else + rp->rr_converted = new; + + return cp; +} + + + + +static char *rfc2report (rp, str) +Report *rp; +char *str; +{ + char *cp = str, + *bp = str; + + int retval; + + + PP_DBG (("Lib/rfc2report (%s)", str)); + + + if ((cp = index (str, ' ')) == NULLCP) + return NULLCP; + else + *cp++ = '\0'; + + switch (rp->rep_type = cmd_srch (bp, drtbl_rep)) { + case DR_REP_SUCCESS: + bp = cp; + if ((cp = index (bp, ';')) == NULLCP) + return NULLCP; + else { + *cp++ = '\0'; + retval = rfc2UTC (bp, &rp->rep.rep_dinfo.del_time); + if (retval == NOTOK) + return NULLCP; + if (*cp == ' ') + cp++; + bp = cp; + if ((cp = index (bp, ';')) == NULLCP) + return NULLCP; + else { + *cp = '\0'; + rp->rep.rep_dinfo.del_type = txt2int (bp); + *cp = ';'; + --cp; + } + } + break; + + + case DR_REP_FAILURE: + /* -- reason code -- */ + bp = cp; + if ((cp = index (bp, '(')) == NULLCP) + return NULLCP; + else { + *cp++ = '\0'; + rp->rep.rep_ndinfo.nd_rcode = atoi (bp); + } + + /* -- diagnostic code -- */ + bp = cp; + if ((cp = index (bp, ';')) == NULLCP) + return NULLCP; + else { + bp = ++cp; + + /* -- no diagnostic given -- */ + if ((cp = index (bp, '(')) == NULLCP) + return --bp; + else + *cp++ = '\0'; + + bp = cp; + + rp->rep.rep_ndinfo.nd_dcode = atoi (bp); + + if ((cp = index (bp, ';')) == NULLCP) + return NULLCP; + } + break; + default: + return NULLCP; + } + + + PP_DBG (("Lib/rfc2report returns ... (%s)", cp)); + + return cp; +} diff --git a/Lib/format/rfc2trace.c b/Lib/format/rfc2trace.c new file mode 100644 index 0000000..b48f91c --- /dev/null +++ b/Lib/format/rfc2trace.c @@ -0,0 +1,56 @@ +/* rfc2trace.c - Converts a RFC string into a Trace struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2trace.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2trace.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2trace.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rfc2trace (tp, str) +Trace *tp; +char *str; +{ + char *cp = str, + *bp = str; + + + PP_DBG (("Lib/rfc2trace (%s)", str)); + + cp = index (str, ';'); + + if (cp == NULLCP) + return NOTOK; + else + *cp++ = '\0'; + + if (*cp == ' ') + cp++; + + if (rfc2globalid (&tp->trace_DomId, bp) == NOTOK) + return NOTOK; + + if (rfc2domsinfo (&tp->trace_DomSinfo, cp) == NOTOK) + return NOTOK; + + return OK; +} diff --git a/Lib/format/rfc2x400trc.c b/Lib/format/rfc2x400trc.c new file mode 100644 index 0000000..ef4a4a1 --- /dev/null +++ b/Lib/format/rfc2x400trc.c @@ -0,0 +1,202 @@ +/* rfc2x400trace.c: converts an RFC string to an x400 trace via rfc 1138 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2x400trc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfc2x400trc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfc2x400trc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +extern char *compress(); +static int do_md_mta(), + do_deferred(), + do_converted(), + do_attempt_md_mta(), + do_arrival(), + do_actions(); + +#define MATCH(a,b) (lexnequ((a),(b),strlen(b)) == 0) + + +int rfc2x400trace (trace, str) +Trace *trace; +char *str; +{ + /* see sect 5.3.7 in 1148 */ + + char *start, *end, *tmp = strdup(str); + int result = OK; + PP_DBG (("Lib/rfc2x400trace (%s)", str)); + + start = tmp; + + while (result == OK && start != NULLCP && *start != '\0') { + if ((end = index (start, ';')) != NULLCP) + *end++ = '\0'; + (void) compress (start, start); + if (MATCH(start, "by")) + /* md and mta bit */ + result = do_md_mta(trace, start); + else if (MATCH(start, "deferred until")) + /* deffered delivery time */ + result = do_deferred (trace, start); + else if (MATCH(start, "converted")) + /* converted eits */ + result = do_converted(trace, start); + else if (MATCH(start, "attempted")) + /* attempted md and mta */ + result = do_attempt_md_mta(trace, start); + else if (end == NULLCP) + /* arrival-time */ + result = do_arrival(trace, start); + else + /* action-list */ + result = do_actions (trace, start); + start = end; + } + free(tmp); + if (trace->trace_DomSinfo.dsi_time == NULL) + trace->trace_DomSinfo.dsi_time = utcnow (); + return result; +} + +static int do_md_mta (trace, start) +Trace *trace; +char *start; +{ + char *end; + PP_DBG (("Lib/rfc2x400trace/do_md_mta (%s)", start)); + start += strlen("by"); + + while (isspace(*start)) start++; + + if (MATCH (start, "mta ")) { + start += strlen("mta "); + while (isspace(*start)) start++; + end = start; + while (*end != ' ') end++; + *end = '\0'; + trace -> trace_mta = strdup(start); + start = end+1; + while (isspace(*start)) start++; + if (!MATCH (start, "in ")) + return NOTOK; + start += strlen("in "); + while (isspace(*start)) start++; + } + + return rfc2x400globalid (&trace -> trace_DomId, start); +} + +static int do_deferred (trace, start) +Trace *trace; +char *start; +{ + PP_DBG (("Lib/rfc2x400trace/do_deferred (%s)", start)); + start += strlen("deferred until"); + while (isspace(*start)) start++; + + return rfc2UTC (start, &trace->trace_DomSinfo.dsi_deferred); +} + +static int do_converted (trace, start) +Trace *trace; +char *start; +{ + char *end; + PP_DBG (("Lib/rfc2x400trace/do_converted (%s)", start)); + if ((start = index(start, '(')) == NULLCP) + return NOTOK; + + start++; + if ((end = index(start, ')')) == NULLCP) + return NOTOK; + *end = '\0'; + + return rfc2encinfo (&trace -> trace_DomSinfo.dsi_converted, start); +} + +static int do_attempt_md_mta(trace, start) +Trace *trace; +char *start; +{ + char *end; + + PP_DBG (("Lib/rfc2x400trace/do_attempt_md_mta (%s)", start)); + + start += strlen("attempted"); + + while (isspace(*start)) start++; + + if (MATCH (start, "mta ")) { + start += strlen("mta "); + while (isspace(*start)) start++; + end = start; + while (*end != ' ') end++; + *end = '\0'; + trace -> trace_DomSinfo.dsi_attempted_mta = strdup(start); + start = end+1; + while (isspace(*start)) start++; + if (!MATCH(start, "in ")) + return NOTOK; + start += strlen("in "); + while (isspace(*start)) start++; + } + + return rfc2x400globalid (&trace -> trace_DomSinfo.dsi_attempted_md, + start); +} + +static int do_actions (trace, start) +Trace *trace; +char *start; +{ + + PP_DBG (("Lib/rfc2x400trace/do_actions (%s)", start)); + + while (start != NULLCP && *start != '\0') { + while (isspace(*start)) start++; + if (MATCH(start, "relayed")) { + trace -> trace_DomSinfo.dsi_action = ACTION_RELAYED; + start += strlen("relayed"); + } else if (MATCH(start, "rerouted")) { + trace -> trace_DomSinfo.dsi_action = ACTION_ROUTED; + start += strlen("rerouted"); + } else if (MATCH(start, "redirected")) { + trace -> trace_DomSinfo.dsi_other_actions + = trace -> trace_DomSinfo.dsi_other_actions + | ACTION_REDIRECTED; + start += strlen("redirected"); + } else if (MATCH (start, "expanded")) { + trace -> trace_DomSinfo.dsi_other_actions + = trace -> trace_DomSinfo.dsi_other_actions + | ACTION_EXPANDED; + start += strlen("expanded"); + } else { + PP_TRACE(("Unknown action in x400 trace '%s'", start)); + return NOTOK; + } + while (isspace(*start)) start++; + } + return OK; +} + +static int do_arrival (trace, start) +Trace *trace; +char *start; +{ + PP_DBG (("Lib/rfc2x400trace/do_arrival (%s)", start)); + + return rfc2UTC (start, &trace->trace_DomSinfo.dsi_time); +} diff --git a/Lib/format/rfctxtfold.c b/Lib/format/rfctxtfold.c new file mode 100644 index 0000000..c4042f9 --- /dev/null +++ b/Lib/format/rfctxtfold.c @@ -0,0 +1,92 @@ +/* rfctxtfold.c - does simple folding for a string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/rfctxtfold.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/rfctxtfold.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: rfctxtfold.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + + +/* ------------- Begin Routines ---------------------------------------- */ + + + + +void rfctxtfold (input, output, linelen) +char *input; +char *output; +int linelen; +{ + int n = 0, + nsav = 0; + char *insav = NULLCP, + *outsav = NULLCP; + + + *output = NULL; + if (input == NULLCP) return; + + while (*input) { + switch (*input) { + + case '\t': + n += 7; + + case ' ': + if (n == linelen && *(input+1)) { + /* -- max len reached & more to come -- */ + input++; + *output ++ = '\n'; + *output ++ = '\t'; + n = 8; + break; + } + else if (n > linelen && *(input+1)) { + /* -- max len exceeded & more to come -- */ + if (nsav && insav) { + /* --- *** --- + if values have been previously saved + then go back to the previous spaces + --- *** --- */ + n = 8; + input = ++insav; + *outsav ++ = '\n'; + *outsav ++ = '\t'; + output = outsav; + nsav = 0; + insav = outsav = NULLCP; + } + else + goto rfctxtfold_save; + } + else { +rfctxtfold_save:; + /* -- save info and then fall -- */ + nsav = n; + insav = input; + outsav = output; + } + + default: + *output ++ = *input ++; + n ++; + break; + } + } + + if (n > 0 && *(output - 1) != '\n') + *output ++ = '\n'; + *output = NULL; +} diff --git a/Lib/format/trace2rfc.c b/Lib/format/trace2rfc.c new file mode 100644 index 0000000..f885f91 --- /dev/null +++ b/Lib/format/trace2rfc.c @@ -0,0 +1,47 @@ +/* trace2rfc.c - Converts a Trace struct into a RFC string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/trace2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/trace2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: trace2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +extern int globalid2rfc (); +extern int domsinfo2rfc (); + +/* --------------------- Begin Routines -------------------------------- */ + + +int trace2rfc (trace, buffer) /* TraceInformation -> RFC */ +Trace *trace; +char *buffer; +{ + char *cp; + Trace *tp = trace; + + if (tp == (Trace *) NULL) + return DONE; + + if (globalid2rfc (&tp -> trace_DomId, buffer) == NOTOK) + return NOTOK; + cp = buffer + strlen(buffer); + + if (domsinfo2rfc (&tp -> trace_DomSinfo, cp) == NOTOK) + return NOTOK; + + PP_DBG (("Lib/trace2rfc returns (%s)", buffer)); + + return OK; +} diff --git a/Lib/format/x400trc2rfc.c b/Lib/format/x400trc2rfc.c new file mode 100644 index 0000000..7c91aca --- /dev/null +++ b/Lib/format/x400trc2rfc.c @@ -0,0 +1,227 @@ +/* x400trace2rfc: converts an x400 Trace struct into an RFC string as by RFC 1138 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/format/RCS/x400trc2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/format/RCS/x400trc2rfc.c,v 6.0 1991/12/18 20:22:06 jpo Rel $ + * + * $Log: x400trc2rfc.c,v $ + * Revision 6.0 1991/12/18 20:22:06 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include +#include "tb_bpt88.h" + +extern CMD_TABLE bptbl_body_parts88 [/* body part types */]; +extern int globalid2rfc(); +extern UTC utclocalise(); +extern char *oid2lstr (); + +static int bodypart2value (bodypart) +char *bodypart; +{ + int ret; + + if (bodypart == NULLCP) + return NOTOK; + + switch (ret = cmd_srch (bodypart, bptbl_body_parts88)) { + case BPT_UNDEFINED: + case BPT_TLX: + case BPT_IA5: + case BPT_G3FAX: + case BPT_TIF0: + case BPT_TTX: + case BPT_VIDEOTEX: + case BPT_VOICE: + case BPT_SFD: + case BPT_TIF1: + return ret; + default: + if (strncmp (bodypart, "oid.", 4) == 0) + return BPT_EXTERNAL; + break; + } + return NOTOK; +} + +int x400eits2rfc (eits, buffer) +EncodedIT *eits; +char *buffer; +{ + LIST_BPT *ep; + + buffer[0] = '\0'; + + for (ep = eits -> eit_types; ep; ep = ep -> li_next) { + switch (bodypart2value (ep -> li_name)) { + case BPT_UNDEFINED: + if (lexequ(ep -> li_name, + rcmd_srch(BPT_UNDEFINED, + bptbl_body_parts88)) == 0) { + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "undefined (0)"); + } + break; + case BPT_TLX: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "telex (1)"); + break; + + case BPT_IA5: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "ia5 text (2)"); + break; + + case BPT_G3FAX: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "g3 facsimile (3)"); + break; + + case BPT_TIF0: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "g4 class 1 (4)"); + break; + + case BPT_TTX: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "teletex (5)"); + break; + + case BPT_VIDEOTEX: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "videotex (6)"); + break; + + case BPT_VOICE: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "voice (7)"); + break; + + case BPT_SFD: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "sfd (8)"); + break; + case BPT_TIF1: + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, "mixed mode (9)"); + break; + + case BPT_EXTERNAL: + /* oid */ + if ('\0' != buffer[0]) + (void) strcat (buffer, ","); + (void) strcat(buffer, + oid2lstr(str2oid + ((ep -> li_name + strlen("oid."))))); + break; + + default: + /* -- unregonised -- */ + break; + } + } + return OK; +} + +int x400trace2rfc (trace, buffer) +Trace *trace; +char *buffer; +{ + char tbuf[LINESIZE], *cp; + UTC lut; + + if (trace == (Trace *) NULL) + return DONE; + + (void) sprintf(cp = buffer, "by "); + cp += strlen (cp); + + if (trace->trace_mta != NULL) { + ap_val2str(tbuf, trace->trace_mta, AP_DOMAIN); + (void) sprintf(cp, "mta %s in ", tbuf); + cp += strlen(cp); + } + if (globalid2rfc(&trace -> trace_DomId, cp) == NOTOK) + return NOTOK; + cp += strlen(cp); + + (void) sprintf(cp, ";"); + cp += strlen(cp); + + if (trace->trace_DomSinfo.dsi_deferred != NULLUTC) { + if ((lut = utclocalise(trace->trace_DomSinfo.dsi_deferred)) != NULLUTC + && UTC2rfc (lut, tbuf) == OK) { + (void) sprintf (cp, " deferred until %s;", tbuf); + free ((char *) lut); + cp += strlen(cp); + } + else return NOTOK; + } + + if (trace->trace_DomSinfo.dsi_converted.eit_types != NULL) { + if (x400eits2rfc(&trace->trace_DomSinfo.dsi_converted, + tbuf) == NOTOK) + return NOTOK; + if ('\0' != tbuf[0]) + (void) sprintf(cp, " converted (%s);", tbuf); + cp += strlen(cp); + } + + if (trace->trace_DomSinfo.dsi_attempted_md.global_Country != NULLCP) { + (void) sprintf(cp, " attempted "); + cp += strlen(cp); + if (trace->trace_DomSinfo.dsi_attempted_mta != NULLCP) { + ap_val2str(trace->trace_DomSinfo.dsi_attempted_mta, + tbuf, AP_DOMAIN); + (void) sprintf(cp, " mta %s in ", tbuf); + cp += strlen(cp); + } + if (globalid2rfc(&(trace->trace_DomSinfo.dsi_attempted_md), + cp) == NOTOK) + return NOTOK; + cp += strlen(cp); + + (void) sprintf(cp, ";"); + cp += strlen(cp); + } + if (trace->trace_DomSinfo.dsi_action == ACTION_RELAYED) + (void) sprintf(cp, " Relayed"); + + else if (trace->trace_DomSinfo.dsi_action == ACTION_ROUTED) + (void) sprintf(cp, " Rerouted"); + + cp += strlen(cp); + + if (trace->trace_DomSinfo.dsi_other_actions & ACTION_REDIRECTED) + (void) sprintf(cp, " Redirected"); + if (trace->trace_DomSinfo.dsi_other_actions & ACTION_EXPANDED) + (void) sprintf(cp, " Expanded"); + cp += strlen(cp); + + lut = utclocalise(trace->trace_DomSinfo.dsi_time); + if (UTC2rfc(lut, tbuf) == OK) + (void) sprintf(cp, "; %s", tbuf); + if (lut) free((char *) lut); + + PP_DBG (("Lib/x400trace2rfc returns (%s)", buffer)); + return OK; +} diff --git a/Lib/io/Makefile b/Lib/io/Makefile new file mode 100644 index 0000000..a124c2d --- /dev/null +++ b/Lib/io/Makefile @@ -0,0 +1,365 @@ +# Input/Output primitives for PP +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/io/RCS/Makefile,v 6.0 1991/12/18 20:22:26 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:22:26 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = io_lib.c rd_adr.c rd_buf.c rd_dr.c rd_msg.c rd_prm.c rd_q.c wr_adr.c \ + wr_dr.c wr_prm.c wr_q.c wr_q2drfile.c +OBJS = io_lib.o rd_adr.o rd_buf.o rd_dr.o rd_msg.o rd_prm.o rd_q.o wr_adr.o \ + wr_dr.o wr_prm.o wr_q.o wr_q2drfile.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = io-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SHADOW) + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lintlib:llib-lio.ln +llib-lio.ln: $(SRCS) + $(LINT) $(LLFLAGS) -Cio $(SRCS) + +clean: tidy + rm -f $(OBJS) llib-lio.ln +tidy: + rm -f core $(SHADOW) *.old *.BAK + +install: + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +io_lib.o: io_lib.c +io_lib.o: ../../h/head.h +io_lib.o: ../../h/util.h +io_lib.o: ../../h/config.h +io_lib.o: ../../h/ll_log.h +io_lib.o: ../../h/retcode.h +io_lib.o: ../../h/q.h +io_lib.o: ../../h/adr.h +io_lib.o: ../../h/list_rchan.h +io_lib.o: ../../h/chan.h +io_lib.o: ../../h/table.h +io_lib.o: ../../h/list_bpt.h +io_lib.o: ../../h/auth.h +io_lib.o: ../../h/list_bpt.h +io_lib.o: ../../h/extension.h +io_lib.o: ../../h/mta.h +io_lib.o: ../../h/adr.h +io_lib.o: ../../h/list_bpt.h +io_lib.o: ../../h/aparse.h +io_lib.o: ../../h/ap.h +io_lib.o: ../../h/util.h +io_lib.o: ../../h/or.h +io_lib.o: ../../h/chan.h +io_lib.o: ../../h/auth.h +io_lib.o: ../../h/list_rchan.h +io_lib.o: ../../h/mta.h +io_lib.o: ../../h/adr.h +io_lib.o: ../../h/prm.h +io_lib.o: ../../h/dr.h +io_lib.o: ../../h/extension.h +io_lib.o: ../../h/mta.h +rd_adr.o: rd_adr.c +rd_adr.o: ../../h/head.h +rd_adr.o: ../../h/util.h +rd_adr.o: ../../h/config.h +rd_adr.o: ../../h/ll_log.h +rd_adr.o: ../../h/retcode.h +rd_adr.o: ../../h/adr.h +rd_adr.o: ../../h/list_rchan.h +rd_adr.o: ../../h/chan.h +rd_adr.o: ../../h/table.h +rd_adr.o: ../../h/list_bpt.h +rd_adr.o: ../../h/auth.h +rd_adr.o: ../../h/list_bpt.h +rd_adr.o: ../../h/extension.h +rd_adr.o: ../../h/mta.h +rd_adr.o: ../../h/adr.h +rd_adr.o: ../../h/list_bpt.h +rd_adr.o: ../../h/aparse.h +rd_adr.o: ../../h/ap.h +rd_adr.o: ../../h/util.h +rd_adr.o: ../../h/or.h +rd_adr.o: ../../h/chan.h +rd_adr.o: ../../h/auth.h +rd_adr.o: ../../h/list_rchan.h +rd_adr.o: ../../h/sys.file.h +rd_adr.o: ../../h/util.h +rd_buf.o: rd_buf.c +rd_buf.o: ../../h/head.h +rd_buf.o: ../../h/util.h +rd_buf.o: ../../h/config.h +rd_buf.o: ../../h/ll_log.h +rd_buf.o: ../../h/retcode.h +rd_dr.o: rd_dr.c +rd_dr.o: ../../h/head.h +rd_dr.o: ../../h/util.h +rd_dr.o: ../../h/config.h +rd_dr.o: ../../h/ll_log.h +rd_dr.o: ../../h/retcode.h +rd_dr.o: ../../h/dr.h +rd_dr.o: ../../h/extension.h +rd_dr.o: ../../h/mta.h +rd_dr.o: ../../h/adr.h +rd_dr.o: ../../h/list_rchan.h +rd_dr.o: ../../h/chan.h +rd_dr.o: ../../h/table.h +rd_dr.o: ../../h/list_bpt.h +rd_dr.o: ../../h/auth.h +rd_dr.o: ../../h/list_bpt.h +rd_dr.o: ../../h/extension.h +rd_dr.o: ../../h/mta.h +rd_dr.o: ../../h/aparse.h +rd_dr.o: ../../h/ap.h +rd_dr.o: ../../h/util.h +rd_dr.o: ../../h/or.h +rd_dr.o: ../../h/chan.h +rd_dr.o: ../../h/auth.h +rd_dr.o: ../../h/list_rchan.h +rd_dr.o: ../../h/list_bpt.h +rd_msg.o: rd_msg.c +rd_msg.o: ../../h/head.h +rd_msg.o: ../../h/util.h +rd_msg.o: ../../h/config.h +rd_msg.o: ../../h/ll_log.h +rd_msg.o: ../../h/retcode.h +rd_msg.o: ../../h/q.h +rd_msg.o: ../../h/adr.h +rd_msg.o: ../../h/list_rchan.h +rd_msg.o: ../../h/chan.h +rd_msg.o: ../../h/table.h +rd_msg.o: ../../h/list_bpt.h +rd_msg.o: ../../h/auth.h +rd_msg.o: ../../h/list_bpt.h +rd_msg.o: ../../h/extension.h +rd_msg.o: ../../h/mta.h +rd_msg.o: ../../h/adr.h +rd_msg.o: ../../h/list_bpt.h +rd_msg.o: ../../h/aparse.h +rd_msg.o: ../../h/ap.h +rd_msg.o: ../../h/util.h +rd_msg.o: ../../h/or.h +rd_msg.o: ../../h/chan.h +rd_msg.o: ../../h/auth.h +rd_msg.o: ../../h/list_rchan.h +rd_msg.o: ../../h/mta.h +rd_msg.o: ../../h/prm.h +rd_prm.o: rd_prm.c +rd_prm.o: ../../h/head.h +rd_prm.o: ../../h/util.h +rd_prm.o: ../../h/config.h +rd_prm.o: ../../h/ll_log.h +rd_prm.o: ../../h/retcode.h +rd_prm.o: ../../h/prm.h +rd_prm.o: ../../h/tb_prm.h +rd_q.o: rd_q.c +rd_q.o: ../../h/head.h +rd_q.o: ../../h/util.h +rd_q.o: ../../h/config.h +rd_q.o: ../../h/ll_log.h +rd_q.o: ../../h/retcode.h +rd_q.o: ../../h/q.h +rd_q.o: ../../h/adr.h +rd_q.o: ../../h/list_rchan.h +rd_q.o: ../../h/chan.h +rd_q.o: ../../h/table.h +rd_q.o: ../../h/list_bpt.h +rd_q.o: ../../h/auth.h +rd_q.o: ../../h/list_bpt.h +rd_q.o: ../../h/extension.h +rd_q.o: ../../h/mta.h +rd_q.o: ../../h/adr.h +rd_q.o: ../../h/list_bpt.h +rd_q.o: ../../h/aparse.h +rd_q.o: ../../h/ap.h +rd_q.o: ../../h/util.h +rd_q.o: ../../h/or.h +rd_q.o: ../../h/chan.h +rd_q.o: ../../h/auth.h +rd_q.o: ../../h/list_rchan.h +rd_q.o: ../../h/mta.h +rd_q.o: ../../h/tb_q.h +wr_adr.o: wr_adr.c +wr_adr.o: ../../h/head.h +wr_adr.o: ../../h/util.h +wr_adr.o: ../../h/config.h +wr_adr.o: ../../h/ll_log.h +wr_adr.o: ../../h/retcode.h +wr_adr.o: ../../h/adr.h +wr_adr.o: ../../h/list_rchan.h +wr_adr.o: ../../h/chan.h +wr_adr.o: ../../h/table.h +wr_adr.o: ../../h/list_bpt.h +wr_adr.o: ../../h/auth.h +wr_adr.o: ../../h/list_bpt.h +wr_adr.o: ../../h/extension.h +wr_adr.o: ../../h/mta.h +wr_adr.o: ../../h/adr.h +wr_adr.o: ../../h/list_bpt.h +wr_adr.o: ../../h/aparse.h +wr_adr.o: ../../h/ap.h +wr_adr.o: ../../h/util.h +wr_adr.o: ../../h/or.h +wr_adr.o: ../../h/chan.h +wr_adr.o: ../../h/auth.h +wr_adr.o: ../../h/list_rchan.h +wr_adr.o: ../../h/sys.file.h +wr_adr.o: ../../h/util.h +wr_dr.o: wr_dr.c +wr_dr.o: ../../h/head.h +wr_dr.o: ../../h/util.h +wr_dr.o: ../../h/config.h +wr_dr.o: ../../h/ll_log.h +wr_dr.o: ../../h/retcode.h +wr_dr.o: ../../h/q.h +wr_dr.o: ../../h/adr.h +wr_dr.o: ../../h/list_rchan.h +wr_dr.o: ../../h/chan.h +wr_dr.o: ../../h/table.h +wr_dr.o: ../../h/list_bpt.h +wr_dr.o: ../../h/auth.h +wr_dr.o: ../../h/list_bpt.h +wr_dr.o: ../../h/extension.h +wr_dr.o: ../../h/mta.h +wr_dr.o: ../../h/adr.h +wr_dr.o: ../../h/list_bpt.h +wr_dr.o: ../../h/aparse.h +wr_dr.o: ../../h/ap.h +wr_dr.o: ../../h/util.h +wr_dr.o: ../../h/or.h +wr_dr.o: ../../h/chan.h +wr_dr.o: ../../h/auth.h +wr_dr.o: ../../h/list_rchan.h +wr_dr.o: ../../h/mta.h +wr_dr.o: ../../h/dr.h +wr_dr.o: ../../h/extension.h +wr_dr.o: ../../h/mta.h +wr_prm.o: wr_prm.c +wr_prm.o: ../../h/head.h +wr_prm.o: ../../h/util.h +wr_prm.o: ../../h/config.h +wr_prm.o: ../../h/ll_log.h +wr_prm.o: ../../h/retcode.h +wr_prm.o: ../../h/prm.h +wr_q.o: wr_q.c +wr_q.o: ../../h/head.h +wr_q.o: ../../h/util.h +wr_q.o: ../../h/config.h +wr_q.o: ../../h/ll_log.h +wr_q.o: ../../h/retcode.h +wr_q.o: ../../h/q.h +wr_q.o: ../../h/adr.h +wr_q.o: ../../h/list_rchan.h +wr_q.o: ../../h/chan.h +wr_q.o: ../../h/table.h +wr_q.o: ../../h/list_bpt.h +wr_q.o: ../../h/auth.h +wr_q.o: ../../h/list_bpt.h +wr_q.o: ../../h/extension.h +wr_q.o: ../../h/mta.h +wr_q.o: ../../h/adr.h +wr_q.o: ../../h/list_bpt.h +wr_q.o: ../../h/aparse.h +wr_q.o: ../../h/ap.h +wr_q.o: ../../h/util.h +wr_q.o: ../../h/or.h +wr_q.o: ../../h/chan.h +wr_q.o: ../../h/auth.h +wr_q.o: ../../h/list_rchan.h +wr_q.o: ../../h/mta.h +wr_q2drfile.o: wr_q2drfile.c +wr_q2drfile.o: ../../h/head.h +wr_q2drfile.o: ../../h/util.h +wr_q2drfile.o: ../../h/config.h +wr_q2drfile.o: ../../h/ll_log.h +wr_q2drfile.o: ../../h/retcode.h +wr_q2drfile.o: ../../h/q.h +wr_q2drfile.o: ../../h/adr.h +wr_q2drfile.o: ../../h/list_rchan.h +wr_q2drfile.o: ../../h/chan.h +wr_q2drfile.o: ../../h/table.h +wr_q2drfile.o: ../../h/list_bpt.h +wr_q2drfile.o: ../../h/auth.h +wr_q2drfile.o: ../../h/list_bpt.h +wr_q2drfile.o: ../../h/extension.h +wr_q2drfile.o: ../../h/mta.h +wr_q2drfile.o: ../../h/adr.h +wr_q2drfile.o: ../../h/list_bpt.h +wr_q2drfile.o: ../../h/aparse.h +wr_q2drfile.o: ../../h/ap.h +wr_q2drfile.o: ../../h/util.h +wr_q2drfile.o: ../../h/or.h +wr_q2drfile.o: ../../h/chan.h +wr_q2drfile.o: ../../h/auth.h +wr_q2drfile.o: ../../h/list_rchan.h +wr_q2drfile.o: ../../h/mta.h +wr_q2drfile.o: ../../h/dr.h +wr_q2drfile.o: ../../h/extension.h +wr_q2drfile.o: ../../h/mta.h +wr_q2drfile.o: ../../h/sys.file.h +wr_q2drfile.o: ../../h/util.h +wr_q2drfile.o: ../../h/list_bpt.h +wr_q2drfile.o: ../../h/or.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/io/io_lib.c b/Lib/io/io_lib.c new file mode 100644 index 0000000..68e4f31 --- /dev/null +++ b/Lib/io/io_lib.c @@ -0,0 +1,777 @@ +/* io.c: This file contains the entire io library */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/io_lib.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/io_lib.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: io_lib.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "adr.h" +#include "prm.h" +#include "dr.h" +#include +#include +#include + + +extern char *cmddfldir; +extern char *submit_addr; +extern int errno; + +static int mm_cid; /* process id of child mail process */ +static FILE *io_wfp, + *io_rfp; + +extern char *submit_prog; +int remote_submit = 0; +char *submit_port = "4001"; +extern int protocol_mode; +static enum { + is_init, + is_parm, + is_queue, + is_addrs, + is_adend, + is_txtinit, + is_data, + is_txtend, + } is_state = is_init; + +#define check_proto(x) if (is_state != (x)) \ + return io_lose (rp, RP_MECH, "Protocol state mismatch") + +static int io_init_remote (); +static int io_init_local (); +static int io_lose (); +static void set_protocol_mode (); +static void unset_protocol_mode (); +static int io_rrply (); +static int io_wrec (); +static int io_rrec (); +static int io_tdata_aux (); +static char *io_data_vis (); +SFP sigpipe; + +extern void getfpath (); +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* +Initialise for submission +*/ + +int io_init (rp) +RP_Buf *rp; +{ + char *remote_info; + char _remote_info[BUFSIZ]; + + is_state = is_init; + if (io_wfp != NULLFILE) { + (void) fclose (io_wfp); + io_wfp = NULLFILE; + } + if (io_rfp != NULLFILE) { + (void) fclose (io_rfp); + io_rfp = NULLFILE; + } + + if (remote_info = getenv("PP_HOST_INFO")) + { + (void) strncpy(_remote_info, remote_info, sizeof _remote_info); + _remote_info[sizeof _remote_info -1] = '\0'; + remote_info = _remote_info; + } + else if (remote_info = submit_addr) + { + (void) strncpy(_remote_info, remote_info, sizeof _remote_info); + _remote_info[sizeof _remote_info -1] = '\0'; + remote_info = _remote_info; + } + else remote_info = NULLCP; + + if (remote_info && *remote_info == '\0') + remote_info = NULLCP; + + PP_TRACE(("remote info %s", remote_info ? remote_info : "")); + + if (remote_info) { + char *argv[50]; + int argc, i; + char *port_name, *p; + + argc = sstr2arg (remote_info, 50, argv, ","); + + for (i = 0; i < argc; i++) { + port_name = submit_port; + + if (p = index (argv[i], ':')) { + *p++ = '\0'; + port_name = p; + } + if (argv[i][0] == '/') { + if (io_init_local (rp, argv[i]) == RP_OK) + return RP_OK; + } + else { + if (io_init_remote (rp, argv[i], + port_name) == RP_OK) + return RP_OK; + } + } + } + return (io_init_local (rp, NULLCP)); +} + + + + +/* +Parameter handling +*/ + +int io_wprm (prm, rp) +struct prm_vars *prm; +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_wprm (prm, rp)")); + + check_proto (is_init); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to sumbit")); + + sigpipe = signal (SIGPIPE, SIG_IGN); + set_protocol_mode(); + retval = wr_prm (prm, io_wfp); + (void) fflush (io_wfp); + unset_protocol_mode(); + (void) signal (SIGPIPE, sigpipe); + + if (rp_isbad (retval) || ferror(io_wfp)) + return (io_lose (rp, retval, "Can't write parameters")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad handshake")); + + is_state = is_parm; + return (rp -> rp_val); +} + + + + +/* +Q structure handling +*/ + +int io_wrq (qp, rp) +Q_struct *qp; +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_wq (q, rp)")); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to submit")); + check_proto (is_parm); + + sigpipe = signal (SIGPIPE, SIG_IGN); + set_protocol_mode(); + retval = wr_q (qp, io_wfp); + (void) fflush (io_wfp); + unset_protocol_mode(); + (void) signal (SIGPIPE, sigpipe); + + if (rp_isbad (retval) || ferror(io_wfp)) + return (io_lose (rp, retval, "Can't write Q structure")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad handshake")); + + is_state = is_addrs; + return (rp -> rp_val); +} + + + + +/* +DR structure handling +*/ + +int io_wdr (dp, rp) +DRmpdu *dp; +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_wdr (dp, rp)")); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to submit")); + check_proto (is_adend); + + sigpipe = signal (SIGPIPE, SIG_IGN); + set_protocol_mode(); + retval = wr_dr (dp, io_wfp); + (void) fflush (io_wfp); + unset_protocol_mode(); + (void) signal (SIGPIPE, sigpipe); + + if (rp_isbad (retval) || ferror(io_wfp)) + return (io_lose (rp, retval, "Can't write DR structure")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad Handshake")); + + is_state = is_adend; + return (rp -> rp_val); +} + + + + +/* +Address handling +*/ + +int io_wadr (ap, type, rp) +ADDR *ap; +int type; +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_wadr (adr, %d, rp)", type)); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to submit")); + check_proto (is_addrs); + + sigpipe = signal (SIGPIPE, SIG_IGN); + set_protocol_mode(); + retval = wr_adr (ap, io_wfp, type); + (void) fflush (io_wfp); + unset_protocol_mode(); + (void) signal (SIGPIPE, sigpipe); + + if (rp_isbad (retval) || ferror(io_wfp)) + return (io_lose (rp, retval, "Can't write address")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad handshake")); + if (rp -> rp_val != RP_AOK) + return RP_BAD; + return (rp -> rp_val); +} + + +/* +Address phase termination +*/ + +int io_adend (rp) +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_adend (rp)")); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to sumbit")); + check_proto (is_addrs); + + if (rp_isbad (retval = io_wrec ("", 0))) + return (io_lose (rp, retval, "Problem ending addreses")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad Handshake")); + + is_state = is_adend; + return (rp -> rp_val); +} + + + + +/* +Text phase - initialisation +*/ + +int io_tinit (rp) +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_tinit()")); + + if (io_wfp == NULLFILE) + return (io_lose (rp, RP_MECH, "Not connected to submit")); + check_proto (is_adend); + + if ( rp_isbad (retval = io_wrec ("", 0))) + return (io_lose (rp, retval, "Problem in text init")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad handshake")); + + PP_DBG (("Returned %s\n", rp->rp_line)); + is_state = is_txtinit; + return (rp -> rp_val); +} + + + + +/* +Initialise to pass a single body part to submit +*/ + +int io_tpart (section, links, rp) +char *section; +int links; +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_tpart (%s, %d)", section, links)); + + check_proto (is_txtinit); + if (rp_isbad (retval = io_wrec (section, strlen (section)))) + return (io_lose (rp, retval, "Error writing to submit")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Handshake failure")); + + if (links != TRUE) + is_state = is_data; + return (rp -> rp_val); +} + + + + +/* +Write data to submit. +*/ + +int io_tdata (buf, len) +char *buf; +int len; +{ + if (is_state != is_data) + return NOTOK; + PP_LOG (LLOG_PDUS, ("Lib/io_tdata(%d): %s", len, + io_data_vis (buf, len))); + return (io_tdata_aux (buf, len, TRUE)); +} + + + + +/* +End a section sent to submit +*/ + +int io_tdend (rp) +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_tdend (ret)")); + + check_proto (is_data); + if (rp_isbad (retval = io_tdata_aux ("", 0, FALSE))) + return (io_lose (rp, retval, "I/O error")); + + (void) fflush (io_wfp); + if (ferror (io_wfp)) + return (io_lose (rp, RP_FIO, "Write error")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad Handshake")); + + is_state = is_txtinit; + return (rp -> rp_val); +} + + + + +/* +Finally finish the data section +*/ + +int io_tend (rp) +RP_Buf *rp; +{ + int retval; + + PP_DBG (("io_tend (ret)")); + + check_proto (is_txtinit); + if (rp_isbad (retval = io_wrec ("", 0))) + return (io_lose (rp, retval, "I/O error")); + + if (rp_isbad (retval = io_rrply (rp))) + return (io_lose (rp, retval, "Bad Handshake")); + + if (rp_isbad (rp -> rp_val)) + return rp -> rp_val; + + if (rp_isbad (retval = io_rrply (rp))) + return io_lose (rp, retval, "Bad Handshake"); + + is_state = is_init; + return (rp -> rp_val); +} + + + + +int io_end (type) +int type; +{ + register int status = OK; + int pid; +#ifdef SVR4 + int w; +#else + union wait w; +#endif + + PP_DBG (("io_end (%d)", type)); + + (void) fclose (io_wfp); + (void) fclose (io_rfp); + io_rfp = NULLFILE; + io_wfp = NULLFILE; + + if (!remote_submit) +#ifdef SVR4 + while ((pid = wait(&w)) != mm_cid && pid != -1) +#else + while ((pid = wait(&w.w_status)) != mm_cid && pid != -1) +#endif + continue; + + mm_cid = 0; + is_state = is_init; + return (status); +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +/* +Helper routine if local connection is required +*/ + +static int io_init_local (rp, command) +RP_Buf *rp; +char *command; +{ + char temppath[LINESIZE]; + int sv[2], + osv[2], + child, + i; + + PP_DBG ((" io_init()")); + + if (pipe (sv) < 0 || pipe (osv) < 0) + return (io_lose (rp, RP_LIO, + "Can't create connection to child")); + + if ((child = tryfork()) < 0) { + (void) close (sv[0]); + (void) close (sv[1]); + (void) close (osv[0]); + (void) close (osv[1]); + return (io_lose (rp, RP_LIO, "Try again (fork)")); + } + + + if (child == 0) { + /* + I am the child (I will use sv[1]) + */ + + if (command && *command) + (void) strncpy (temppath, command, sizeof temppath); + else + getfpath (cmddfldir, submit_prog, temppath); + + if (osv[0] != 0) { + (void) dup2 (osv[0], 0); + (void) close (osv[0]); + } + if (sv[1] != 1) { + (void) dup2 (sv[1], 1); + (void) close (sv[1]); + } + (void) close (osv[1]); + (void) close (sv[0]); + for (i = getdtablesize() ; i >= 2 ; i--) + (void) close (i); + + (void) execl (temppath, submit_prog, 0); + + PP_OPER (temppath, ("Cannot exec")); + + _exit (1); + } + + /* + I am the parent - I will use sv[0] + */ + mm_cid = child; + (void) close (sv[1]); + io_rfp = fdopen (sv[0], "r"); + (void) close (osv[0]); + io_wfp = fdopen (osv[1], "w"); + return (RP_OK); +} + + + + +/* +Helper routine for remote connect (submit server) +*/ + +static int io_init_remote (rp, submit_host, submit_port_name) +RP_Buf *rp; +char *submit_host; +char *submit_port_name; +{ + struct servent *sp; + u_short port; + struct hostent *host; + struct sockaddr_in s_in; + int sd; + + PP_DBG ((" io_init()")); + + if (isdigit (*submit_port_name)) + port = htons ((u_short)atoi(submit_port_name)); + else if ((sp = getservbyname (submit_port_name, "tcp")) != NULL) + port = sp -> s_port; + else + port = htons ((u_short)atoi(submit_port)); + + sd = socket (AF_INET, SOCK_STREAM, 0); + if (sd < 0) + return (io_lose (rp, RP_LIO, "Can't get a socket")); + + bzero ((char *)&s_in, sizeof (s_in)); + s_in.sin_family = AF_INET; + s_in.sin_port = port; + + if ((host = gethostbyname (submit_host)) == NULL) { + (void) close (sd); + PP_LOG (LLOG_EXCEPTIONS, + ("Remote server %s not found", submit_host)); + return (io_lose (rp, RP_MECH, "Can't locate host")); + } + + bcopy ((char *)host -> h_addr, (char *)&s_in.sin_addr, + host -> h_length); + + if (connect (sd, (struct sockaddr *)&s_in, sizeof s_in) < 0) { + (void) close (sd); + return (io_lose (rp, RP_LIO, "Can't connect to submit")); + } + + io_rfp = fdopen (sd, "r"); + io_wfp = fdopen (sd, "w"); + + if (io_wfp == NULLFILE || io_rfp == NULLFILE) + { int was = errno; + if (io_wfp == NULLFILE) + (void) fclose(io_wfp); + if (io_rfp == NULLFILE) + (void) fclose(io_rfp); + (void) close(sd); + errno = was; + return (io_lose (rp, RP_FIO, "File pointers not set")); + } + return (RP_OK); +} + + +/* +Helper routine to ensure correct protocol +*/ + +static int io_tdata_aux (buf, len, flag) +char *buf; +int len; +int flag; +{ + long datalen = htonl ((u_long)len); + + if (flag && len == 0) + return (RP_MECH); + + (void) fwrite ((char *)&datalen, sizeof (datalen), 1, io_wfp); + (void) fwrite (buf, sizeof (char), len, io_wfp); + + return ((ferror (io_wfp) ? RP_FIO : RP_OK)); +} + + +/* +Get a reply from remote process +*/ + +static int io_rrply (rp) +RP_Buf *rp; +{ + int len; + char *rplystr; + int c; + + PP_DBG (("io_rrply (rp)")); + + if ((c = getc(io_rfp)) == EOF) + return RP_EOF; + rp -> rp_val = c; + for (rplystr = rp -> rp_line, len = sizeof rp -> rp_line - 2; + len > 0; len --) { + if ((c = getc(io_rfp)) == EOF) + return RP_EOF; + if (c == '\n') + break; + *rplystr++ = c; + } + if (c != '\n') { /* no newline - find it */ + while ((c = getc(io_rfp)) != EOF && c != '\n') + continue; + } + *rplystr = '\0'; + + rplystr = rp_valstr ((int)rp -> rp_val); + + if (*rplystr == '*') { + /* + Replyer did a no-no + */ + PP_LOG (LLOG_EXCEPTIONS, ("ILLEGAL REPLY: (%s)", rplystr)); + rp -> rp_val = RP_RPLY; + } + + return (RP_OK); +} + + + + + + +/* +Write a record +*/ + +static int io_wrec (linebuf, len) /* write a record/packet */ +register char *linebuf; /* chars to write */ +register int len; /* number of chars to write */ +{ + static char *io_data_vis (); + PP_LOG (LLOG_PDUS, ("io_wrec ('%s', %d)", + io_data_vis (linebuf, len), len)); + + + sigpipe = signal (SIGPIPE, SIG_IGN); + (void) fwrite (linebuf, sizeof (char), len, io_wfp); + (void) putc ('\n', io_wfp); + (void) fflush (io_wfp); /* force it out */ + (void) signal (SIGPIPE, sigpipe); + + return (ferror (io_wfp) ? RP_LIO : RP_OK); +} + + + + +static int io_lose (rp, state, str) +RP_Buf *rp; +int state; +char *str; +{ + rp -> rp_val = rp_gval (state); + + (void) strcpy (rp -> rp_line, str); + + PP_LOG (LLOG_NOTICE, + ("io_lose -> %s [%s]", rp_valstr (state), str)); + + is_state = is_init; + return (state); +} + +static char *io_data_vis (str, n) +char *str; +int n; +{ + static char buffer[128]; + char *cp, *ep; + + for(cp = buffer, ep = buffer + sizeof(buffer) -1; + cp < ep && n-- > 0; str ++) { + if (isprint (*str)) + *cp++ = *str; + else if (cp >= ep - 3) + break; + else { + *cp ++ = '\\'; + *cp ++ = '0' + ((*str >> 6) & 03); + *cp ++ = '0' + ((*str >> 3) & 07); + *cp ++ = '0' + ((*str) & 07); + } + } + *cp = 0; + return buffer; +} + +static void set_protocol_mode () +{ + unset_protocol_mode(); + protocol_mode = 1; + return; +} + + +static void unset_protocol_mode () +{ + static int save = -1; + + if (save == -1) + save = protocol_mode; + else { + protocol_mode = save; + save = -1; + } +} diff --git a/Lib/io/make b/Lib/io/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/io/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/io/rd_adr.c b/Lib/io/rd_adr.c new file mode 100644 index 0000000..d35062a --- /dev/null +++ b/Lib/io/rd_adr.c @@ -0,0 +1,81 @@ +/* rd_adr.c: read a text address struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_adr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_adr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_adr.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "adr.h" +#include "sys.file.h" +#include + + +extern int ad_count; +CHAN *ch_nm2struct(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int rd_adr (fp, justone, base) /* get an addr seq from a file */ +FILE *fp; +int justone; +ADDR **base; +{ + long fp_startln; + char *argv[100], + buf[10 * BUFSIZ]; + int argc, + gotone=FALSE, + retval; + + PP_DBG (("Lib/io/rd_adr (fp, %d, base)", justone)); + + for (;;) { + + fp_startln = ftell(fp); + + if (rp_isbad (retval = txt2buf (buf, sizeof buf, fp))) { + PP_DBG (("Lib/io/rd_adr txt2buf retval (%d - %s)", + retval, rp_valstr (retval))); + if (retval == RP_EOF && !justone && gotone) + return (RP_DONE); + return (retval); + } + + if (retval == RP_DONE) + return (RP_DONE); + + if ((argc = str2arg (buf, 100, argv)) == 0) + return (RP_PARM); + + retval = txt2adr (base, fp_startln, argv, argc); + + PP_DBG (("Lib/io/rd_adr retval (%d)", retval)); + + if (retval == NOTOK) + return (RP_PARM); + + if (gotone == FALSE) + gotone = TRUE; + + ad_count ++; + + if (justone) + return (RP_OK); + } +} diff --git a/Lib/io/rd_buf.c b/Lib/io/rd_buf.c new file mode 100644 index 0000000..3c03811 --- /dev/null +++ b/Lib/io/rd_buf.c @@ -0,0 +1,123 @@ +/* rd_buf.c: low level line reading of Control and DR Txt Files */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_buf.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_buf.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_buf.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" + +#define COMMENTCHAR '#' +int protocol_mode = 0; + +static int glinread (); + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int txt2buf (linebuf, len, fp) +FILE *fp; +int len; +char *linebuf; +{ + int n; + + PP_DBG (("Lib/io/txt2buf()")); + + if ((n = glinread (fp, linebuf, len)) < 0) + return (RP_EOF); + if (n == 0) /* time for a resync */ + return (RP_PARM); + if (n == 1) + return (RP_DONE); + if (linebuf[--n] != '\n') + return (RP_MECH); + linebuf[n] = '\0'; + return (RP_OK); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int glinread (fp, buf, size) +register FILE *fp; +char *buf; +int size; +{ + register int c; + register int i; + extern int protocol_mode; + + PP_DBG (("Lib/io/glinread()")); + + if (feof(fp)) + return EOF; + + for (--size, i = 0; i < size; i++) + switch (c = getc (fp)) { + case EOF: + return (EOF); + + case '\0': + return (0); + + case '\n': + *buf++ = c; + if (protocol_mode == 0) { + /* -- first char on next line -- */ + (void) ungetc (c = getc (fp), fp); + if (c == COMMENTCHAR) { + /* + check for comments within folding. + Ignore everything up to and + including new line character which + is not followed by COMMENTCHAR, + this could probably be recursive and + clever - but what the hell + */ + while (42) { + if ((c = getc (fp)) == '\n') { + (void) ungetc (c = + getc (fp), fp); + if (c != COMMENTCHAR) + break; + } + } + } + + if (c == ' ' || c == '\t') { + /* continuation line */ + c = getc (fp); + *(buf - 1) = ' '; + break; + } + } + *buf = 0; + return (++i); + + default: + *buf++ = c; + } + + /* + * if ever get here then line too long + */ + *buf = 0; + return (i); +} diff --git a/Lib/io/rd_dr.c b/Lib/io/rd_dr.c new file mode 100644 index 0000000..8937a23 --- /dev/null +++ b/Lib/io/rd_dr.c @@ -0,0 +1,35 @@ +/* rd_dr.c: read a DR file from q/msg/dir/dr.999 into a DR struct */ +/* see man page QUEUE (5) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_dr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_dr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_dr.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "dr.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + +int rd_dr (dp, fp) +register DRmpdu *dp; +FILE *fp; +{ + + PP_DBG (("Lib/io/rd_dr()")); + dr_init (dp); + return (txt2dr (dp, fp)); +} diff --git a/Lib/io/rd_msg.c b/Lib/io/rd_msg.c new file mode 100644 index 0000000..5c5288c --- /dev/null +++ b/Lib/io/rd_msg.c @@ -0,0 +1,239 @@ +/* rd_msg.c: read in a msg from the queue + write addr offset routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_msg.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_msg.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_msg.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +/* +-- These routines are 'high level' taking care of most of the housekeeping. -- +*/ + + + +#include "head.h" +#include "q.h" +#include +#include +#include "prm.h" + + +extern void getfpath (); +extern long lseek (); + +extern int errno; +extern char *aquefile, + *no2txt3(); +static FILE *msg_fp; +static char msgname[MAXPATHLENGTH]; +int ad_count; + + +void rd_end (); + +/* --------------------- Read Message Routines -------------------------- */ + + + +int rd_msg_file (mdir, prm, que, sender, recip, rcount, mode) +char *mdir; +struct prm_vars *prm; +Q_struct *que; +ADDR **sender; +ADDR **recip; +int *rcount; +int mode; +{ + int retval; + extern char *quedfldir; + + (void) sprintf (msgname, "%s/%s", mdir, aquefile); + PP_DBG (("Lib/io/rd_msg(%s)", msgname)); + + switch (mode) { + default: + return RP_MECH; + + case RDMSG_RDONLY: + if ((msg_fp = fopen (msgname, "r")) == NULLFILE) { + PP_SLOG (LLOG_EXCEPTIONS, msgname, + ("Lib/io/rd_msg flckopen error")); + return RP_FOPN; + } + break; + case RDMSG_RDWR: + case RDMSG_RDONLYLCK: + if ((msg_fp = flckopen (msgname, + mode == RDMSG_RDWR ? "r+" : "r")) + == NULLFILE) { + PP_SLOG (LLOG_EXCEPTIONS, msgname, + ("Lib/io/rd_msg flckopen error")); + return (RP_FOPN); + } + break; + } + + if (rp_isbad (retval = rd_prm (prm, msg_fp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/rd_msg/rd_prm err: '%s'", msgname)); + rd_end(); + return (retval); + } + + if (rp_isbad (retval = rd_q (que, msg_fp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/rd_msg/rd_q err: '%s'", msgname)); + rd_end(); + return (retval); + } + + if (rp_isbad (retval = rd_adr (msg_fp, TRUE, sender))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/rd_msg/rd_adr sender err: %s %s", + rp_valstr (retval), msgname)); + rd_end(); + return (retval); + } + + ad_count = 0; + + if (rp_isbad (retval = rd_adr (msg_fp, FALSE, recip))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/rd_msg/rd_adr recip err: %s %s", + rp_valstr(retval), msgname)); + rd_end(); + return (retval); + } + + que -> Oaddress = *sender; + que -> Raddress = *recip; + *rcount = ad_count; + + return (RP_OK); +} + + + + +void rd_end () +{ + PP_DBG (("Lib/io/rd_end()")); + if (msg_fp) (void) flckclose (msg_fp); + msg_fp = NULLFILE; +} + + + + +/* --------------------- Write Address Offset Routines ------------------ */ + + + + +int wr_ad_status (ap, status) +ADDR *ap; +int status; +{ + char *str; + extern CMD_TABLE atbl_status[]; + + PP_DBG (("Lib/io/wr_ad_status()")); + + if (msg_fp == NULLFILE) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/wr_ad_status (NULLFILE)")); + return (RP_MECH); + } + + switch (status) { + case AD_STAT_PEND: + case AD_STAT_DONE: + case AD_STAT_DRREQUIRED: + case AD_STAT_DRWRITTEN: + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/wr_ad_status unknown")); + status = AD_STAT_UNKNOWN; + break; + } + str = rcmd_srch (status, atbl_status); + + if (lseek (fileno (msg_fp), ap -> ad_stat_offset, 0) == -1) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_ad_status lseek err %s", msgname)); + return (RP_FIO); + } + + + if (write (fileno (msg_fp), str, 4) != 4) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_ad_status write err %s", msgname)); + return (RP_FIO); + } + return (RP_OK); +} + +int wr_ad_rcntno (ap, rcnt) +ADDR *ap; +int rcnt; +{ + char buf[5]; + + PP_DBG (("Lib/io/wr_ad_rcntno(%d)", rcnt)); + + if (msg_fp == NULLFILE) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/io/wr_ad_rcntno (NULLFILE)")); + return (RP_MECH); + } + + if (lseek (fileno (msg_fp), ap -> ad_rcnt_offset, 0) == -1) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_ad_rcntno lseek err %s", msgname)); + return (RP_FIO); + } + + if (write (fileno (msg_fp), no2txt3 (rcnt, &buf[0]), 3) != 3) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_ad_rcntno write err %s", msgname)); + return (RP_FIO); + } + return (RP_OK); +} + +int wr_q_nwarns (q) +Q_struct *q; +{ + char buf[5]; + + PP_DBG (("Lib/io/wr_q_nwarns(%d)", q->nwarns)); + + if (msg_fp == NULLFILE) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/io/wr_q_nwarns (NULLFILE)")); + return (RP_MECH); + } + + if (lseek (fileno (msg_fp), q -> nwarns_offset, 0) == -1) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_q_nwarns lseek err %s", msgname)); + return (RP_FIO); + } + + if (write (fileno (msg_fp), no2txt3 (q->nwarns, &buf[0]), 3) != 3) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_q_nwarns write err %s", msgname)); + return (RP_FIO); + } + return (RP_OK); +} + diff --git a/Lib/io/rd_prm.c b/Lib/io/rd_prm.c new file mode 100644 index 0000000..fc2524e --- /dev/null +++ b/Lib/io/rd_prm.c @@ -0,0 +1,82 @@ +/* rd_prm.c: read in a prm_vars struct from fp */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_prm.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_prm.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_prm.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "tb_prm.h" + + +/* --------------------- Begin Routines -------------------------------- */ + + +static char *save_file; +static int save_level; + +int rd_prm (pp, fp) +register struct prm_vars *pp; +FILE *fp; +{ + char buf[BUFSIZ], + *argv[50]; + int argc, + retval; + + PP_DBG (("Lib/io/rd_prm()")); + + prm_init (pp); + if (save_file) { + free (pp_log_norm -> ll_file); + pp_log_norm -> ll_file = save_file; + pp_log_norm -> ll_stat = save_level; + save_file = NULLCP; + } + + for (;;) { + retval = txt2buf (buf, sizeof buf, fp); + + if (rp_isbad (retval)) { + PP_DBG (("Lib/rd_prm txt2buf retval (%d - %s)", + retval, rp_valstr (retval))); + return (retval); + } + + argc = str2arg (buf, 50, argv); + if (argc == 0) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/rd_prm err (str2arg)")); + return (RP_PARM); + } + + retval = txt2prm (pp, argv, argc); + if (retval == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/rd_prm err (txt2prm)")); + return (RP_PARM); + } + if (retval == PRM_END) + break; + } + + if (pp -> prm_logfile || pp -> prm_loglevel) { + save_file = pp_log_norm -> ll_file; + save_level = pp_log_norm -> ll_stat; + if (pp -> prm_logfile) + pp_log_norm -> ll_file = strdup(pp -> prm_logfile); + if (pp -> prm_loglevel) + pp_log_norm -> ll_events = pp -> prm_loglevel; + (void) ll_close (pp_log_norm); + } + return RP_OK; +} diff --git a/Lib/io/rd_q.c b/Lib/io/rd_q.c new file mode 100644 index 0000000..8af9336 --- /dev/null +++ b/Lib/io/rd_q.c @@ -0,0 +1,82 @@ +/* rd_q.c: reads the control file in Q/addr into memory */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_q.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/rd_q.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: rd_q.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include "q.h" +#include "tb_q.h" + + +/* --------------------- Begin Routines -------------------------------- */ + +static int R_umpdu (); + +int rd_q (qp, fp) +register Q_struct *qp; +FILE *fp; +{ + + PP_DBG (("Lib/io/rd_q()")); + q_init (qp); + return (R_umpdu (qp, fp)); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int R_umpdu (qp, fp) +register Q_struct *qp; +FILE *fp; +{ + char buf[10*BUFSIZ], + *argv[100]; + int argc, + retval; + long fp_startln; + + + PP_DBG (("Lib/io/R_umpdu()")); + + q_init (qp); + + for (;;) { + + fp_startln = ftell(fp); + + retval = txt2buf (buf, sizeof buf, fp); + + if (rp_isbad (retval)) { + PP_DBG (("Lib/io/R_umpdu txt2buf retval (%d - %s)", + retval, rp_valstr (retval))); + return (retval); + } + + PP_DBG (("Lib/io/R_umpdu(buf='%.999s')", &buf[0])); + + if ((argc = str2arg (buf, 100, argv)) == 0) + return (RP_PARM); + + retval = txt2q (qp, fp_startln, argv, argc); + + PP_DBG (("Lib/io/R_umpdu (txt2q=%d)", retval)); + if (retval == NOTOK) return (RP_PARM); + if (retval == Q_END) return (RP_OK); + } +} diff --git a/Lib/io/wr_adr.c b/Lib/io/wr_adr.c new file mode 100644 index 0000000..4943947 --- /dev/null +++ b/Lib/io/wr_adr.c @@ -0,0 +1,49 @@ +/* wr_adr: address writing routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_adr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_adr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_adr.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +/* --- *** --- +This routine is used so that there is only one entry point to adr2txt() +which is located in Lib/pp/adr2txt.c +--- *** --- */ + + +#include "head.h" +#include "adr.h" +#include "sys.file.h" +#include + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int wr_adr (ap, fp, type) +ADDR *ap; +FILE *fp; +int type; +{ + int retval; + + PP_DBG (("wr_adr (%d)", type)); + + retval = adr2txt (fp, ap, type); + if (retval == NOTOK) + return (RP_FIO); + return (RP_OK); +} diff --git a/Lib/io/wr_dr.c b/Lib/io/wr_dr.c new file mode 100644 index 0000000..e97848b --- /dev/null +++ b/Lib/io/wr_dr.c @@ -0,0 +1,40 @@ +/* wr_dr.c: writes out a DR struct from an incomming chan */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_dr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_dr.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_dr.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int wr_dr (dp, fp) +register DRmpdu *dp; +FILE *fp; +{ + int retval; + + + PP_DBG (("Lib/io/wr_dr()")); + + retval = dr2txt (fp, dp); + if (retval == NOTOK) + return (RP_FIO); + return (RP_OK); +} diff --git a/Lib/io/wr_drfile.c b/Lib/io/wr_drfile.c new file mode 100644 index 0000000..e81942e --- /dev/null +++ b/Lib/io/wr_drfile.c @@ -0,0 +1,104 @@ +/* wr_q2drsubmit.c: write out a Delivery Notification struct + from the info held in the queue and address structures of submit +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_drfile.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_drfile.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_drfile.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" +#include "sys.file.h" +#include "list_bpt.h" +#include + +extern char *dr_file; + + +/* --------------------- Begin Routines -------------------------------- */ + + +int wr_q2drsubmit (qp, path) +register Q_struct *qp; +char *path; +{ + FILE *fp; + ADDR *ap; + char *fname = NULL, + buf[MAXPATHLENGTH], + odir[MAXPATHLENGTH]; + int retval=NOTOK, + dr_file_no = -1, + dr_required = FALSE; + + (void) strcpy (odir, path); + + PP_DBG (("Lib/io/wr_q2drsubmit (dir=%s)", odir)); + + + /* open a DR file (dr.999) name is determined by recip */ + + for (ap=qp->Raddress, retval=OK; + ap != NULLADDR && retval == OK; ap=ap->ad_next) + + if (ap->ad_status == AD_STAT_DRREQUIRED) { + + dr_required = TRUE; + + dr_file_no = ap->ad_no; + PP_DBG(("ap->ad_no = %d",ap->ad_no)); + (void) sprintf (&buf[0], "%s%d", dr_file, dr_file_no); + + fname = multcat (odir, "/", &buf[0], NULLCP); + + if (access (fname, F_OK) == NOTOK) + break; + + + retval = NOTOK; + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/wr_q2drsubmit (file %s exists)", + fname)); + } + + if (ap == NULLADDR && dr_required == FALSE) return (RP_OK); + + if (retval == NOTOK) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_q2drsubmit (dr required but first file in use)")); + return (RP_BAD); + } + + PP_DBG (("Lib/io/wr_q2drsubmit (opening %s)", fname)); + + if ((fp = fopen (fname, "w")) == NULLFILE) { + PP_LOG (LLOG_FATAL, + ("Lib/io/wr_q2drsubmit (unable to open %s)", fname)); + return (RP_FIO); + } + + + retval = wr_dr_info (fp, qp, dr_file_no, TRUE); + + (void) fclose(fp); + + if (chmod(fname, 0666) != 0) + PP_SLOG(LLOG_EXCEPTIONS, fname, + ("chmod failed")); + + if (retval == NOTOK) return (RP_FIO); + + return (RP_OK); +} diff --git a/Lib/io/wr_prm.c b/Lib/io/wr_prm.c new file mode 100644 index 0000000..bba1c82 --- /dev/null +++ b/Lib/io/wr_prm.c @@ -0,0 +1,39 @@ +/* wr_prm.c: send the parameter structure to submit */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_prm.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_prm.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_prm.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int wr_prm (pp, fp) +struct prm_vars *pp; +FILE *fp; +{ + int retval; + + PP_DBG (("Lib/io/wr_prm()")); + + retval = prm2txt (fp, pp); + if (retval == NOTOK) + return (RP_FIO); + return (RP_OK); +} diff --git a/Lib/io/wr_q.c b/Lib/io/wr_q.c new file mode 100644 index 0000000..c2a7b35 --- /dev/null +++ b/Lib/io/wr_q.c @@ -0,0 +1,49 @@ +/* wr_q.c: write out a queue structure to a Control File in Q/ADDR */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_q.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_q.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_q.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +/* __________________________________________________________________________ + +This routine is used so that there is only one entry point to q2txt() +which is located in Lib/pp/tx_q.c + +____________________________________________________________________________*/ + + + +#include "head.h" +#include "q.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int wr_q (qp, fp) +register Q_struct *qp; +FILE *fp; +{ + int retval; + + PP_DBG (("Lib/wr_q (type=%d, size=%d)", qp->msgtype, qp->msgsize)); + + retval = q2txt (fp, qp); + if (retval == NOTOK) + return (RP_FIO); + return (RP_OK); +} diff --git a/Lib/io/wr_q2drfile.c b/Lib/io/wr_q2drfile.c new file mode 100644 index 0000000..f295345 --- /dev/null +++ b/Lib/io/wr_q2drfile.c @@ -0,0 +1,244 @@ +/* wr_q2drfile.c: write out a Delivery Notification struct + from the info held in the queue and address structures +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_q2drfile.c,v 6.0 1991/12/18 20:22:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/io/RCS/wr_q2drfile.c,v 6.0 1991/12/18 20:22:26 jpo Rel $ + * + * $Log: wr_q2drfile.c,v $ + * Revision 6.0 1991/12/18 20:22:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" +#include "sys.file.h" +#include +#include "list_bpt.h" +#include +#include "or.h" + +extern char *dr_file; +extern char *x400_mta; +static void set_succ_suppl (); +static int wr_dr_info (); + +/* --------------------- Begin Routines -------------------------------- */ + +int wr_q2dr (qp, msg_id) +register Q_struct *qp; +char *msg_id; +{ + return wr_q2drfile (qp, msg_id, 1); +} + +int wr_q2drfile (qp, path, update) +register Q_struct *qp; +char *path; +int update; +{ + FILE *fp; + ADDR *ap; + char odir[MAXPATHLENGTH]; + int retval=NOTOK, + dr_file_no = -1, + dr_required = FALSE; + struct stat stbuf; + + PP_DBG (("Lib/io/wr_q2drfile (dir=%s)", path)); + + for (ap=qp->Raddress; ap != NULLADDR; ap=ap->ad_next) { + if (ap->ad_status != AD_STAT_DRREQUIRED) + continue; + + dr_required = TRUE; + + dr_file_no = ap->ad_no; + + (void) sprintf (odir, "%s/%s%d", path, + dr_file, dr_file_no); + + PP_DBG(("ap->ad_no = %d file = %s",ap->ad_no, odir)); + + if (stat (odir, &stbuf) == NOTOK) + break; + + + if (stbuf.st_size == 0) { + PP_NOTICE (("Removing empty file %s", + odir)); + (void) unlink(odir); + break; + } + PP_OPER (NULLCP, + ("wr_q2drfile: File %s already exists of size %d", + odir, stbuf.st_size)); + return RP_LIO; + } + + if (ap == NULLADDR && dr_required == FALSE) + return (RP_OK); + + qp->Oaddress->ad_status = AD_STAT_PEND; + if (update && + rp_isbad(retval = wr_ad_status(qp->Oaddress, qp->Oaddress->ad_status))) + return retval; + + PP_DBG (("Lib/io/wr_q2drfile (opening %s)", odir)); + + if ((fp = fopen (odir, "w")) == NULLFILE) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/io/wr_q2drfile (unable to open %s)", odir)); + return (RP_FIO); + } + + + retval = wr_dr_info (fp, qp, dr_file_no, update); + + if (check_close (fp) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, odir, ("Error writing to file")); + (void) unlink (odir); + return RP_FIO; + } + + if (chmod(odir, 0666) == NOTOK) + PP_SLOG(LLOG_EXCEPTIONS, odir, ("chmod failed")); + + return (retval); +} + + + + +static int wr_dr_info (fp, qp, dr_file_no, update) /* Creates a DR output */ +FILE *fp; +register Q_struct *qp; +int dr_file_no; +int update; +{ + ADDR *ap; + time_t time(); + int retval; + DRmpdu DeliveryReport, *dr; + Rrinfo *nxt, *new; + Report *rep; + char buf[LINESIZE]; + + + PP_DBG (("Lib/io/wr_dr_info()")); + + /* -- Initialize -- */ + dr_init (dr = &DeliveryReport); + + or_myinit(); /* in case */ + + /* -- set MPDUid -- */ + dr -> dr_mpduid = (MPDUid *) smalloc (sizeof (*dr->dr_mpduid)); + bzero ((char*) dr->dr_mpduid, sizeof (*dr->dr_mpduid)); + MPDUid_new (dr -> dr_mpduid); + + /* -- set Trace -- */ + trace_add (&dr -> dr_trace, trace_new()); + trace_add(&dr -> dr_subject_intermediate_trace, trace_dup(qp -> trace)); + for (ap = qp->Raddress; ap != NULLADDR; ap = ap->ad_next) + if (ap->ad_status == AD_STAT_DRREQUIRED) { + + if (ap -> ad_no == dr_file_no) + ap->ad_status = AD_STAT_DRWRITTEN; + else ap -> ad_status = AD_STAT_DONE; + + new = (Rrinfo *) smalloc (sizeof (*new)); + bzero ((char *)new, sizeof (*new)); + + if (dr -> dr_recip_list != NULL) { + for (nxt = dr->dr_recip_list; nxt -> rr_next; + nxt = nxt->rr_next) + continue; + nxt -> rr_next = new; + } + else + dr -> dr_recip_list = new; + + + new -> rr_recip = ap -> ad_no; + new -> rr_arrival = utcdup (qp -> queuetime); + rep = &new -> rr_report; + + switch (ap->ad_reason) { + case DRR_NO_REASON: + rep->rep_type = DR_REP_SUCCESS; + rep->rep.rep_dinfo.del_time = utcnow(); + rep->rep.rep_dinfo.del_type = 1; + + if (ap -> ad_add_info == NULLCP) { + set_succ_suppl (ap, qp->msgtype, buf); + new -> rr_supplementary = strdup (buf); + } else + new -> rr_supplementary = strdup(ap -> ad_add_info); + break; + + default: + rep->rep_type = DR_REP_FAILURE; + rep->rep.rep_ndinfo.nd_rcode = ap->ad_reason; + rep->rep.rep_ndinfo.nd_dcode = ap->ad_diagnostic; + if (ap->ad_add_info != NULLCP) + new ->rr_supplementary = + strdup (ap->ad_add_info); + + new -> rr_converted = (EncodedIT *) + calloc (1, sizeof *new -> rr_converted); + new -> rr_converted->eit_types = + list_bpt_dup(qp -> encodedinfo.eit_types); + break; + } + + if (update && + rp_isbad (retval = wr_ad_status(ap, ap -> ad_status))) + return retval; + } + + + retval = dr2txt (fp, &DeliveryReport); + + dr_free (&DeliveryReport); + + return (retval == OK ? RP_OK : RP_FIO); +} + + + + +static void set_succ_suppl (ap, msgtype, msg_buf) +ADDR *ap; +int msgtype; +char *msg_buf; +{ + + char *str; + + + if (ap->ad_outchan && ap->ad_outchan->li_chan && + ap->ad_outchan->li_chan->ch_access == CH_MTS) + str = "Delivered"; + else + str = "Relayed"; + + if (msgtype == MT_PMPDU) { /* probe */ + (void) sprintf (msg_buf, +"%s to '%s' (Probe acknowledgement by PP gateway at '%s')", + str, ap->ad_outchan->li_mta, x400_mta); + } + else + (void) sprintf (msg_buf, "%s to '%s'", + str, ap->ad_outchan->li_mta); + + return; +} diff --git a/Lib/make b/Lib/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Lib/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/or/Makefile b/Lib/or/Makefile new file mode 100644 index 0000000..5da3860 --- /dev/null +++ b/Lib/or/Makefile @@ -0,0 +1,313 @@ +# Makefile for the O/R-name library routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/or/RCS/Makefile,v 6.0 1991/12/18 20:23:08 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:23:08 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = or2pe.c or_add.c or_asc2ps.c or_basic.c \ + or_blank.c or_buildpn.c or_check.c or_default.c or_dmn2or.c \ + or_getpn.c or_init.c or_misc.c or_or2dmn.c or_or2rbits.c \ + or_or2rfc.c or_or2std.c or_ps2asc.c or_rbits2or.c or_rfc2or.c \ + or_search.c or_std2or.c or_tables.c or_util.c \ + orn-dec.c orn-enc.c orn-util.c pe2or.c or_downgrade.c \ + or_up_bnds.c or_valid.c +OBJS = or2pe.o or_add.o or_asc2ps.o or_basic.o \ + or_blank.o or_buildpn.o or_check.o or_default.o or_dmn2or.o \ + or_getpn.o or_init.o or_misc.o or_or2dmn.o or_or2rbits.o \ + or_or2rfc.o or_or2std.o or_ps2asc.o or_rbits2or.o or_rfc2or.o \ + or_search.o or_std2or.o or_tables.o or_util.o \ + orn-dec.o orn-enc.o orn-util.o pe2or.o or_downgrade.o \ + or_up_bnds.o or_valid.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h + +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = or-made +LIBPP = ../libpp.a + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +.SUFFIXES: .py + +.py.c: + $(PEPY) $(PYFLAGS) -o $@ $*.py + +default: $(SHADOW) + + + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) $(LIBPP) $? + touch $@ + +lintlib:llib-lor.ln +llib-lor.ln: $(SRCS) + $(LINT) -Cor $(LLFLAGS) $(SRCS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +install:; + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +clean: tidy + rm -f $(OBJS) or2pe.c pe2or.c llib-lor.ln *.ph ORN* + +tidy: + rm -f core $(SHADOW) $(PROGS) *.old *.BAK + +depend: $(SRCS) + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of building rules +# +############################################################ +# + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +or2pe.o: or2pe.c +or2pe.o: ../../h/util.h +or2pe.o: ../../h/config.h +or2pe.o: ../../h/ll_log.h +or2pe.o: ../../h/or.h +or_add.o: or_add.c +or_add.o: ../../h/util.h +or_add.o: ../../h/config.h +or_add.o: ../../h/ll_log.h +or_add.o: ../../h/or.h +or_asc2ps.o: or_asc2ps.c +or_asc2ps.o: ../../h/util.h +or_asc2ps.o: ../../h/config.h +or_asc2ps.o: ../../h/ll_log.h +or_asc2ps.o: ../../h/or.h +or_basic.o: or_basic.c +or_basic.o: ../../h/or.h +or_basic.o: ../../h/util.h +or_basic.o: ../../h/config.h +or_basic.o: ../../h/ll_log.h +or_blank.o: or_blank.c +or_blank.o: ../../h/or.h +or_blank.o: ../../h/util.h +or_blank.o: ../../h/config.h +or_blank.o: ../../h/ll_log.h +or_buildpn.o: or_buildpn.c +or_buildpn.o: ../../h/or.h +or_buildpn.o: ../../h/util.h +or_buildpn.o: ../../h/config.h +or_buildpn.o: ../../h/ll_log.h +or_check.o: or_check.c +or_check.o: ../../h/util.h +or_check.o: ../../h/config.h +or_check.o: ../../h/ll_log.h +or_check.o: ../../h/or.h +or_check.o: ../../h/table.h +or_default.o: or_default.c +or_default.o: ../../h/or.h +or_default.o: ../../h/util.h +or_default.o: ../../h/config.h +or_default.o: ../../h/ll_log.h +or_dmn2or.o: or_dmn2or.c +or_dmn2or.o: ../../h/or.h +or_dmn2or.o: ../../h/util.h +or_dmn2or.o: ../../h/config.h +or_dmn2or.o: ../../h/ll_log.h +or_getpn.o: or_getpn.c +or_getpn.o: ../../h/or.h +or_getpn.o: ../../h/util.h +or_getpn.o: ../../h/config.h +or_getpn.o: ../../h/ll_log.h +or_init.o: or_init.c +or_init.o: ../../h/head.h +or_init.o: ../../h/util.h +or_init.o: ../../h/config.h +or_init.o: ../../h/ll_log.h +or_init.o: ../../h/retcode.h +or_init.o: ../../h/mta.h +or_init.o: ../../h/adr.h +or_init.o: ../../h/list_rchan.h +or_init.o: ../../h/chan.h +or_init.o: ../../h/table.h +or_init.o: ../../h/list_bpt.h +or_init.o: ../../h/auth.h +or_init.o: ../../h/list_bpt.h +or_init.o: ../../h/extension.h +or_init.o: ../../h/mta.h +or_init.o: ../../h/aparse.h +or_init.o: ../../h/ap.h +or_init.o: ../../h/util.h +or_init.o: ../../h/or.h +or_init.o: ../../h/chan.h +or_init.o: ../../h/auth.h +or_init.o: ../../h/list_rchan.h +or_init.o: ../../h/list_bpt.h +or_init.o: ../../h/or.h +or_misc.o: or_misc.c +or_misc.o: ../../h/util.h +or_misc.o: ../../h/config.h +or_misc.o: ../../h/ll_log.h +or_misc.o: ../../h/table.h +or_misc.o: ../../h/or.h +or_misc.o: ../../h/ap.h +or_misc.o: ../../h/util.h +or_or2dmn.o: or_or2dmn.c +or_or2dmn.o: ../../h/or.h +or_or2dmn.o: ../../h/util.h +or_or2dmn.o: ../../h/config.h +or_or2dmn.o: ../../h/ll_log.h +or_or2rbits.o: or_or2rbits.c +or_or2rbits.o: ../../h/or.h +or_or2rbits.o: ../../h/util.h +or_or2rbits.o: ../../h/config.h +or_or2rbits.o: ../../h/ll_log.h +or_or2rbits.o: ../../h/table.h +or_or2rfc.o: or_or2rfc.c +or_or2rfc.o: ../../h/or.h +or_or2rfc.o: ../../h/util.h +or_or2rfc.o: ../../h/config.h +or_or2rfc.o: ../../h/ll_log.h +or_or2rfc.o: ../../h/ap.h +or_or2rfc.o: ../../h/util.h +or_or2std.o: or_or2std.c +or_or2std.o: ../../h/or.h +or_or2std.o: ../../h/util.h +or_or2std.o: ../../h/config.h +or_or2std.o: ../../h/ll_log.h +or_ps2asc.o: or_ps2asc.c +or_ps2asc.o: ../../h/util.h +or_ps2asc.o: ../../h/config.h +or_ps2asc.o: ../../h/ll_log.h +or_rbits2or.o: or_rbits2or.c +or_rbits2or.o: ../../h/or.h +or_rbits2or.o: ../../h/util.h +or_rbits2or.o: ../../h/config.h +or_rbits2or.o: ../../h/ll_log.h +or_rbits2or.o: ../../h/table.h +or_rfc2or.o: or_rfc2or.c +or_rfc2or.o: ../../h/or.h +or_rfc2or.o: ../../h/util.h +or_rfc2or.o: ../../h/config.h +or_rfc2or.o: ../../h/ll_log.h +or_rfc2or.o: ../../h/ap.h +or_rfc2or.o: ../../h/util.h +or_search.o: or_search.c +or_search.o: ../../h/or.h +or_search.o: ../../h/util.h +or_search.o: ../../h/config.h +or_search.o: ../../h/ll_log.h +or_std2or.o: or_std2or.c +or_std2or.o: ../../h/or.h +or_std2or.o: ../../h/util.h +or_std2or.o: ../../h/config.h +or_std2or.o: ../../h/ll_log.h +or_tables.o: or_tables.c +or_tables.o: ../../h/config.h +or_tables.o: ../../h/or.h +or_util.o: or_util.c +or_util.o: ../../h/util.h +or_util.o: ../../h/config.h +or_util.o: ../../h/ll_log.h +or_util.o: ../../h/or.h +orn-dec.o: orn-dec.c +orn-dec.o: ../../h/MTA-types.h +orn-dec.o: ../../h/Toks-types.h +orn-dec.o: ../../h/Auth-types.h +orn-dec.o: ../../h/Ext-types.h +orn-dec.o: ../../h/MTA-types.h +orn-dec.o: ../../h/Toks-types.h +orn-dec.o: ../../h/Auth-types.h +orn-dec.o: ../../h/util.h +orn-dec.o: ../../h/config.h +orn-dec.o: ../../h/ll_log.h +orn-dec.o: ../../h/or.h +orn-dec.o: ../../h/extension.h +orn-dec.o: ../../h/IOB-types.h +orn-dec.o: ../../h/MTA-types.h +orn-enc.o: orn-enc.c +orn-enc.o: ../../h/util.h +orn-enc.o: ../../h/config.h +orn-enc.o: ../../h/ll_log.h +orn-enc.o: ../../h/or.h +orn-enc.o: ../../h/IOB-types.h +orn-enc.o: ../../h/MTA-types.h +orn-enc.o: ../../h/Toks-types.h +orn-enc.o: ../../h/Auth-types.h +orn-enc.o: ../../h/MTA-types.h +orn-enc.o: ../../h/Ext-types.h +orn-enc.o: ../../h/MTA-types.h +orn-enc.o: ../../h/Toks-types.h +orn-enc.o: ../../h/Auth-types.h +orn-enc.o: ../../h/extension.h +orn-util.o: orn-util.c +orn-util.o: ../../h/util.h +orn-util.o: ../../h/config.h +orn-util.o: ../../h/ll_log.h +orn-util.o: ../../h/or.h +orn-util.o: ../../h/IOB-types.h +orn-util.o: ../../h/MTA-types.h +orn-util.o: ../../h/Toks-types.h +orn-util.o: ../../h/Auth-types.h +orn-util.o: ../../h/MTA-types.h +orn-util.o: ../../h/Ext-types.h +orn-util.o: ../../h/MTA-types.h +orn-util.o: ../../h/Toks-types.h +orn-util.o: ../../h/Auth-types.h +orn-util.o: ../../h/extension.h +pe2or.o: pe2or.c +pe2or.o: ../../h/util.h +pe2or.o: ../../h/config.h +pe2or.o: ../../h/ll_log.h +pe2or.o: ../../h/or.h +or_downgrade.o: or_downgrade.c +or_downgrade.o: ../../h/util.h +or_downgrade.o: ../../h/config.h +or_downgrade.o: ../../h/ll_log.h +or_downgrade.o: ../../h/or.h +or_downgrade.o: ../../h/ap.h +or_downgrade.o: ../../h/util.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/or/make b/Lib/or/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/or/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/or/or2pe.py b/Lib/or/or2pe.py new file mode 100644 index 0000000..04de7e5 --- /dev/null +++ b/Lib/or/or2pe.py @@ -0,0 +1,198 @@ +-- or2pe: OR structure to P1 OR name + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/or/RCS/or2pe.py,v 6.0 1991/12/18 20:23:08 jpo Rel $ +-- +-- $Log: or2pe.py,v $ +-- Revision 6.0 1991/12/18 20:23:08 jpo +-- Release 6.0 +-- +-- +-- + + +OR DEFINITIONS ::= + +%{ +#ifndef lint +static char *Rcsid = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or2pe.py,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +#endif lint + +#include "util.h" +#include "or.h" +#include + +# define PEPYPARM OR_ptr + +# define or_present(or, type) (or_locate(or, type) != NULLOR) + +PE or2pe (or) +OR_ptr or; +{ + PE pe = NULLPE; + PE tpe; + + if (build_OR_ORName (&pe, 1, 0, NULLCP, or) == NOTOK) { + if (pe) + pe_free (pe); + return NULLPE; + } + /* SEK - strip off the APPLICATION TAG */ + tpe = pe -> pe_cons; + pe -> pe_cons = NULLPE; + pe_free (pe); + return tpe; +} + +#undef DEBUG +%} + +BEGIN + +ENCODER build +-- O/R name + +ORName ::= + [APPLICATION 0] + IMPLICIT SEQUENCE { + standard + StandardAttributeList [[p parm]], + + domaindefined + DomainDefinedAttributeList [[p parm]] + OPTIONAL <> + } + +StandardAttributeList + %{ + OR_ptr op; + %} ::= + SEQUENCE { + CountryName + [[p or_locate (parm, OR_C)]] + OPTIONAL + <>, + + AdministrationDomainName + [[p or_locate (parm, OR_ADMD)]] + OPTIONAL + << or_present (parm, OR_ADMD) >>, + + [0] + IMPLICIT X121Address + [[s or_value (parm, OR_X121)]] + OPTIONAL + << or_present (parm, OR_X121) >>, + + [1] + IMPLICIT TerminalID [[s or_value (parm, OR_TID) ]] + OPTIONAL << or_present (parm, OR_TID) >>, + + [2] + PrivateDomainName + [[p or_locate (parm, OR_PRMD)]] + OPTIONAL << or_present (parm, OR_PRMD) >>, + + [3] + IMPLICIT OrganizationName [[s or_value (parm, OR_O)]] + OPTIONAL <>, + + [4] + IMPLICIT UniqueUAIdentifier + [[p or_locate (parm, OR_UAID)]] + OPTIONAL << or_present (parm, OR_UAID) >>, + + [5] + IMPLICIT PersonalName [[p parm]] + OPTIONAL <>, + + [6] + IMPLICIT SEQUENCE OF + < or_type == OR_OU; + op = op -> or_next >> + OrganizationalUnit [[s op -> or_value]] + OPTIONAL <> + } + +DomainDefinedAttributeList +%{ + OR_ptr op; +%} ::= + SEQUENCE OF << op = or_lastpart (parm); + op && op -> or_type == OR_DD; + op = op -> or_prev>> + DomainDefinedAttribute [[p op]] + +DomainDefinedAttribute ::= + SEQUENCE { + type + PrintableString [[s parm -> or_ddname]], + + value + PrintableString [[s parm -> or_value]] + } + +CountryName ::= + [APPLICATION 1] + CHOICE << or_str_isns (parm -> or_value) ? 1 : 2 >> { + NumericString [[s parm -> or_value ]], + PrintableString [[s parm -> or_value ]] + } + +AdministrationDomainName ::= + [APPLICATION 2] + CHOICE << or_str_isns (parm -> or_value) ? 1 : 2 >> { + NumericString [[s parm -> or_value]], + PrintableString [[s parm -> or_value]] + } + +PrivateDomainIdentifier ::= + CHOICE << or_str_isns (parm -> or_value) ? 1 : 2 >> { + NumericString [[s parm -> or_value]], + + PrintableString [[s parm -> or_value]] + } + + +X121Address ::= + NumericString + +TerminalID ::= + PrintableString + +OrganizationName ::= + PrintableString + +UniqueUAIdentifier ::= + NumericString [[s parm -> or_value]] + +PersonalName ::= + SET { + surName[0] + IMPLICIT PrintableString [[s or_value (parm, OR_S)]], + + givenName[1] + IMPLICIT PrintableString [[s or_value (parm, OR_G)]] + OPTIONAL <>, + + initials[2] + IMPLICIT PrintableString [[s or_value (parm, OR_I)]] + OPTIONAL <>, + + generalQualifier[3] + IMPLICIT PrintableString [[s or_value (parm, OR_GQ)]] + OPTIONAL <> + } + +OrganizationalUnit ::= + PrintableString + +PrivateDomainName ::= + CHOICE << or_str_isns (parm -> or_value) ? 1 : 2 >> { + NumericString [[s parm -> or_value]], + + PrintableString [[s parm -> or_value]] + } + +END diff --git a/Lib/or/or_add.c b/Lib/or/or_add.c new file mode 100644 index 0000000..59f4308 --- /dev/null +++ b/Lib/or/or_add.c @@ -0,0 +1,247 @@ +/* or_add.c: add an orname component to the list */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_add.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_add.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_add.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "or.h" + +OR_ptr or_add (tree, or, before) +OR_ptr tree; +OR_ptr or; +int before; /* if true then add equal values at front */ +{ + OR_ptr current; + char *name; + + /* this routine is horrible */ + /* MUST be able to rewrite more efficiently */ + + PP_DBG (("or_util.c/or_add ('%d', '%s')", + or -> or_type, or -> or_value)); + + if (or == NULLOR) + return tree; + + if (tree == NULLOR) { + or -> or_next = NULLOR; + or -> or_prev = NULLOR; + return (or); + } + + if (or -> or_type == OR_OU) { + int ou_count = 1; + /* check for exceding upper limit */ + for (current = tree; + current != NULLOR && current->or_type <= OR_OU; + current = current -> or_next) + if (current->or_type == OR_OU) + ou_count++; + if (ou_count > MAX_OU) { + (void) or_lose("Exceeds upperbound on the number of OrganizataionalUnits (%d OUs)", + MAX_OU); + return NULLOR; + } + } else if (or -> or_type == OR_DD) { + int dda_count = 1; + /* check for exceding upper limit */ + for (current = tree; + current != NULLOR && current->or_type <= OR_DD; + current = current -> or_next) + if (current->or_type == OR_DD) + dda_count++; + if (dda_count > MAX_DDA) { + (void) or_lose("Exceeds upperbound on the number of Domain Defined Attributes (%d DDAs)", + MAX_DDA); + return NULLOR; + } + } + + + if (or -> or_type < tree -> or_type) { + or -> or_next = tree; + tree -> or_prev = or; + or -> or_prev = NULLOR; + return (or); + } + + + if (or -> or_type == tree -> or_type) { + + if (or -> or_type != OR_OU && or -> or_type != OR_DD) { + if ((name = or_type2name (or -> or_type)) == NULLCP) + (void) or_lose("Illegal duplicate component type '%d' (%s & %s)", + or -> or_type, + or -> or_value, tree -> or_value); + else + (void) or_lose("Illegal duplicate component type '%s' (%s & %s)", + name, + or -> or_value, tree -> or_value); + + return NULLOR; + } + + if (before) { + or -> or_next = tree; + tree -> or_prev = or; + or -> or_prev = NULLOR; + return (or); + } + } + + + for (current = tree; current != NULLOR; current = current -> or_next) { + + if (current -> or_next == NULLOR) { + current -> or_next = or; + or -> or_prev = current; + or -> or_next = NULLOR; + return (tree); + } + + if (or -> or_type < current -> or_next -> or_type) { + or -> or_next = current -> or_next; + current -> or_next -> or_prev = or; + or -> or_prev = current; + current -> or_next = or; + return (tree); + } + + if (or -> or_type == current -> or_next -> or_type) { + + if (or -> or_type != OR_OU && or -> or_type != OR_DD) { + if ((name = or_type2name (or -> or_type)) == NULLCP) + (void) or_lose("Illegal duplicate type '%d' (%s & %s)", + or->or_type, + or->or_value, current->or_value); + else + (void) or_lose ("Illegal duplicate type '%s' (%s & %s)", + name, + or -> or_value, + current -> or_value); + return NULLOR; + } + + if (before) { + or -> or_next = current -> or_next; + current -> or_next -> or_prev = or; + or -> or_prev = current; + current -> or_next = or; + return (tree); + } + + } /* end of if */ + + } /* end of for */ + + + PP_LOG (LLOG_EXCEPTIONS, ("or_util.c/or_add () - serious problem")); + return NULLOR; +} + +OR_ptr or_add_t61 (tree, type, value,len, before) +OR_ptr tree; +int type; +unsigned char *value; +int before; +{ + OR_ptr or; + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + + or_t61encode (buf, value, len); + if ((or = or_locate (tree, type)) == NULLOR) { + (void) sprintf (buf2, "*%s", buf); + or = or_new_aux (type, NULLCP, buf2, OR_ENC_TTX); + return or_add (tree, or, before); + } + + if (or -> or_encoding != OR_ENC_PS) { + PP_LOG(LLOG_EXCEPTIONS, ("Encoding not plain PS")); + return NULLOR; + } + + (void) sprintf (buf2, "%s*%s", or -> or_value, buf); + or -> or_encoding = OR_ENC_TTX_AND_OR_PS; + if (or -> or_value) + free (or -> or_value); + or -> or_value = strdup (buf2); + return tree; +} + +void or_t61encode (buf, str, len) +char *buf; +unsigned char *str; +int len; +{ + int n; + int inbracket = 0; + char *p = buf; + + for (n = 0; n < len; n++) { + if (*str < 128 && or_isps(*str)) { + if (inbracket) { + *p ++ = '}'; + inbracket = 0; + } + *p ++ = *str ++; + } + else { + if (! inbracket) { + inbracket = 1; + *p++ = '{'; + } + *p++ = (*str) / 100 + '0'; + *p++ = (unsigned char) ((*str) % 100) / 10 + '0'; + *p++ = (*str++) % 10 + '0'; + } + } + if (inbracket) + *p++ = '}'; + *p = 0; +} + +struct qbuf *or_t61decode (str) +char *str; +{ + unsigned char buf[BUFSIZ]; + unsigned char *p; + int n; + int inbracket = 0; + + for (n = 0, p = buf; *str; n++) { + if (inbracket) { + if (*str == '}') { + inbracket = 0; + str ++; + } + else { + *p = (*str++ - '0') * 100; + *p += (*str++ - '0') * 10; + *p++ += (*str++ - '0'); + } + } + else { + if (*str == '{') { + inbracket = 1; + str ++; + } + else + *p++ = *str++; + } + } + p = 0; + return str2qb ((char *)buf, n, 1); +} diff --git a/Lib/or/or_asc2ps.c b/Lib/or/or_asc2ps.c new file mode 100644 index 0000000..ab47cdf --- /dev/null +++ b/Lib/or/or_asc2ps.c @@ -0,0 +1,81 @@ +/* or_asc2ps.c: convert ascii to printable string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_asc2ps.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_asc2ps.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_asc2ps.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "or.h" + +int real987 = NOTOK; + +int or_asc2ps (ascii, ps) +char *ascii; +char *ps; +{ + register char *p, *q; + int converted; + PP_DBG (("Lib/or_asc2ps()")); + + q = ps; + converted = OK; + for (p = ascii; *p != '\0'; p++) { + + if (or_isps (*p) && *p != ')' && *p != '(') + *q++ = *p; + else { + converted = NOTOK; + *q++ = '('; + switch (*p) { + case '@': + *q++ = 'a'; + break; + case '%': + *q++ = 'p'; + break; + case '!': + *q++ = 'b'; + break; + case '"': + *q++ = 'q'; + break; + case '_': + *q++ = 'u'; + break; + case '(': + if (real987 == NOTOK) { + *q++ = 'l'; + break; + } + case ')': + if (real987 == NOTOK) { + *q++ = 'r'; + break; + } + default: + (void) sprintf (q, "%03d", *p); + q = q + 3; + break; + + } /* end of switch */ + + *q++ = ')'; + + } /* end of if */ + + } /* end of for */ + + *q = '\0'; + return converted; +} diff --git a/Lib/or/or_basic.c b/Lib/or/or_basic.c new file mode 100644 index 0000000..46ea704 --- /dev/null +++ b/Lib/or/or_basic.c @@ -0,0 +1,152 @@ +/* or_basic.c: basic low level or structure manipulation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_basic.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_basic.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_basic.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + + +OR_ptr or_new (type, ddname, value) +int type; +char *ddname; +char *value; +{ + int enc = or_type2charset (type); + char *cp; + + if (strcmp(value, "@") == 0) + return or_new_aux(type, ddname, value, OR_ENC_PP); + + switch (enc) { + case OR_ENC_TTX_AND_OR_PS: + for (cp = value; *cp; cp ++) { + if (!or_isps (*cp)) { + if (*cp == '*') { + if(cp == value) + enc = OR_ENC_TTX; + /* else stay as you were */ + } + (void) or_lose ("Bad string syntax %s", + value); + return NULLOR; + } + } + if (*cp == '\0') + enc = OR_ENC_PS; + break; + case OR_ENC_PS: + case OR_ENC_NUM: + case OR_ENC_TTX: + case OR_ENC_INT: + case OR_ENC_PSAP: + case OR_ENC_PP: + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown encoding for type %d val %s", + type, value)); + } + return or_new_aux (type, ddname, value, enc); +} + +OR_ptr or_new_aux (type, ddname, value, encoding) +int type; +char *ddname; +char *value; +int encoding; +{ + OR_ptr or; + + PP_DBG (("or_util.c/or_new ('%d', '%s', '%s')", + type, ddname ? ddname : "", + value ? value : "")); + + switch (encoding) { /* check the easy ones */ + case OR_ENC_PS: + if (!or_str_isps (value)) { + (void) or_lose ("Not a printable string %s", value); + return NULLOR; + } + if (type == OR_DD && !or_str_isps (ddname)) { + (void) or_lose ("DD type %s not a printable string", + ddname); + return NULLOR; + } + break; + case OR_ENC_NUM: + if (!or_str_isns (value)) { + (void) or_lose ("Not a numeric string %s", value); + return NULLOR; + } + break; + default: + break; + } + or = (OR_ptr) smalloc (sizeof (struct or_part)); + if (or == NULLOR) + return NULLOR; + + or -> or_type = type; + or -> or_encoding = encoding; + or -> or_next = NULLOR; + or -> or_prev = NULLOR; + + if (type != OR_DD ) { + or -> or_ddname = NULLCP; + or -> or_value = strdup (value); + } + else { + or -> or_ddname = strdup (ddname); + or -> or_value = strdup (value); + } + return (or); +} + +OR_ptr or_dup (or) +OR_ptr or; +{ + return (or_new_aux (or -> or_type, or -> or_ddname, + or -> or_value, or -> or_encoding)); +} + +OR_ptr or_tdup (or) +OR_ptr or; +{ + OR_ptr new = NULLOR; + + if (or == NULLOR) + return NULLOR; + new = or_dup (or); + new -> or_next = or_tdup (or -> or_next); + if (new -> or_next) + new -> or_next -> or_prev = new; + return new; +} + +void or_free (tree) +OR_ptr tree; +{ + if (tree == NULLOR) + return; + + if (tree -> or_next) + or_free (tree -> or_next); + if (tree -> or_value) + free (tree -> or_value); + if (tree -> or_ddname) + free (tree -> or_ddname); + free ((char *)tree); +} diff --git a/Lib/or/or_blank.c b/Lib/or/or_blank.c new file mode 100644 index 0000000..b9f9734 --- /dev/null +++ b/Lib/or/or_blank.c @@ -0,0 +1,60 @@ +/* or_blank.c: do strange things with blanks. */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_blank.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_blank.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_blank.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +int or_blank (or) +OR_ptr *or; +{ + OR_ptr ptr; + + PP_DBG (("Lib/or_blankor (i.e no addr given)")); + + *or = or_new (OR_S, "", ""); + ptr = or_new (OR_OU, "", ""); + *or = or_add (*or, ptr, TRUE); + + if (*or == NULLOR) + return (NOTOK); + + ptr = or_new (OR_O, "", ""); + *or = or_add (*or, ptr, TRUE); + + if (*or == NULLOR) + return (NOTOK); + + ptr = or_new (OR_PRMD, NULLCP, ""); + *or = or_add (*or, ptr, TRUE); + + if (*or == NULLOR) + return (NOTOK); + + ptr = or_new (OR_ADMD, NULLCP, ""); + *or = or_add (*or, ptr, TRUE); + + if (*or == NULLOR) + return (NOTOK); + + ptr = or_new (OR_C, NULLCP, ""); + *or = or_add (*or, ptr, TRUE); + + if (*or == NULLOR) + return (NOTOK); + + return (OK); +} diff --git a/Lib/or/or_buildpn.c b/Lib/or/or_buildpn.c new file mode 100644 index 0000000..f286b43 --- /dev/null +++ b/Lib/or/or_buildpn.c @@ -0,0 +1,95 @@ +/* or_buildpn: build a personal name from string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_buildpn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_buildpn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_buildpn.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +/* +Takes string and builds a tree +*/ + +OR_ptr or_buildpn (str) +char *str; +{ + OR_ptr or, + tor, + tree; + char tbuf[LINESIZE], + *q, + *r; + + PP_DBG (("or_util.c/or_buildpn (%s)", str)); + + tree = NULLOR; + + if ((q = index (str, '.')) == NULLCP) + /* + Only a surname is specified + */ + q = str; + else { + if ((q - str) > 1) { + /* + A given name is specified + */ + *q++ = '\0'; + tree = or_new (OR_G, NULLCP, str); + } + else + q = str; + + /* + Do the initials from q + */ + + r = tbuf; + + while (TRUE) { + if (!isalnum (*q) || (*(q + 1) != '.')) + break; + *r++ = *q; + q = q + 2; + } + + *r = '\0'; + + if (tbuf[0] != '\0') { + if ((or = or_new (OR_I, NULLCP, tbuf)) == NULLOR) + return NULLOR; + + if ((tor = or_add (tree, or, TRUE)) == NULLOR) { + or_free (or); + return NULLOR; + } + tree = tor; + } + } + + /* + q now points to start of surname + */ + + if ((or = or_new (OR_S, NULLCP, q)) == NULLOR) + return NULLOR; + tor = or_add (tree, or, TRUE); + if (tor == NULLOR) { + or_free (tree); + return NULLOR; + } + tree = tor; + return tree; +} diff --git a/Lib/or/or_check.c b/Lib/or/or_check.c new file mode 100644 index 0000000..6a93ce8 --- /dev/null +++ b/Lib/or/or_check.c @@ -0,0 +1,390 @@ +/* or_check.c: check and normalise or names */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_check.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_check.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_check.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "or.h" +#include "table.h" +#include + +extern CMD_TABLE ortbl_rfc822ddas[]; +extern char *or_tbl; +static Table *tb_or; +char or_error[BUFSIZ] = ""; + + +/* --------------------- Begin Routines -------------------------------- */ + + +/* --- *** --- +or_check (or, buf, buf_type, locname) where: + or - what is being checked + buf - what is returned + buf_type - Channel or local + lsubdom - local proferred table + replace - if synonym'd place to put replacement or +--- *** --- */ + +#define MAX_NUM_REPLACES 25 +#define WILDCARD "*" + +static int or_fill_wilds_and_swap(); + +static int allRFC822DDA (or) +OR_ptr or; +{ + while (or != NULLOR + && or->or_type == OR_DD + && cmd_srch(or->or_ddname, ortbl_rfc822ddas) != -1) + or = or->or_next; + if (or == NULLOR) + return TRUE; + return FALSE; +} + +int or_check (or, buf, buf_type, lsubdom, replace, lastMatch) +OR_ptr *or; +char *buf; +int *buf_type; +char **lsubdom; +char **replace; +OR_ptr *lastMatch; +{ + OR_ptr tptr, + sptr, + current_ptr, + tree; + char current_val[LINESIZE], + tbuf[LINESIZE], + tracebuf[LINESIZE], + *oargv[10]; + int oargc; + char first_lookup[BUFSIZ]; + int postReplace = FALSE, + num_replaces = 0, + aliased = FALSE; + + PP_DBG (("Lib/or_chk()")); + + first_lookup[0] ='\0'; + if (replace != (char **) NULL) + *replace = NULLCP; + + *lastMatch = NULLOR; + *lsubdom = NULLCP; + if ((tptr = loc_ortree) == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/or_chk: loc_ortree missing")); + return NOTOK; + } + + if ((current_ptr = tree = or_tdup(*or)) == NULLOR) + return or_lose ("No OR specified for checking"); + + + if (tb_or == NULLTBL) { + if ((tb_or = tb_nm2struct (or_tbl)) == NULLTBL) + return or_lose ("No or table!!!"); + } + + or_or2std (tree, tracebuf, FALSE); + PP_TRACE (("Lib/or_chk's tracebuf: '%s'", tracebuf)); + + buf[0] = '\0'; + + for (;;) { + or_or2dmn (NULLOR, current_ptr, current_val); + PP_DBG (("Lib/or_chk: Checking part: '%s'", current_val)); + + + if (tb_k2val (tb_or, current_val, tbuf, TRUE) != OK) { + char *holder = NULLCP; + char prev_current_val[LINESIZE]; + (void) strcpy(prev_current_val, current_val); + if (current_ptr != NULLOR) { + holder = current_ptr -> or_value; + current_ptr -> or_value = strdup(WILDCARD); + or_or2dmn (NULLOR, current_ptr, current_val); + } + if (current_ptr != NULLOR + && tb_k2val (tb_or, current_val, tbuf, TRUE) == OK) { + if (holder) + free(holder); + } else { + if (current_ptr) { + free(current_ptr -> or_value); + current_ptr -> or_value = holder; + } + if (buf[0] == '\0' && postReplace == FALSE) { + char *orargv[10], tmp[BUFSIZ]; + char *dollar; + (void) strcpy(current_val, prev_current_val); + PP_DBG (("Lib/or_chk: Check failed '%s' '%s'", + current_val, tracebuf)); + if (first_lookup[0] != '\0') + or_or2std(or_lastpart(tree), tmp, FALSE); + else + tmp[0] = '\0'; + + if (sstr2arg (current_val, 9, orargv, ".")) { + if ((dollar = index (orargv[0], '$')) != NULLCP) + *dollar = ' '; + if (first_lookup[0] == '\0' + || lexequ(first_lookup, tmp) == 0) + (void) or_lose ( + "Unknown '%s' in '%s'", + orargv[0], tracebuf); + else + (void) or_lose ( + "Unknown '%s' in '%s' (aka '%s')", + orargv[0], tmp, first_lookup); + } + else { + if (first_lookup[0] == '\0' + || lexequ(first_lookup, tmp) == 0) + (void) or_lose ( + "Unknown '%s' in '%s'", + current_val, tracebuf); + else + (void) or_lose ( + "Unknown '%s' in '%s' (aka '%s')", + current_val, tmp, first_lookup); + } + return NOTOK; + } + else if (buf[0] == '\0' && postReplace == TRUE) { + /* no direct match with replacement */ + /* rewind checking and start again */ + current_ptr = tree; + postReplace = FALSE; + continue; + } + else { + if (or_fill_wilds_and_swap(or, tree) != OK) { + (void) or_lose ("Local wildcard OR problems for '%s'", + tracebuf); + return NOTOK; + } + or_chk_admd(or); + return OK; + } + } + } + + postReplace = FALSE; + + PP_DBG (("Lib/or_chk: Hit: '%s'", tbuf)); + + /* --- Have found a pointer --- */ + oargc = sstr2arg (tbuf, 9, oargv, " \t\n,"); + + if (lexequ (oargv[0], "valid") == 0) { + buf[0] = '\0'; + current_ptr = current_ptr -> or_next; + continue; + } + + + if (lexequ (oargv[0], "local") == 0) { + /* --- This is local - map rest to buf --- */ + if (current_ptr -> or_next == NULLOR) + return or_lose ( + "local entry found - but no more components '%s'", + tracebuf); + else if (allRFC822DDA(current_ptr -> or_next) == TRUE) { + tptr = current_ptr->or_next; + tptr->or_prev = NULLOR; + or_or2std(tptr, buf, TRUE); + tptr->or_prev = current_ptr; + return or_lose( + "unknown local user '%s'", + buf); + } + + *lastMatch = tptr = current_ptr; + current_ptr = current_ptr -> or_next; + current_ptr -> or_prev = NULLOR; + + if (current_ptr -> or_type <= OR_OU + || (or_getpn (current_ptr, buf) == FALSE)) + or_or2std (current_ptr, buf, TRUE); + + current_ptr -> or_prev = tptr; + *buf_type = OR_ISLOCAL; + + PP_TRACE (("Lib/or_chk: Returning local: '%s' '%s' ", + buf, tracebuf)); + if (oargc > 1) + *lsubdom = strdup (oargv[1]); + continue; + } /* --- end of if local --- */ + + + if (oargc < 2) + return or_lose ("Format error in OR table '%s' '%s'", + current_val, tracebuf); + + + if (lexequ (oargv[0], "mta") == 0) { + (void) strcpy (buf, oargv[1]); + *buf_type = OR_ISMTA; + *lastMatch = current_ptr; + current_ptr = current_ptr -> or_next; + continue; + } + + + if (lexequ (oargv[0], "realalias") == 0) { + /* --- invalidate previous hits --- */ + buf[0] = '\0'; + postReplace = TRUE; + aliased = TRUE; + if (++num_replaces > MAX_NUM_REPLACES) + return or_lose ("Too many aliases/synonyms when resolving '%s'", + tracebuf); + + if ((tptr = or_dmn2or (oargv[1])) == NULLOR) + return or_lose ("Invalid syntax alias '%s' '%s'", + oargv[1], tracebuf); + + if (first_lookup[0] == '\0') + or_or2std(or_lastpart(tree), first_lookup, FALSE); + + /* --- free off old head --- */ + if ((sptr = current_ptr -> or_next) != NULLOR) { + sptr -> or_prev = NULLOR; + current_ptr -> or_next = NULLOR; + } + or_free (tree); + + /* --- add in the new stuff --- */ + tree = tptr; + current_ptr = or_lastpart (tptr); + + if (sptr != NULLOR) { + /* --- add back in the rest of old stuff */ + if (sptr -> or_type < current_ptr -> or_type) + return or_lose ("Alias out of order '%s' '%s'", + oargv[1], tracebuf); + + current_ptr -> or_next = sptr; + sptr -> or_prev = current_ptr; + } + continue; + } /* --- end of if alias --- */ + + if (lexequ (oargv[0], "synonym") == 0 + || lexequ (oargv[0], "alias") == 0) { + /* --- invalidate previous hits --- */ + buf[0] = '\0'; + postReplace = TRUE; + + if (++num_replaces > MAX_NUM_REPLACES) + return or_lose ("Too many aliases/synonyms when resolving '%s'", + tracebuf); + + if ((tptr = or_dmn2or (oargv[1])) == NULLOR) + return or_lose ( + "Invalid syntax alias '%s' '%s'", + oargv[1], tracebuf); + + if (first_lookup[0] == '\0') + or_or2std(or_lastpart(tree), first_lookup, FALSE); + + /* --- free off old head --- */ + if ((sptr = current_ptr -> or_next) != NULLOR) { + sptr -> or_prev = NULLOR; + current_ptr -> or_next = NULLOR; + } + or_free (tree); + + /* --- add in the new stuff --- */ + tree = tptr; + current_ptr = or_lastpart (tptr); + + if (sptr != NULLOR) { + /* --- add back in the rest of old stuff */ + if (sptr -> or_type < current_ptr -> or_type) + return or_lose ( + "Alias out of order '%s' '%s'", + oargv[1], tracebuf); + + current_ptr -> or_next = sptr; + sptr -> or_prev = current_ptr; + } + if (aliased == FALSE + && replace != (char **) NULL) { + char tmp[BUFSIZ]; + if (*replace != NULLCP) + free(*replace); + or_or2std(or_lastpart(tree), tmp, FALSE); + *replace = strdup(tmp); + } + continue; + } /* --- end of if synonym --- */ + + return or_lose ("Unknown alias type '%s' '%s'", + oargv[1], tracebuf); + } /* end of for */ +} + +/* */ + +static int or_fill_wilds_and_swap(por, tree) +OR_ptr *por, tree; +{ + /* take WILDCARDS from por and replace in tree */ + /* then swap trees */ + + OR_ptr ixor, ixt; + int numOU1 = 0, numOU2 = 0; + + for (ixt = tree, ixor = *por; ixt != NULLOR; ixt = ixt->or_next) { + if (lexequ(ixt->or_value, WILDCARD) == 0) { + if (ixt->or_type == OR_OU) { + while (ixor != NULLOR + && (ixor -> or_type != ixt -> or_type + || numOU1 != numOU2)) { + if (ixor -> or_type == OR_OU) + numOU2++; + ixor = ixor -> or_next; + } + } else { + while (ixor != NULLOR && + ixor -> or_type != ixt -> or_type) { + if (ixor -> or_type == OR_OU) + numOU2++; + ixor = ixor -> or_next; + } + } + if (ixor == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to find original valure for wildcard '%s'", + or_type2name(ixt -> or_type))); + return NOTOK; + } + free (ixt -> or_value); + ixt -> or_value = strdup(ixor -> or_value); + ixor = ixor -> or_next; + } + if (ixt->or_type == OR_OU) + numOU1++; + } + + or_free(*por); + + *por = tree; + return OK; +} diff --git a/Lib/or/or_default.c b/Lib/or/or_default.c new file mode 100644 index 0000000..be09921 --- /dev/null +++ b/Lib/or/or_default.c @@ -0,0 +1,122 @@ +/* or_default: add suitable defaults for or structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_default.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_default.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_default.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +extern void fixup_space(); + +OR_ptr or_default_aux (); + +int or_form_type(or) +OR_ptr or; +{ + int or_components[OR_DD+1]; /* must be big enough ... */ + OR_ptr defptr; + + bzero ((char *)or_components, sizeof or_components); + for (defptr = or; defptr; defptr = defptr -> or_next) { + if (defptr -> or_type > OR_DD) + PP_LOG (LLOG_EXCEPTIONS, ("Unknown OR type %d", + defptr -> or_type)); + else + or_components[defptr -> or_type] ++; + } + + /* check for forms of OR address */ + if (or_components[OR_X121]) + return OR_FORM_TERM; + if (or_components[OR_ADMD] && or_components[OR_C] && + or_components[OR_PD_C] && or_components[OR_POSTCODE]) + return OR_FORM_POST; + if (or_components[OR_C] && or_components[OR_ADMD] && + or_components[OR_UAID]) + return OR_FORM_NUMR; + if (or_components[OR_C] && or_components[OR_ADMD]) + return OR_FORM_MNEM; + return OR_FORM_NONE; +} + + +OR_ptr or_default (or) +OR_ptr or; +{ + return or_default_aux(or, loc_ortree); +} + + +OR_ptr or_default_aux (or, merge) +OR_ptr or, merge; +{ + OR_ptr defptr; + OR_ptr new_tree; + OR_ptr tptr = NULLOR; + int before; + char spaceless[BUFSIZ], defspless[BUFSIZ]; + + PP_DBG (("Lib/or_default()")); + + if (or == NULLOR) + return or_tdup(merge); + + new_tree = NULLOR; + switch (or_form_type(or)) { + case OR_FORM_TERM: + case OR_FORM_POST: + case OR_FORM_NUMR: + case OR_FORM_MNEM: + /* recognised form of OrAaddress */ + /* don't merge */ + return or_tdup(or); + default: + break; + } + + for (defptr = merge; defptr != NULLOR; defptr = defptr -> or_next) { + if (or -> or_type <= defptr -> or_type) + if (or->or_type == OR_OU) { + fixup_space(or -> or_value, spaceless); + fixup_space(defptr -> or_value, defspless); + if (lexequ (spaceless, defspless) == 0) + break; + } + else + break; + + tptr = or_dup (defptr); + + if (tptr -> or_type == OR_OU) + before = FALSE; + else + before = TRUE; + + if ((new_tree = or_add (new_tree, tptr, before)) == NULLOR) + return NULLOR; + } + + /* + As we know both are ordered, tptr will be at the end of the tree + */ + + if (new_tree == NULLOR) + return (or); + + tptr -> or_next = or; + or -> or_prev = tptr; + + return (new_tree); +} diff --git a/Lib/or/or_dmn2or.c b/Lib/or/or_dmn2or.c new file mode 100644 index 0000000..c855482 --- /dev/null +++ b/Lib/or/or_dmn2or.c @@ -0,0 +1,88 @@ +/* or_dmn2or: convert dmn form to or list */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_dmn2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_dmn2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_dmn2or.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +OR_ptr or_dmn2or (istr) +char *istr; +{ + OR_ptr tree, + part; + char *sargv[50], + *valptr, + str[LINESIZE]; + int count, + ortype, + sargc; + + PP_DBG (("or_dmn2or (%s)", istr)); + + (void) strcpy (str, istr); + + /* + sstr2arg isn't nice, add cheks for legal char set + */ + + tree = NULLOR; + sargc = sstr2arg (str, 49, sargv, "."); + + for (count = 0; count < sargc; count++) { + + PP_DBG (("or_dmn2or Component '%s'", sargv[sargc] ? sargv[sargc] : "")); + + valptr = index (sargv[count], '$'); + + if (valptr == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("or_dmn2or No dollar in dmn encoding")); + or_free (tree); + return NULLOR; + } + + *valptr = '\0'; + valptr++; + + /* + domain defined + */ + + if (sargv[count][0] == '~') { + part = or_new (OR_DD, &sargv[count][1], valptr); + if ((tree = or_add (tree, part, TRUE)) == NULLOR) + return NULLOR; + } + else { + ortype = or_name2type (sargv[count]); + + if (ortype == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("or_dmn2or Unknown type '%s'", + sargv[count])); + or_free (tree); + return NULLOR; + } + + part = or_new (ortype, NULLCP, valptr); + if ((tree = or_add (tree, part, TRUE)) == NULLOR) + return NULLOR; + } + + } /* end of for */ + + return (tree); +} diff --git a/Lib/or/or_downgrade.c b/Lib/or/or_downgrade.c new file mode 100644 index 0000000..0fad7ba --- /dev/null +++ b/Lib/or/or_downgrade.c @@ -0,0 +1,144 @@ +/* or_downgrade: downgrade an 88 address to an 84 address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_downgrade.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_downgrade.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_downgrade.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "or.h" +#include "ap.h" + +extern char *loc_or; + +static int is84component(or) +OR_ptr or; +{ + typestruct *ptr; + + if (or->or_encoding == OR_ENC_PS + || or->or_encoding == OR_ENC_NUM) { + for (ptr = typetab; (ptr -> ty_string) != NULLCP; ptr++) + if (or->or_type == ptr->ty_int) + return TRUE; + } + return FALSE; +} + +void or_downgrade(ptree) +OR_ptr *ptree; +{ + OR_ptr ix = *ptree, ret, cn = NULLOR; + int x40088 = FALSE; + + while (ix != NULLOR && x40088 == FALSE) { + if (is84component(ix) != TRUE) { + if (ix -> or_type == OR_CN) { + cn = ix; + ix = ix -> or_next; + } else + x40088 = TRUE; + } else + ix = ix -> or_next; + } + + if (cn != NULLOR && x40088 != TRUE) { + /* CN sole x40088 comp */ + char buf[BUFSIZ], *sep; + + /* convert cn to DD.Common */ + switch(cn->or_encoding) { + case OR_ENC_PS: + (void) strcpy(buf, cn->or_value); + break; + + case OR_ENC_TTX: + case OR_ENC_TTX_AND_OR_PS: + if ((sep = index(cn->or_value, '*')) == NULLCP) + (void) strcpy (buf, cn->or_value); + else { + *sep = '\0'; + if (sep != cn->or_value) + /* ps encoding */ + (void) strcpy (buf, cn->or_value); + else + /* ttx encoding */ + (void) or_asc2ps (sep+1, buf); + } + break; + + default: + /* give up on DD common */ + cn = NULLOR; + x40088 = TRUE; + } + + if (cn != NULLOR) { + /* remove cn */ + if (cn->or_prev) + cn->or_prev->or_next = cn->or_next; + if (cn->or_next) + cn->or_next->or_prev = cn->or_prev; + if (cn == *ptree) + *ptree = cn->or_next; + + cn->or_next = NULLOR; + cn->or_prev = NULLOR; + or_free(cn); + + *ptree = or_add(*ptree, + or_new_aux (OR_DD, + "Common", + buf, OR_ENC_PS), + TRUE); + } + } + + if (x40088 == TRUE) { + char lbuf[LINESIZE], + dbuf[LINESIZE], + *cp; + AP_ptr local, + domain; + OR_ptr ptr; + + if (or_or2rbits(*ptree, lbuf, dbuf) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("or_downgrade: or_or2rbits failed")); + return; + } + + PP_TRACE (("or_downgrade lbuf='%s' dbuf='%s'", + lbuf, dbuf)); + + local = ap_new (AP_MAILBOX, lbuf); + domain = ap_new (AP_DOMAIN, dbuf); + + cp = ap_p2s(NULLAP, NULLAP, local, domain, NULLAP); + + + ap_free(local); + ap_free(domain); + + (void) or_asc2ps (cp, lbuf); + + ptr = or_new_aux (OR_DD, "X400-88", lbuf, OR_ENC_PS); + + ret = or_std2or(loc_or); + ret = or_add(ret, ptr, TRUE); + or_free(*ptree); + *ptree = ret; + } + +} + + + diff --git a/Lib/or/or_getpn.c b/Lib/or/or_getpn.c new file mode 100644 index 0000000..34d1cb1 --- /dev/null +++ b/Lib/or/or_getpn.c @@ -0,0 +1,83 @@ +/* or_getpn.c: get personal name out of the tree */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_getpn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_getpn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_getpn.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + + +extern void fixup_space(); + +/* --- *** --- +Get PN out of tree and put into buf +--- *** --- */ + + +int or_getpn (or, buf) +OR_ptr or; +char *buf; +{ + OR_ptr ptr; + + PP_DBG (("or_util.c/or_getpn ()")); + buf[0] = '\0'; + + + if ((ptr = or_find (or, OR_G, NULLCP)) != NULLOR) { + if ((int)strlen (ptr -> or_value) > 1 + && index (ptr -> or_value, '.') == NULLCP) { + (void) strcat (buf, ptr -> or_value); + (void) strcat (buf, "."); + } + else + return FALSE; + } + + + if ((ptr = or_find (or, OR_I, NULLCP)) != NULLOR) { + char *p, + *q; + + q = &buf[strlen(buf)]; + for (p = ptr -> or_value; *p != '\0'; p++) { + if (!isalpha (*p)) + return FALSE; + *q++ = *p; + *q++ = '.'; + } + *q = '\0'; + } + + + + if ((ptr = or_find (or, OR_S, NULLCP)) != NULLOR) { + if (index (ptr -> or_value, '.') != NULLCP) { + /* Surname with "." - yuk */ + if (buf[0] == '\0' + || (int)strlen (ptr -> or_value) < 3 + || ptr -> or_value[0] == '.' + || ptr -> or_value[1] == '.' ) + return FALSE; + } + (void) strcat (buf, ptr -> or_value); + } + else + return FALSE; + + fixup_space(buf, buf); + PP_DBG (("or_util.c/or_getpn: Got PN '%s'", buf)); + return TRUE; +} diff --git a/Lib/or/or_init.c b/Lib/or/or_init.c new file mode 100644 index 0000000..bd82e89 --- /dev/null +++ b/Lib/or/or_init.c @@ -0,0 +1,59 @@ +/* or_init.c: or-name initialisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_init.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_init.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_init.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "mta.h" +#include "or.h" + + +GlobalDomId Myglobalname; +extern OR_ptr loc_ortree; + + +extern void err_abrt (); + +/* --------------------- Start Routines -------------------------------- */ + + + + +/* +Starts up the or package etc. +*/ + +void or_myinit() +{ + static char or_inited = 0; + OR_ptr or = NULLOR; + + if (or_inited) + return; + or_inited++; + if (or_init() == NOTOK) + err_abrt (RP_MECH, "or_init failed"); + or = or_find (loc_ortree, OR_C, NULLCP); + if (or == NULLOR) + err_abrt (RP_MECH, "or_init - no country in loc_or"); + Myglobalname.global_Country = or->or_value; + or = or_find (loc_ortree, OR_ADMD, NULLCP); + if (or == NULLOR) + err_abrt (RP_MECH, "or_init - no ADMD in loc_or"); + Myglobalname.global_Admin = or->or_value; + or = or_find (loc_ortree, OR_PRMD, NULLCP); + if (or != NULLOR) + Myglobalname.global_Private = or->or_value; +} diff --git a/Lib/or/or_misc.c b/Lib/or/or_misc.c new file mode 100644 index 0000000..0a86146 --- /dev/null +++ b/Lib/or/or_misc.c @@ -0,0 +1,161 @@ +/* or_misc.c: misc or-name handling routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_misc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_misc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_misc.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "table.h" +#include "or.h" +#include "ap.h" +#include +#include + +extern CMD_TABLE ortbl_ddvalid[]; + +extern char *loc_dom_site; +extern char *loc_or; + +OR_ptr loc_ortree; + + + + +/* --------------------- Start Routines -------------------------------- */ + + + + +int or_init() +{ + char tbuf[LINESIZE]; + + + PP_DBG (("Lib/or_init()")); + + if (loc_or == NULLCP || *loc_or == '\0') { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/or_init: loc_or NULL !")); + return NOTOK; + } + (void) strcpy (tbuf, loc_or); + loc_ortree = or_std2or (tbuf); + + if (loc_ortree == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/or_init: loc_ortree NULL! %s", loc_or)); + return NOTOK; + } + + return OK; +} + + + + +/* +domain syntax is valid if it contains +one or more ASCII chars EXCEPT FOR specials spaces and ctrls +*/ + +int or_isdomsyntax (s) +register char *s; +{ + + PP_DBG (("Lib/or_isdomsyntax('%s')", s)); + + for (; *s != '\0'; s++) { + switch (*s) { + + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '"': + case '.': + case '[': + case ']': + case ' ': + /* --- specials --- */ + return FALSE; + + default: + if (!isascii (*s)) return FALSE; + if (iscntrl (*s)) return FALSE; + break; + } + } + + return TRUE; +} + + +int or_ddname_chk (key) +char *key; +{ + int value = cmd_srch(key, ortbl_ddvalid); + + if (value == OR_DDVALID_RFC822 + || value == OR_DDVALID_X40088 + || value == OR_DDVALID_JNT + || value == OR_DDVALID_UUCP) + return TRUE; + return FALSE; +} + + + + +int rfc_space (s) +char *s; +{ + int retval = TRUE; + + for (; *s != '\0'; s++) + if (*s != ' ') { + retval = FALSE; + break; + } + PP_DBG (("Lib/rfc_space ('%d')", retval)); + return retval; +} + +#ifdef lint +/* VARARGS1 */ +int or_lose (str) +char *str; +{ + return or_lose (str); +} +#else +int or_lose (va_alist) +va_dcl +{ + va_list ap; + extern char or_error[]; + + va_start (ap); + + _asprintf (or_error, NULLCP, ap); + + PP_LOG (LLOG_EXCEPTIONS, ("or_lose: %s", or_error)); + + va_end(ap); + + return NOTOK; +} +#endif diff --git a/Lib/or/or_or2dmn.c b/Lib/or/or_or2dmn.c new file mode 100644 index 0000000..ab88a94 --- /dev/null +++ b/Lib/or/or_or2dmn.c @@ -0,0 +1,94 @@ +/* or_or2dmn: convert or list into domain form */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2dmn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2dmn.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_or2dmn.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +void fixup_space(str, dest) +char *str; +char *dest; +{ + int seen_space = TRUE; + char *sp, *dp; + + for (sp = str, dp = dest; *sp; sp++) { + if (*sp == ' ') { + if (seen_space == FALSE) + seen_space = TRUE; + else + continue; + } else + seen_space = FALSE; + *dp++ = *sp; + } + if (dp > dest && dp[-1] == ' ') + dp --; + if (dp == dest) + (void) strcpy (dest, " "); + else + *dp = NULL; +} + +void or_or2dmn (first, last, buf) +OR_ptr first; +OR_ptr last; +char *buf; +{ + OR_ptr or; + + PP_DBG (("or_util.c/or_or2dmn ()")); + + /* + We print from BOTTOM of tree + */ + + if (last == NULLOR) + or = or_lastpart (first); + else + or = last; + + buf[0] = '\0'; + + for (; or != NULLOR; or = or -> or_prev ) { + + PP_DBG (("or_util.c/or_or2dmn Comp type='%d' ddname='%s' val='%s'", + or -> or_type, or-> or_ddname, or -> or_value)); + + if (buf[0] != '\0') + (void) strcat (buf, "."); + + if (or -> or_type == OR_DD) { + (void) strcat (buf, "~"); + dstrcat (buf, or -> or_ddname ); + (void) strcat (buf, "$"); + dstrcat (buf, or -> or_value); + } + else { + char *name; + char tbuf[BUFSIZ]; + if ((name = or_type2name (or -> or_type)) != NULLCP) + (void) strcat (buf, name); + else + (void) strcat (buf, "BOGUS"); + (void) strcat (buf, "$" ); + fixup_space (or -> or_value, tbuf); + dstrcat (buf, tbuf); + } + } + + PP_DBG (("or_util.c/or_or2dmn Returns: '%s'", buf)); +} diff --git a/Lib/or/or_or2rbits.c b/Lib/or/or_or2rbits.c new file mode 100644 index 0000000..fa5a6fc --- /dev/null +++ b/Lib/or/or_or2rbits.c @@ -0,0 +1,343 @@ +/* or_or2rbits.c: break or into bits */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2rbits.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2rbits.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_or2rbits.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" +#include "table.h" + +extern char *loc_dom_site; +extern char or_error[]; +extern char *or2rfc_tbl; +static Table *tb_or2rfc; +static int or_or2rbits_ckdmn(), or_isOKforRHS(); +extern void fixup_space(); + +/* --- definitions --- */ +#define NO_MATCH 0 +#define OU_O_MATCH 1 +#define PRMD_ADMD_C_MATCH 2 + + +/* -- local routines -- */ +int or_or2rbits(); +static get_psORasc(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* --- Get local + domain from or --- */ + +#ifdef NOTNEEDED +static char *at_str = "@"; +#endif + +int or_or2rbits (or, local, domain) +OR_ptr or; +char *local; +char *domain; +{ + OR_ptr ptr, + dptr, + tptr; + char buf[LINESIZE], + tbuf[LINESIZE], + tmp[LINESIZE], + loc_ps[LINESIZE], /* --- Printable String --- */ + dom_ps[LINESIZE]; /* --- Printable String --- */ + int cont, or_form; +#ifdef NOTNEEDED + int atmatch = FALSE; +#endif + + PP_DBG (("Lib/or_or2rbits()")); + + if (tb_or2rfc == NULLTBL) + if ((tb_or2rfc = tb_nm2struct (or2rfc_tbl)) == NULLTBL) + return or_lose ("No or2rfc table!"); + + or_form = or_form_type(or); + domain[0] = '\0'; + if (or_add_atsigns (&or) == NOTOK) + return NOTOK; + + + /* --- See how much we can domain check against --- */ + + for (ptr = or; ptr -> or_next != NULLOR; ptr = ptr -> or_next) + if (ptr -> or_type > OR_OU) + break; + + + /* --- pointing to the first non-dom compt --- */ + + if (ptr != or) { + dptr = ptr; + ptr = ptr -> or_prev; + + /* --- move until we find a match --- */ + + for (; ptr != NULLOR; ptr = ptr->or_prev) { + or_or2dmn (NULLOR, ptr, buf); + + if (tb_k2val (tb_or2rfc, buf, tbuf, TRUE) != OK) + continue; + + /* got a match */ + + /* --- check that tbuf is a valid domain syntax --- */ + if (or_or2rbits_ckdmn (tbuf) == NOTOK) + goto doexplicit; + + switch (or_form) { + case OR_FORM_TERM: + case OR_FORM_POST: + case OR_FORM_NUMR: + /* fully lhs encode */ + (void) strcpy (dom_ps, tbuf); + get_psORasc (dom_ps, domain); + if (index(domain, '.') == NULLCP) + /* only one component to domain */ + /* so LHS encode with loc_dom_site */ + domain[0] = '\0'; + goto doexplicit; + default: + case OR_FORM_MNEM: + break; + } + + /* ptr is ones we've matched */ + /* dptr is end of components that may be added to RHS */ + + ptr = ptr -> or_next; + cont = TRUE; + + (void) strcpy (dom_ps, tbuf); + + while (cont == TRUE + && ptr != dptr) { + if (lexequ (ptr -> or_value, "@") == 0) { + /* missing next component */ + /* lhs encode from here */ + cont = FALSE; + continue; + } + + fixup_space(ptr -> or_value, tmp); + if (or_isOKforRHS(tmp)) { + (void) sprintf(tbuf, "%s.%s", tmp, dom_ps); + (void) strcpy(dom_ps, tbuf); + ptr = ptr -> or_next; + } else + cont = FALSE; + } + + /* appended what could to rhs */ + /* lhs encode from here */ + + tptr = ptr -> or_prev; + ptr -> or_prev = NULLOR; + + if (or_delete_atsigns (&ptr) == NOTOK) + return NOTOK; + + or_or2std (ptr, loc_ps, TRUE); + if (loc_ps[strlen (loc_ps) - 1] == '/') + or_or2std (ptr, loc_ps, FALSE); + + + ptr -> or_prev = tptr; + tptr -> or_next = ptr; + + get_psORasc (dom_ps, domain); + + if (index(domain, '.') == NULLCP) { + /* only one component to domain */ + /* so LHS encode */ + domain[0] = '\0'; + goto doexplicit; + } + get_psORasc (loc_ps, local); + + PP_DBG (( + "Lib/or_or2rbits DMN encoded local='%s', dmn='%s'", + local, domain + )); + + if (or_delete_atsigns (&or) == NOTOK) + return NOTOK; + + return OK; + + } /* end of for */ + + } /* end of if */ + + +doexplicit: + /* --- Do full LHS encoding --- */ + if (or_delete_atsigns (&or) == NOTOK) + return NOTOK; + + if (domain[0] == '\0') + (void) strcpy (domain, loc_dom_site); + or_or2std (or, loc_ps, FALSE); + get_psORasc (loc_ps, local); + + PP_DBG (("Lib/or_or2rbits/Default setting local='%s' domain='%s'", + local, domain)); + + return OK; +} + + + + +/* -------------------------- Static Routines ---------------------------- */ + +static int or_isOKforRHS (dmn) +char *dmn; +{ + char asc[BUFSIZ], *ix; + get_psORasc(dmn, asc); + + if (!isalnum(asc[0]) || + !isalnum(asc[strlen(asc)-1])) + return FALSE; + + for (ix = &asc[0]; + ix != NULL && *ix != '\0'; + ix++) + if (!isalnum(*ix) + && *ix != '-') + return FALSE; + return TRUE; +} + +static int or_or2rbits_ckdmn (dmn) +char *dmn; +{ + char buf[LINESIZE]; + char *ptr = dmn; + + PP_DBG (("Lib/or_or2rbits_ckdmn (%s)", dmn)); + + buf[0] = '\0'; + + while (or_gettoken (&ptr, '.', buf) == OK) + if (!or_isOKforRHS (buf)) + return or_lose ("Bad style RFC-822 domain '%s'", dmn); + return OK; +} + + + +#ifdef NOTNEEDED +static int or_or2rbits_match (start, dmn) +OR_ptr start; +OR_ptr *dmn; +{ + char buf[LINESIZE]; + OR_ptr curr; + + + /* --- *** --- + Build domain - match. If attribute value does not hold a valid domain + syntax, then move that part to the local part. This is only done if + no mapping for that attribute has been specified in the or2rfc table. + Example: + '/s=user/ou=org unit/prmd=valid/admd=gold 400/c=gb/' + will be RFC987 mapped to: + '"/s=user/ou=org unit/"@valid.gold-400.gb' + --- *** --- */ + + for (curr = *dmn; curr != start; curr = curr -> or_prev) { + get_psORasc (curr -> or_value, buf); + fixup_space(buf, buf); + if ((!or_isOKforRHS (buf)) && (lexequ (buf, "@") != 0)) { + if (curr -> or_prev) + *dmn = curr -> or_prev; + else + return or_lose ("No OR prev '%s'", + curr->or_value); + } + } + + return OK; +} + +/* --- match for "@" signs in the or2rfc table --- */ + +static int or_or2rbits_atsigns (or) +OR_ptr or; +{ + OR_ptr next = or -> or_next; /* save the value */ + int type = or -> or_type; + OR_ptr at; + char key[LINESIZE], value[LINESIZE]; + int retval; + + + if (type < OR_OU) + type++; + else + return NO_MATCH; + + at = or_new (type, NULLCP, "@"); + + at -> or_prev = or; + at -> or_next = NULLOR; + or -> or_next = at; + + + or_or2dmn (NULLOR, at, key); + + retval = tb_k2val (tb_or2rfc, key, value, TRUE); + + or -> or_next = next; + + at -> or_prev = at -> or_next = NULLOR; + or_free (at); + + if (retval != OK) + return NO_MATCH; + + if (type < OR_O) + return PRMD_ADMD_C_MATCH; + + return OU_O_MATCH; +} +#endif + + +static get_psORasc (value, buf) +char *value; +char *buf; +{ + +#ifndef STRICT_1148 + if (!(value[0] == '/' + && index(value, '=') != NULLCP)) + (void) or_ps2asc (value, buf); + else +#endif + (void) strcpy (buf, value); +} diff --git a/Lib/or/or_or2rfc.c b/Lib/or/or_or2rfc.c new file mode 100644 index 0000000..2ab65fd --- /dev/null +++ b/Lib/or/or_or2rfc.c @@ -0,0 +1,197 @@ +/* or_or2rfc.c: convert from or address to rfc address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2rfc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2rfc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_or2rfc.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" +#include "ap.h" +#include +extern char *loc_dom_site; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* +Maps OR struct into a RFC822 string +*/ + +#define UB_DDA_VALUE 128 + +#define RFC822C1 100 +#define RFC822C2 101 +#define RFC822C3 102 + +CMD_TABLE ortbl_rfc822ddas[] = { /* type strings for rfc 822 ddas */ + "RFC-822", OR_DDVALID_RFC822, + "RFC822C1", RFC822C1, + "RFC822C2", RFC822C2, + "RFC822C3", RFC822C3, + 0, -1 + }; + +int or_or2rfc_aux (or, buf, addr_check) +OR_ptr or; +char *buf; +int addr_check; +{ + AP_ptr local, + domain; + OR_ptr current_ptr; + char lbuf[LINESIZE], + dbuf[LINESIZE], + *cp; + + PP_DBG (("Lib/or_or2rfc()" )); + if (or == NULLOR) + return NOTOK; + + or = or_default (or); + current_ptr = or; + + if ((current_ptr = or_find (current_ptr, OR_DD, NULLCP)) != NULLOR) { + if (current_ptr -> or_next == NULLOR) { + /* --- single DD attributes --- */ + if (or_ddname_chk (current_ptr -> or_ddname)) { + /* --- Special DD type --- */ + if (or_str_isps(current_ptr->or_value)) { + or_ps2asc (current_ptr -> or_value, buf); + PP_DBG (("Lib/or_or2rfc: Matched dd, '%s' = '%s'", + current_ptr -> or_ddname, buf)); + return OK; + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("dd '%s' value '%s' is not a printable string", + current_ptr->or_ddname, + current_ptr -> or_value)); + return NOTOK; + } + } + } else { + /* --- multiple DD attributes --- */ + /* --- look to merge RFC-822s --- */ + char rfc822[UB_DDA_VALUE+1], + rfc822c1[UB_DDA_VALUE+1], + rfc822c2[UB_DDA_VALUE+1], + rfc822c3[UB_DDA_VALUE+1]; + int allRFC822s = TRUE; + + rfc822[0] = '\0'; + rfc822c1[0] = '\0'; + rfc822c2[0] = '\0'; + rfc822c3[0] = '\0'; + do { + if (current_ptr -> or_type == OR_DD) { + if (or_str_isps (current_ptr->or_value)) { + switch(cmd_srch(current_ptr -> or_ddname, + ortbl_rfc822ddas)) { + case OR_DDVALID_RFC822: + or_ps2asc(current_ptr->or_value, + rfc822); + break; + + case RFC822C1: + or_ps2asc(current_ptr->or_value, + rfc822c1); + break; + + case RFC822C2: + or_ps2asc(current_ptr->or_value, + rfc822c2); + break; + case RFC822C3: + or_ps2asc(current_ptr->or_value, + rfc822c3); + break; + default: + allRFC822s = FALSE; + break; + } + PP_DBG(("Lib/or_or2rfc: Matched dd, '%s' = '%s'", + current_ptr->or_ddname, + current_ptr->or_value)); + } else { + PP_LOG(LLOG_EXCEPTIONS, + ("dd '%s' value '%s' is not a printable string", + current_ptr->or_ddname, + current_ptr->or_value)); + return NOTOK; + } + } else + allRFC822s = FALSE; + + current_ptr = current_ptr -> or_next; + } while (current_ptr != NULLOR); + + if (allRFC822s == TRUE) { + buf[0] = '\0'; + + if (rfc822[0]) + (void) strcat(buf, rfc822); + + if (rfc822c1[0]) + (void) strcat(buf, rfc822c1); + + if (rfc822c2[0]) + (void) strcat(buf, rfc822c2); + + if (rfc822c3[0]) + (void) strcat(buf, rfc822c3); + if (buf[0] != '\0') + return OK; + } + } + } + + if (or_or2rbits (or, lbuf, dbuf) == NOTOK) + return NOTOK; + + + /* --- if NUL domain - explicit encoding --- */ + + if (dbuf[0] == '\0') { + (void) strcpy (buf, lbuf); + PP_DBG (("Lib/or_or2rfc Returns '%s'", buf)); + return OK; + } + + + PP_TRACE (("Lib/or_or2rfc lbuf='%s' dbuf='%s'", lbuf, dbuf)); + + + if (lexequ (dbuf, loc_dom_site) == 0) + if (addr_check) + return DONE; + + local = ap_new (AP_MAILBOX, lbuf); + domain = ap_new (AP_DOMAIN, dbuf); + + cp = ap_p2s (NULLAP, NULLAP, local, domain, NULLAP); + + (void) strcpy (buf, cp); + + free (cp); + ap_free (local); + ap_free (domain); + + PP_TRACE (("Lib/or_or2rfc returns '%s'", buf)); + + return OK; +} diff --git a/Lib/or/or_or2std.c b/Lib/or/or_or2std.c new file mode 100644 index 0000000..289e222 --- /dev/null +++ b/Lib/or/or_or2std.c @@ -0,0 +1,91 @@ +/* or_or2std.c: convert interanl list to standard format or name */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2std.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_or2std.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_or2std.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +void or_or2std (or, buf, nicepn) +OR_ptr or; +char *buf; +int nicepn; /* pretty pn required ? */ +{ + OR_ptr ptr; + char tbuf[LINESIZE]; + int gotpn, + addslash; + + + PP_DBG (("or_or2std ()")); + + buf[0] = '\0'; + + if (nicepn) { + gotpn = or_getpn (or, buf); + if (!gotpn) + buf[0] = '\0'; + } + else + gotpn = FALSE; + + ptr = or_lastpart (or); + + for (addslash = FALSE ; ptr != NULLOR; ptr = ptr -> or_prev ) { + + PP_DBG (( + "or_or2std: Comp type='%d' ddname='%s' value='%s'", + ptr -> or_type, + ptr-> or_ddname ? ptr -> or_ddname : "", + ptr -> or_value ? ptr -> or_value : "" + )); + + if (gotpn && (ptr -> or_type == OR_S || + ptr -> or_type == OR_G || + ptr -> or_type == OR_I)) + continue; + + addslash = TRUE; + + (void) strcat (buf, "/"); + + if (ptr -> or_type == OR_DD) { + if (or_ddvalid_chk (ptr -> or_ddname, &tbuf[0]) == NOTOK) + { + (void) strcat (buf, "DD."); + qstrcat (buf, ptr -> or_ddname ); + } + else + qstrcat (buf, tbuf); + + (void) strcat (buf, "="); + qstrcat (buf, ptr -> or_value); + } + else { + char *name; + if ((name = or_type2name (ptr -> or_type)) != NULLCP) + (void) strcat (buf, name); + else + (void) strcat (buf, "BOGUS"); + (void) strcat (buf, "=" ); + qstrcat (buf, ptr -> or_value); + } + } + + if (addslash) + (void) strcat (buf, "/"); + + PP_DBG (("or_or2std returns ('%s')", buf)); +} diff --git a/Lib/or/or_ps2asc.c b/Lib/or/or_ps2asc.c new file mode 100644 index 0000000..ef9b502 --- /dev/null +++ b/Lib/or/or_ps2asc.c @@ -0,0 +1,114 @@ +/* or_ps2asc.c: convert printable string to ascii */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_ps2asc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_ps2asc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_ps2asc.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + +/* +Map printable string to ASCII +*/ + +void or_ps2asc (ps, ascii) +char *ps; +char *ascii; +{ + register char *p, *q; + int i; + + PP_DBG (("Lib/or_ps2asc('%s')", ps)); + + p = ps; + q = ascii; + for (;*p != '\0';) { + + if (*p != '(') + *q++ = *p++; + else { + if (*(p + 2) == ')') { + switch (*(p + 1)) { + case 'a': + case 'A': + *q++ = '@'; + break; + case 'p': + case 'P': + *q++ = '%'; + break; + case 'b': + case 'B': + *q++ = '!'; + break; + case 'q': + case 'Q': + *q++ = '"'; + break; + case 'u': + case 'U': + *q++ = '_'; + break; + case 'l': + case 'L': + *q++ = '('; + break; + case 'r': + case 'R': + *q++ = ')'; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown Printable Char '%s'", ps)); + (void) strcpy (ascii, ps); + return; + } + p = p + 3; + } + + else { + + if (isdigit (*(p + 1)) && isdigit (*(p + 2)) + && (*(p + 3)) && *(p + 4) == ')') + { + (void) sscanf (p + 1, "%3d", &i); + p = p + 5; + } + else + { + PP_LOG (LLOG_EXCEPTIONS, + ("Unkown digit '%s'", ps)); + (void) strcpy (ascii, ps); + return; + } + + + if (i <= 0 || i >= 127) { + PP_LOG (LLOG_EXCEPTIONS, + ("Digit '%d' out of range '%s'", i, ps)); + (void) strcpy (ascii, ps); + return; + } + + *q++ = (char) i; + + } /* end of if */ + + } /* end of if */ + + } /* end of for */ + + *q = '\0'; +} diff --git a/Lib/or/or_rbits2or.c b/Lib/or/or_rbits2or.c new file mode 100644 index 0000000..7dff2c5 --- /dev/null +++ b/Lib/or/or_rbits2or.c @@ -0,0 +1,147 @@ +/* or_rbits2or.c: maps bits into OR */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_rbits2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_rbits2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_rbits2or.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" +#include "table.h" + +static Table *tb_rfc2or = NULLTBL; + +extern char *rfc2or_tbl, + or_error[]; +extern OR_upperbound ortbl_88_ubs[]; + +/* --------------------- Begin Routines -------------------------------- */ + + + +int or_domain2or (domain, or) +char *domain; +OR_ptr *or; +{ + OR_ptr ptr, tmp; + char buf[LINESIZE], + *p; + + PP_DBG (("Lib/or_domain2or (%s)", domain)); + + if (tb_rfc2or == NULLTBL) { + if ((tb_rfc2or = tb_nm2struct (rfc2or_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/or_rbits2or: rfc2or table NULL!")); + return NOTOK; + } + } + + for (p = domain; *p != '\0';) { + if (tb_k2val (tb_rfc2or, p, buf, TRUE) == OK) + break; + p = index (p, '.'); + if (p == NULLCP) + break; + else + p++; + } + + if (p == NULLCP || *p == '\0') { + (void) sprintf (or_error, + "No translation of '%s' to X400 address", + domain); + return NOTOK; + } + + else { + *or = or_dmn2or (buf); + if (*or == NULLOR) + return or_lose ("format error '%s':'%s'", + p, buf); + + + + if (p != domain) { + /* --- Must add more bits --- */ + int i; + int tconst; + int type; + int oargc; + char *oargv[50]; + + p--; + *p = '\0'; + oargc = sstr2arg (domain, 49, oargv, "."); + + if (*or != NULLOR) { + ptr = *or; + tconst = (or_lastpart (ptr)) -> or_type; + } + else + tconst = OR_OU; + + for (i = oargc - 1; i >= 0; i--) { + tconst++; + if (tconst > OR_OU) + type = OR_OU; + else + type = tconst; + + if (!or_isdomsyntax (oargv[i])) + return or_lose ("domain syntax error '%s'", + oargv[i]); + + ptr = or_new (type, NULLCP, oargv[i]); + if (or_check_upper (ptr, ortbl_88_ubs) == NOTOK) { + if (ptr) + or_free(ptr); + return NOTOK; + } + tmp = or_add (*or, ptr, FALSE); + if (tmp == NULLOR) + return NOTOK; + else + *or = tmp; + + } /* --- end of for --- */ + + } /* --- end of if --- */ + + } /* --- end of else --- */ + + return OK; + +} + +int or_local2or (local, or) +char *local; +OR_ptr *or; +{ + OR_ptr ptr; + /* --- Add in the local bits --- */ + + PP_DBG (("Lib/or_local2or (%s)", local)); + + if ((ptr = or_std2or (local)) == NULLOR) + return or_lose ("local syntax error '%s'", + local); + + *or = or_default_aux(ptr, *or); + /* try adding in loc_or for missing bits */ + *or = or_default (*or); + + if (or_delete_atsigns (or) == NOTOK) + return NOTOK; + return OK; +} + diff --git a/Lib/or/or_rfc2or.c b/Lib/or/or_rfc2or.c new file mode 100644 index 0000000..c520de5 --- /dev/null +++ b/Lib/or/or_rfc2or.c @@ -0,0 +1,240 @@ +/* or_rfc2or.c: convert from rfc address to or address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_rfc2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_rfc2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_rfc2or.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" +#include "ap.h" + +extern char *loc_dom_site; +extern char *loc_or; +extern char or_error[]; +static int RFC_encode(); +static void get_loc_val (); +static int my_or_str_isps(); + +int or_rfc2or_aux (rfc, or, adno) +char *rfc; +OR_ptr *or; +int adno; +{ + AP_ptr ap, + group, + name, + local, + route, + domain; + char buf[LINESIZE]; + int retval; + OR_ptr tmp; + PP_DBG (("Lib/or_rfc2or ('%s')", rfc)); + + /* + An address can be specified as: 'xxxx: ;' + */ + + if (rfc_space (rfc)) + return (or_blank (or)); + + + local = NULLAP; + domain = NULLAP; + route = NULLAP; + *or = NULLOR; + + if ((ap = ap_s2t (rfc)) != BADAP + && ap_t2p (ap, &group, &name, &local, &domain, &route) + != BADAP) + { + if (route != NULLAP) { + ap_val2str(buf, route->ap_obvalue, route->ap_obtype); + if (or_str_isps (buf)) + (void) or_domain2or (buf, or); + goto i_was_forced_into_this; + } + + if (domain != NULLAP) { + ap_val2str(buf, domain->ap_obvalue, domain->ap_obtype); + if (!or_str_isps (buf)) + goto i_was_forced_into_this; + } else + (void) strcpy (buf, loc_dom_site); + + if (or_domain2or(buf, or) == NOTOK) + goto i_was_forced_into_this; + + if (local != NULLAP) { + get_loc_val (local, buf); + if(!my_or_str_isps (buf)) + goto i_was_forced_into_this; + } else + buf[0] = '\0'; + + tmp = or_tdup(*or); + if (or_local2or(buf, or) == OK) { + or_chk_admd(or); + /* check to see if what we've created */ + /* actually matches with the standard */ + if (or_valid_or(*or) == OK) { + or_free(tmp); + return (OK); + } + /* not valid so put rhs generated tree back */ + or_free(*or); + *or = tmp; + } else { + or_free(*or); + *or = tmp; + } + } else { + if (ap != BADAP) + ap_free(ap); + return or_lose ("Can't parse address '%s'",rfc); + } + +i_was_forced_into_this:; + retval = RFC_encode(rfc, or, adno, domain, route); + or_chk_admd(or); + if (ap != BADAP) + ap_free(ap); + return retval; + +} + +/* check 1148 constraints on str */ +static int my_or_str_isps(str) +char *str; +{ + int cont = TRUE, seenspace = FALSE; + if (isspace(*str) || isspace(str[strlen(str)-1])) + /* leading or trailing spaces */ + return 0; + + while (*str && cont == TRUE) { + + if (isspace(*str)) { + if (seenspace == TRUE) { + /* adjacent spaces */ + cont = FALSE; + continue; + } + seenspace = TRUE; + } else + seenspace = FALSE; + + if ((*str == '$' + && (*(str+1) == '=' || *(str+1) == '/') || *(str+1) == ';') + || *str == ';' || *str == '/' + || (or_isps(*str))) + str++; + else + cont = FALSE; + } + return *str == '\0'; +} + +#define UB_DDA_VALUE 128 +#define UB_DDA_TYPE 8 + +static int RFC_encode(rfc, or, adno, domain, route) +char *rfc; +OR_ptr *or; +int adno; +AP_ptr domain, + route; +{ + char buf[LINESIZE]; + OR_ptr ptr = NULLOR, new; + char *dmn = NULLCP; + char *start, *end, savech; + int len; + char dda_type[UB_DDA_TYPE+1]; + int ddacount = 0; + /* + Make explicit RFC encoding + */ + (void) or_asc2ps (rfc, buf); + len = strlen(buf); + start = &(buf[0]); + do { + if (len < UB_DDA_VALUE) + end = NULLCP; + else { + end = start + UB_DDA_VALUE; + savech = *end; + *end = '\0'; + } + if (ddacount == 0) + (void) strcpy(dda_type, "RFC-822"); + else + (void) sprintf(dda_type, "RFC822C%d", ddacount); + ddacount++; + new = or_new (OR_DD, dda_type, start); + if ((ptr = or_add (ptr, new, FALSE)) == NULLOR) + return NOTOK; + + len -= strlen(start); + start = end; + if (end != NULLCP) + *end = savech; + } while (start != NULLCP && *start != '\0'); + + + if (*or == NULLOR) { + if (route != NULLAP) + dmn = route -> ap_obvalue; + else if (domain != NULLAP) + dmn = domain -> ap_obvalue; + + if (adno == 0 + /* MTS originator */ + || dmn == NULLCP + || tb_get1148gate (dmn, or) != OK) + /* RFC_encode with local or */ + *or = or_std2or (loc_or); + } + for (new = ptr; new != NULLOR; new = ptr) { + ptr = new -> or_next; + new -> or_next = NULLOR; + *or = or_add( *or, new, TRUE); + if (*or == NULLOR) + return NOTOK; + } + return (OK); +} + +static void get_loc_val (lap, buf) +AP_ptr lap; +char buf[]; +{ + for (buf[0] = '\0'; lap != NULLAP; lap = lap -> ap_next) { + switch (lap -> ap_obtype) { + default: + case AP_NIL: + break; + case AP_COMMENT: + continue; + + case AP_GENERIC_WORD: + case AP_MAILBOX: + if (buf[0]) + (void) strcat (buf, " "); + (void) strcat (buf, lap -> ap_obvalue); + continue; + } + break; + } +} diff --git a/Lib/or/or_search.c b/Lib/or/or_search.c new file mode 100644 index 0000000..24798aa --- /dev/null +++ b/Lib/or/or_search.c @@ -0,0 +1,240 @@ +/* or_search.c: misc functions to do with locating or bits */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_search.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_search.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_search.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +OR_ptr or_lastpart (or) +OR_ptr or; +{ + PP_DBG (("or_util.c/or_lastpart()")); + + if (or == NULLOR) + return NULLOR; + + while (or -> or_next != NULLOR) + or = or -> or_next; + + return or; +} + + + + +OR_ptr or_find (tree, type, ddname) +OR_ptr tree; +int type; +char *ddname; +{ + OR_ptr ptr; + + PP_DBG (("or_util.c/or_find()")); + + for (ptr = tree; ptr != NULLOR; ptr = ptr -> or_next) + if (ptr -> or_type == type) + if (ptr -> or_type != OR_DD || ddname == NULLCP) + return ptr; + else + if (lexequ (ptr -> or_ddname, ddname) == 0) + return ptr; + return NULLOR; +} + + + + +int or_cmp (or1, or2) +OR_ptr or1; +OR_ptr or2; +{ + + PP_DBG (("or_util.c/or_cmp: ('%d', '%s', '%s') ('%d', '%s', '%s')", + or1 -> or_type, or1 -> or_ddname, or1 -> or_value, + or2 -> or_type, or2 -> or_ddname, or2 -> or_value)); + + if (or1 -> or_type != or2 -> or_type + || lexequ (or1 -> or_value, or2 -> or_value) != 0) + return FALSE; + + if (or1 -> or_type == OR_DD + && lexequ (or1 -> or_ddname, or2 -> or_ddname) != 0) + return FALSE; + + return TRUE; +} + + + + +/* --- *** --- +or_locate: given a or tree, find the first component + of the specified type. +--- *** --- */ + +OR_ptr or_locate (or, type) +OR_ptr or; +int type; +{ + register OR_ptr orp; + + PP_DBG (("Lib/or/or_locate (%d)", type)); + for (orp = or; orp != NULLOR && or -> or_type <= type; + orp = orp -> or_next) + if (orp -> or_type == type) + return orp; + return NULLOR; +} + + + + +/* --- *** --- +or_value: given an or tree, return the value of the first element of a + given type. +--- *** --- */ + +char* or_value (or, type) +OR_ptr or; +int type; +{ + register OR_ptr orp; + + PP_DBG (("Lib/or/or_value (%d)", type)); + for (orp = or; orp != NULLOR && or -> or_type <= type; + orp = orp -> or_next) + if (type == orp -> or_type) + return (orp -> or_value); + return NULLCP; +} + + + + +/* --- *** --- +or_add_atsigns: For any missing OR Components insert that + component as a NULL ("@") attribute +--- *** --- */ + +int or_add_atsigns (orp) +OR_ptr *orp; +{ + OR_ptr or, + old, + new; + int type; + + PP_DBG (("Lib/or_add_atsigns()")); + + old = *orp; + or = new = NULLOR; + + if (old == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/or_add_atsigns - No OR specified")); + return NOTOK; + } + + + for (type = OR_C; type < OR_OU; type++) { + + /* -- add the attribute as NULL ("@") -- */ + if ((or = or_find (old, type, NULLCP)) == NULLOR) + or = or_new_aux (type, NULLCP, "@", OR_ENC_PP); + else + old = old -> or_next; + + if ((new = or_add (new, or, TRUE)) == NULLOR) + return NOTOK; + + if (old == NULLOR) + break; + } + + + for (;;) { + if (old == NULLOR) + break; + if (old -> or_type < OR_OU) + continue; + or = old; + old = old -> or_next; + if (or_add (new, or, FALSE) == NULLOR) + return NOTOK; + } + + *orp = new; + return OK; +} + + + + +/* --- *** --- +or_delete_atsigns: For any NULL OR Components delete + that component +--- *** --- */ + +int or_delete_atsigns (ptr) +OR_ptr *ptr; +{ + OR_ptr old, top, or, + bk, fw, rm; + + PP_DBG (("Lib/or_delete_atsigns()")); + + old = top = *ptr; + + if (old == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/or_delete_atsigns - No OR specified")); + return NOTOK; + } + + + for (or = old; or; or = fw) { + bk = or -> or_prev; + fw = or -> or_next; + rm = or; + if (or -> or_type >= OR_OU) + break; + if (lexequ (or -> or_value, "@") == 0) { + if (bk) { + bk -> or_next = fw; + if (or == *ptr || + (lexequ (top -> or_value, "@") == 0)) + top = fw; + } + else + top = fw; + fw -> or_prev = bk; + rm -> or_next = rm -> or_prev = NULLOR; + or_free (rm); + } + } + + + *ptr = top; + return OK; +} diff --git a/Lib/or/or_std2or.c b/Lib/or/or_std2or.c new file mode 100644 index 0000000..6263c11 --- /dev/null +++ b/Lib/or/or_std2or.c @@ -0,0 +1,271 @@ +/* or_std2or.c: convert standard or representation to tree */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_std2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_std2or.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_std2or.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" + +extern char or_error[]; +/* +Input standard to form orname +*/ + +static OR_ptr or_std2or_aux(); + +OR_ptr or_std2or (str) +char *str; +{ + OR_ptr tree; + char *p, tmp[BUFSIZ]; + int firstpn; + PP_DBG (("or_util.c/or_std2or (%s)", str)); + + if (str == NULLCP) + return NULLOR; + + tree = NULLOR; + + if (str[0] == '/') { + /* + No implicit PN + */ + firstpn = FALSE; + p = &str[1]; + } + else { + firstpn = TRUE; + p = str; + } + + if ((tree = or_std2or_aux(p, '/', firstpn)) == NULLOR) { + char *colon, *equal; + char or_error_sav[BUFSIZ]; + + (void) strcpy (or_error_sav, or_error); + + /* ignore leading semicolon */ + if (str[0] == ';') + p = &str[1]; + else + p = str; + + colon = index(p, ';'); + equal = index(p, '='); + + if (equal == NULLCP) + /* no equals */ + firstpn = TRUE; + else if (colon == NULLCP) + /* no semicolon but equals */ + firstpn = FALSE; + else if (colon < equal) + /* semicolon before equals */ + + firstpn = TRUE; + else + firstpn = FALSE; + + if ((tree = or_std2or_aux(p, ';', firstpn)) == NULLOR) { + (void) strcpy (or_error, or_error_sav); + return NULLOR; + } + } + + or_chk_admd(&tree); + if (or_checktypes(tree, tmp) == NOTOK) { + or_free(tree); + (void) or_lose("Bad OR Address '%s'", tmp); + return NULLOR; + } + + return tree; +} + +static OR_ptr or_std2or_aux(str, sep, firstpn) +char *str; +char sep; +int firstpn; +{ + OR_ptr tree = NULLOR, + or = NULLOR; + char keybuf[LINESIZE], + valbuf[LINESIZE], + tbuf[LINESIZE], + *p, + *r; + int ortype, + before = TRUE; + + p = str; + + for (; *p != '\0';) { + r = keybuf; + for (; *p != '\0';) { + if (*p == sep) { + if (!firstpn) { + (void) or_lose ("Bad AV Syntax '%s'", + str); + or_free (tree); + return NULLOR; + } + p++; + + } else { + switch (*p) { + case '=': + if (firstpn) { + (void) or_lose ("Bad PN syntax '%s'", str); + return NULLOR; + } + p++; + break; + case '$': + p++; + default: + *r++ = *p++; + continue; + } + } + break; + } + + *r = '\0'; + + if (firstpn) { + tree = or_buildpn (keybuf); + if (*p == '\0') + return (tree); + firstpn = FALSE; + continue; + } + + if (*p == '\0') { + if (keybuf[0] == '\0') + return (tree); + (void) or_lose ("Prematurely terminated OR '%s'", str); + or_free (tree); + return NULLOR; + } + + r = valbuf; + + for (; *p != '\0';) { + if (*p != sep) { + switch (*p) { + case '=': + (void) or_lose("Bad AV syntax '%s'",str); + or_free (tree); + return NULLOR; + case '$': + p++; + default: + *r++ = *p++; + continue; + } + } + break; + } + + *r = '\0'; + + if (*p != sep) + PP_DBG (("Prematurely ended OR - no slash '%s'", str)); + else + p++; + + PP_DBG (( + "or_util.c/or_std2or: Component '%s' = '%s'", keybuf, valbuf)); + + /* + Process string from BACK to optimise or-add + */ + + switch (ortype = or_name2type (keybuf)) { +#ifdef NOTDEF + case OR_C: + case OR_ADMD: + case OR_PRMD: +#endif + case OR_O: + before = FALSE; + default: + break; + } + + if (ortype != NOTOK) { + or = or_new (ortype, NULLCP, valbuf); + if (or == NULLOR) return NULLOR; + if ((tree = or_add (tree, or, before)) == NULLOR) + return NULLOR; + continue; + } + + if (lexequ (keybuf, "pn") == 0) { + OR_ptr pntree, orp, ix = NULLOR; + pntree = or_buildpn (valbuf); + for (orp = pntree; orp != NULLOR; orp = ix) { + ix = orp -> or_next; + orp -> or_next = NULLOR; + if ((tree = or_add(tree, orp, before)) == NULLOR) + return NULLOR; + } + continue; + } + + (void) strncpy (tbuf, keybuf, 3); + tbuf[3] = '\0'; + + if (((int)strlen (keybuf) > 2) && lexequ (tbuf, "dd.") == 0) { + if (!or_str_isps(valbuf)) { + (void) or_lose("DDA '%s' is not a printable string", + valbuf); + or_free(tree); + return NULLOR; + } + if (lexequ(&keybuf[3], "common") == 0) + or = or_new (OR_CN, NULLCP, valbuf); + else + or = or_new (OR_DD, &keybuf[3], valbuf); + if (or == NULLOR) return NULLOR; + if ((tree = or_add (tree, or, TRUE)) == NULLOR) + return NULLOR; + continue; + } + + /* + Might need new table if this becomes assymetrical + */ + + if (or_ddvalid_chk (keybuf, &tbuf[0]) == OK) { + if (!or_str_isps(valbuf)) { + (void) or_lose("DDA '%s' is not a printable string", + valbuf); + or_free(tree); + return NULLOR; + } + or = or_new (OR_DD, tbuf, valbuf); + if (or == NULLOR) return NULLOR; + if ((tree = or_add (tree, or, TRUE)) == NULLOR) + return NULLOR; + continue; + } + + (void) or_lose ("Unknown Key '%s'", keybuf); + or_free (tree); + return NULLOR; + } + return tree; +} diff --git a/Lib/or/or_tables.c b/Lib/or/or_tables.c new file mode 100644 index 0000000..d59dd5c --- /dev/null +++ b/Lib/or/or_tables.c @@ -0,0 +1,209 @@ +/* or_tables.c: various tables of values */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_tables.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_tables.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_tables.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + +#include "config.h" +#include "or.h" +#include + +typestruct typetab[] = { + "C", OR_C, OR_ENC_PS, + "ADMD", OR_ADMD, OR_ENC_PS, + "A", OR_ADMD, OR_ENC_PS, + "PRMD", OR_PRMD, OR_ENC_PS, + "P", OR_PRMD, OR_ENC_PS, + "X121", OR_X121, OR_ENC_NUM, + "X.121", OR_X121, OR_ENC_NUM, + "T-ID", OR_TID, OR_ENC_PS, + "O", OR_O, OR_ENC_PS, + "OU", OR_OU, OR_ENC_PS, + "UA-ID", OR_UAID, OR_ENC_NUM, + "N-ID", OR_UAID, OR_ENC_NUM, + "S", OR_S, OR_ENC_PS, + "G", OR_G, OR_ENC_PS, + "I", OR_I, OR_ENC_PS, + "GQ", OR_GQ, OR_ENC_PS, + "Q", OR_GQ, OR_ENC_PS, + "DD", OR_DD, OR_ENC_PS, + 0, 0, 0 +}; + +typestruct typetab88[] = { + "C", OR_C, OR_ENC_PS, + "ADMD", OR_ADMD, OR_ENC_PS, + "A", OR_ADMD, OR_ENC_PS, + "PRMD", OR_PRMD, OR_ENC_PS, + "P", OR_PRMD, OR_ENC_PS, + "X121", OR_X121, OR_ENC_NUM, + "X.121", OR_X121, OR_ENC_NUM, + "T-ID", OR_TID, OR_ENC_PS, + "O", OR_O, OR_ENC_TTX_AND_OR_PS, + "OU", OR_OU, OR_ENC_TTX_AND_OR_PS, + "OU1", OR_OU1, OR_ENC_TTX_AND_OR_PS, + "OU2", OR_OU2, OR_ENC_TTX_AND_OR_PS, + "OU3", OR_OU3, OR_ENC_TTX_AND_OR_PS, + "OU4", OR_OU4, OR_ENC_TTX_AND_OR_PS, + "UA-ID", OR_UAID, OR_ENC_NUM, + "N-ID", OR_UAID, OR_ENC_NUM, + "S", OR_S, OR_ENC_TTX_AND_OR_PS, + "G", OR_G, OR_ENC_TTX_AND_OR_PS, + "I", OR_I, OR_ENC_TTX_AND_OR_PS, + "GQ", OR_GQ, OR_ENC_TTX_AND_OR_PS, + "Q", OR_GQ, OR_ENC_TTX_AND_OR_PS, + "CN", OR_CN, OR_ENC_TTX_AND_OR_PS, + "PD-SYSTEM",OR_PDSNAME, OR_ENC_PS, + "PD-C", OR_PD_C, OR_ENC_PS, + "POSTCODE", OR_POSTCODE, OR_ENC_PS, + "PD-OFFICE",OR_PDO_NAME, OR_ENC_TTX_AND_OR_PS, + "PD-OFFICE-NUM",OR_PDO_NUM, OR_ENC_TTX_AND_OR_PS, + "PD-OFFICE-NUMBER",OR_PDO_NUM, OR_ENC_TTX_AND_OR_PS, + "PD-OFFICE NUMBER",OR_PDO_NUM, OR_ENC_TTX_AND_OR_PS, + "PD-EXT-D", OR_OR_COMPS, OR_ENC_TTX_AND_OR_PS, + "PD-PN", OR_PD_PN, OR_ENC_TTX_AND_OR_PS, + "PD-O", OR_PD_O, OR_ENC_TTX_AND_OR_PS, + "PD-EXT-LOC",OR_PD_COMPS, OR_ENC_TTX_AND_OR_PS, + "PD-ADDRESS",OR_UPA_PA, OR_ENC_TTX_AND_OR_PS, + "STREET", OR_STREET, OR_ENC_TTX_AND_OR_PS, + "PO-BOX", OR_PO_BOX, OR_ENC_TTX_AND_OR_PS, + "POSTE-RESTANTE",OR_PRA, OR_ENC_TTX_AND_OR_PS, + "PD-UNIQUE",OR_UPN, OR_ENC_TTX_AND_OR_PS, + "PD-LOCAL", OR_LPA, OR_ENC_TTX_AND_OR_PS, + "NET-NUM", OR_ENA_N, OR_ENC_NUM, + "NET-SUB", OR_ENA_S, OR_ENC_NUM, + "NET-PSAP", OR_ENA_P, OR_ENC_PSAP, + "NET-TTYPE",OR_TT, OR_ENC_INT, + "DD", OR_DD, OR_ENC_PS, + 0, 0, 0 + }; + + + +char _pstable[] = { + 0, 0, 0, 0, /* 000-003 nul */ + 0, 0, 0, 0, /* 004-007 */ + 0, 0, 0, 0, /* 010-013 bs tab lf */ + 0, 0, 0, 0, /* 014-017 */ + 0, 0, 0, 0, /* 020-023 */ + 0, 0, 0, 0, /* 024-027 */ + 0, 0, 0, 0, /* 030-033 */ + 0, 0, 0, 0, /* 034-037 */ + CHR_PS|CHR_NS, 0, 0, 0, /* 040-043 sp ! " # */ + 0, 0, 0, CHR_PS, /* 044-047 $ % & ' */ + CHR_PS, CHR_PS, 0, CHR_PS, /* 050-053 ( ) * + */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 054-057 , - . / */ + CHR_PS|CHR_NS, CHR_PS|CHR_NS, CHR_PS|CHR_NS, CHR_PS|CHR_NS, + /* 060-063 0 1 2 3 */ + CHR_PS|CHR_NS, CHR_PS|CHR_NS, CHR_PS|CHR_NS, CHR_PS|CHR_NS, + /* 014-067 4 5 6 7 */ + CHR_PS|CHR_NS, CHR_PS|CHR_NS, CHR_PS, 0, + /* 070-073 8 9 : ; */ + 0, CHR_PS, 0, CHR_PS, /* 074-077 < = > ? */ + 0, CHR_PS, CHR_PS, CHR_PS, /* 100-103 @ A B C */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 014-107 D E F G */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 110-114 H I J K */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 115-117 L M N O */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 120-123 P Q R S */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 124-127 T U V W */ + CHR_PS, CHR_PS, CHR_PS, 0, /* 130-133 X Y Z [ */ + 0, 0, 0, 0, /* 134-137 \ ] ^ _ */ + 0, CHR_PS, CHR_PS, CHR_PS, /* 140-143 ` a b c */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 144-147 d e f g */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 150-153 h i j k */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 154-157 l m n o */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 160-163 p q r s */ + CHR_PS, CHR_PS, CHR_PS, CHR_PS, /* 164-167 t u v w */ + CHR_PS, CHR_PS, CHR_PS, 0, /* 170-173 x y z { */ + 0, 0, 0, 0, /* 174-177 | } ~ del */ + }; + + + + + +CMD_TABLE ortbl_ddvalid[] = { /* ddvalid keys */ + "RFC-822", OR_DDVALID_RFC822, + "X400-88", OR_DDVALID_X40088, +#ifndef STRICT_1148 + "JNT-MAIL", OR_DDVALID_JNT, +#endif + "UUCP", OR_DDVALID_UUCP, + "LIST", OR_DDVALID_LIST, + "ROLE", OR_DDVALID_ROLE, + "FAX", OR_DDVALID_FAX, + "ATTN", OR_DDVALID_ATTN, + 0, -1 + }; + + +OR_upperbound ortbl_88_ubs[] = { /* upperbounds on 88 components */ +{OR_C, OR_UB_C_ALPHA}, +{OR_ADMD, OR_UB_MD}, +{OR_PRMD, OR_UB_MD}, +{OR_O, OR_UB_O}, +{OR_OU, OR_UB_OU}, +{OR_OU1, OR_UB_OU}, +{OR_OU2, OR_UB_OU}, +{OR_OU3, OR_UB_OU}, +{OR_OU4, OR_UB_OU}, +{OR_X121, OR_UB_X121}, +{OR_TID, OR_UB_TID}, +{OR_UAID, OR_UB_UAID}, +{OR_S, OR_UB_S}, +{OR_G, OR_UB_G}, +{OR_I, OR_UB_I}, +{OR_GQ, OR_UB_GQ}, +{OR_CN, OR_UB_CN}, +{OR_PDSNAME, OR_UB_PDSNAME}, +{OR_PD_C, OR_UB_PDS_PARAM}, +{OR_POSTCODE, OR_UB_POSTCODE}, +{OR_PDO_NAME, OR_UB_PDS_PARAM}, +{OR_PDO_NUM, OR_UB_PDS_PARAM}, +{OR_OR_COMPS, OR_UB_OR_COMPS}, +{OR_PD_PN, OR_UB_PDS_PARAM}, +{OR_PD_O, OR_UB_PDS_PARAM}, +{OR_PD_COMPS, OR_UB_PDS_PARAM}, +{OR_UPA_PA, OR_UB_UPA_PA}, +{OR_STREET, OR_UB_PDS_PARAM}, +{OR_PO_BOX, OR_UB_PDS_PARAM}, +{OR_PRA, OR_UB_PDS_PARAM}, +{OR_UPN, OR_UB_PDS_PARAM}, +{OR_LPA, OR_UB_PDS_PARAM}, +{OR_ENA_N, OR_UB_ENA_N}, +{OR_ENA_S, OR_UB_ENA_S}, +{OR_ENA_P, -1}, +{OR_TT, OR_UB_INT_OPTS}, +{OR_DD, OR_UB_DDA_VALUE}, +{0, -1} +}; + +OR_upperbound ortbl_84_ubs[] = { /* upperbounds on 84 components */ +{OR_C, OR_UB_C_ALPHA}, +{OR_ADMD, OR_UB_MD}, +{OR_PRMD, OR_UB_MD}, +{OR_O, OR_UB_O}, +{OR_OU, OR_UB_OU}, +{OR_OU1, OR_UB_OU}, +{OR_OU2, OR_UB_OU}, +{OR_OU3, OR_UB_OU}, +{OR_OU4, OR_UB_OU}, +{OR_X121, OR_UB_X121}, +{OR_TID, OR_UB_TID}, +{OR_UAID, OR_UB_UAID}, +{OR_S, OR_UB_S}, +{OR_G, OR_UB_G}, +{OR_I, OR_UB_I}, +{OR_GQ, OR_UB_GQ}, +{0, -1} +}; diff --git a/Lib/or/or_up_bnds.c b/Lib/or/or_up_bnds.c new file mode 100644 index 0000000..5be4f80 --- /dev/null +++ b/Lib/or/or_up_bnds.c @@ -0,0 +1,75 @@ +/* or_up_bnds.c: routine to check length of O/R components fit in with standards */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_up_bnds.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_up_bnds.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_up_bnds.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "or.h" + +static int get_ub(or, ubs) +OR_ptr or; +OR_upperbound *ubs; +{ + int i; + + for (i = 0; ubs[i].or_type != 0; i++) { + if (ubs[i].or_type == or->or_type) + return ubs[i].or_upperbound; + } + return 0; +} + +int or_check_upper (or, ubs) +OR_ptr or; +OR_upperbound *ubs; +{ + int ub; + + if (or == NULLOR) + return NOTOK; + + if ((ub = get_ub(or, ubs)) != -1) { + if (ub == 0) { + (void) or_lose("Illegal x400 O/R component '%s'", + or_type2name(or->or_type)); + return NOTOK; + } + if (ub < (int) strlen(or->or_value)) { + (void) or_lose ("Exceeds the upperbound on length of '%s' components (%d chars)", + or_type2name(or->or_type), + ub); + return NOTOK; + } + } + + if (or->or_type == OR_DD && + (int) strlen (or->or_ddname) > OR_UB_DDA_TYPE) { + (void) or_lose("'%s' exceeds the upperbound on length of domain defined types (%d chars)", + or->or_ddname, OR_UB_DDA_TYPE); + return NOTOK; + } + + return OK; +} + +int or_chk_ubs (or, ubs) +OR_ptr or; +OR_upperbound *ubs; +{ + + while (or != NULLOR) { + if (or_check_upper(or, ubs) == NOTOK) + return NOTOK; + or = or->or_next; + } + return OK; +} diff --git a/Lib/or/or_util.c b/Lib/or/or_util.c new file mode 100644 index 0000000..4dead52 --- /dev/null +++ b/Lib/or/or_util.c @@ -0,0 +1,283 @@ +/* or_util.c: or-name utility routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_util.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_util.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_util.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + + + +/* +OR Name handling Utilities +*/ + +#include "util.h" +#include "or.h" + +char *or_type2name (type) +int type; +{ + typestruct *ptr; + + PP_DBG (("or_util.c/or_type2name()")); + + for (ptr = typetab88; (ptr -> ty_string) != NULLCP; ptr++) + if (type == ptr->ty_int) + return (ptr->ty_string); + + PP_LOG(LLOG_EXCEPTIONS, + ("BOGUS Unknown type '%d'", type)); + return NULLCP; +} + +int or_name2type (name) +char *name; +{ + typestruct *ptr; + + PP_DBG (("or_util.c/or_name2type (%s)", name ? name : "null")); + + if (!isstr (name)) + return NOTOK; + + for (ptr = typetab88; (ptr -> ty_string) != NULLCP; ptr++) + if (lexequ (name, ptr->ty_string) == 0) + return (ptr->ty_int); + + return NOTOK; +} + +/* +Strcat + dot quoting +*/ + +void dstrcat (s1, s2) +char *s1; +char *s2; +{ + register char *p, *q; + + p = s1 + strlen (s1); + for (q = s2; *q != '\0';) + switch (*q) { + case '.': + case '"': + case '\\': + /* + Shouldn't be any backslashes tho... + */ + *p++ = '\\'; + default: + *p++ = *q++; + break; + } + *p = '\0'; + + PP_DBG (("or_util.c/dstrcat(%s, %s)", s1, s2)); +} + +/* +Strcat + dollar quoting +*/ + +void qstrcat (s1, s2) +char *s1; +char *s2; +{ + register char *p, + *q; + + PP_DBG (("qstrcat()")); + + p = s1 + strlen (s1); + for (q = s2; *q != '\0';) + switch (*q) { + case '/': + case '=': + *p++ = '$'; + default: + *p++ = *q++; + break; + } + *p = '\0'; +} + +int or_gettoken (str, delim, buf) +char **str; +char delim; +char *buf; +{ + + char *ind = *str, + *x; + + x = buf; + if (*ind == '\0') + return NOTOK; + for (; (*ind != delim) && (*ind != '\0'); ind++, buf++) + *buf = *ind; + if (*ind != '\0') ind++; + *str = ind; + *buf = '\0'; + + PP_DBG (("or_util.c/or_gettoken (%s)", x)); + + return OK; +} + +int or_ddvalid_chk (key, buf) +char *key; +char *buf; +{ + int retval; + + switch (retval = cmd_srch (key, ortbl_ddvalid)) { + case OR_DDVALID_RFC822: + case OR_DDVALID_X40088: + case OR_DDVALID_JNT: + case OR_DDVALID_UUCP: + case OR_DDVALID_LIST: + case OR_DDVALID_ROLE: + case OR_DDVALID_FAX: + case OR_DDVALID_ATTN: + (void) strcpy (buf, rcmd_srch (retval, ortbl_ddvalid)); + return OK; + default: + return NOTOK; + } + + /*NOTREACHED*/ +} + +int or_str_isps (str) +char *str; +{ + while (*str && or_isps (*str)) + str ++; + return *str == '\0'; +} + +int or_str_isns (str) +char *str; +{ + int seen_digit = 0; + while (*str) { + if (!or_isns(*str)) + return 0; + if (isdigit (*str)) + seen_digit = 1; + str ++; + } + return seen_digit; +} + +int or_type2charset84 (type) +int type; +{ + typestruct *ptr; + + PP_DBG (("or_util.c/or_type2charset()")); + + for (ptr = typetab; (ptr -> ty_string) != NULLCP; ptr++) + if (type == ptr->ty_int) + return (ptr->ty_charset); + + return 0; +} + +int or_type2charset (type) +int type; +{ + typestruct *ptr; + + PP_DBG (("or_util.c/or_type2charset()")); + + for (ptr = typetab88; (ptr -> ty_string) != NULLCP; ptr++) + if (type == ptr->ty_int) + return (ptr->ty_charset); + + return 0; +} + +int or_checktypes (or, buf) +OR_ptr or; +char *buf; +{ + char *name; + for (; or != NULLOR; or = or -> or_next) { + switch (or -> or_type) { + case OR_OU1: + case OR_OU2: + case OR_OU3: + case OR_OU4: + or -> or_type = OR_OU; + default: + break; + } + + switch (or -> or_encoding) { + case OR_ENC_PS: + if (!or_str_isps (or -> or_value)) { + if ((name = or_type2name (or -> or_type)) != NULLCP) + (void) sprintf (buf, "Attribute %s=%s is not a Printable String", + name, + or -> or_value); + else + (void) sprintf (buf, "Attribute %d=%s is not a Printable String", + or -> or_type, + or -> or_value); + return NOTOK; + } + break; + case OR_ENC_NUM: + if (!or_str_isns (or -> or_value)) { + if ((name = or_type2name (or -> or_type)) != NULLCP) + (void) sprintf (buf, "Attribute %s=%s in not a Numeric String", + name, + or -> or_value); + else + (void) sprintf (buf, "Attribute %d=%s in not a Numeric String", + or -> or_type, + or -> or_value); + return NOTOK; + } + break; + case OR_ENC_TTX: + case OR_ENC_TTX_AND_OR_PS: + case OR_ENC_INT: + case OR_ENC_PSAP: + default: + break; + } + } + return OK; +} + +/* */ + +void or_chk_admd (or) +OR_ptr *or; +{ + OR_ptr ptr; + + if ((ptr = or_find (*or, OR_ADMD, NULLCP)) == NULLOR) { + if (or_find (*or, OR_C, NULLCP) != NULLOR + && or_find (*or, OR_PRMD, NULLCP) != NULLOR) + *or = or_add (*or, + or_new (OR_ADMD, " ", " "), + TRUE); + } else if (ptr -> or_value == NULLCP + || *(ptr -> or_value) == '\0') { + if (ptr -> or_value) + free (ptr -> or_value); + ptr -> or_value = strdup(" "); + } +} diff --git a/Lib/or/or_valid.c b/Lib/or/or_valid.c new file mode 100644 index 0000000..fcc3de5 --- /dev/null +++ b/Lib/or/or_valid.c @@ -0,0 +1,399 @@ +/* or_valid.c: check to see that OR tree matches with standard */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/or_valid.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/or_valid.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: or_valid.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "or.h" + +/* see table 10 in X.402 */ +/* forms of O/R address */ + +static int or_valid_term(), or_valid_post(), or_valid_mnem(), or_valid_none(); + +int or_valid_or (or) +OR_ptr or; +{ + switch (or_form_type(or)) { + case OR_FORM_TERM: + return or_valid_term(or); + case OR_FORM_POST: + return or_valid_post(or); + case OR_FORM_NUMR: + return or_valid_numr(or); + case OR_FORM_MNEM: + return or_valid_mnem(or); + default: + return or_valid_none(or); + } +} + +/* */ +static int or_valid_term(or) +OR_ptr or; +{ + int country, admd, x121, prmd, tid, dda; + country = admd = x121 = prmd = tid = dda = 0; + +#define too_many(x) { PP_LOG (LLOG_EXCEPTIONS, ("Too many %s components", (x))); return NOTOK; } + + while (or != NULLOR) { + switch (or->or_type) { + case OR_C: + if (country++ > 0) + too_many("Country"); + break; + case OR_ADMD: + if (admd++ > 0) + too_many("ADMD"); + break; + case OR_X121: + if (x121++ > 0) + too_many ("X121"); + break; + case OR_PRMD: + if (prmd++ > 0) + too_many ("PRMD"); + break; + case OR_TID: + if (tid++ > 0) + too_many ("TID"); + break; + case OR_DD: + if (dda++ > 3) + too_many ("DD"); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Invalid component '%s=%s' for term form OR", + or_type2name(or->or_type), + or->or_value)); + return NOTOK; + } + or = or -> or_next; + } + + if (x121 < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for term form OR", + or_type2name(OR_X121))); + return NOTOK; + } + return OK; +} + +/* */ +static int or_valid_post(or) +OR_ptr or; +{ + int country, admd, prmd, pdsname, pd_c, postcode, + or_comps, pd_comps, lpa, pdo_name, pdo_num, pd_o, + pd_pn, po_box, pra, street, upa_pa, upn; + + country = admd = prmd = pdsname = pd_c = postcode + = or_comps = pd_comps = lpa = pdo_name = pdo_num = pd_o + = pd_pn = po_box = pra = street = upa_pa = upn = 0; + + while (or != NULLOR) { + switch (or->or_type) { + case OR_C: + country++; + break; + case OR_ADMD: + admd++; + break; + case OR_PRMD: + if (prmd++ > 0) + too_many ("prmd"); + break; + case OR_PDSNAME: + if (pdsname++ > 0) + too_many ("pdsname"); + break; + case OR_PD_C: + pd_c++; + break; + case OR_POSTCODE: + postcode++; + break; + case OR_OR_COMPS: + or_comps++; + break; + case OR_PD_COMPS: + pd_comps++; + break; + case OR_LPA: + lpa++; + break; + case OR_PDO_NAME: + pdo_name++; + break; + case OR_PDO_NUM: + pdo_num++; + break; + case OR_PD_O: + pd_o++; + break; + case OR_PD_PN: + pd_pn++; + break; + case OR_PO_BOX: + po_box++; + break; + case OR_PRA: + pra++; + break; + case OR_STREET: + street++; + break; + case OR_UPA_PA: + upa_pa++; + break; + case OR_UPN: + upn++; + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Invalid component '%s=%s' for postal form OR", + or_type2name(or->or_type), + or->or_value)); + return NOTOK; + } + or = or -> or_next; + } + + if (country < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for postal form OR", + or_type2name(OR_C))); + return NOTOK; + } + + if (admd < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for postal form OR", + or_type2name(OR_ADMD))); + return NOTOK; + } + + if (pd_c < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for postal form OR", + or_type2name(OR_PD_C))); + return NOTOK; + } + + if (postcode < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for postal form OR", + or_type2name(OR_POSTCODE))); + return NOTOK; + } + + if (upa_pa == 1 && + (or_comps > 0 || pd_comps > 0 || lpa > 0 || pdo_name > 0 + || pdo_num > 0 || pd_o > 0 || pd_pn > 0 || po_box > 0 + || pra > 0 || street > 0 || upn > 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal postal components in an unformatted postal OR")); + return NOTOK; + } + + return OK; +} + +/* */ +static int or_valid_numr(or) +OR_ptr or; +{ + int country, admd, prmd, uaid, dda; + country = admd = prmd = uaid = dda = 0; + + while (or != NULLOR) { + switch (or->or_type) { + case OR_C: + country++; + break; + case OR_ADMD: + admd++; + break; + case OR_PRMD: + if (prmd++ > 0) + too_many ("PRMD"); + break; + case OR_UAID: + uaid++; + break; + case OR_DD: + if (dda++ > 3) + too_many ("DD"); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Invalid component '%s=%s' for numeric form OR", + or_type2name(or->or_type), + or->or_value)); + return NOTOK; + } + or = or -> or_next; + } + + if (country < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for numeric form OR", + or_type2name(OR_C))); + return NOTOK; + } + + if (admd < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for numeric form OR", + or_type2name(OR_ADMD))); + return NOTOK; + } + + if (uaid < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for numeric form OR", + or_type2name(OR_UAID))); + return NOTOK; + } + + return OK; +} + +/* */ +static int or_valid_mnem(or) +OR_ptr or; +{ + int country, admd, prmd, cn, o, ou, s, g, i, gq, dda; + country = admd = prmd = cn = o = ou = s = g = i = gq = dda = 0; + + while (or != NULLOR) { + switch (or->or_type) { + case OR_C: + country++; + break; + case OR_ADMD: + admd++; + break; + case OR_CN: + if (cn++ > 0) + too_many ("CN"); + break; + case OR_PRMD: + if (prmd++ > 0) + too_many ("PRMD"); + break; + case OR_O: + if (o++ > 0) + too_many ("O"); + break; + case OR_OU: + case OR_OU1: + case OR_OU2: + case OR_OU3: + case OR_OU4: + if (ou++ > 3) + too_many("OU"); + break; + case OR_S: + s++; + break; + case OR_G: + g++; + break; + case OR_I: + i++; + break; + case OR_GQ: + gq++; + break; + case OR_DD: + if (dda++ > 3) + too_many ("DD"); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Invalid component '%s=%s' for mnemonic form OR", + or_type2name(or->or_type), + or->or_value)); + return NOTOK; + } + or = or -> or_next; + } + + if (country < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for mnemonic form OR", + or_type2name(OR_C))); + return NOTOK; + } + + if (admd < 1) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory component '%s' for mnemonic form OR", + or_type2name(OR_ADMD))); + return NOTOK; + } + + if (s == 0 && + (g > 0 || i > 0 || gq > 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory surname component '%s' for personal name", + or_type2name(OR_S))); + return NOTOK; + } + + return OK; +} +/* */ +static int or_valid_none(or) +OR_ptr or; +{ + int s, g, i, gq; + s = g = i = gq = 0; + +/* just check personal name */ + while (or != NULLOR) { + switch (or->or_type) { + case OR_S: + s++; + break; + case OR_G: + g++; + break; + case OR_I: + i++; + break; + case OR_GQ: + gq++; + break; + default: + /* don't know what form */ + break; + } + or = or -> or_next; + } + + if (s == 0 && + (g > 0 || i > 0 || gq > 0)) { + PP_LOG(LLOG_EXCEPTIONS, + ("Missing mandatory surname component '%s' for personal name", + or_type2name(OR_S))); + return NOTOK; + } + + return OK; +} +#undef too_many diff --git a/Lib/or/orn-dec.c b/Lib/or/orn-dec.c new file mode 100644 index 0000000..09d51d2 --- /dev/null +++ b/Lib/or/orn-dec.c @@ -0,0 +1,529 @@ +/* orn-dec.c: routines to decode ORNames */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-dec.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-dec.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: orn-dec.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "MTA-types.h" +#include "Ext-types.h" + +#include "util.h" +#include "or.h" +#include "extension.h" +#include "IOB-types.h" +#include + +static int do_or_address (), do_addr_ext(), decode_adr_ext(); + +struct type_IOB_ORName *pe2orname (pe) +PE pe; +{ + struct type_IOB_ORName *orn; + + PP_PDUP (IOB_ORName, pe, "ORName", PDU_READ); + + if (decode_IOB_ORName (pe, 1, NULLIP, NULLVP, &orn) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't decode ORName [%s]", + PY_pepy)); + return NULL; + } + return orn; +} + +ORName *orname2orn(orn) +struct type_IOB_ORName *orn; +{ + ORName *orname; + + if (orn == (struct type_IOB_ORName *) NULL) + return NULLORName; + + orname = (ORName *)malloc (sizeof *orname); + if (do_or_address (&orname->on_or, + orn -> standard__attributes, + orn -> domain__defined, + orn -> extension__attributes) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, ("Failed to decipher ORaddress")); + free ((char *)orname); + return NULLORName; + } + + if (orn->directory__name) { + PE dn = orn -> directory__name; + + if (dn -> pe_form != PE_FORM_CONS){ + PP_LOG (LLOG_EXCEPTIONS, ("DN not a constructor form")); + ORName_free (orname); + return NULLORName; + } + if (decode_IF_Name (dn -> pe_cons, 1, + NULLVP, NULLIP, + &orname -> on_dn) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't decode DN [%s]", + PY_pepy)); + ORName_free(orname); + return NULLORName; + } + } else + orname -> on_dn = NULL; + return orname; +} + +ORName *pe2orn(pe) +PE pe; +{ + struct type_IOB_ORName *orn; + ORName *orname; + + if ((orn = pe2orname(pe)) == NULL) + return NULLORName; + + orname = orname2orn(orn); + free_IOB_ORName (orn); + return orname; +} + +struct type_MTA_ORAddress *pe2oradr (pe) +PE pe; +{ + struct type_MTA_ORAddress *ora; + + PP_PDUP (MTA_ORAddress, pe, "ORAddress", PDU_READ); + + if (decode_MTA_ORAddress (pe, 1, NULLIP, NULLVP, &ora) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't decode ORAddress [%s]", + PY_pepy)); + return NULL; + } + return ora; +} + +OR_ptr oradr2ora (ora) +struct type_MTA_ORAddress *ora; +{ + OR_ptr or; + if(do_or_address (&or, + ora -> standard__attributes, + ora -> domain__defined__attributes, + ora -> extension__attributes) == NOTOK) + or = NULLOR; + return or; +} + +OR_ptr pe2ora (pe) +PE pe; +{ + struct type_MTA_ORAddress *ora; + OR_ptr or; + + if ((ora = pe2oradr(pe)) == NULL) + return NULLOR; + or = oradr2ora(ora); + free_MTA_ORAddress (ora); + return or; +} + +static int do_or_address (orp, std, dd, ext) +OR_ptr *orp; +struct type_MTA_StandardAttributes *std; +struct type_MTA_DomainDefinedAttributes *dd; +struct type_MTA_ExtensionAttributes *ext; +{ + struct type_MTA_OrganizationalUnitNames *ou; + OR_ptr tree = NULLOR, or; + char *p; + struct qbuf *qb; + + *orp = NULLOR; +#define do_component(x,y,enc) \ + if (x) {\ + or = or_new_aux (y, NULLCP, p = qb2str (x), (enc));\ + free (p); \ + if (or == NULLOR) return NOTOK; \ + if (or_append (&tree, or) != OK)\ + return NOTOK; \ + } + + if (std) { + if (std -> country__name) { + qb = (std -> country__name -> offset == + type_MTA_CountryName_x121__dcc__code) ? + std -> country__name -> un.x121__dcc__code : + std -> country__name -> + un.iso__3166__alpha2__code; + do_component (qb, OR_C, OR_ENC_PS); + } + if (std -> administration__domain__name) { + qb = (std -> administration__domain__name -> offset == + type_MTA_AdministrationDomainName_numeric) ? + std -> administration__domain__name -> + un.numeric : + std -> administration__domain__name -> + un.printable; + do_component (qb, OR_ADMD, OR_ENC_PS); + } + do_component (std -> network__address, OR_X121, OR_ENC_NUM); + do_component (std -> terminal__identifier, OR_TID, OR_ENC_PS); + if (std -> private__domain__name) { + qb = (std -> private__domain__name -> offset == + type_MTA_PrivateDomainName_numeric) ? + std -> private__domain__name -> + un.numeric : + std -> private__domain__name -> + un.printable; + do_component (qb, OR_PRMD, OR_ENC_PS); + } + do_component (std -> organization__name, OR_O, OR_ENC_PS); + do_component (std -> numeric__user__identifier, OR_UAID, OR_ENC_NUM); + if (std -> personal__name) { + do_component (std -> personal__name -> surname, OR_S, OR_ENC_PS); + do_component (std -> personal__name -> given__name, + OR_G, OR_ENC_PS); + do_component (std -> personal__name -> initials, OR_I, OR_ENC_PS); + do_component (std -> personal__name -> + generation__qualifier, OR_GQ, OR_ENC_PS); + } + for (ou = std -> organizational__unit__names; + ou; ou = ou -> next) { + do_component (ou -> OrganizationUnitName, OR_OU, OR_ENC_PS); + } + } +#undef do_component + for ( ; dd; dd = dd -> next) { + char *q; + + or = or_new_aux (OR_DD, + p = qb2str(dd -> DomainDefinedAttribute -> type), + q = qb2str (dd -> DomainDefinedAttribute -> value), + OR_ENC_PS); + free (q); + free (p); + if (or == NULLOR) return NOTOK; + if (or_append (&tree, or) != OK) + return NOTOK;; + } + + for (; ext; ext = ext -> next) + if (do_addr_ext (&tree, ext -> ExtensionAttribute) == NOTOK) + return NOTOK; + *orp = tree; + return OK; +} + +static int do_addrext_ps (treep, type, qb) +OR_ptr *treep; +int type; +struct qbuf *qb; +{ + char *p; + OR_ptr or; + int retval; + + p = qb2str (qb); + or = or_new_aux (type, NULLCP, p, OR_ENC_PS); + if (or == NULLOR) return NOTOK; + retval = or_append (treep, or); + free (p); + return retval; +} + +static int do_addr_tt (treep, type, tt) +OR_ptr *treep; +int type; +struct type_Ext_TerminalType *tt; +{ + char buf[64]; + OR_ptr or; + + (void) sprintf (buf, "%d", tt -> parm); + or = or_new_aux (type, NULLCP, buf, OR_ENC_INT); + if (or == NULLOR) return NOTOK; + return or_append (treep, or); +} + +static int do_addrext_ttx (treep, type, qb) +OR_ptr *treep; +int type; +struct qbuf *qb; +{ + char *p; + OR_ptr or; + int retval = OK; + + p = qb2str (qb); + if ((or = or_add_t61 (*treep, type, (unsigned char *)p, + qb -> qb_len, 0)) == NULL) + retval = NOTOK; + else + *treep = or; + free (p); + return retval; +} + +static int do_addrext_psorns (treep, type, parm) +OR_ptr *treep; +int type; +struct type_Ext_PostalCode *parm; +{ + char *p; + OR_ptr or; + int retval = OK; + + switch (parm -> offset) { + case type_Ext_PostalCode_numeric__code: + p = qb2str (parm -> un.numeric__code); + or = or_new_aux (type, NULLCP, p, OR_ENC_NUM); + if (or == NULLOR) + return NOTOK; + retval = or_append (treep, or); + break; + case type_Ext_PostalCode_printable__code: + p = qb2str (parm -> un.printable__code); + or = or_new_aux (type, NULLCP, p, OR_ENC_PS); + if (or == NULLOR) + return NOTOK; + retval = or_append (treep, or); + default: + return NOTOK; + } + free (p); + return retval; +} + +static int do_addrext_pds (treep, type, parm) +OR_ptr *treep; +int type; +struct type_Ext_PDSParameter *parm; +{ + int retval; + OR_ptr or; + char *p; + + if (parm -> printable__string) { + p = qb2str (parm -> printable__string); + or = or_new_aux (type, NULLCP, p, OR_ENC_PS); + free (p); + if (or == NULLOR) return NOTOK; + retval = or_append (treep, or); + if (retval != OK) + return retval; + } + if (parm -> teletex__string) { + p = qb2str (parm -> teletex__string); + or = or_add_t61 (*treep, type, (unsigned char *)p, + parm -> teletex__string -> qb_len, 0); + free (p); + if (or == NULL) + return NOTOK; + *treep = or; + } + return OK; +} + +/* ARGSUSED */ +static int do_addrext_ena (treep, type, parm) +OR_ptr *treep; +int type; +struct type_Ext_ExtendedNetworkAddress *parm; +{ + OR_ptr or; + struct PSAPaddr *pa; + + switch (parm -> offset) { + case type_Ext_ExtendedNetworkAddress_e163__4__address: + if (parm -> un.e163__4__address -> number) { + char *p = qb2str (parm -> un.e163__4__address -> number); + or = or_new_aux (OR_ENA_N, NULLCP, p, OR_ENC_NUM); + free (p); + if (or == NULLOR) return NOTOK; + if (or_append (treep, or) == NOTOK) + return NOTOK; + } + if (parm -> un.e163__4__address -> sub__address) { + char *p = qb2str (parm -> un.e163__4__address -> sub__address); + or = or_new_aux (OR_ENA_S, NULLCP, p, OR_ENC_NUM); + free (p); + if (or == NULLOR) return NOTOK; + if (or_append (treep, or) == NOTOK) + return NOTOK; + } + break; + + case type_Ext_ExtendedNetworkAddress_psap__address: + if (parse_DSE_PSAPaddr (parm -> un.psap__address, + 1, NULLIP, NULLVP, &pa) == NOTOK) + return NOTOK; + or = or_new_aux (OR_ENA_P, NULLCP, + paddr2str(pa, NULLNA), OR_ENC_PSAP); + if (or == NULLOR) return NOTOK; + if (or_append (treep, or) == NOTOK) + return NOTOK; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown ena type %d", + parm -> offset)); + return NOTOK; + } + return OK; +} + +static int do_addr_ext (treep, ext) +OR_ptr *treep; +struct type_MTA_ExtensionAttribute *ext; +{ + PY_pepy[0] = 0; + +#define dec_axt(off, type, fnx, lab) \ + decode_adr_ext (ext -> value, &_ZExt_mod,\ + (off), (type), (fnx), (lab), treep) + + switch (ext -> type) { + case AEXT_CN: /* common-name */ + return dec_axt (_ZCommonNameExt, OR_CN, do_addrext_ps, + "CommonName"); + + case AEXT_TTXCN: /* teletex-common-name */ + return dec_axt (_ZTeletexCommonNameExt, OR_CN, + do_addrext_ttx, "TelexCommonName"); + + case AEXT_TTXORG: /* teletex-organization */ + return dec_axt (_ZTeletexOrganizationNameExt, OR_O, + do_addrext_ttx, "TeletexOrganizationName"); + + case AEXT_TTXPN: /* teletex-personal-name */ + case AEXT_TTXOU: /* teletex-organizational-unit-names */ + case AEXT_TTXDD: /* teletex-domain-defined-attributes */ + break; + case AEXT_PDSNAME: /* pds-name */ + return dec_axt (_ZPDSNameExt, OR_PDSNAME, + do_addrext_ps, "PDSName"); + + case AEXT_PDCN: /* physical-delivery-country-name */ + return dec_axt (_ZPhysicalDeliveryCountryNameExt, OR_PD_C, + do_addrext_psorns, + "PhysicalDeliveryCountryName"); + + case AEXT_POSTCODE: /* postal-code */ + return dec_axt (_ZPostalCodeExt, OR_POSTCODE, + do_addrext_psorns, "PostalCode"); + + case AEXT_PDONAME: /* physical-delivery-office-name */ + return dec_axt (_ZPhysicalDeliveryOfficeNameExt, + OR_PDO_NAME, do_addrext_pds, + "PhysicalDeliveryOfficeName"); + + case AEXT_PDONUMB: /* physical-delivery-office-number */ + return dec_axt (_ZPhysicalDeliveryOfficeNumberExt, + OR_PDO_NUM, do_addrext_pds, + "PhysicalDeliveryOfficeNumber"); + + case AEXT_ORAC: /* extension-OR-address-components */ + return dec_axt (_ZExtensionORAddressComponentsExt, + OR_OR_COMPS, do_addrext_pds, + "ExtensionORAddressComponents"); + + case AEXT_PDPN: /* physical-delivery-personal-name */ + return dec_axt (_ZPhysicalDeliveryPersonalNameExt, + OR_PD_PN, do_addrext_pds, + "PhysicalDeliveryPersonalName"); + + case AEXT_PDORG: /* physical-delivery-organization-name */ + return dec_axt (_ZPhysicalDeliveryOrganizationNameExt, + OR_PD_O, do_addrext_pds, + "PhysicalDeliveryOrganizationName"); + + case AEXT_EPDAC: /* extension-physical-delivery-address-components */ + return dec_axt (_ZExtensionPhysicalDeliveryAddressComponentsExt, + OR_PD_COMPS, do_addrext_pds, + "ExtensionPhysicalDeliveryAddressComponents"); + + case AEXT_UNFPA: /* unformatted-postal-address */ + break; + + case AEXT_STREET: /* street-address */ + return dec_axt (_ZStreetAddressExt, OR_STREET, + do_addrext_pds, "StreetAddress"); + + case AEXT_POBOX: /* post-office-box-address */ + return dec_axt (_ZPostOfficeBoxAddressExt, OR_PO_BOX, + do_addrext_pds, "PostOfficeBoxAddress"); + + case AEXT_POSTERES: /* poste-restante-address */ + return dec_axt (_ZPosteRestanteAddressExt, + OR_PRA, do_addrext_pds, + "PosteRestanteAddress"); + + case AEXT_UNIQPA: /* unique-postal-address */ + return dec_axt (_ZUniquePostalNameExt, + OR_UPN, do_addrext_pds, + "UniquePostalName"); + + case AEXT_LPA: /* local-postal-attribute */ + return dec_axt (_ZLocalPostalAttributesExt, + OR_LPA, do_addrext_pds, + "LocalPostalAttributes"); + + case AEXT_NETADDR: /* extended-network-address */ + return dec_axt (_ZExtendedNetworkAddressExt, + OR_ENA_S, do_addrext_ena, + "ExtendedNetworkAddress"); + + case AEXT_TT: /* terminal-type */ + return dec_axt (_ZTerminalTypeExt, OR_TT, + do_addr_tt, "TerminalType"); + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown address extension %d", + ext -> type)); + break; + } + return OK; +} + +static int decode_adr_ext (petag, mod, offset, type, fnx, label, treep) +PE petag; +modtyp *mod; +int offset; +int type; +IFP fnx; +char *label; +OR_ptr *treep; +{ + caddr_t genp; + int retval; + PE pe; + + if (petag -> pe_class != PE_CLASS_CONT && + petag -> pe_form != PE_FORM_CONS && + petag -> pe_id != 1) { + PP_LOG (LLOG_EXCEPTIONS, ("Missing [1] tag in adr extension")); + return NOTOK; + } + pe = petag -> pe_cons; /* strip off the tag */ +#if PP_DEBUG > 0 + if (pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, offset, mod, + pe, label, PDU_READ); +#endif + if (dec_f (offset, mod, pe, 1, NULLIP, NULLVP, &genp) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't parse %s [%s]", + label, PY_pepy)); + return NOTOK; + } + + if ((retval = (*fnx) (treep, type, genp)) != OK) + return retval; + + (void) fre_obj ((char *)genp, mod -> md_dtab[offset], mod, 1); + + return OK; +} diff --git a/Lib/or/orn-enc.c b/Lib/or/orn-enc.c new file mode 100644 index 0000000..5f0127f --- /dev/null +++ b/Lib/or/orn-enc.c @@ -0,0 +1,1002 @@ +/* orn-enc.c: routines to encode ORNames */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-enc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-enc.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: orn-enc.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "or.h" +#include "IOB-types.h" +#include "MTA-types.h" +#include "Ext-types.h" +#include "extension.h" +#include + +static int build_std_or(), build_dd_or(), build_ext_or(); + +#define STR2QB(s) str2qb(s, strlen(s), 1) + +struct type_IOB_ORName *orn2orname(orn) +ORName *orn; +{ + struct type_IOB_ORName *orname; + OR_ptr or; + int ret; + + + orname = (struct type_IOB_ORName *) smalloc (sizeof *orname); + bzero ((char *)orname, sizeof *orname); + + for (or = orn -> on_or; or; or = or -> or_next) { + switch (or -> or_type) { + case OR_C: + case OR_ADMD: + case OR_PRMD: + case OR_X121: + case OR_TID: + case OR_UAID: + ret = build_std_or (&orname -> standard__attributes, + or); + break; + + case OR_O: + case OR_OU: + case OR_S: + case OR_G: + case OR_I: + case OR_GQ: + if (or -> or_encoding == OR_ENC_PS) + ret = build_std_or (&orname -> standard__attributes, + or); + else if (or -> or_encoding == OR_ENC_TTX) + ret = build_ext_or (&orname -> extension__attributes, + or); + else { + ret = build_std_or (&orname -> standard__attributes, + or); + if (ret == OK) + ret = build_ext_or (&orname -> extension__attributes, + or); + } + break; + case OR_DD: + if (or -> or_encoding == OR_ENC_PS) + ret = build_dd_or (&orname -> domain__defined, + or); + else if (or -> or_encoding == OR_ENC_TTX) + ret = build_ext_or (&orname -> extension__attributes, + or); + else { + ret = build_dd_or (&orname -> domain__defined, + or); + if (ret == OK) + ret = build_ext_or (&orname -> extension__attributes, + or); + } + break; + case OR_CN: + case OR_PDSNAME: + case OR_PD_C: + case OR_POSTCODE: + case OR_PDO_NAME: + case OR_PDO_NUM: + case OR_OR_COMPS: + case OR_PD_PN: + case OR_PD_O: + case OR_PD_COMPS: + case OR_UPA_PA: + case OR_STREET: + case OR_PO_BOX: + case OR_PRA: + case OR_UPN: + case OR_LPA: + case OR_ENA_N: + case OR_ENA_S: + case OR_ENA_P: + case OR_TT: + ret = build_ext_or (&orname -> extension__attributes, + or); + break; + } + if (ret == NOTOK) { + free_IOB_ORName (orname); + return NULL; + } + } + if (orname -> standard__attributes == NULL) + orname -> standard__attributes = + (struct type_MTA_StandardAttributes *) calloc + (1, sizeof (struct type_MTA_StandardAttributes)); + + if (orn -> on_dn) { + PE pet; + if (encode_IF_Name (&orname -> directory__name, 1, NULLCP, 0, + orn -> on_dn) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode DN [%s]", + PY_pepy)); + free_IOB_ORName (orname); + return NULL; + } + if ((pet = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 0)) == + NULLPE) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't allocate PE")); + free_IOB_ORName (orname); + return NULL; + } + pet -> pe_cons = orname->directory__name; + orname->directory__name = pet; + } else + orname->directory__name = NULL; + return orname; +} + +PE orname2pe(orname) +struct type_IOB_ORName *orname; +{ + PE pe; + if (encode_IOB_ORName (&pe, 1, NULLCP, 0, orname) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode DN [%s]", + PY_pepy)); + return NULLPE; + } + return pe; +} + +PE orn2pe (orn) +ORName *orn; +{ + struct type_IOB_ORName *orname; + PE pe; + + if ((orname = orn2orname(orn)) == NULL) + return NULLPE; + pe = orname2pe(orname); + free_IOB_ORName(orname); + return pe; +} + +struct type_MTA_ORAddress *ora2oradr (ortree) +OR_ptr ortree; +{ + struct type_MTA_ORAddress *ora; + OR_ptr or; + int ret; + + ora = (struct type_MTA_ORAddress *) smalloc (sizeof *ora); + bzero ((char *)ora, sizeof *ora); + + for (or = ortree; or; or = or -> or_next) { + switch (or -> or_type) { + case OR_C: + case OR_ADMD: + case OR_PRMD: + case OR_X121: + case OR_TID: + case OR_UAID: + ret = build_std_or (&ora -> standard__attributes, + or); + break; + + case OR_O: + case OR_OU: + case OR_S: + case OR_G: + case OR_I: + case OR_GQ: + if (or -> or_encoding == OR_ENC_PS) + ret = build_std_or (&ora -> standard__attributes, + or); + else if (or -> or_encoding == OR_ENC_TTX) + ret = build_ext_or (&ora -> extension__attributes, + or); + else { + ret = build_std_or (&ora -> standard__attributes, + or); + if (ret == OK) + ret = build_ext_or (&ora -> extension__attributes, + or); + } + break; + case OR_DD: + if (or -> or_encoding == OR_ENC_PS) + ret = build_dd_or (&ora -> domain__defined__attributes, + or); + else if (or -> or_encoding == OR_ENC_TTX) + ret = build_ext_or (&ora -> extension__attributes, + or); + else { + ret = build_dd_or (&ora -> domain__defined__attributes, + or); + if (ret == OK) + ret = build_ext_or (&ora -> extension__attributes, + or); + } + break; + case OR_CN: + case OR_PDSNAME: + case OR_PD_C: + case OR_POSTCODE: + case OR_PDO_NAME: + case OR_PDO_NUM: + case OR_OR_COMPS: + case OR_PD_PN: + case OR_PD_O: + case OR_PD_COMPS: + case OR_UPA_PA: + case OR_STREET: + case OR_PO_BOX: + case OR_PRA: + case OR_UPN: + case OR_LPA: + case OR_ENA_N: + case OR_ENA_S: + case OR_ENA_P: + case OR_TT: + ret = build_ext_or (&ora -> extension__attributes, + or); + break; + } + if (ret == NOTOK) { + free_MTA_ORAddress (ora); + return NULL; + } + } + return ora; +} + +PE oradr2pe(ora) +struct type_MTA_ORAddress *ora; +{ + PE pe; + if (encode_MTA_ORAddress (&pe, 1, NULLCP, 0, ora) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode ORAddress [%s]", + PY_pepy)); + return NULLPE; + } + + return pe; +} + +PE ora2pe(ortree) +OR_ptr ortree; +{ + struct type_MTA_ORAddress *ora; + PE pe; + if ((ora = ora2oradr(ortree)) == NULL) + return NULLPE; + pe = oradr2pe(ora); + free_MTA_ORAddress(ora); + return pe; +} + +static int build_std_or (std, or) +struct type_MTA_StandardAttributes **std; +OR_ptr or; +{ + if (*std == NULL) { + *std = (struct type_MTA_StandardAttributes *) + smalloc (sizeof **std); + bzero ((char *)*std, sizeof **std); + } + + switch (or -> or_type) { + case OR_C: + { + struct type_MTA_CountryName *co; + if ((*std) -> country__name) { + PP_LOG (LLOG_EXCEPTIONS, + ("two country attributes")); + return NOTOK; + } + co = (struct type_MTA_CountryName *) + smalloc (sizeof *co); + if (or_str_isns (or -> or_value)) { + co -> offset = type_MTA_CountryName_x121__dcc__code; + co -> un.x121__dcc__code = + STR2QB(or->or_value); + } + else { + co -> offset = type_MTA_CountryName_iso__3166__alpha2__code; + co -> un.iso__3166__alpha2__code = + STR2QB (or -> or_value); + } + (*std) -> country__name = co; + } + break; + case OR_ADMD: + { + struct type_MTA_AdministrationDomainName *admd; + + if ((*std) -> administration__domain__name != NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Already got an ADMD")); + return NOTOK; + } + admd = (*std) -> administration__domain__name = + (struct type_MTA_AdministrationDomainName *) + smalloc (sizeof *admd); + if (or_str_isns (or -> or_value)) { + admd -> offset = type_MTA_AdministrationDomainName_numeric; + admd -> un.numeric = STR2QB (or -> or_value); + } + else { + admd -> offset = + type_MTA_AdministrationDomainName_printable; + admd -> un.printable = STR2QB (or -> or_value); + } + } + break; + + case OR_PRMD: + { + struct type_MTA_PrivateDomainName *prmd; + + if ((*std) -> private__domain__name != NULL ){ + PP_LOG (LLOG_EXCEPTIONS, + ("Already got a PRMD")); + return NOTOK; + } + prmd = (*std) -> private__domain__name = + (struct type_MTA_PrivateDomainName *) + smalloc (sizeof *prmd); + if (or_str_isns (or -> or_value)) { + prmd -> offset = type_MTA_PrivateDomainName_numeric; + prmd -> un.numeric = STR2QB (or-> or_value); + } + else { + prmd -> offset = type_MTA_PrivateDomainName_printable; + prmd -> un.printable = STR2QB (or-> or_value); + } + } + break; + + case OR_O: + { + if (or -> or_encoding == OR_ENC_TTX) + break; + if ((*std) -> organization__name != NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Already got an Organization")); + return NOTOK; + } + (*std) -> organization__name = + or_getps (or -> or_value, or->or_encoding); + } + break; + case OR_OU: + { + struct type_MTA_OrganizationalUnitNames *ou, **oup; + + if (or -> or_encoding == OR_ENC_TTX) + break; + for (oup = &(*std) -> organizational__unit__names; + *oup; oup = &(*oup) -> next) + continue; + ou = (struct type_MTA_OrganizationalUnitNames *) + smalloc (sizeof *ou); + ou -> OrganizationUnitName = + or_getps (or -> or_value, or -> or_encoding); + ou -> next = NULL; + *oup = ou; + } + break; + + case OR_X121: + { + if ((*std) -> network__address != NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Extra X121 id")); + return NOTOK; + } + (*std) -> network__address = STR2QB (or -> or_value); + } + break; + + case OR_TID: + { + if ((*std) -> terminal__identifier != NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Extra terminal identifier")); + return NOTOK; + } + (*std) -> terminal__identifier = STR2QB (or -> or_value); + } + break; + + case OR_UAID: + { + if ((*std) -> numeric__user__identifier != NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("extra numeric user id")); + return NOTOK; + } + (*std) -> numeric__user__identifier = + STR2QB (or -> or_value); + } + break; + + case OR_S: + case OR_G: + case OR_I: + case OR_GQ: + { + struct type_MTA_PersonalName *pn; + + if ((*std) -> personal__name == NULL) { + pn = (*std) -> personal__name = + (struct type_MTA_PersonalName *) + smalloc (sizeof *pn); + bzero ((char *)pn, sizeof *pn); + } + else pn = (*std) -> personal__name; + + switch (or -> or_type) { + case OR_S: + pn -> surname = or_getps (or -> or_value, + or -> or_encoding); + break; + + case OR_G: + pn -> given__name = or_getps (or -> or_value, + or -> or_encoding); + break; + + case OR_I: + pn -> initials = or_getps (or -> or_value, + or -> or_encoding); + break; + + case OR_GQ: + pn -> generation__qualifier = + or_getps (or -> or_value, + or -> or_encoding); + break; + } + } + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Bad type %d", or -> or_type)); + return NOTOK; + } + return OK; +} + +static int build_dd_or (domd, or) +struct type_MTA_DomainDefinedAttributes **domd; +OR_ptr or; +{ + struct type_MTA_DomainDefinedAttributes **ddp, *dp; + + for (ddp = domd; *ddp; ddp = &(*ddp) -> next) + continue; + + dp = (struct type_MTA_DomainDefinedAttributes *) + smalloc (sizeof *dp); + if (dp == NULL) + return NOTOK; + dp -> DomainDefinedAttribute = + (struct type_MTA_DomainDefinedAttribute *) + smalloc (sizeof *dp -> DomainDefinedAttribute); + dp -> next = NULL; + dp -> DomainDefinedAttribute -> type = STR2QB (or -> or_ddname); + dp -> DomainDefinedAttribute -> value = STR2QB (or -> or_value); + + *ddp = dp; + return OK; +} + + +static int build_aext (or, mod, offset, label, fnx, type, ext) +OR_ptr or; +modtyp *mod; +int offset; +IFP fnx; +char *label; +struct type_MTA_ExtensionAttributes **ext; +{ + struct type_MTA_ExtensionAttribute *ep; + struct type_MTA_ExtensionAttributes *epa; + caddr_t parm; + PE pe; + + if ((*fnx) (or, &parm) == NOTOK) + return NOTOK; + + ep = (struct type_MTA_ExtensionAttribute *) smalloc (sizeof *ep); + ep -> type = type; + + if (enc_f (offset, mod, &pe, 1, 0, NULLCP, parm) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't encode value %s: %s", + label, PY_pepy)); + return NOTOK; + } + /* insert tag */ + ep -> value = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, 1); + ep -> value -> pe_cons = pe; +#if PP_DEBUG > 0 + if(pp_log_norm -> ll_events & LLOG_PDUS) + pvpdu (pp_log_norm, offset, mod, + ep -> value, label, PDU_WRITE); +#endif + (void) fre_obj (parm, mod->md_dtab[offset], mod, 1); + + epa = (struct type_MTA_ExtensionAttributes *) smalloc (sizeof *epa); + epa -> next = *ext; + *ext = epa; + epa -> ExtensionAttribute = ep; + + return OK; +} + +static int ext_ttx_str (or, qb) +OR_ptr or; +struct qbuf **qb; +{ + if ((*qb = or_getttx (or -> or_value, or -> or_encoding)) == NULL) + return NOTOK; + return OK; +} + +static int ext_ps_str (or, qb) +OR_ptr or; +struct qbuf **qb; +{ + if ((*qb = or_getps (or -> or_value, or -> or_encoding)) == NULL) + return NOTOK; + return OK; +} + +static int ext_pdsparm (or, parm) +OR_ptr or; +struct type_Ext_PDSParameter **parm; +{ + *parm = (struct type_Ext_PDSParameter *) + smalloc (sizeof **parm); + + switch (or -> or_encoding) { + case OR_ENC_TTX_AND_OR_PS: + (*parm) -> printable__string = or_getps (or -> or_value, + or -> or_encoding); + /* fall */ + case OR_ENC_TTX: + (*parm) -> teletex__string = or_getttx (or -> or_value, + or -> or_encoding); + return OK; + + case OR_ENC_PS: + (*parm) -> printable__string = or_getps (or -> or_value, + or -> or_encoding); + return OK; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown encoding type %d for %s", + or -> or_encoding, or -> or_value)); + return NOTOK; + } +} + +static int ext_upa (or, parm) /* XXX BROKEN */ +OR_ptr or; +struct type_Ext_UnformattedPostalAddress **parm; +{ + struct element_Ext_1 **pap; + *parm = (struct type_Ext_UnformattedPostalAddress *) + smalloc (sizeof **parm); + pap = &(*parm)->printable__address; + + for (;or && or -> or_type == OR_UPA_PA; or = or -> or_next) { + switch (or -> or_encoding) { + case OR_ENC_TTX: + (*parm) -> teletex__string = + or_getttx (or -> or_value, + or -> or_encoding); + break; + case OR_ENC_PS: + *pap = (struct element_Ext_1 *) + smalloc (sizeof **pap); + (*pap) -> PrintableString = + or_getps (or -> or_value, or -> or_encoding); + (*pap) -> next = NULL; + pap = &(*pap) -> next; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unexpected encoding in UFPA %s %d", + or -> or_value, or -> or_encoding)); + return NOTOK; + } + } + return OK; +} + +static int ext_psorns_str (or, parm) +OR_ptr or; +struct type_Ext_PostalCode **parm; +{ + *parm = (struct type_Ext_PostalCode *) + smalloc (sizeof **parm); + switch (or -> or_encoding) { + case OR_ENC_NUM: + (*parm) -> offset = type_Ext_PostalCode_numeric__code; + (*parm) -> un.numeric__code = STR2QB (or -> or_value); + break; + case OR_ENC_PS: + (*parm) -> offset = type_Ext_PostalCode_printable__code; + (*parm) -> un.printable__code = STR2QB(or -> or_value); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unexpected postalcode encoding %d %s", + or -> or_encoding, or -> or_value)); + return NOTOK; + } + return OK; +} + +static int ext_ttxous (or, parm) +OR_ptr or; +struct type_Ext_TeletexOrganizationalUnitNames **parm; +{ + for (;or && or -> or_type == OR_OU; or = or -> or_next) { + if (or -> or_encoding != OR_ENC_TTX && + or -> or_encoding != OR_ENC_TTX_AND_OR_PS) + continue; + *parm = (struct type_Ext_TeletexOrganizationalUnitNames *) + smalloc (sizeof **parm); + (*parm) -> next = NULL; + (*parm) -> TeletexOrganizationalUnitName = + or_getttx (or -> or_value, + or -> or_encoding); + parm = &(*parm) -> next; + } + return OK; +} + +static int ext_ttx_pn (or, parm) +OR_ptr or; +struct type_Ext_TeletexPersonalName **parm; +{ + *parm = (struct type_Ext_TeletexPersonalName *) + smalloc (sizeof **parm); + while (or) { + if (or -> or_encoding != OR_ENC_TTX && + or -> or_encoding != OR_ENC_TTX_AND_OR_PS) + continue; + switch (or -> or_type) { + case OR_S: + (*parm) -> surname = or_getttx (or->or_value, + or -> or_encoding); + break; + case OR_GQ: + (*parm) -> given__name = or_getttx (or -> or_value, + or -> or_encoding); + break; + case OR_I: + (*parm) -> initials = or_getttx (or -> or_value, + or -> or_encoding); + break; + case OR_G: + (*parm) -> generation__qualifier = + or_getttx (or -> or_value, + or -> or_encoding); + break; + + default: + return OK; + } + } + return OK; +} + +static int ext_ttx_dd (or, parm) +OR_ptr or; +struct type_Ext_TeletexDomainDefinedAttributes **parm; +{ + for (;or && or -> or_type == OR_DD; or = or -> or_next) { + if (or -> or_encoding != OR_ENC_TTX && + or -> or_encoding != OR_ENC_TTX_AND_OR_PS) + continue; + *parm = (struct type_Ext_TeletexDomainDefinedAttributes *) + smalloc (sizeof **parm); + (*parm) -> next = NULL; + (*parm) -> TeletexDomainDefinedAttribute = + (struct type_Ext_TeletexDomainDefinedAttribute *) + smalloc (sizeof (struct type_Ext_TeletexDomainDefinedAttribute)); + (*parm) -> TeletexDomainDefinedAttribute -> type = + or_getttx (or -> or_ddname, or -> or_encoding); + (*parm) -> TeletexDomainDefinedAttribute -> value = + or_getttx (or -> or_value, or -> or_encoding); + parm = &(*parm) -> next; + } + return OK; +} + +static int ext_tt (or, parm) +OR_ptr or; +struct type_Ext_TerminalType **parm; +{ + (*parm) = (struct type_Ext_TerminalType *) smalloc (sizeof **parm); + (*parm) -> parm = atoi(or -> or_value); + return OK; +} + +static int ext_ena (or, parm) +OR_ptr or; +struct type_Ext_ExtendedNetworkAddress **parm; +{ + PE pe; + struct PSAPaddr *pa; + + *parm = (struct type_Ext_ExtendedNetworkAddress *) + smalloc (sizeof **parm); + bzero ((char *)*parm, sizeof **parm); + + while (or) { + switch (or -> or_type) { + case OR_ENA_N: + if ((*parm) -> offset == 0) { + (*parm) -> offset = type_Ext_ExtendedNetworkAddress_e163__4__address; + (*parm) -> un.e163__4__address = + (struct element_Ext_2 *) + smalloc (sizeof (struct element_Ext_2)); + } + (*parm) -> un.e163__4__address -> + number = STR2QB (or -> or_value); + break; + + case OR_ENA_S: + if ((*parm) -> offset == 0) { + (*parm) -> offset = type_Ext_ExtendedNetworkAddress_e163__4__address; + (*parm) -> un.e163__4__address = + (struct element_Ext_2 *) + smalloc (sizeof (struct element_Ext_2)); + } + (*parm) -> un.e163__4__address -> + sub__address = STR2QB(or -> or_value); + break; + + case OR_ENA_P: + if ((*parm) -> offset != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Both PSAP & e163 addr in OR")); + return NOTOK; + } + if ((pa = str2paddr (or -> or_value)) == NULLPA) + return NOTOK; + if (build_DSE_PSAPaddr (&pe, 1, 0, NULLCP, pa) == NOTOK) + return NOTOK; + (*parm) -> offset = type_Ext_ExtendedNetworkAddress_psap__address; + (*parm) -> un.psap__address = pe; + break; + default: + break; + } + or = or -> or_next; + } + return OK; +} + +static int find_ext (ext, type) +struct type_MTA_ExtensionAttributes **ext; +int type; +{ + struct type_MTA_ExtensionAttributes *ep; + + for (ep = *ext; ep; ep = ep -> next) { + if (ep -> ExtensionAttribute -> type == type) + return 1; + } + return 0; +} + +static int build_ext_or (ext, or) +struct type_MTA_ExtensionAttributes **ext; +OR_ptr or; +{ + switch (or -> or_type) { + case OR_O: + return build_aext (or, + &_ZExt_mod, + _ZTeletexOrganizationNameExt, + "TeletexOrganizationName", + ext_ttx_str, + AEXT_TTXORG, + ext); + + case OR_OU: + if (find_ext (ext, AEXT_TTXOU)) + return OK; + return build_aext (or, + &_ZExt_mod, + _ZTeletexOrganizationalUnitNamesExt, + "TeletexOrganizationalUnitNames", + ext_ttxous, + AEXT_TTXOU, + ext); + case OR_S: /* first one */ + case OR_G: + case OR_I: + case OR_GQ: + if (find_ext (ext, AEXT_TTXPN)) + return OK; + return build_aext (or, + &_ZExt_mod, + _ZTeletexPersonalNameExt, + "TeletexPersonalName", + ext_ttx_pn, + AEXT_TTXPN, + ext); + case OR_DD: + if (find_ext (ext, AEXT_TTXDD)) + return OK; + return build_aext (or, + &_ZExt_mod, + _ZTeletexDomainDefinedAttributesExt, + "TeletexDomainDefinedAttributes", + ext_ttx_dd, + AEXT_TTXDD, + ext); + case OR_CN: + return build_aext (or, + &_ZExt_mod, + _ZCommonNameExt, + "CommonName", + ext_ps_str, + AEXT_CN, + ext); + case OR_PDSNAME: + return build_aext (or, + &_ZExt_mod, + _ZPDSNameExt, + "PDSName", + ext_ps_str, + AEXT_PDSNAME, + ext); + case OR_PD_C: + return build_aext (or, + &_ZExt_mod, + _ZPhysicalDeliveryCountryNameExt, + "PhysicalDeliveryCountryName", + ext_psorns_str, + AEXT_PDCN, + ext); + case OR_POSTCODE: + return build_aext (or, + &_ZExt_mod, + _ZPostalCodeExt, + "PostalCode", + ext_psorns_str, + AEXT_POSTCODE, + ext); + case OR_PDO_NAME: + return build_aext (or, + &_ZExt_mod, + _ZPhysicalDeliveryOfficeNameExt, + "PhysicalDeliveryOfficeName", + ext_pdsparm, + AEXT_PDONAME, + ext); + case OR_PDO_NUM: + return build_aext (or, + &_ZExt_mod, + _ZPhysicalDeliveryOfficeNumberExt, + "PhysicalDeliveryOfficeNumber", + ext_pdsparm, + AEXT_PDONUMB, + ext); + case OR_OR_COMPS: + return build_aext (or, + &_ZExt_mod, + _ZExtensionORAddressComponentsExt, + "ExtensionORAddressComponents", + ext_pdsparm, + AEXT_ORAC, + ext); + case OR_PD_PN: + return build_aext (or, + &_ZExt_mod, + _ZPhysicalDeliveryPersonalNameExt, + "PhysicalDeliveryPersonalName", + ext_pdsparm, + AEXT_PDPN, + ext); + case OR_PD_O: + return build_aext (or, + &_ZExt_mod, + _ZPhysicalDeliveryOrganizationNameExt, + "PhysicalDeliveryOrganizationName", + ext_pdsparm, + AEXT_PDORG, + ext); + case OR_PD_COMPS: + return build_aext (or, + &_ZExt_mod, + _ZExtensionPhysicalDeliveryAddressComponentsExt, + "ExtensionPhysicalDeliveryAddressComponents", + ext_pdsparm, + AEXT_EPDAC, + ext); + case OR_UPA_PA: + if (find_ext (ext, AEXT_UNFPA)) + return OK; /* already done it */ + return build_aext (or, + &_ZExt_mod, + _ZUnformattedPostalAddressExt, + "UnformattedPostalAddress", + ext_upa, + AEXT_UNFPA, + ext); + + case OR_STREET: + return build_aext (or, + &_ZExt_mod, + _ZStreetAddressExt, + "StreetAddress", + ext_pdsparm, + AEXT_STREET, + ext); + case OR_PO_BOX: + return build_aext (or, + &_ZExt_mod, + _ZPostOfficeBoxAddressExt, + "PostOfficeBoxAddress", + ext_pdsparm, + AEXT_POBOX, + ext); + case OR_PRA: + return build_aext (or, + &_ZExt_mod, + _ZPosteRestanteAddressExt, + "PosteRestanteAddress", + ext_pdsparm, + AEXT_POSTERES, + ext); + case OR_UPN: + return build_aext (or, + &_ZExt_mod, + _ZUniquePostalNameExt, + "UniquePostalName", + ext_pdsparm, + AEXT_UNIQPA, + ext); + case OR_LPA: + return build_aext (or, + &_ZExt_mod, + _ZLocalPostalAttributesExt, + "LocalPostalAttributes", + ext_pdsparm, + AEXT_LPA, + ext); + case OR_ENA_N: + case OR_ENA_S: + case OR_ENA_P: + if (find_ext (ext, AEXT_NETADDR)) + return OK; + return build_aext (or, + &_ZExt_mod, + _ZExtendedNetworkAddressExt, + "ExtendedNetworkAddress", + ext_ena, + AEXT_NETADDR, + ext); + case OR_TT: + return build_aext (or, + &_ZExt_mod, + _ZTerminalTypeExt, + "TerminalType", + ext_tt, + AEXT_TT, + ext); + } + return OK; +} diff --git a/Lib/or/orn-util.c b/Lib/or/orn-util.c new file mode 100644 index 0000000..c18e2f2 --- /dev/null +++ b/Lib/or/orn-util.c @@ -0,0 +1,95 @@ +/* orn-util.c: utility routines for ORNames */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-util.c,v 6.0 1991/12/18 20:23:08 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/or/RCS/orn-util.c,v 6.0 1991/12/18 20:23:08 jpo Rel $ + * + * $Log: orn-util.c,v $ + * Revision 6.0 1991/12/18 20:23:08 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "or.h" +#include "IOB-types.h" +#include "MTA-types.h" +#include "Ext-types.h" +#include "extension.h" + +#define STR2QB(s) str2qb(s, strlen(s), 1) + +void ORName_free (orn) +ORName *orn; +{ + if (orn == NULLORName) + return; + + if (orn -> on_or) + or_free (orn->on_or); + if (orn -> on_dn) + dn_free (orn -> on_dn); + free ((char *)orn); +} + +int or_append (tree, new) +OR_ptr *tree; +OR_ptr new; +{ + OR_ptr tn; + + tn = or_add (*tree, new, 0); + if (tn == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("or_add failed on node %s", + new -> or_value)); + return NOTOK; + } + *tree = tn; + return OK; +} + + +struct qbuf *or_getttx (val, enc) +char *val; +int enc; +{ + char *cp; + + switch (enc) { + case OR_ENC_TTX: + case OR_ENC_TTX_AND_OR_PS: + if ((cp = index (val, '*')) == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Missing * in T.61 encoding for %s", val)); + return NULL; + } + return or_t61decode (cp + 1); + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Not a TTX encoding")); + return NULL; + } +} + +struct qbuf *or_getps (val, enc) +char *val; +int enc; +{ + char *cp; + + switch (enc) { + case OR_ENC_PS: + return STR2QB (val); + case OR_ENC_TTX_AND_OR_PS: + if ((cp = index(val, '*')) == NULLCP) + return STR2QB (val); + else + return str2qb (val, cp - val, 1); + default: + PP_LOG (LLOG_EXCEPTIONS, ("getps called with bad encoding")); + return NULL; + } +} diff --git a/Lib/or/pe2or.py b/Lib/or/pe2or.py new file mode 100644 index 0000000..1b1de64 --- /dev/null +++ b/Lib/or/pe2or.py @@ -0,0 +1,300 @@ +-- pe2or: P1 O/R to OR_ptr conversion routines + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/or/RCS/pe2or.py,v 6.0 1991/12/18 20:23:08 jpo Rel $ +-- +-- $Log: pe2or.py,v $ +-- Revision 6.0 1991/12/18 20:23:08 jpo +-- Release 6.0 +-- +-- +-- + + +-- SEK add application 1 tag back into PE + +OR DEFINITIONS ::= + +%{ +#ifndef lint +static char Rcsid[] = "@(#)$Header"; +#endif lint + +#include "util.h" +#include "or.h" + +extern char or_error[]; +static int or_concat (); + +#define PEPYPARM OR_ptr * + +OR_ptr pe2or (pe) +PE pe; +{ + OR_ptr or = NULLOR; + PE tpe; + + /* SEK put in an extra tage */ + tpe = pe_alloc (PE_CLASS_APPL, PE_FORM_CONS, 0); + tpe -> pe_cons = pe; + if (decode_OR_ORName (tpe, 1, NULLIP, NULLVP, &or) == NOTOK) { + if (or) + or_free (or); + or = NULLOR; + } + tpe -> pe_cons = NULLPE; + pe_free (tpe); + return or; +} + +#undef DEBUG +%} + +BEGIN + +DECODER decode + +-- O/R name + +ORName ::= + [APPLICATION 0] + IMPLICIT SEQUENCE { + standard + StandardAttributeList [[p parm]], + + domaindefined + DomainDefinedAttributeList [[p parm]] OPTIONAL + } + +StandardAttributeList + %{ + char *str; + %} ::= + SEQUENCE { + CountryName [[p parm]] OPTIONAL, + + AdministrationDomainName [[p parm]] OPTIONAL, + + [0] + IMPLICIT X121Address [[s str]] + %{ if (or_concat (parm, OR_X121, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + [1] + IMPLICIT TerminalID [[s str]] + %{ if (or_concat (parm, OR_TID, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + [2] + PrivateDomainName [[p parm]] OPTIONAL, + + [3] + IMPLICIT OrganizationName [[s str]] + %{ if (or_concat (parm, OR_O, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + [4] + IMPLICIT UniqueUAIdentifier [[s str]] + %{ if (or_concat (parm, OR_UAID, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + [5] + IMPLICIT PersonalName [[p parm]] OPTIONAL, + + [6] + IMPLICIT SEQUENCE OF OrganizationalUnit [[s str]] + %{ + if (or_concat (parm, OR_OU, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL + } + + +DomainDefinedAttributeList ::= + SEQUENCE OF DomainDefinedAttribute [[p parm]] + + +DomainDefinedAttribute + %{ + char *dd_type, *dd_val; + %} + ::= + SEQUENCE { + type + PrintableString [[s dd_type]], + + value + PrintableString [[s dd_val]] + } + %{ + if (or_concat (parm, OR_DD, dd_type, dd_val) == NOTOK) + return NOTOK; + %} + + +CountryName + %{ + char *country; + %} ::= + [APPLICATION 1] + CHOICE { + NumericString [[s country]], + + PrintableString [[s country]] + } + %{ + if (or_concat (parm, OR_C, NULLCP, country) == NOTOK) + return NOTOK; + %} + + +AdministrationDomainName + %{ + char *admd; + %} ::= + [APPLICATION 2] + CHOICE { + NumericString [[s admd]], + PrintableString [[s admd]] + } + %{ + if (or_concat (parm, OR_ADMD, NULLCP, admd) == NOTOK) + return NOTOK; + %} + + +PrivateDomainIdentifier + %{ + char *prmd; + %} ::= + CHOICE { + NumericString [[s prmd]], + + PrintableString [[s prmd]] + } + %{ + if (or_concat (parm, OR_PRMD, NULLCP, prmd) == NOTOK) + return NOTOK; + %} + +X121Address ::= + NumericString + +TerminalID ::= + PrintableString + +OrganizationName ::= + PrintableString + +UniqueUAIdentifier ::= + NumericString + +PersonalName + %{ + char *str; + %} ::= + SET { + surName[0] + IMPLICIT PrintableString [[s str]] + %{ + if (or_concat (parm, OR_S, NULLCP, str) == NOTOK) + return NOTOK; + %}, + + givenName[1] + IMPLICIT PrintableString [[s str]] + %{ + if (or_concat (parm, OR_G, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + initials[2] + IMPLICIT PrintableString [[s str]] + %{ + if (or_concat (parm, OR_I, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL, + + generalQualifier[3] + IMPLICIT PrintableString [[s str]] + %{ + if (or_concat (parm, OR_GQ, NULLCP, str) == NOTOK) + return NOTOK; + %} + OPTIONAL + } + + +OrganizationalUnit ::= + PrintableString + +PrivateDomainName + %{ + char *prmd; + %} ::= + CHOICE { + NumericString [[s prmd]], + + PrintableString [[s prmd]] + } + %{ if (or_concat (parm, OR_PRMD, NULLCP, prmd) == NOTOK) + return NOTOK; + %} + + + + +END + +%{ + + + +static int or_concat (orp, type, str1, str2) +OR_ptr *orp; +int type; +char *str1, *str2; +{ + OR_ptr or1, + or2; + + if (*orp == NULLOR) { + *orp = or_new (type, str1, str2); + if (*orp == NULLOR) + return NOTOK; + } + else { + or1 = or_new (type, str1, str2); + if (or1 == NULLOR) { + (void) strcpy (PY_pepy, or_error); + return NOTOK; + } + + if (type == OR_OU) + or2 = or_add (*orp, or1, FALSE); + else + or2 = or_add (*orp, or1, TRUE); + + if (or2 != NULLOR) + *orp = or2; + else { + PP_LOG (LLOG_EXCEPTIONS, ("or_add failed on %s %s", + str1 ? str1 : "", str2 ? str2 : "" )); + return NOTOK; + } + } + return OK; +} + +%} diff --git a/Lib/parse/Makefile b/Lib/parse/Makefile new file mode 100644 index 0000000..736fbeb --- /dev/null +++ b/Lib/parse/Makefile @@ -0,0 +1,352 @@ +# address parsing routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/parse/RCS/Makefile,v 6.0 1991/12/18 20:23:41 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:23:41 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ad_local.c ad_parse.c ad_getlocal.c \ + rfc822_dnorm.c rfc822_parse.c rfc822_x400.c rfc822_val.c \ + x400_parse.c x400_rfc822.c x400_val.c aparse_norm.c +OBJS = ad_local.o ad_parse.o ad_getlocal.o \ + rfc822_dnorm.o rfc822_parse.o rfc822_x400.o rfc822_val.o \ + x400_parse.o x400_rfc822.o x400_val.o aparse_norm.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +INCLUDE = -I$(HEADERS) +LIBPP = ../libpp.a + +CFLAGS = $(CCOPTIONS) $(INCLUDE) $(LCF) +LLFLAGS = $(LINTFLAGS) $(INCLUDE) -u +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + +SHADOW = parse-made + + +############################################################ +# +# Building rules +# +############################################################ + +default: $(SHADOW) + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) $(LIBPP) $? + touch $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lintlib:llib-lparse.ln +llib-lparse.ln: ${SRCS} + $(LINT) -Cparse $(LLFLAGS) ${SRCS} + +clean: tidy + rm -f ${OBJS} llib-lparse.ln + +tidy: + rm -f core ${SHADOW} *.old a.out *.BAK + +lint: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +install: ; + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + + +############################################################ +# +# End of building rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ad_local.o: ad_local.c +ad_local.o: ../../h/head.h +ad_local.o: ../../h/util.h +ad_local.o: ../../h/config.h +ad_local.o: ../../h/ll_log.h +ad_local.o: ../../h/retcode.h +ad_local.o: ../../h/adr.h +ad_local.o: ../../h/list_rchan.h +ad_local.o: ../../h/chan.h +ad_local.o: ../../h/table.h +ad_local.o: ../../h/list_bpt.h +ad_local.o: ../../h/auth.h +ad_local.o: ../../h/list_bpt.h +ad_local.o: ../../h/extension.h +ad_local.o: ../../h/mta.h +ad_local.o: ../../h/adr.h +ad_local.o: ../../h/list_bpt.h +ad_local.o: ../../h/aparse.h +ad_local.o: ../../h/ap.h +ad_local.o: ../../h/util.h +ad_local.o: ../../h/or.h +ad_local.o: ../../h/chan.h +ad_local.o: ../../h/auth.h +ad_local.o: ../../h/list_rchan.h +ad_local.o: ../../h/alias.h +ad_parse.o: ad_parse.c +ad_parse.o: ../../h/head.h +ad_parse.o: ../../h/util.h +ad_parse.o: ../../h/config.h +ad_parse.o: ../../h/ll_log.h +ad_parse.o: ../../h/retcode.h +ad_parse.o: ../../h/adr.h +ad_parse.o: ../../h/list_rchan.h +ad_parse.o: ../../h/chan.h +ad_parse.o: ../../h/table.h +ad_parse.o: ../../h/list_bpt.h +ad_parse.o: ../../h/auth.h +ad_parse.o: ../../h/list_bpt.h +ad_parse.o: ../../h/extension.h +ad_parse.o: ../../h/mta.h +ad_parse.o: ../../h/adr.h +ad_parse.o: ../../h/list_bpt.h +ad_parse.o: ../../h/aparse.h +ad_parse.o: ../../h/ap.h +ad_parse.o: ../../h/util.h +ad_parse.o: ../../h/or.h +ad_parse.o: ../../h/chan.h +ad_parse.o: ../../h/auth.h +ad_parse.o: ../../h/list_rchan.h +ad_getlocal.o: ad_getlocal.c +ad_getlocal.o: ../../h/head.h +ad_getlocal.o: ../../h/util.h +ad_getlocal.o: ../../h/config.h +ad_getlocal.o: ../../h/ll_log.h +ad_getlocal.o: ../../h/retcode.h +ad_getlocal.o: ../../h/adr.h +ad_getlocal.o: ../../h/list_rchan.h +ad_getlocal.o: ../../h/chan.h +ad_getlocal.o: ../../h/table.h +ad_getlocal.o: ../../h/list_bpt.h +ad_getlocal.o: ../../h/auth.h +ad_getlocal.o: ../../h/list_bpt.h +ad_getlocal.o: ../../h/extension.h +ad_getlocal.o: ../../h/mta.h +ad_getlocal.o: ../../h/adr.h +ad_getlocal.o: ../../h/list_bpt.h +ad_getlocal.o: ../../h/aparse.h +ad_getlocal.o: ../../h/ap.h +ad_getlocal.o: ../../h/util.h +ad_getlocal.o: ../../h/or.h +ad_getlocal.o: ../../h/chan.h +ad_getlocal.o: ../../h/auth.h +ad_getlocal.o: ../../h/list_rchan.h +rfc822_dnorm.o: rfc822_dnorm.c +rfc822_dnorm.o: ../../h/head.h +rfc822_dnorm.o: ../../h/util.h +rfc822_dnorm.o: ../../h/config.h +rfc822_dnorm.o: ../../h/ll_log.h +rfc822_dnorm.o: ../../h/retcode.h +rfc822_dnorm.o: ../../h/ap.h +rfc822_dnorm.o: ../../h/util.h +rfc822_dnorm.o: ../../h/chan.h +rfc822_dnorm.o: ../../h/table.h +rfc822_dnorm.o: ../../h/list_bpt.h +rfc822_parse.o: rfc822_parse.c +rfc822_parse.o: ../../h/head.h +rfc822_parse.o: ../../h/util.h +rfc822_parse.o: ../../h/config.h +rfc822_parse.o: ../../h/ll_log.h +rfc822_parse.o: ../../h/retcode.h +rfc822_parse.o: ../../h/adr.h +rfc822_parse.o: ../../h/list_rchan.h +rfc822_parse.o: ../../h/chan.h +rfc822_parse.o: ../../h/table.h +rfc822_parse.o: ../../h/list_bpt.h +rfc822_parse.o: ../../h/auth.h +rfc822_parse.o: ../../h/list_bpt.h +rfc822_parse.o: ../../h/extension.h +rfc822_parse.o: ../../h/mta.h +rfc822_parse.o: ../../h/adr.h +rfc822_parse.o: ../../h/list_bpt.h +rfc822_parse.o: ../../h/aparse.h +rfc822_parse.o: ../../h/ap.h +rfc822_parse.o: ../../h/util.h +rfc822_parse.o: ../../h/or.h +rfc822_parse.o: ../../h/chan.h +rfc822_parse.o: ../../h/auth.h +rfc822_parse.o: ../../h/list_rchan.h +rfc822_x400.o: rfc822_x400.c +rfc822_x400.o: ../../h/head.h +rfc822_x400.o: ../../h/util.h +rfc822_x400.o: ../../h/config.h +rfc822_x400.o: ../../h/ll_log.h +rfc822_x400.o: ../../h/retcode.h +rfc822_x400.o: ../../h/adr.h +rfc822_x400.o: ../../h/list_rchan.h +rfc822_x400.o: ../../h/chan.h +rfc822_x400.o: ../../h/table.h +rfc822_x400.o: ../../h/list_bpt.h +rfc822_x400.o: ../../h/auth.h +rfc822_x400.o: ../../h/list_bpt.h +rfc822_x400.o: ../../h/extension.h +rfc822_x400.o: ../../h/mta.h +rfc822_x400.o: ../../h/adr.h +rfc822_x400.o: ../../h/list_bpt.h +rfc822_x400.o: ../../h/aparse.h +rfc822_x400.o: ../../h/ap.h +rfc822_x400.o: ../../h/util.h +rfc822_x400.o: ../../h/or.h +rfc822_x400.o: ../../h/chan.h +rfc822_x400.o: ../../h/auth.h +rfc822_x400.o: ../../h/list_rchan.h +rfc822_val.o: rfc822_val.c +rfc822_val.o: ../../h/head.h +rfc822_val.o: ../../h/util.h +rfc822_val.o: ../../h/config.h +rfc822_val.o: ../../h/ll_log.h +rfc822_val.o: ../../h/retcode.h +rfc822_val.o: ../../h/adr.h +rfc822_val.o: ../../h/list_rchan.h +rfc822_val.o: ../../h/chan.h +rfc822_val.o: ../../h/table.h +rfc822_val.o: ../../h/list_bpt.h +rfc822_val.o: ../../h/auth.h +rfc822_val.o: ../../h/list_bpt.h +rfc822_val.o: ../../h/extension.h +rfc822_val.o: ../../h/mta.h +rfc822_val.o: ../../h/adr.h +rfc822_val.o: ../../h/list_bpt.h +rfc822_val.o: ../../h/aparse.h +rfc822_val.o: ../../h/ap.h +rfc822_val.o: ../../h/util.h +rfc822_val.o: ../../h/or.h +rfc822_val.o: ../../h/chan.h +rfc822_val.o: ../../h/auth.h +rfc822_val.o: ../../h/list_rchan.h +x400_parse.o: x400_parse.c +x400_parse.o: ../../h/head.h +x400_parse.o: ../../h/util.h +x400_parse.o: ../../h/config.h +x400_parse.o: ../../h/ll_log.h +x400_parse.o: ../../h/retcode.h +x400_parse.o: ../../h/adr.h +x400_parse.o: ../../h/list_rchan.h +x400_parse.o: ../../h/chan.h +x400_parse.o: ../../h/table.h +x400_parse.o: ../../h/list_bpt.h +x400_parse.o: ../../h/auth.h +x400_parse.o: ../../h/list_bpt.h +x400_parse.o: ../../h/extension.h +x400_parse.o: ../../h/mta.h +x400_parse.o: ../../h/adr.h +x400_parse.o: ../../h/list_bpt.h +x400_parse.o: ../../h/aparse.h +x400_parse.o: ../../h/ap.h +x400_parse.o: ../../h/util.h +x400_parse.o: ../../h/or.h +x400_parse.o: ../../h/chan.h +x400_parse.o: ../../h/auth.h +x400_parse.o: ../../h/list_rchan.h +x400_rfc822.o: x400_rfc822.c +x400_rfc822.o: ../../h/head.h +x400_rfc822.o: ../../h/util.h +x400_rfc822.o: ../../h/config.h +x400_rfc822.o: ../../h/ll_log.h +x400_rfc822.o: ../../h/retcode.h +x400_rfc822.o: ../../h/adr.h +x400_rfc822.o: ../../h/list_rchan.h +x400_rfc822.o: ../../h/chan.h +x400_rfc822.o: ../../h/table.h +x400_rfc822.o: ../../h/list_bpt.h +x400_rfc822.o: ../../h/auth.h +x400_rfc822.o: ../../h/list_bpt.h +x400_rfc822.o: ../../h/extension.h +x400_rfc822.o: ../../h/mta.h +x400_rfc822.o: ../../h/adr.h +x400_rfc822.o: ../../h/list_bpt.h +x400_rfc822.o: ../../h/aparse.h +x400_rfc822.o: ../../h/ap.h +x400_rfc822.o: ../../h/util.h +x400_rfc822.o: ../../h/or.h +x400_rfc822.o: ../../h/chan.h +x400_rfc822.o: ../../h/auth.h +x400_rfc822.o: ../../h/list_rchan.h +x400_val.o: x400_val.c +x400_val.o: ../../h/head.h +x400_val.o: ../../h/util.h +x400_val.o: ../../h/config.h +x400_val.o: ../../h/ll_log.h +x400_val.o: ../../h/retcode.h +x400_val.o: ../../h/adr.h +x400_val.o: ../../h/list_rchan.h +x400_val.o: ../../h/chan.h +x400_val.o: ../../h/table.h +x400_val.o: ../../h/list_bpt.h +x400_val.o: ../../h/auth.h +x400_val.o: ../../h/list_bpt.h +x400_val.o: ../../h/extension.h +x400_val.o: ../../h/mta.h +x400_val.o: ../../h/adr.h +x400_val.o: ../../h/list_bpt.h +x400_val.o: ../../h/aparse.h +x400_val.o: ../../h/ap.h +x400_val.o: ../../h/util.h +x400_val.o: ../../h/or.h +x400_val.o: ../../h/chan.h +x400_val.o: ../../h/auth.h +x400_val.o: ../../h/list_rchan.h +x400_val.o: ../../h/or.h +aparse_norm.o: aparse_norm.c +aparse_norm.o: ../../h/util.h +aparse_norm.o: ../../h/config.h +aparse_norm.o: ../../h/ll_log.h +aparse_norm.o: ../../h/adr.h +aparse_norm.o: ../../h/list_rchan.h +aparse_norm.o: ../../h/chan.h +aparse_norm.o: ../../h/table.h +aparse_norm.o: ../../h/list_bpt.h +aparse_norm.o: ../../h/auth.h +aparse_norm.o: ../../h/list_bpt.h +aparse_norm.o: ../../h/extension.h +aparse_norm.o: ../../h/mta.h +aparse_norm.o: ../../h/adr.h +aparse_norm.o: ../../h/list_bpt.h +aparse_norm.o: ../../h/aparse.h +aparse_norm.o: ../../h/ap.h +aparse_norm.o: ../../h/util.h +aparse_norm.o: ../../h/or.h +aparse_norm.o: ../../h/chan.h +aparse_norm.o: ../../h/auth.h +aparse_norm.o: ../../h/list_rchan.h +aparse_norm.o: ../../h/aparse.h +aparse_norm.o: ../../h/alias.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/parse/ad_getlocal.c b/Lib/parse/ad_getlocal.c new file mode 100644 index 0000000..d9397be --- /dev/null +++ b/Lib/parse/ad_getlocal.c @@ -0,0 +1,73 @@ +/* ad_getlocal.c: get the local part of the address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_getlocal.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_getlocal.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: ad_getlocal.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ +#include "head.h" +#include "adr.h" + +extern char *rfc822_getlocal(), *x400_getlocal(); + +char *ad_getlocal (addr, type, resp) +char *addr; +int type, + resp; +{ + if (type == AD_X400_TYPE) + return x400_getlocal(addr, resp); + else + return rfc822_getlocal(addr, resp); +} + +/* */ + +char *rfc822_getlocal(addr, resp) +char *addr; +int resp; +{ + RP_Buf rp; + char *retstr; + ADDR *ad = adr_new(addr, AD_822_TYPE, 1); + ad->ad_resp = resp; + + if (!rp_isbad (rfc822_parse(ad)) + && !rp_isbad(rfc822_validate(ad, &rp)) + && ad->aparse->r822_local) + retstr = strdup(ad->aparse->r822_local); + else + retstr = NULLCP; + + adr_free(ad); + return retstr; +} + +/* */ + +char *x400_getlocal(addr, resp) +char *addr; +int resp; +{ + RP_Buf rp; + char *retstr; + ADDR *ad = adr_new(addr, AD_X400_TYPE, 1); + ad->ad_resp = resp; + + if (!rp_isbad(x400_parse(ad)) + && !rp_isbad(x400_validate(ad, &rp)) + && ad->aparse->x400_local) + retstr = strdup(ad->aparse->x400_local); + else + retstr = NULLCP; + + adr_free(ad); + return retstr; +} diff --git a/Lib/parse/ad_local.c b/Lib/parse/ad_local.c new file mode 100644 index 0000000..dcf7e36 --- /dev/null +++ b/Lib/parse/ad_local.c @@ -0,0 +1,568 @@ +/* ad_local.c: process a local address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_local.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_local.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: ad_local.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" +#include "alias.h" + +extern char *loc_dom_mta; +extern LIST_RCHAN *tb_getuser(); +extern Redirection *redirect_new(); +extern void redirect_add(); +extern void redirect_free (); + +static int do_alias_check(), do_user_check(), reparse_local(); + +int ad_local (locname, ad, rp) +char *locname; +register ADDR *ad; +RP_Buf *rp; +{ + ALIAS alias_struct, + *alp = &alias_struct; + int retval; + char tmp[BUFSIZ]; + + PP_TRACE (("ad_local (%s, ad=%s, %s)", + locname, ad->ad_value, + (ad->aparse->local_hub_name) ? ad->aparse->local_hub_name : "main hub")); + + if (ad->aparse->dont_use_aliases != TRUE) { + switch (tb_getalias (locname, alp, + ad->aparse->local_hub_name)) { + case NOTOK: + /* -- routine or table error -- */ + PP_TRACE (("ad_local/tb_getalias failed on %s", + locname)); + (void) sprintf(tmp, "Alias error for '%s'", locname); + set_error(ad, tmp); + return parselose (rp, RP_USER, + "Alias error for %s", + locname); + case OK: + /* -- found, do alias check -- */ + if (alp->alias_external != ALIAS_EXTERNAL + || ad->ad_resp == NO) + return do_alias_check (locname, + alp, ad, rp); + + default: + break; + } + } + /* -- otherwise do the user checks -- */ + if (rp_isbad(retval = do_user_check(locname, + ad, + rp)) + && !rp_isbad(reparse_local(locname, ad, rp))) + retval = RP_AOK; + return retval; + + + /* NOTREACHED */ +} + +/* */ + +static int redirect_copy (pto, from, ad, rp) +Redirection **pto, *from; +ADDR *ad; +RP_Buf *rp; +{ + Redirection *tmp; + char buf[BUFSIZ]; + + while (from != (Redirection *) NULL) { + if (redirect_before(*pto, from) == TRUE) { + (void) sprintf(buf, + "Redirection loop detected for '%s'", + from->rd_addr); + set_error(ad, buf); + return parselose (rp, RP_USER, + "Redirection loop detected for '%s'", + from->rd_addr); + } + tmp = from->rd_next; + from->rd_next = (Redirection *) NULL; + redirect_add(pto, from); + from = tmp; + } + return RP_AOK; +} + +static void ad_copy (ad, new, resp) +register ADDR *ad; +ADDR *new; +int resp; +{ + PP_DBG (("ad_copy()")); + + if (ad->ad_outchan) + list_rchan_free (ad->ad_outchan); + ad->ad_outchan = new->ad_outchan; + new->ad_outchan = NULLIST_RCHAN; + ad->ad_parse_stat = new->ad_parse_stat; + + if (resp == YES) { + Aparse_ptr tmp = ad->aparse; + ad->aparse = new->aparse; + ad->aparse->recurse_count = tmp->recurse_count; + ad->aparse->dont_use_aliases = tmp->dont_use_aliases; + new->aparse = tmp; + } +} + + +int alias2adr (buf, alp, ap) +char *buf; +ALIAS *alp; +register Aparse_ptr ap; +{ + char tmp[BUFSIZ]; + OR_ptr holder; + + if (alp->alias_ad_type == AD_ANY_TYPE) { + /* need to keep domain as may be local subdom */ + switch (ap->ad_type) { + case AD_822_TYPE: + if (ap->ap_domain) + (void) sprintf(buf, "%s@%s", + alp->alias_user, + ap->ap_domain->ap_obvalue); + else + (void) strcpy(buf, alp->alias_user); + break; + case AD_X400_TYPE: + if (ap->lastMatch + && ap->orname->on_or) { + holder = ap->lastMatch->or_next; + ap->lastMatch->or_next = NULLOR; + + or_or2std(ap->lastMatch, tmp, FALSE); + ap->lastMatch->or_next = holder; + (void) sprintf(buf, "%s%s", + alp->alias_user, + tmp); + } else + (void) strcpy(buf, alp->alias_user); + break; + default: + (void) strcpy (buf, alp->alias_user); + break; + } + } else + (void) strcpy (buf, alp->alias_user); +} + +static int do_alias_check (name, alp, ad, rp) +char *name; +ALIAS *alp; +register ADDR *ad; +RP_Buf *rp; +{ + char tmp[BUFSIZ], buf[BUFSIZ]; + register ADDR *new; + int copy_results, retval, type; + + if ((type = alp->alias_ad_type) == AD_ANY_TYPE) + type = ad->aparse->ad_type; + + alias2adr(buf, alp, ad->aparse); + if (aparse_inAliasList (buf, ad->aparse->aliases) == OK) { + if (alp->alias_external == ALIAS_EXTERNAL) + PP_NOTICE(("circular aliases found '%s' ['%s' -> '%s'] - BUT external so ignore !", + alp->alias_user, name, + buf)); + else { + PP_LOG(LLOG_EXCEPTIONS, + ("do_alias_check circular aliases '%s' ['%s' -> '%s']", + alp->alias_user, name, + buf)); + (void) sprintf(tmp, + "local circular alias/synonym detected"); + set_error(ad, tmp); + (void) strcpy(rp->rp_line, tmp); + return RP_PARSE; + } + } else + aparse_addToAliasList (buf, + &(ad->aparse->aliases)); + + new = adr_new(buf, + type, + ad->ad_extension); + aparse_copy_for_recursion(new->aparse, ad->aparse); + if (alp->alias_external == ALIAS_EXTERNAL) + new->aparse->dont_use_aliases = TRUE; + + switch (alp->alias_type) { + case ALIAS_SYNONYM: + new->ad_resp = ad->ad_resp; + copy_results = YES; + break; + + case ALIAS_PROPER: + new->ad_resp = YES; + copy_results = ad->ad_resp; + break; + } + + + retval = ad_parse_aux (new, rp); + if (!rp_isbad(retval) && + alp->alias_type == ALIAS_PROPER) { + /* add redirect */ + char tbuf[BUFSIZ], *dn = NULLCP; + OR_ptr or; + + switch (ad->aparse->ad_type) { + case AD_X400_TYPE: + if (isstr(ad->aparse->x400_str)) + (void) strcpy(tbuf, ad->aparse->x400_str); + else if (ad->aparse->orname->on_or != NULLOR) + or_or2std(ad->aparse->orname->on_or, + tbuf, FALSE); + else if (isstr(ad->ad_r400adr)) + (void) strcpy(tbuf, ad->ad_r400adr); + else + tbuf[0] = '\0'; + + if (isstr(ad->aparse->x400_dn)) + dn = ad->aparse->x400_dn; + break; + case AD_822_TYPE: + default: + if (isstr(ad->aparse->r822_str)) + (void) or_rfc2or_aux(ad->aparse->r822_str, + &or, + ad->ad_no); + else if (isstr(ad->ad_r822adr)) + (void) or_rfc2or_aux(ad->ad_r822adr, + &or, + ad->ad_no); + else + or = NULLOR; + + if (or != NULLOR) { + or_or2std(or, tbuf, FALSE); + or_free (or); + } else + tbuf[0] = '\0'; + } + if (tbuf[0] != '\0') { + Redirection *rtmp ; + + rtmp = redirect_new(tbuf, + (dn == NULLCP) ? "" : dn, + NULLUTC, + RDR_MD_ASSIGNED); + + /* add in redirect */ + if (rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history), + rtmp, + ad, rp))) { + /* redirect loop so don't copy results */ + copy_results = NO; + redirect_free(rtmp); + } + } + + } + + if (!rp_isbad(retval) + && new->ad_redirection_history != (Redirection *) NULL) { + /* add in redirection history from recursion */ + if (rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history), + new->ad_redirection_history, + ad, rp))) { + /* redirect loop so don't copy results */ + copy_results = NO; + } else + new->ad_redirection_history = (Redirection *) NULL; + } + + ad_copy (ad, new, copy_results); + + if (new) + adr_free(new); + + return retval; +} + +/* */ + +static int do_user_check(name, ad, rp) +char *name; +register ADDR *ad; +RP_Buf *rp; +{ + char buf[BUFSIZ], tmp[BUFSIZ]; + int next; + AP_ptr dmn = NULLAP; + + LIST_RCHAN *ix, *ix2, *newchan = NULLIST_RCHAN, *end; + + PP_TRACE (("ad_local/do_user_check (%s, %s)", + name, + (ad->aparse->local_hub_name) ? ad->aparse->local_hub_name : "main hub")); + + if ((ad->ad_outchan = + tb_getuser (name, ad->aparse->local_hub_name)) == NULLIST_RCHAN) { + (void) sprintf(buf, + "Unknown local user '%s'", + name); + set_error(ad, buf); + return parselose (rp, ad->ad_parse_stat = RP_USER, + "Unknown local user '%s'", name); + } + + next = TRUE; + for (ix = ad->ad_outchan; + ix != NULLIST_RCHAN; + ix = (next == TRUE) ? ix -> li_next : ix) { + /* -- check this is the machine on --*/ + /* -- which local delivery is done -- */ + next = TRUE; + + if (ix -> li_mta != NULLCP + && lexequ (ix->li_mta, loc_dom_mta) != 0) { + /* -- not this machine, update ix -- */ + + /* lookup given mta */ + if (tb_getchan (ix -> li_mta, &newchan) == NOTOK) + newchan = NULLIST_RCHAN; + + if (newchan == NULLIST_RCHAN) { + /* try normalising given mta */ + dmn = ap_new(AP_DOMAIN, ix->li_mta); + if (rfc822_norm_dmn (dmn, + ad->aparse->dmnorder) != OK + || dmn -> ap_recognised == FALSE + || dmn -> ap_chankey == NULLCP) { + if (dmn -> ap_recognised == FALSE) + PP_LOG(LLOG_EXCEPTIONS, + ("Internal routing (users table) error for mta '%s' [unable to normalise domain]", + ix->li_mta)); + else if (dmn->ap_chankey == NULLCP) + PP_LOG(LLOG_EXCEPTIONS, + ("Internal routing (users table) error for mta '%s' [no index to routing info for '%s']", + ix->li_mta, + dmn->ap_obvalue)); + + (void) sprintf(tmp, + "Unknown internal domain '%s'", + ix->li_mta); + set_error(ad, tmp); + ap_free(dmn); + return ad->ad_parse_stat = + parselose (rp, + RP_USER, + "Unknown internal domain '%s'", + ix -> li_mta); + } + if (dmn -> ap_islocal == FALSE) + PP_LOG(LLOG_EXCEPTIONS, + ("Mta '%s' is used for internal routing (users table) but is not marked as local in domain table", + dmn -> ap_obvalue)); + + } + if (newchan == NULLIST_RCHAN + && dmn != NULLAP + && tb_getchan (dmn->ap_chankey, &newchan) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Internal routing (users table) error for mta '%s' [no routing info for '%s']", + ix -> li_mta, dmn->ap_chankey)); + (void) sprintf(tmp, + "Unknown internal domain '%s'", + ix -> li_mta); + set_error(ad, tmp); + return ad->ad_parse_stat = + parselose (rp, + RP_USER, + "Domain '%s' not registered in channel table", + ix -> li_mta); + } + + if (dmn != NULLAP) { + ap_free(dmn); + dmn = NULLAP; + } + /* insert new list_rchan into ad->ad_outchan */ + end = newchan; + while (end->li_next != NULLIST_RCHAN) + end = end->li_next; + if (ix == ad->ad_outchan) { + end -> li_next = ad->ad_outchan->li_next; + ad->ad_outchan = newchan; + } else { + ix2 = ad->ad_outchan; + while (ix2 != NULLIST_RCHAN + && ix2 -> li_next != ix) + ix2 = ix2->li_next; + if (ix2 != NULLIST_RCHAN) { + end -> li_next = ix -> li_next; + ix2->li_next = newchan; + } + } + ix -> li_next = NULLIST_RCHAN; + list_rchan_free(ix); + ix = end; + } else if (ix -> li_chan == NULLCHAN) { + /* invalid local channel */ + if (ix == ad->ad_outchan) { + ix2 = ix; + ix = ad->ad_outchan = ad->ad_outchan->li_next; + next = FALSE; + /* yuch */ + } else { + for (end = ad->ad_outchan; + end -> li_next != ix; + end = end->li_next) + continue; + end -> li_next = ix -> li_next; + ix2 = ix; + ix = end; + } + ix2->li_next = NULLIST_RCHAN; + list_rchan_free(ix2); + } + } + + if (ad->ad_outchan == NULLIST_RCHAN) { + set_error(ad, "No valid local delivery channels"); + return ad->ad_parse_stat = + parselose(rp, RP_USER, "%s", + "No valid local delivery channels"); + } + + for (ix = ad->ad_outchan; ix; ix = ix -> li_next) + if (ix->li_mta == NULLCP) + ix->li_mta = strdup(loc_dom_mta); + + return (ad->ad_parse_stat = RP_AOK); +} + +/* */ + +static int reparsing = 0; + +static int reparse_local (inname, ad, rp) +char *inname; +register ADDR *ad; +RP_Buf *rp; +{ + char *bang = NULLCP, + *percent = NULLCP, + *at = NULLCP, + *ix, *newadrstr, *name, + *start = strdup(inname); + int retval = NOTOK; + register ADDR *newadr; + + name = start; + if (reparsing > 0) + /* more than one level of reparsing wrong */ + return NOTOK; + /* remove preceding and trailing quotes */ + while (*name == '"' && *name != '\0') name++; + + ix = &(name[strlen(name)]); + while (*ix == '"' && ix != name) { + *ix = '\0'; + ix --; + } + + bang = index(name, '!'); + percent = index(name, '%'); + at = index(name, '@'); + + /* only allow one type of addressing */ + if (!((bang && !percent && !at) || + (percent && !bang && !at) || + (at && !bang && !percent))) { + free(start); + return NOTOK; + } + + if (bang) { + int numBangs = 0; + char *iix, *jx; + + bang = name; + while ((bang = index(bang, '!')) != NULLCP) { + numBangs++; + bang++; + } + + newadrstr = malloc((unsigned)strlen(name) + 2 * (numBangs - 1) + + 1); + iix = name; + jx = newadrstr; + while (numBangs > 1) { + *jx++ = '@'; + while (*iix != '!' && *iix != '\0') + *jx++ = *iix++; + if (*iix == '!') { + numBangs--; + if (numBangs == 1) + *jx++ = ':'; + else + *jx++ = ','; + iix++; + } + } + *jx = '\0'; + bang = rindex(iix, '!'); + *bang++ = '\0'; + (void) sprintf(newadrstr, "%s%s@%s", + newadrstr, bang, iix); + } else + newadrstr = strdup(name); + + /* with bangs, percents etc. got to be 822 */ + newadr = adr_new(newadrstr, + AD_822_TYPE, + ad->ad_no); + aparse_copy_for_recursion(newadr->aparse, ad->aparse); + + if (percent + || ad->aparse->percents == TRUE) + newadr->aparse->percents = TRUE; + + reparsing++; + + if (!(rp_isbad(retval = ad_parse_aux(newadr, rp)))) { + /* parsed okay so copy relevant bits across */ + if (newadr->ad_redirection_history != (Redirection *) NULL) { + /* add in redirection history from recursion */ + if (!rp_isbad(retval = redirect_copy(&(ad->ad_redirection_history), + newadr->ad_redirection_history, + ad, rp))) + newadr->ad_redirection_history = (Redirection *) NULL; + } + if (!rp_isbad(retval)) + ad_copy(ad, newadr, YES); + } else { + /* didn't work so ignore errors */ + ; + } + + reparsing--; + + free(start); + free(newadrstr); + adr_free(newadr); + return retval; +} diff --git a/Lib/parse/ad_parse.c b/Lib/parse/ad_parse.c new file mode 100644 index 0000000..e005ed5 --- /dev/null +++ b/Lib/parse/ad_parse.c @@ -0,0 +1,499 @@ +/* ad_parse.c: parse an address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/ad_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: ad_parse.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" +#include + +static void ad_copy_addresses(), + ad_copy_errors(); + +static int rfc822thenx40090, x400thenrfc822(), parselose_exception(); + +int ad_fullparse (ad, rp, order_pref) +register ADDR *ad; +RP_Buf *rp; +int order_pref; +{ + ad->aparse->full = OK; + ad->aparse->dmnorder = order_pref; + + return ad_parse_aux (ad, rp); +} + +int ad_parse (ad, rp, order_pref) +register ADDR *ad; +RP_Buf *rp; +int order_pref; +{ + ad->aparse->full = NOTOK; + ad->aparse->dmnorder = order_pref; + + return ad_parse_aux (ad, rp); +} + +/* */ + +int ad_parse_aux (ad, rp) +register ADDR *ad; +RP_Buf *rp; +{ + int is822, retval; + PP_DBG(("ad_parse ('%s', '%d')", + ad->ad_value, + ad->ad_type)); + + or_myinit(); + + switch (ad->ad_type) { + case AD_X400_TYPE: + return x400thenrfc822 (ad, rp); + case AD_822_TYPE: + return rfc822thenx400 (ad, rp); + default: + + /* guess */ + /* shouldn't ever be call */ + is822 = TRUE; + if (index(ad->ad_value, '/') != NULLCP) + is822 = FALSE; + if (index(ad->ad_value, '@') != NULLCP) + is822 = TRUE; + + if (is822 == TRUE) { + if (rp_isbad(retval = + rfc822thenx400(ad, rp))) { + /* may have guessed wrong */ + if (ad->ad_r400adr) { + free(ad->ad_r400adr); + ad->ad_r400adr = NULLCP; + } + + if (ad->ad_r822adr) { + free (ad->ad_r822adr); + ad->ad_r822adr = NULLCP; + } + if (ad->ad_parse_message) { + free(ad->ad_parse_message); + ad->ad_parse_message = NULLCP; + } + + return x400thenrfc822(ad, rp); + } + } else { + if (rp_isbad(retval = + x400thenrfc822(ad, rp))) { + /* wrong guess */ + if (ad->ad_r400adr) { + free(ad->ad_r400adr); + ad->ad_r400adr = NULLCP; + } + + if (ad->ad_r822adr) { + free (ad->ad_r822adr); + ad->ad_r822adr = NULLCP; + } + if (ad->ad_parse_message) { + free(ad->ad_parse_message); + ad->ad_parse_message = NULLCP; + } + return rfc822thenx400(ad, rp); + } + } + return retval; + } +} + +/* */ +extern char or_error[]; +#define MAX_LOOP 10 + +static int rfc822thenx400 (ad, rp) +register ADDR *ad; +RP_Buf *rp; +{ + int retval, cont, count; + char *prev822adr, logerr[BUFSIZ]; + + PP_DBG (("rfc822thenx400 ('%s', '%d')", + ad->ad_value, ad->ad_type)); + + cont = TRUE; + count = 0; + /* parse 822 */ + if (rp_isbad (retval = + rfc822_parse (ad))) { + ad_copy_errors(ad, logerr, TRUE); + return parselose_exception (rp, + retval, + logerr, + ad->ad_parse_message); + } + do { + /* validate 822 */ + ad->aparse->ad_type = AD_822_TYPE; + retval = rfc822_validate(ad, rp); + + /* convert 822 to x400 */ + or_error[0] = '\0'; + if (rp_isbad(rfc822_x400 (ad))) { + if (ad->ad_parse_message == NULLCP) + ad_copy_errors (ad, logerr, FALSE); + ad_copy_addresses (ad, FALSE); + return parselose_exception(rp, + retval, + logerr, + ad->ad_parse_message); + } + + if (!rp_isbad(retval)) { + /* 822 is okay */ + ad_copy_addresses (ad, TRUE); + return (ad->ad_parse_stat = RP_AOK); + } + + /* validate x400 */ + or_error[0] = '\0'; + ad->aparse->ad_type = AD_X400_TYPE; + retval = x400_validate(ad, rp); + + /* save first forms of address in main adr struct */ + if (ad->ad_r822adr == NULLCP + || ad->ad_r400adr == NULLCP) + ad_copy_addresses(ad, FALSE); + + /* save first error messages in main adr struct */ + if (ad->ad_parse_message == NULLCP) + ad_copy_errors(ad, logerr, FALSE); + + + /* reconvert back to 822 and see if different */ + if (isstr(ad->aparse->r822_str)) + prev822adr = strdup(ad->aparse->r822_str); + else + prev822adr = NULLCP; + + if (rp_isbad(x400_rfc822(ad)) + || !isstr(ad->aparse->r822_str) + || prev822adr == NULLCP + || lexequ(ad->aparse->r822_str, prev822adr) == 0 + || lexequ(ad->aparse->r822_str, ad->ad_value) == 0) + cont = FALSE; + else + count++; + if (prev822adr) free(prev822adr); + + if (!rp_isbad(retval)) { + /* x400 is okay */ + ad_copy_addresses(ad, TRUE); + return (ad->ad_parse_stat = RP_AOK); + } + + } while (count < MAX_LOOP && cont == TRUE); + + ad->aparse->ad_type = AD_822_TYPE; + return parselose_exception(rp, + retval, + logerr, + ad->ad_parse_message); +} + +/* */ + +static int x400thenrfc822 (ad, rp) +register ADDR *ad; +RP_Buf *rp; +{ + int retval, cont, count; + char *prevx400adr, logerr[BUFSIZ]; + + cont = TRUE; + count = 0; + + PP_DBG (("x400thenrfc822 ('%s', '%d')", + ad->ad_value, ad->ad_type)); + + /* parse x400 */ + or_error[0] = '\0'; + if (rp_isbad(retval = x400_parse(ad))) { + ad_copy_errors(ad, logerr, TRUE); + return parselose_exception (rp, + retval, + logerr, + ad->ad_parse_message); + } + do { + + /* validate x400 */ + or_error[0] = '\0'; + ad->aparse->ad_type = AD_X400_TYPE; + retval = x400_validate(ad, rp); + + /* convert x400 to rfc */ + + if (rp_isbad(x400_rfc822 (ad))) { + if (ad->ad_parse_message == NULLCP) + ad_copy_errors(ad, logerr, FALSE); + ad_copy_addresses(ad, FALSE); + return parselose_exception(rp, + retval, + logerr, + ad->ad_parse_message); + } + + if (!rp_isbad(retval)) { + /* x400 is okay */ + ad_copy_addresses(ad, TRUE); + return (ad->ad_parse_stat = RP_AOK); + } + + /* validate 822 */ + ad->aparse->ad_type = AD_822_TYPE; + retval = rfc822_validate(ad, rp); + + /* save first form of address in main adr struct */ + if (ad->ad_r822adr == NULLCP + || ad->ad_r400adr == NULLCP) + ad_copy_addresses(ad, FALSE); + + /* save first form of address in main adr struct */ + if (ad->ad_parse_message == NULLCP) + ad_copy_errors(ad, logerr, FALSE); + + /* reconvert back to x400 and see if different */ + if (isstr(ad->aparse->x400_str)) + prevx400adr = strdup(ad->aparse->x400_str); + else + prevx400adr = NULLCP; + + or_error[0] = '\0'; + if (rp_isbad (rfc822_x400 (ad)) + || !isstr(ad->aparse->x400_str) + || prevx400adr == NULLCP + || lexequ (ad->aparse->x400_str, prevx400adr) == 0 + || lexequ (ad->aparse->x400_str, ad->ad_value) == 0) + cont = FALSE; + else + /* lets go round again */ + count++; + + if (prevx400adr) + free(prevx400adr); + + if (!rp_isbad(retval)) { + /* 822 is okay */ + ad_copy_addresses(ad, TRUE); + return (ad->ad_parse_stat = RP_AOK); + } + } while (count < MAX_LOOP && cont == TRUE); + + ad->aparse->ad_type = AD_X400_TYPE; + + return parselose_exception(rp, + retval, + logerr, + ad->ad_parse_message); +} + +/* */ + +/* copy addresses from ad->aparse to ad->ad_r*adr */ +/* overwriting depending on setting of force */ + +static void ad_copy_r822_address(ad, force) +register ADDR *ad; +int force; +{ + if (!ad->aparse->r822_str) + return; + if (ad->ad_r822adr) { + if (force != TRUE) + return; + free(ad->ad_r822adr); + } + ad->ad_r822adr = strdup(ad->aparse->r822_str); +} + +static void ad_copy_x400_address(ad, force) +register ADDR *ad; +int force; +{ + if (!ad->aparse->x400_str) + return; + if (ad->ad_r400adr) { + if (force != TRUE) + return; + free(ad->ad_r400adr); + } + ad->ad_r400adr = strdup(ad->aparse->x400_str); +} + +static void ad_copy_addresses(ad, force) +register ADDR *ad; +int force; +{ + ad_copy_r822_address(ad, force); + ad_copy_x400_address(ad, force); +} + +/* concat errors from ad->aparse to ad->ad_parse_message */ +/* overwriting depending on setting of force */ + +static void ad_copy_errors(ad, old, force) +register ADDR *ad; +char *old; +int force; +{ + char *str; + if (ad->aparse->x400_error == NULLCP + && ad->aparse->r822_error == NULLCP) + return; + + if (ad->ad_type == AD_X400_TYPE) { + if (ad->aparse->x400_error) + str = ad->aparse->x400_error; + else + str = ad->aparse->r822_error; + } else { + if (ad->aparse->r822_error) + str = ad->aparse->r822_error; + else + str = ad->aparse->x400_error; + } + + if (ad->ad_parse_message) { + if (force != TRUE) + return; + if (str) + free(ad->ad_parse_message); + } + + ad->ad_parse_message = strdup(str); + + if (old == NULLCP) + return; + + if (ad->aparse->r822_error + && ad->aparse->x400_error) { + /* both errors */ + if (lexequ(ad->aparse->x400_error, + ad->aparse->r822_error) == 0) { + (void) sprintf(old, "%s", ad->aparse->r822_error); + return; + } + + if (ad->ad_type == AD_X400_TYPE) + (void) sprintf(old, + "%s (%s)", + ad->aparse->x400_error, + ad->aparse->r822_error); + else + (void) sprintf(old, + "%s (%s)", + ad->aparse->r822_error, + ad->aparse->x400_error); + return; + } + + if (ad->aparse->r822_error) + (void) sprintf(old, "%s", ad->aparse->r822_error); + else if (ad->aparse->x400_error) + (void) sprintf(old, "%s", ad->aparse->x400_error); +} + +/* */ + +set_error (ad, buf) +register ADDR *ad; +char *buf; +{ + char **perr; + if (ad->aparse->ad_type == AD_X400_TYPE) + perr = &(ad->aparse->x400_error); + else + perr = &(ad->aparse->r822_error); + + if (*perr) + free(*perr); + + *perr = strdup(buf); +} + +/* */ + +static int parselose_exception (rp, val, logstr, str) +RP_Buf *rp; +int val; +char *logstr; +char *str; +{ + int minlen; + + PP_LOG (LLOG_EXCEPTIONS, + ("parselose (%s, '%s')", rp_valstr (val), logstr)); + + rp -> rp_val = val; + + if (isstr(str)) { + minlen = (strlen(str) < sizeof (rp -> rp_line) - 1) ? + strlen(str) : sizeof (rp -> rp_line) - 1; + (void) strncpy (rp -> rp_line, str, minlen); + rp -> rp_line[minlen] = '\0'; + } else + (void) strcpy (rp -> rp_line, + "ERROR"); + + + return val; +} + + +#ifdef lint +/* VARARGS3 */ +int parselose (rp, val, str) +RP_Buf *rp; +int val; +char *str; +{ + return parselose (rp, val, str); +} +#else +int parselose (va_alist) +va_dcl +{ + va_list ap; + RP_Buf *rp; + int val; + char buf[BUFSIZ]; + + va_start (ap); + + rp = va_arg (ap, RP_Buf *); + val = va_arg (ap, int); + + _asprintf (buf, NULLCP, ap); + + PP_LOG (LLOG_TRACE, + ("parselose (%s, '%s')", rp_valstr (val), buf)); + + rp -> rp_val = val; + (void) strncpy (rp -> rp_line, buf, sizeof (rp -> rp_line) - 1); + + va_end (ap); + + return val; +} +#endif + diff --git a/Lib/parse/aparse_norm.c b/Lib/parse/aparse_norm.c new file mode 100644 index 0000000..be9d063 --- /dev/null +++ b/Lib/parse/aparse_norm.c @@ -0,0 +1,615 @@ +/* aparse_norm.c: normalise an address folloing local synonyms */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/aparse_norm.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/aparse_norm.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: aparse_norm.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ +#include "util.h" +#include "adr.h" +#include "aparse.h" +#include "alias.h" + +extern char *loc_dom_site; + +static int x400_norm(), x400_local_norm(), + rfc822_norm(), rfc822_local_norm(), + convert_to_x400(), convert_to_rfc822(); + +int aparse_norm (ap) +register Aparse_ptr ap; +{ + int out_adr_type = ap->ad_type; + + if (ap->aliases) { + aparse_freeAliasList (ap->aliases); + ap->aliases = NULL; + } + + switch (ap->ad_type) { + case AD_X400_TYPE: + if (x400_norm(ap) != OK) + return NOTOK; + if (ap->ad_type != out_adr_type + && convert_to_x400 (ap) != OK) + return NOTOK; + return OK; + + case AD_822_TYPE: + default: + if (rfc822_norm(ap) != OK) + return NOTOK; + if (ap->ad_type != out_adr_type + && convert_to_rfc822 (ap) != OK) + return NOTOK; + return OK; + } +} + +/* */ + +static int x400_norm (ap) +register Aparse_ptr ap; +{ + int type; + char *replace; + char buf[BUFSIZ]; + + if (ap->x400_str == NULLCP + && ap->orname->on_or == NULLOR) + return NOTOK; + + if (ap->orname->on_or == NULLOR) { + ap->orname->on_or = + or_std2or(ap->x400_str); + ap->orname->on_or = or_default(ap->orname->on_or); + } + + + if (ap->x400_local) { + free(ap->x400_local); + ap->x400_local = NULLCP; + } + if (or_check (&(ap->orname->on_or), + buf, &type, + &(ap->local_hub_name), + &replace, + &(ap->lastMatch)) == NOTOK) + return NOTOK; + if (replace) free(replace); + + if (type == OR_ISLOCAL) { + ap->x400_local = strdup(buf); + return x400_local_norm (ap); + } + ap->ad_type = AD_X400_TYPE; + return OK; +} + +/* */ + +static int x400_local_norm (ap) +register Aparse_ptr ap; +{ + ALIAS alias_struct, *alp = &alias_struct; + OR_ptr syn, tmp; + char buf[BUFSIZ]; + + if (ap->x400_local == NULLCP) + return NOTOK; /* ? */ + if (ap->dont_use_aliases == TRUE) { + ap->ad_type = AD_X400_TYPE; + return OK; + } + if (tb_getalias (ap->x400_local, + alp, ap->local_hub_name) != OK + || alp->alias_type != ALIAS_SYNONYM) { + /* no synonym */ + ap->ad_type = AD_X400_TYPE; + return OK; + } + + if (alp->alias_external == ALIAS_EXTERNAL) { + if (ap->internal == TRUE) { + /* don't follow */ + ap->ad_type = AD_X400_TYPE; + return OK; + } + /* follow but don't use aliases table */ + /* may still need to normalise */ + ap->dont_use_aliases = TRUE; + } + + alias2adr (buf, alp, ap); + + if (aparse_inAliasList (buf, ap->aliases) == OK) { + if (alp->alias_external != ALIAS_EXTERNAL) + /* looping synonym */ + return NOTOK; + /* ignore loops if external */ + }else + aparse_addToAliasList (buf, &(ap->aliases)); + + switch (alp->alias_ad_type) { + case AD_ANY_TYPE: + /* replace from *ptree to lastMatch -> or_prev */ + /* with alp->alias_user */ + + if ((syn = or_std2or(alp->alias_user)) == NULLOR) + return NOTOK; + + /* rmoove old stuff */ + tmp = ap->lastMatch->or_next; + tmp->or_prev = NULLOR; + ap->lastMatch->or_next = NULLOR; + or_free(tmp); + + while (syn != NULLOR) { + tmp = syn -> or_next; + if (tmp != NULLOR) { + syn -> or_next = NULLOR; + tmp -> or_prev = NULLOR; + } + + if ((ap->orname->on_or = or_add (ap->orname->on_or, + syn, TRUE)) == NULLOR) + return NOTOK; + syn = tmp; + } + break; + + case AD_X400_TYPE: + /* completely replace old tree */ + or_free (ap->orname->on_or); + if ((ap->orname->on_or = or_std2or(alp->alias_user)) == NULLOR) + return NOTOK; + ap->orname->on_or = or_default(ap->orname->on_or); + break; + + default: + /* 822 synonym */ + aparse_rewindr822(ap); + ap->r822_str = strdup(alp->alias_user); + return rfc822_norm (ap); + } + + return x400_norm(ap); +} + +/* */ + +AP_ptr merge_new (ap, ntree, nloc, ndom) +AP_ptr ap, ntree, nloc, ndom; +{ + AP_ptr hdr, ix, nix = NULLAP, tmp; + int cont = TRUE; + + hdr = ap_new(AP_COMMENT, "header"); + hdr->ap_next = ap; + hdr->ap_ptrtype = AP_PTR_MORE; + ix = hdr; + + /* delete up to first mailbox */ + while (ix->ap_next != NULL + && cont == TRUE) { + switch (ix -> ap_next -> ap_obtype) { + case AP_DOMAIN: + case AP_DOMAIN_LITERAL: + /* part of route */ + ap_delete (ix); + break; + + case AP_MAILBOX: + case AP_GENERIC_WORD: + /* reached mailbox */ + cont = FALSE; + break; + + case AP_COMMENT: + default: + /* preserve */ + ix = ix->ap_next; + break; + } + } + + /* merge in ntree up to inclusive */ + if (ntree) { + for (nix = ntree; + nix -> ap_next != NULLAP + && nix -> ap_next != nloc -> ap_next; + nix = nix -> ap_next) + continue; + if (nix) { + tmp = nix -> ap_next; + nix -> ap_next = NULLAP; + } else + tmp = NULLAP; + + ix = ap_sqinsert(ix, + AP_PTR_MORE, + ntree); + nix = tmp; + } + + cont = TRUE; + /* delete up to next domain */ + while (ix->ap_next != NULL + && cont == TRUE) { + switch (ix -> ap_next -> ap_obtype) { + case AP_DOMAIN: + case AP_DOMAIN_LITERAL: + cont = FALSE; + break; + + case AP_MAILBOX: + case AP_GENERIC_WORD: + ap_delete (ix); + break; + + case AP_COMMENT: + default: + /* preserve */ + ix = ix->ap_next; + break; + } + } + + /* merge in up to ndom inclusive */ + if (nix) { + ntree = nix; + for (; + nix -> ap_next != NULLAP + && nix -> ap_next != ndom -> ap_next; + nix = nix -> ap_next) + continue; + if (nix) { + tmp = nix -> ap_next; + nix -> ap_next = NULLAP; + } else + tmp = NULLAP; + ix = ap_sqinsert(ix, + AP_PTR_MORE, + ntree); + nix = tmp; + } else + /* no local */ + return NULLAP; + + /* delete remaining domains */ + cont = TRUE; + while (ix->ap_next != NULLAP && cont == TRUE) { + switch (ix -> ap_next -> ap_obtype) { + case AP_DOMAIN: + case AP_DOMAIN_LITERAL: + case AP_MAILBOX: + case AP_GENERIC_WORD: + ap_delete(ix); + break; + case AP_COMMENT: + /* preserve */ + ix = ix -> ap_next; + break; + default: + /* save end of names etc */ + cont = FALSE; + break; + } + } + + if (nix) + ix = ap_sqinsert(ix, + AP_PTR_MORE, + nix); + ap = hdr -> ap_next; + ap_free(hdr); + return ap; +} + +#ifdef VAT +static void db_check(name, loc, dom, route) +AP_ptr name, + loc, + dom, + route; +{ + AP_ptr ix = name; + + while (ix != NULLAP && + ix != loc && + ix != dom && + ix != route) { + if ((ix -> ap_obtype == AP_PERSON_END + || ix -> ap_obtype == AP_PERSON_NAME + || ix -> ap_obtype == AP_PERSON_START) + && ix->ap_obvalue != NULLCP + && lexequ("Hardcastle-Kille", ix->ap_obvalue) == 0) { + AP_ptr ix2, tmp = ap_s2t("Hardcastle(Hyphen)Kille"); + + for (ix2 = tmp; ix2 != NULLAP; ix2 = ix2->ap_next) { + if (ix2->ap_obtype != AP_COMMENT) + ix2->ap_obtype = ix->ap_obtype; + } + (void) ap_sqinsert (ix, AP_PTR_MORE, tmp); + /* copy up and delete */ + tmp = ix -> ap_next; + ix -> ap_obtype = tmp -> ap_obtype; + ix -> ap_ptrtype = tmp -> ap_ptrtype; + if (ix -> ap_obvalue) + free (ix->ap_obvalue); + ix -> ap_obvalue = tmp -> ap_obvalue; + tmp -> ap_obvalue = NULLCP; + ix -> ap_next = tmp -> ap_next; + tmp -> ap_next = NULLAP; + ap_free(tmp); + } + ix = ix -> ap_next; + } +} +#endif + +static AP_ptr get_next_route (ap, startfrom) +register Aparse_ptr ap; +AP_ptr startfrom; +{ + AP_ptr ret; + + if (startfrom == NULLAP) + return NULLAP; + + if (startfrom->ap_obtype == AP_DOMAIN + || startfrom->ap_obtype == AP_DOMAIN_LITERAL) + return startfrom; + + ret = startfrom; + for (;;) { + switch (ret->ap_ptrtype) { + case AP_PTR_MORE: + /* -- next is part of this address -- */ + ret = ret -> ap_next; + if (ret == ap->ap_group || + ret == ap->ap_name || + ret == ap->ap_local || + ret == ap->ap_domain) + return NULLAP; + + switch (ret -> ap_obtype) { + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + return ret; + default: + break; + } + break; + default: + return NULLAP; + } + } +} + +static int rfc822_norm (ap) +register Aparse_ptr ap; +{ + AP_ptr rout; + + if (ap->r822_str == NULLCP + && ap->ap_tree == NULLAP) + return NOTOK; + + if (ap->ap_tree == NULLAP) + ap->ap_tree = ap_s2t(ap->r822_str); + + (void) ap_t2p (ap->ap_tree, &(ap->ap_group), + &(ap->ap_name), &(ap->ap_local), + &(ap->ap_domain), &(ap->ap_route)); + +#ifdef VAT + if ((getpid() % 10) == 2) + db_check (ap->ap_name, ap->ap_local, + ap->ap_domain, ap->ap_route); +#endif + + if (ap->normalised == APARSE_NORM_ALL) { + /* normalise all domains */ + rout = ap->ap_route; + while (rout && + (rout = get_next_route(ap, rout)) != NULLAP) { + (void) rfc822_norm_dmn(rout, ap->dmnorder); + rout = rout->ap_next; + } + if (ap->ap_domain) + (void) rfc822_norm_dmn (ap->ap_domain, ap->dmnorder); + rout = get_next_route (ap, ap->ap_route); + } else { + /* normalise first domain */ + if ((rout = get_next_route(ap, ap->ap_route)) != NULLAP) + (void) rfc822_norm_dmn (rout, ap->dmnorder); + else if (ap->ap_domain) + (void) rfc822_norm_dmn(ap->ap_domain, ap->dmnorder); + + } + + while (rout && rout->ap_islocal == TRUE) { + /* local so remove from route */ + ap->ap_route = rout = get_next_route(ap, rout->ap_next); + if (rout && rout->ap_normalised != TRUE) + (void) rfc822_norm_dmn(rout, ap->dmnorder); + } + + if (rout == NULLAP) { + /* no route */ + if (ap->ap_domain == NULLAP) { + /* no domain either so add default */ + if (ap->ap_local == NULLAP) + /* no local either so fail */ + return NOTOK; + for (rout = ap->ap_local; + rout -> ap_next != NULLAP; + rout = rout -> ap_next) + continue; + (void) ap_append(rout, AP_DOMAIN, loc_dom_site); + ap->ap_domain = rout -> ap_next; + (void) rfc822_norm_dmn(ap->ap_domain, ap->dmnorder); + } else if (ap->ap_domain->ap_normalised != TRUE) + (void) rfc822_norm_dmn(ap->ap_domain, ap->dmnorder); + + if (ap->ap_domain->ap_islocal == TRUE) + return rfc822_local_norm(ap); + } + ap->ad_type = AD_822_TYPE; + return OK; +} + +static int rfc822_local_norm(ap) +register Aparse_ptr ap; +{ + ALIAS alias_struct, *alp = &alias_struct; + char buf[BUFSIZ], *str; + AP_ptr newtree, newgroup, newname, newloc, newdom, newroute; + + if (ap->r822_local) free(ap->r822_local); + ap->r822_local = ap_p2s_nc(NULLAP, NULLAP, + ap->ap_local, + NULLAP, NULLAP); + + if (ap->dont_use_aliases == TRUE) { + ap->ad_type = AD_822_TYPE; + return OK; + } + + if (tb_getalias(ap->r822_local, alp, ap->ap_domain->ap_localhub) != OK + || alp->alias_type != ALIAS_SYNONYM) { + /* no synonym */ + ap->ad_type = AD_822_TYPE; + return OK; + } + + if (alp->alias_external == ALIAS_EXTERNAL) { + if (ap->internal == TRUE) { + /* don't follow */ + ap->ad_type = AD_822_TYPE; + return OK; + } + /* follow but don't use aliases table */ + /* may still need to normalise */ + ap->dont_use_aliases = TRUE; + } + + alias2adr (buf, alp, ap); + + if (aparse_inAliasList (buf, ap->aliases) == OK) { + if (alp->alias_external != ALIAS_EXTERNAL) + /* looping synonym */ + return NOTOK; + /* ignore lopps if external */ + } else + aparse_addToAliasList (buf, &(ap->aliases)); + + switch (alp->alias_ad_type) { + case AD_ANY_TYPE: + /* use existing domian but replace loc */ + newloc = ap_s2t(alp->alias_user); + str = ap_p2s(NULLAP, NULLAP, newloc, ap->ap_domain, NULLAP); + ap_free(newloc); + break; + + case AD_822_TYPE: + /* replace all */ + str = strdup(alp->alias_user); + break; + + default: + aparse_rewindx400(ap); + ap->x400_str = strdup(alp->alias_user); + return x400_norm(ap); + } + + newtree= ap_s2t(str); + (void) ap_t2p(newtree, &newgroup, + &newname, &newloc, + &newdom, &newroute); + ap->ap_tree = merge_new(ap->ap_tree, newtree, newloc, newdom); + + free(str); + (void) ap_t2p (ap->ap_tree, &(ap->ap_group), + &(ap->ap_name), &(ap->ap_local), + &(ap->ap_domain), &(ap->ap_route)); + + if (ap->r822_str) free(ap->r822_str); + ap->r822_str = ap_p2s(ap->ap_group, ap->ap_name, + ap->ap_local, ap->ap_domain, + ap->ap_route); + return rfc822_norm (ap); +} + + +/* */ + +extern char or_error[]; + +static int convert_to_x400 (ap) +register Aparse_ptr ap; +{ + char tbuf[BUFSIZ]; + OR_ptr or; + + if (ap -> r822_str == NULLCP) + return NOTOK; + + aparse_rewindx400(ap); + + if (or_rfc2or_aux (ap->r822_str, + &(ap->orname->on_or), 1) == NOTOK) { + or_free(ap->orname->on_or); + ap->orname->on_or = NULLOR; + PP_DBG(("convert_to_x400 failed (%s)", or_error)); + return NOTOK; + } + + if ((or = or_default (ap->orname->on_or)) == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("or_default failed")); + return NOTOK; + } + ap -> orname -> on_or = or; + + or_or2std (ap->orname->on_or, tbuf, FALSE); + ap->x400_str = strdup(tbuf); + ap->ad_type = AD_X400_TYPE; + + return OK; +} + +/* */ + +static int convert_to_rfc822 (ap) +register Aparse_ptr ap; +{ + char tbuf[BUFSIZ]; + + if (ap->orname->on_or == NULLOR) + return NOTOK; + + aparse_rewindr822(ap); + + if (or_or2rfc (ap->orname->on_or, tbuf) == NOTOK) { + PP_DBG(("convert_to_rfc822 failed (%s)", or_error)); + return NOTOK; + } + + ap->r822_str = strdup(tbuf); + ap->ap_tree = ap_s2t(ap->r822_str); + (void) ap_t2p (ap->ap_tree, &(ap->ap_group), + &(ap->ap_name), &(ap->ap_local), + &(ap->ap_domain), &(ap->ap_route)); + + ap->ad_type = AD_822_TYPE; + + return OK; +} diff --git a/Lib/parse/make b/Lib/parse/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/parse/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/parse/rfc822_dnorm.c b/Lib/parse/rfc822_dnorm.c new file mode 100644 index 0000000..e97c1fe --- /dev/null +++ b/Lib/parse/rfc822_dnorm.c @@ -0,0 +1,82 @@ +/* rfc822_dnorm.c: normalise an 822 domain */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_dnorm.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_dnorm.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: rfc822_dnorm.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ +#include "head.h" +#include "ap.h" +#include "chan.h" + +extern char *bits2str(); + +rfc822_norm_dmn (dmn, dmnorder) +register AP_ptr dmn; +int dmnorder; +{ + int retval; + char official[LINESIZE], + mta_key[LINESIZE], + tbuf[BUFSIZ], + *one_ord[LINESIZE], + *other_ord[LINESIZE]; + + if (dmn == NULL) + return NOTOK; + + + /* hardwire in local mta and site */ + (void) strcpy (tbuf, dmn->ap_obvalue); + (void) str2bits (tbuf, '.', one_ord, other_ord); + + retval = tb_getdomain(dmn->ap_obvalue, + mta_key, + official, + dmnorder, + &(dmn->ap_localhub)); + + dmn->ap_normalised = TRUE; + if (retval == OK) { + + dmn->ap_recognised = TRUE; + if (official[0]) { + free (dmn->ap_obvalue); + dmn->ap_obvalue = strdup(official); + PP_DBG(("rfc822_norm_dmn Official = '%s'", + official)); + } + if (mta_key[0]) { + if (dmn->ap_chankey) + free(dmn->ap_chankey); + dmn->ap_chankey = strdup(mta_key); + PP_DBG(("rfc822_norm_dmn channel key = '%s'", + mta_key)); + } + if (dmn->ap_localhub != NULLCP) + dmn->ap_islocal = TRUE; + else + dmn->ap_islocal = FALSE; + + } else { + + dmn->ap_recognised = FALSE; + (void) sprintf(official, + "Unknown domain '%s'", + dmn->ap_obvalue); + dmn->ap_error = strdup(official); + PP_LOG (LLOG_EXCEPTIONS, + ("%s is not a known domain reference", + dmn->ap_obvalue)); + + } + + return retval; +} diff --git a/Lib/parse/rfc822_parse.c b/Lib/parse/rfc822_parse.c new file mode 100644 index 0000000..7f5e9af --- /dev/null +++ b/Lib/parse/rfc822_parse.c @@ -0,0 +1,193 @@ +/* rfc822_parse.c: 822 address parsing and normalisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: rfc822_parse.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" + +extern int ap_lex_percent; +extern char *loc_dom_site; +static int normalise_and_strip_excess_locals(); + +int rfc822_parse(ad) +register ADDR *ad; +{ + int old_ap_lex = ap_lex_percent; + char buf[BUFSIZ]; + ap_lex_percent = ad->aparse->percents; + switch ((int) (ad->aparse->ap_tree = + ap_s2t ((ad->aparse->r822_str) ? + ad->aparse->r822_str : + ad->ad_value))) { + case 0: + /* -- could parse it and found it to be duff -- */ + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + (void) sprintf(buf, "Unparseable address '%s'", + (ad->aparse->r822_str) ? ad->aparse->r822_str : ad->ad_value); + + ad->aparse->r822_error = strdup(buf); + ap_lex_percent = old_ap_lex; + return RP_NO; + + case NOTOK: + /* -- couldn't parse it (x400 ?) -- */ + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + ad->aparse->r822_error = strdup("822 parse error"); + ap_lex_percent = old_ap_lex; + return RP_PARSE; + + default: + ap_lex_percent = old_ap_lex; + break; + } + + /* -- split into parts -- */ + + (void) ap_t2p(ad->aparse->ap_tree, + &ad->aparse->ap_group, + &ad->aparse->ap_name, + &ad->aparse->ap_local, + &ad->aparse->ap_domain, + &ad->aparse->ap_route); + + if (rp_isbad(normalise_and_strip_excess_locals(ad))) + return RP_PARSE; + + fillin_822_str(ad); + + return RP_OK; +} + +static AP_ptr get_next_route (ad, startfrom) +register ADDR *ad; +AP_ptr startfrom; +{ + AP_ptr ret; + + if (startfrom == NULLAP) + return NULLAP; + + if (startfrom->ap_obtype == AP_DOMAIN + || startfrom->ap_obtype == AP_DOMAIN_LITERAL) + return startfrom; + + ret = startfrom; + for (;;) { + switch (ret->ap_ptrtype) { + case AP_PTR_MORE: + /* -- next is part of this address -- */ + ret = ret -> ap_next; + if (ret == ad->aparse->ap_group || + ret == ad->aparse->ap_name || + ret == ad->aparse->ap_local || + ret == ad->aparse->ap_domain) + return NULLAP; + + switch (ret -> ap_obtype) { + case AP_DOMAIN_LITERAL: + case AP_DOMAIN: + return ret; + default: + break; + } + break; + default: + return NULLAP; + } + } +} + +static int normalise_and_strip_excess_locals(ad) +register ADDR *ad; +{ + AP_ptr rout; + + if (ad->aparse->normalised == APARSE_NORM_ALL) { + /* normalise all domains */ + rout = ad->aparse->ap_route; + while (rout && + (rout = get_next_route(ad, rout)) != NULLAP) { + (void) rfc822_norm_dmn(rout, ad->aparse->dmnorder); + rout = rout->ap_next; + } + if (ad->aparse->ap_domain) + (void) rfc822_norm_dmn(ad->aparse->ap_domain, + ad->aparse->dmnorder); + rout = get_next_route (ad, ad->aparse->ap_route); + } else { + /* normalise first domain */ + if ((rout = get_next_route(ad, ad->aparse->ap_route)) + != NULLAP) + (void) rfc822_norm_dmn(rout, + ad->aparse->dmnorder); + else if (ad->aparse->ap_domain) + (void) rfc822_norm_dmn(ad->aparse->ap_domain, + ad->aparse->dmnorder); + } + + while (rout && rout->ap_islocal == TRUE) { + /* local so remove from route */ + ad->aparse->ap_route = rout = get_next_route(ad, rout->ap_next); + if (rout && rout->ap_normalised != TRUE) + /* normalise ad->aparse->ap_route */ + (void) rfc822_norm_dmn(rout, + ad->aparse->dmnorder); + } + + if (rout == NULLAP) { + /* no route */ + if (ad->aparse->ap_domain == NULLAP) { + /* -- no domain either so add default -- */ + AP_ptr ix; + if (ad->aparse->ap_local == NULLAP) { + /* -- no local either so fail */ + char tmp[BUFSIZ]; + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + (void) sprintf(tmp, + "No route, domain or local part to '%s'", + ad->ad_value); + ad->aparse->r822_error = strdup(tmp); + return RP_PARSE; + } + for (ix = ad->aparse->ap_local; + ix -> ap_next != NULLAP; + ix = ix -> ap_next) + continue; + if (loc_dom_site == NULLCP + || *loc_dom_site == '\0') { + char tmp[BUFSIZ]; + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + (void) sprintf(tmp, + "loc_dom_site is invalid"); + ad->aparse->r822_error = strdup(tmp); + return RP_PARSE; + } + (void) ap_append (ix, AP_DOMAIN, loc_dom_site); + ad->aparse->ap_domain = ix->ap_next; + (void) rfc822_norm_dmn(ad->aparse->ap_domain, + ad->aparse->dmnorder); + + } else if (ad->aparse->ap_domain->ap_normalised != TRUE) + /* normalise ad->aparse->ap_domain */ + (void) rfc822_norm_dmn(ad->aparse->ap_domain, + ad->aparse->dmnorder); + } + return RP_OK; +} + + diff --git a/Lib/parse/rfc822_val.c b/Lib/parse/rfc822_val.c new file mode 100644 index 0000000..2e8885d --- /dev/null +++ b/Lib/parse/rfc822_val.c @@ -0,0 +1,192 @@ +/* rfc822_validate.c: validate a syntatic rfc 822 address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_val.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_val.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: rfc822_val.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" + +static int rfc822_val_domain(), rfc822_val_local(); + +int rfc822_validate (ad, rp) +register ADDR *ad; +RP_Buf *rp; +{ + /* -- some debugging statements -- */ + AP_ptr dom_ptr, hptr; + int cont; + char tmp[BUFSIZ]; + + if (ad->aparse->ap_route) { + for (hptr = ad->aparse->ap_route, cont = TRUE; + cont == TRUE; + hptr = hptr->ap_next) { + PP_DBG(("rfc822_validate (route=%s, type=%d)", + hptr->ap_obvalue, + hptr->ap_obtype)); + switch (hptr -> ap_ptrtype) { + case AP_PTR_MORE: + break; + default: + /* -- no more route -- */ + cont = FALSE; + break; + } + } + } + + if (ad->aparse->ap_domain) + PP_DBG(("rfc822_validate (dmn=%s, type=%d)", + ad->aparse->ap_domain->ap_obvalue, + ad->aparse->ap_domain->ap_obtype)); + + if (ad->aparse->ap_local) + PP_DBG(("rfc822_validate (dmn=%s, type=%d)", + ad->aparse->ap_local->ap_obvalue, + ad->aparse->ap_local->ap_obtype)); + + if (ad->aparse->ap_local == NULLAP) { + (void) sprintf (tmp, + "No local address in %s", + ad->ad_value); + ad->aparse->r822_error = strdup(tmp); + fillin_822_str(ad); + return RP_BAD; + } + + /* assume have stripped excess local domains from route */ + + dom_ptr = (ad->aparse->ap_route) ? + ad->aparse->ap_route : + ad->aparse->ap_domain; + + if (dom_ptr && dom_ptr->ap_normalised != TRUE) + /* -- shouldn't happen --*/ + /* normalise dom_ptr */ + (void) rfc822_norm_dmn(dom_ptr, ad->aparse->dmnorder); + + fillin_822_str(ad); + + if (dom_ptr && dom_ptr->ap_islocal == FALSE) + return rfc822_val_domain(ad, dom_ptr, rp); + else + return rfc822_val_local(ad, dom_ptr, rp); +} + +/* */ + +static int rfc822_val_domain(ad, dom_ptr, rp) +register ADDR *ad; +AP_ptr dom_ptr; +RP_Buf *rp; +{ + char tmp[BUFSIZ]; + LIST_RCHAN *rlp; + /* not local so remove local if there */ + if (ad->aparse->r822_local) { + free(ad->aparse->r822_local); + ad->aparse->r822_local = NULLCP; + } + + if (dom_ptr->ap_recognised == FALSE) { + /* unrecgonised domain */ + /* dom_ptr->ap_error should be filled */ + /* in when normalise was done */ + if (dom_ptr->ap_error) { + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + ad->aparse->r822_error = dom_ptr->ap_error; + dom_ptr->ap_error = NULLCP; + } + return RP_BAD; + } + + /* -- look up the channel table -- */ + if (ad->ad_outchan == NULLIST_RCHAN) + if (dom_ptr->ap_chankey == NULLCP) { + /* just norm in domain table */ + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + PP_NOTICE(("No routing information associated with domain '%s'", + dom_ptr->ap_obvalue)); + (void) sprintf (tmp, + "Unrouteable domain '%s'", + ad->aparse->ap_domain->ap_obvalue); + ad->aparse->r822_error = strdup(tmp); + return parselose (rp, RP_BAD, "%s", tmp); + } else if (tb_getchan (dom_ptr->ap_chankey, + &(ad->ad_outchan)) != OK) { + if (ad->aparse->r822_error) + free(ad->aparse->r822_error); + (void) sprintf (tmp, + "Unknown domain '%s'", + ad->aparse->ap_domain->ap_obvalue); + PP_NOTICE(("No 822 channel registered for '%s'", + dom_ptr->ap_chankey)); + ad->aparse->r822_error = strdup(tmp); + return parselose (rp, RP_BAD, "%s", tmp); + } + /* --- *** --- + Go thru list of channels. if li_mta (i.e. mta) is not set + insert the official. + --- *** --- */ + for (rlp=ad->ad_outchan; rlp; rlp = rlp->li_next) + if (rlp->li_mta == NULLCP) + rlp->li_mta = strdup (dom_ptr->ap_obvalue); + + if (ad->ad_outchan == NULL) + return RP_BAD; + return RP_AOK; +} + +/* */ + +static int rfc822_val_local(ad, dom_ptr, rp) +register ADDR *ad; +AP_ptr dom_ptr; +RP_Buf *rp; +{ + if (ad->aparse->r822_local) free(ad->aparse->r822_local); + ad->aparse->r822_local = ap_p2s(NULLAP, NULLAP, + ad->aparse->ap_local, + NULLAP, NULLAP); + + if (dom_ptr + && dom_ptr->ap_localhub) { + if (ad->aparse->local_hub_name) + free(ad->aparse->local_hub_name); + ad->aparse->local_hub_name = strdup(dom_ptr->ap_localhub); + } + + return ad_local(ad->aparse->r822_local, ad, rp); + +} + +/* */ + +int fillin_822_str(ad) +register ADDR *ad; +{ + if (ad->aparse->r822_str) free(ad->aparse->r822_str); + if (ad->aparse->full == OK) + ad->aparse->r822_str = + ap_p2s(ad->aparse->ap_group, ad->aparse->ap_name, + ad->aparse->ap_local, ad->aparse->ap_domain, + ad->aparse->ap_route); + else + ad->aparse->r822_str = + ap_p2s_nc(NULLAP, NULLAP, + ad->aparse->ap_local, ad->aparse->ap_domain, + ad->aparse->ap_route); + +} diff --git a/Lib/parse/rfc822_x400.c b/Lib/parse/rfc822_x400.c new file mode 100644 index 0000000..802b6d6 --- /dev/null +++ b/Lib/parse/rfc822_x400.c @@ -0,0 +1,61 @@ +/* rfc822_x400.c: address conversion from 822 to x400 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_x400.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/rfc822_x400.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: rfc822_x400.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" + +extern char or_error[]; + +int rfc822_x400(ad) +register ADDR *ad; +{ + OR_ptr or; + char *p = ad->aparse->r822_str ? + ad->aparse->r822_str : ad->ad_value; + PP_DBG(("rfc822_x400('%s')", p)); + + aparse_rewindx400(ad->aparse); + + if (or_rfc2or_aux (p, &(ad->aparse->orname->on_or), ad->ad_no) == NOTOK) { + or_free (ad->aparse->orname->on_or); + ad->aparse->orname->on_or = NULLOR; + PP_DBG(("rfc822_x400 conversion failed (%s)", or_error)); + return RP_PARSE; + } + + if ((or = or_default (ad->aparse->orname->on_or)) == NULLOR) { + PP_LOG (LLOG_EXCEPTIONS, ("or_default failed")); + return RP_PARSE; + } + ad -> aparse -> orname -> on_or = or; + + fillin_400_str(ad); + + return RP_AOK; +} + +void x400_add(ad) +register ADDR *ad; +{ + (void) rfc822_x400(ad); + + if (ad->aparse->x400_str) { + if (ad->ad_r400adr) + free (ad->ad_r400adr); + + ad->ad_r400adr = strdup (ad->aparse->x400_str); + } + PP_DBG (("x400_add returns (x400_str=%s)", ad->aparse->x400_str)); +} diff --git a/Lib/parse/x400_parse.c b/Lib/parse/x400_parse.c new file mode 100644 index 0000000..391dc79 --- /dev/null +++ b/Lib/parse/x400_parse.c @@ -0,0 +1,48 @@ +/* x400_parse.c: x400 address parsing */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_parse.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: x400_parse.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" + +extern char or_error[]; + +int x400_parse (ad) +register ADDR *ad; +{ + if (ad->aparse->x400_str) + ad->aparse->orname->on_or = + or_std2or(ad->aparse->x400_str); + else { + if ((ad->aparse->orname->on_or = + or_std2or(ad->ad_value)) != NULLOR) { + ad->aparse->orname->on_or = + or_default(ad->aparse->orname->on_or); + } + + } + + if (ad->aparse->x400_dn) + /* do something with dn ? */ + ; + + if (ad->aparse->orname->on_or == NULLOR) { + ad->aparse->x400_error = strdup(or_error); + return RP_PARSE; + } + + fillin_400_str(ad); + + return RP_AOK; +} diff --git a/Lib/parse/x400_rfc822.c b/Lib/parse/x400_rfc822.c new file mode 100644 index 0000000..b4ada2a --- /dev/null +++ b/Lib/parse/x400_rfc822.c @@ -0,0 +1,70 @@ +/* x400_rfc822.c: address conversion from x400 to 822 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_rfc822.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_rfc822.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: x400_rfc822.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" + +extern char or_error[]; + +int x400_rfc822 (ad) +register ADDR *ad; +{ + char tbuf[LINESIZE]; + + PP_DBG(("x400_rfc822('%s')", + ad->aparse->x400_str ? ad->aparse->x400_str : ad->ad_value)); + + if (ad->aparse->orname->on_or == NULLOR) { + /* ??? shouldn't happen */ + return RP_PARSE; + } + + aparse_rewindr822(ad->aparse); + + switch (or_or2rfc (ad->aparse->orname->on_or, tbuf)) { + case DONE: + /* ??? */ + return RP_AOK; + case NOTOK: + PP_DBG(("x400_rfc822 Conversion failed (%s)", or_error)); + return RP_PARSE; + default: + break; + } + /* do something with DNs */ + + ad->aparse->r822_str = strdup(tbuf); + + if (rp_isbad(rfc822_parse (ad))) + return RP_PARSE; + + PP_DBG(("x400_rfc822 result ('%s')", tbuf)); + + return (RP_AOK); +} + +void rfc822_add(ad) +register ADDR *ad; +{ + (void) x400_rfc822(ad); + + if (ad->aparse->r822_str) { + if (ad->ad_r822adr) + free(ad->ad_r822adr); + ad->ad_r822adr = strdup(ad->aparse->r822_str); + } + PP_DBG (("rfc822_add returns (r822_str=%s)", ad->aparse->r822_str)); +} + diff --git a/Lib/parse/x400_val.c b/Lib/parse/x400_val.c new file mode 100644 index 0000000..6eb6b8f --- /dev/null +++ b/Lib/parse/x400_val.c @@ -0,0 +1,174 @@ +/* x400_validate.c: validate an x400 address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_val.c,v 6.0 1991/12/18 20:23:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/parse/RCS/x400_val.c,v 6.0 1991/12/18 20:23:41 jpo Rel $ + * + * $Log: x400_val.c,v $ + * Revision 6.0 1991/12/18 20:23:41 jpo + * Release 6.0 + * + */ + +#include "head.h" +#include "adr.h" +#include "or.h" + +extern char or_error[]; + +static int x400_val_mta(), x400_val_local(); + +int x400_validate(ad, rp) +register ADDR *ad; +RP_Buf *rp; +{ + char tbuf[BUFSIZ], *replace; + int type; + +#ifdef NOTNEEDED + /* should have already been done when on_or was being set up */ + if (or_checktypes (ad->aparse->orname->on_or, + tmp) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad OR address '%s'", tmp)); + if (ad->aparse->x400_error) + free(ad->aparse->x400_error); + ad->aparse->x400_error = strdup(tmp); + return RP_BAD; + } +#endif + + if (or_check (&(ad->aparse->orname->on_or), + tbuf, &type, + &(ad->aparse->local_hub_name), + &replace, + &(ad->aparse->lastMatch)) == NOTOK) { + PP_DBG (("x400_validate OR_check failed '%s'", + or_error)); + if (ad->aparse->x400_error) + free(ad->aparse->x400_error); + ad->aparse->x400_error = strdup(or_error); + return RP_BAD; + } + + PP_DBG (("x400_validate (tbuf=%s, type=%d)", + tbuf, type)); + + if (replace != NULLCP) + free(replace); + + fillin_400_str(ad); + + switch (type) { + case OR_ISLOCAL: + return x400_val_local(ad,tbuf,rp); + case OR_ISMTA: + return x400_val_mta(ad,tbuf,rp); + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Illegal return from or_check '%d'", type)); + return RP_MECH; + } +} + +/* */ + +static int x400_val_mta (ad, name, rp) +register ADDR *ad; +char *name; +RP_Buf *rp; +{ + char tmp[BUFSIZ]; + LIST_RCHAN *rlp; + + /* not local so remove local if there */ + if (ad->aparse->x400_local) { + free(ad->aparse->x400_local); + ad->aparse->x400_local = NULLCP; + } + + /* -- look up the channel table -- */ + if (ad->ad_outchan == NULLIST_RCHAN) + if (tb_getchan (name, + &(ad->ad_outchan)) != OK) { + if (ad->aparse->x400_error) + free(ad->aparse->x400_error); + + (void) sprintf(tmp, + "Unknown domain '%s'", + name); + PP_NOTICE(("No x400 channel regisitered for '%s'", + name)); + ad->aparse->x400_error = strdup(tmp); + } + + for (rlp=ad->ad_outchan;rlp;rlp=rlp->li_next) + if (rlp->li_mta == NULLCP) + rlp->li_mta = strdup(name); + + if (ad->ad_outchan == NULLIST_RCHAN) { + (void) strcpy (rp -> rp_line, ad -> aparse->x400_error); + return rp -> rp_val = RP_BAD; + } + return RP_AOK; +} + +/* */ + +static int x400_val_local (ad, name, rp) +register ADDR *ad; +char *name; +RP_Buf *rp; +{ + char tmp[BUFSIZ]; + OR_ptr local; + + + if (ad->aparse->lastMatch != NULLOR + && (local = ad->aparse->lastMatch->or_next) != NULLOR) { + /* try first looking up with all components */ + /* including DDAs */ + int retval; + char *saveerror = ad->aparse->x400_error; + ad->aparse->x400_error = NULLCP; + local -> or_prev = NULLOR; + or_or2std(local, tmp, FALSE); + if (ad->aparse->x400_local) + free (ad->aparse->x400_local); + ad->aparse->x400_local = strdup(tmp); + local -> or_prev = ad->aparse->lastMatch; + + if (!rp_isbad(retval = ad_local(tmp, ad, rp))) + return retval; + if (ad->aparse->x400_error) + free(ad->aparse->x400_error); + ad->aparse->x400_error = saveerror; + } + + if (ad->aparse->x400_local) + free (ad->aparse->x400_local); + if (or_getpn(ad->aparse->orname->on_or, + tmp) == TRUE) + ad->aparse->x400_local = strdup(tmp); + else + ad->aparse->x400_local = NULLCP; + + return ad_local(name, ad, rp); +} + +/* */ + +int fillin_400_str (ad) +register ADDR *ad; +{ + char tbuf[BUFSIZ]; + + if (ad->aparse->x400_str) free(ad->aparse->x400_str); + + or_or2std(ad->aparse->orname->on_or, tbuf, FALSE); + + ad->aparse->x400_str = strdup(tbuf); +} diff --git a/Lib/pp/Makefile b/Lib/pp/Makefile new file mode 100644 index 0000000..bc15615 --- /dev/null +++ b/Lib/pp/Makefile @@ -0,0 +1,1001 @@ +# PP specific routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/pp/RCS/Makefile,v 6.0 1991/12/18 20:49:15 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:49:15 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = adr2txt.c chan_acheck.c conf.c dchan_acheck.c dr2txt.c get_dr.c \ + lchan_acheck.c list_bpt.c list_rchan.c mta2txt.c p32txt.c \ + pps_mail.c prm2txt.c q2txt.c set_1dr.c static.c tb_a.c tb_bpt84.c \ + tb_bpt88.c tb_dr.c tb_misc.c tb_p1.c tb_p3prm.c tb_prm.c tb_q.c \ + txt2adr.c txt2dr.c txt2mta.c txt2p3.c txt2prm.c txt2q.c ut_a.c \ + ut_com.c ut_dlh.c ut_dr.c ut_fn.c ut_free.c ut_gldm.c ut_mm2p1.c \ + ut_mpduid.c ut_msg.c ut_p12mm.c ut_p1_st.c ut_prm.c ut_q.c \ + ut_qid.c ut_trace.c wr_stat.c ut_aparse.c ut_postie.c \ + ut_redirect.c +OBJS = adr2txt.o chan_acheck.o conf.o dchan_acheck.o dr2txt.o get_dr.o \ + lchan_acheck.o list_bpt.o list_rchan.o mta2txt.o p32txt.o \ + pps_mail.o prm2txt.o q2txt.o set_1dr.o static.o tb_a.o tb_bpt84.o \ + tb_bpt88.o tb_dr.o tb_misc.o tb_p1.o tb_p3prm.o tb_prm.o tb_q.o \ + txt2adr.o txt2dr.o txt2mta.o txt2p3.o txt2prm.o txt2q.o ut_a.o \ + ut_com.o ut_dlh.o ut_dr.o ut_fn.o ut_free.o ut_gldm.o ut_mm2p1.o \ + ut_mpduid.o ut_msg.o ut_p12mm.o ut_p1_st.o ut_prm.o ut_q.o \ + ut_qid.o ut_trace.o wr_stat.o ut_aparse.o ut_postie.o \ + ut_redirect.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h + +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = pp-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: ${SHADOW} + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lintlib:llib-lpp.ln +llib-lpp.ln: ${SRCS} + $(LINT) -Cpp $(LLFLAGS) ${SRCS} + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +install:; + +clean: tidy + rm -f $(OBJS) llib-lpp.ln + +tidy: + rm -f core ${SHADOW} *.old a.out *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +conf.o: conf.c ../../Make.defs + $(CC) $(CFLAGS) -c \ + '-DTAILOR="$(TAILOR)"' \ + '-DCMDDIR="$(CMDDIR)"' \ + '-DLOGDIR="$(LOGDIR)"' \ + '-DQUEDIR="$(QUEDIR)"' \ + '-DTBLDIR="$(TBLDIR)"' \ + conf.c + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +adr2txt.o: adr2txt.c +adr2txt.o: ../../h/util.h +adr2txt.o: ../../h/config.h +adr2txt.o: ../../h/ll_log.h +adr2txt.o: ../../h/adr.h +adr2txt.o: ../../h/list_rchan.h +adr2txt.o: ../../h/chan.h +adr2txt.o: ../../h/table.h +adr2txt.o: ../../h/list_bpt.h +adr2txt.o: ../../h/auth.h +adr2txt.o: ../../h/list_bpt.h +adr2txt.o: ../../h/extension.h +adr2txt.o: ../../h/mta.h +adr2txt.o: ../../h/adr.h +adr2txt.o: ../../h/list_bpt.h +adr2txt.o: ../../h/aparse.h +adr2txt.o: ../../h/ap.h +adr2txt.o: ../../h/util.h +adr2txt.o: ../../h/or.h +adr2txt.o: ../../h/chan.h +adr2txt.o: ../../h/auth.h +adr2txt.o: ../../h/list_rchan.h +adr2txt.o: ../../h/tb_com.h +adr2txt.o: ../../h/tb_a.h +chan_acheck.o: chan_acheck.c +chan_acheck.o: ../../h/util.h +chan_acheck.o: ../../h/config.h +chan_acheck.o: ../../h/ll_log.h +chan_acheck.o: ../../h/adr.h +chan_acheck.o: ../../h/list_rchan.h +chan_acheck.o: ../../h/chan.h +chan_acheck.o: ../../h/table.h +chan_acheck.o: ../../h/list_bpt.h +chan_acheck.o: ../../h/auth.h +chan_acheck.o: ../../h/list_bpt.h +chan_acheck.o: ../../h/extension.h +chan_acheck.o: ../../h/mta.h +chan_acheck.o: ../../h/adr.h +chan_acheck.o: ../../h/list_bpt.h +chan_acheck.o: ../../h/aparse.h +chan_acheck.o: ../../h/ap.h +chan_acheck.o: ../../h/util.h +chan_acheck.o: ../../h/or.h +chan_acheck.o: ../../h/chan.h +chan_acheck.o: ../../h/auth.h +chan_acheck.o: ../../h/list_rchan.h +chan_acheck.o: ../../h/qmgr.h +chan_acheck.o: ../../h/Qmgr-types.h +chan_acheck.o: ../../h/Qmgr-ops.h +conf.o: conf.c +dchan_acheck.o: dchan_acheck.c +dchan_acheck.o: ../../h/util.h +dchan_acheck.o: ../../h/config.h +dchan_acheck.o: ../../h/ll_log.h +dchan_acheck.o: ../../h/adr.h +dchan_acheck.o: ../../h/list_rchan.h +dchan_acheck.o: ../../h/chan.h +dchan_acheck.o: ../../h/table.h +dchan_acheck.o: ../../h/list_bpt.h +dchan_acheck.o: ../../h/auth.h +dchan_acheck.o: ../../h/list_bpt.h +dchan_acheck.o: ../../h/extension.h +dchan_acheck.o: ../../h/mta.h +dchan_acheck.o: ../../h/adr.h +dchan_acheck.o: ../../h/list_bpt.h +dchan_acheck.o: ../../h/aparse.h +dchan_acheck.o: ../../h/ap.h +dchan_acheck.o: ../../h/util.h +dchan_acheck.o: ../../h/or.h +dchan_acheck.o: ../../h/chan.h +dchan_acheck.o: ../../h/auth.h +dchan_acheck.o: ../../h/list_rchan.h +dchan_acheck.o: ../../h/qmgr.h +dchan_acheck.o: ../../h/Qmgr-types.h +dchan_acheck.o: ../../h/Qmgr-ops.h +dr2txt.o: dr2txt.c +dr2txt.o: ../../h/util.h +dr2txt.o: ../../h/config.h +dr2txt.o: ../../h/ll_log.h +dr2txt.o: ../../h/dr.h +dr2txt.o: ../../h/extension.h +dr2txt.o: ../../h/mta.h +dr2txt.o: ../../h/adr.h +dr2txt.o: ../../h/list_rchan.h +dr2txt.o: ../../h/chan.h +dr2txt.o: ../../h/table.h +dr2txt.o: ../../h/list_bpt.h +dr2txt.o: ../../h/auth.h +dr2txt.o: ../../h/list_bpt.h +dr2txt.o: ../../h/extension.h +dr2txt.o: ../../h/mta.h +dr2txt.o: ../../h/aparse.h +dr2txt.o: ../../h/ap.h +dr2txt.o: ../../h/util.h +dr2txt.o: ../../h/or.h +dr2txt.o: ../../h/chan.h +dr2txt.o: ../../h/auth.h +dr2txt.o: ../../h/list_rchan.h +dr2txt.o: ../../h/list_bpt.h +dr2txt.o: ../../h/tb_dr.h +get_dr.o: get_dr.c +get_dr.o: ../../h/util.h +get_dr.o: ../../h/config.h +get_dr.o: ../../h/ll_log.h +get_dr.o: ../../h/adr.h +get_dr.o: ../../h/list_rchan.h +get_dr.o: ../../h/chan.h +get_dr.o: ../../h/table.h +get_dr.o: ../../h/list_bpt.h +get_dr.o: ../../h/auth.h +get_dr.o: ../../h/list_bpt.h +get_dr.o: ../../h/extension.h +get_dr.o: ../../h/mta.h +get_dr.o: ../../h/adr.h +get_dr.o: ../../h/list_bpt.h +get_dr.o: ../../h/aparse.h +get_dr.o: ../../h/ap.h +get_dr.o: ../../h/util.h +get_dr.o: ../../h/or.h +get_dr.o: ../../h/chan.h +get_dr.o: ../../h/auth.h +get_dr.o: ../../h/list_rchan.h +get_dr.o: ../../h/q.h +get_dr.o: ../../h/adr.h +get_dr.o: ../../h/mta.h +get_dr.o: ../../h/dr.h +get_dr.o: ../../h/extension.h +get_dr.o: ../../h/mta.h +get_dr.o: ../../h/retcode.h +lchan_acheck.o: lchan_acheck.c +lchan_acheck.o: ../../h/util.h +lchan_acheck.o: ../../h/config.h +lchan_acheck.o: ../../h/ll_log.h +lchan_acheck.o: ../../h/adr.h +lchan_acheck.o: ../../h/list_rchan.h +lchan_acheck.o: ../../h/chan.h +lchan_acheck.o: ../../h/table.h +lchan_acheck.o: ../../h/list_bpt.h +lchan_acheck.o: ../../h/auth.h +lchan_acheck.o: ../../h/list_bpt.h +lchan_acheck.o: ../../h/extension.h +lchan_acheck.o: ../../h/mta.h +lchan_acheck.o: ../../h/adr.h +lchan_acheck.o: ../../h/list_bpt.h +lchan_acheck.o: ../../h/aparse.h +lchan_acheck.o: ../../h/ap.h +lchan_acheck.o: ../../h/util.h +lchan_acheck.o: ../../h/or.h +lchan_acheck.o: ../../h/chan.h +lchan_acheck.o: ../../h/auth.h +lchan_acheck.o: ../../h/list_rchan.h +lchan_acheck.o: ../../h/qmgr.h +lchan_acheck.o: ../../h/Qmgr-types.h +lchan_acheck.o: ../../h/Qmgr-ops.h +list_bpt.o: list_bpt.c +list_bpt.o: ../../h/util.h +list_bpt.o: ../../h/config.h +list_bpt.o: ../../h/ll_log.h +list_bpt.o: ../../h/list_bpt.h +list_rchan.o: list_rchan.c +list_rchan.o: ../../h/util.h +list_rchan.o: ../../h/config.h +list_rchan.o: ../../h/ll_log.h +list_rchan.o: ../../h/list_rchan.h +list_rchan.o: ../../h/chan.h +list_rchan.o: ../../h/table.h +list_rchan.o: ../../h/list_bpt.h +list_rchan.o: ../../h/auth.h +list_rchan.o: ../../h/list_bpt.h +mta2txt.o: mta2txt.c +mta2txt.o: ../../h/util.h +mta2txt.o: ../../h/config.h +mta2txt.o: ../../h/ll_log.h +mta2txt.o: ../../h/mta.h +mta2txt.o: ../../h/adr.h +mta2txt.o: ../../h/list_rchan.h +mta2txt.o: ../../h/chan.h +mta2txt.o: ../../h/table.h +mta2txt.o: ../../h/list_bpt.h +mta2txt.o: ../../h/auth.h +mta2txt.o: ../../h/list_bpt.h +mta2txt.o: ../../h/extension.h +mta2txt.o: ../../h/mta.h +mta2txt.o: ../../h/aparse.h +mta2txt.o: ../../h/ap.h +mta2txt.o: ../../h/util.h +mta2txt.o: ../../h/or.h +mta2txt.o: ../../h/chan.h +mta2txt.o: ../../h/auth.h +mta2txt.o: ../../h/list_rchan.h +mta2txt.o: ../../h/list_bpt.h +mta2txt.o: ../../h/tb_com.h +mta2txt.o: ../../h/tb_a.h +mta2txt.o: ../../h/tb_p1.h +p32txt.o: p32txt.c +p32txt.o: ../../h/util.h +p32txt.o: ../../h/config.h +p32txt.o: ../../h/ll_log.h +p32txt.o: ../../h/q.h +p32txt.o: ../../h/adr.h +p32txt.o: ../../h/list_rchan.h +p32txt.o: ../../h/chan.h +p32txt.o: ../../h/table.h +p32txt.o: ../../h/list_bpt.h +p32txt.o: ../../h/auth.h +p32txt.o: ../../h/list_bpt.h +p32txt.o: ../../h/extension.h +p32txt.o: ../../h/mta.h +p32txt.o: ../../h/adr.h +p32txt.o: ../../h/list_bpt.h +p32txt.o: ../../h/aparse.h +p32txt.o: ../../h/ap.h +p32txt.o: ../../h/util.h +p32txt.o: ../../h/or.h +p32txt.o: ../../h/chan.h +p32txt.o: ../../h/auth.h +p32txt.o: ../../h/list_rchan.h +p32txt.o: ../../h/mta.h +p32txt.o: ../../h/tb_p3prm.h +pps_mail.o: pps_mail.c +pps_mail.o: ../../h/head.h +pps_mail.o: ../../h/util.h +pps_mail.o: ../../h/config.h +pps_mail.o: ../../h/ll_log.h +pps_mail.o: ../../h/retcode.h +pps_mail.o: ../../h/prm.h +pps_mail.o: ../../h/q.h +pps_mail.o: ../../h/adr.h +pps_mail.o: ../../h/list_rchan.h +pps_mail.o: ../../h/chan.h +pps_mail.o: ../../h/table.h +pps_mail.o: ../../h/list_bpt.h +pps_mail.o: ../../h/auth.h +pps_mail.o: ../../h/list_bpt.h +pps_mail.o: ../../h/extension.h +pps_mail.o: ../../h/mta.h +pps_mail.o: ../../h/adr.h +pps_mail.o: ../../h/list_bpt.h +pps_mail.o: ../../h/aparse.h +pps_mail.o: ../../h/ap.h +pps_mail.o: ../../h/util.h +pps_mail.o: ../../h/or.h +pps_mail.o: ../../h/chan.h +pps_mail.o: ../../h/auth.h +pps_mail.o: ../../h/list_rchan.h +pps_mail.o: ../../h/mta.h +pps_mail.o: ../../h/adr.h +prm2txt.o: prm2txt.c +prm2txt.o: ../../h/util.h +prm2txt.o: ../../h/config.h +prm2txt.o: ../../h/ll_log.h +prm2txt.o: ../../h/prm.h +prm2txt.o: ../../h/tb_prm.h +q2txt.o: q2txt.c +q2txt.o: ../../h/util.h +q2txt.o: ../../h/config.h +q2txt.o: ../../h/ll_log.h +q2txt.o: ../../h/q.h +q2txt.o: ../../h/adr.h +q2txt.o: ../../h/list_rchan.h +q2txt.o: ../../h/chan.h +q2txt.o: ../../h/table.h +q2txt.o: ../../h/list_bpt.h +q2txt.o: ../../h/auth.h +q2txt.o: ../../h/list_bpt.h +q2txt.o: ../../h/extension.h +q2txt.o: ../../h/mta.h +q2txt.o: ../../h/adr.h +q2txt.o: ../../h/list_bpt.h +q2txt.o: ../../h/aparse.h +q2txt.o: ../../h/ap.h +q2txt.o: ../../h/util.h +q2txt.o: ../../h/or.h +q2txt.o: ../../h/chan.h +q2txt.o: ../../h/auth.h +q2txt.o: ../../h/list_rchan.h +q2txt.o: ../../h/mta.h +q2txt.o: ../../h/tb_com.h +q2txt.o: ../../h/tb_q.h +q2txt.o: ../../h/mta.h +set_1dr.o: set_1dr.c +set_1dr.o: ../../h/util.h +set_1dr.o: ../../h/config.h +set_1dr.o: ../../h/ll_log.h +set_1dr.o: ../../h/adr.h +set_1dr.o: ../../h/list_rchan.h +set_1dr.o: ../../h/chan.h +set_1dr.o: ../../h/table.h +set_1dr.o: ../../h/list_bpt.h +set_1dr.o: ../../h/auth.h +set_1dr.o: ../../h/list_bpt.h +set_1dr.o: ../../h/extension.h +set_1dr.o: ../../h/mta.h +set_1dr.o: ../../h/adr.h +set_1dr.o: ../../h/list_bpt.h +set_1dr.o: ../../h/aparse.h +set_1dr.o: ../../h/ap.h +set_1dr.o: ../../h/util.h +set_1dr.o: ../../h/or.h +set_1dr.o: ../../h/chan.h +set_1dr.o: ../../h/auth.h +set_1dr.o: ../../h/list_rchan.h +set_1dr.o: ../../h/q.h +set_1dr.o: ../../h/adr.h +set_1dr.o: ../../h/mta.h +set_1dr.o: ../../h/dr.h +set_1dr.o: ../../h/extension.h +set_1dr.o: ../../h/mta.h +set_1dr.o: ../../h/retcode.h +static.o: static.c +static.o: ../../h/util.h +static.o: ../../h/config.h +static.o: ../../h/ll_log.h +static.o: ../../h/chan.h +static.o: ../../h/table.h +static.o: ../../h/list_bpt.h +static.o: ../../h/list_bpt.h +tb_a.o: tb_a.c +tb_a.o: ../../h/util.h +tb_a.o: ../../h/config.h +tb_a.o: ../../h/ll_log.h +tb_a.o: ../../h/tb_a.h +tb_a.o: ../../h/adr.h +tb_a.o: ../../h/list_rchan.h +tb_a.o: ../../h/chan.h +tb_a.o: ../../h/table.h +tb_a.o: ../../h/list_bpt.h +tb_a.o: ../../h/auth.h +tb_a.o: ../../h/list_bpt.h +tb_a.o: ../../h/extension.h +tb_a.o: ../../h/mta.h +tb_a.o: ../../h/adr.h +tb_a.o: ../../h/list_bpt.h +tb_a.o: ../../h/aparse.h +tb_a.o: ../../h/ap.h +tb_a.o: ../../h/util.h +tb_a.o: ../../h/or.h +tb_a.o: ../../h/chan.h +tb_a.o: ../../h/auth.h +tb_a.o: ../../h/list_rchan.h +tb_bpt84.o: tb_bpt84.c +tb_bpt84.o: ../../h/tb_bpt84.h +tb_bpt88.o: tb_bpt88.c +tb_bpt88.o: ../../h/tb_bpt88.h +tb_dr.o: tb_dr.c +tb_dr.o: ../../h/util.h +tb_dr.o: ../../h/config.h +tb_dr.o: ../../h/ll_log.h +tb_dr.o: ../../h/dr.h +tb_dr.o: ../../h/extension.h +tb_dr.o: ../../h/mta.h +tb_dr.o: ../../h/adr.h +tb_dr.o: ../../h/list_rchan.h +tb_dr.o: ../../h/chan.h +tb_dr.o: ../../h/table.h +tb_dr.o: ../../h/list_bpt.h +tb_dr.o: ../../h/auth.h +tb_dr.o: ../../h/list_bpt.h +tb_dr.o: ../../h/extension.h +tb_dr.o: ../../h/mta.h +tb_dr.o: ../../h/aparse.h +tb_dr.o: ../../h/ap.h +tb_dr.o: ../../h/util.h +tb_dr.o: ../../h/or.h +tb_dr.o: ../../h/chan.h +tb_dr.o: ../../h/auth.h +tb_dr.o: ../../h/list_rchan.h +tb_dr.o: ../../h/list_bpt.h +tb_dr.o: ../../h/tb_com.h +tb_dr.o: ../../h/tb_dr.h +tb_misc.o: tb_misc.c +tb_misc.o: ../../h/util.h +tb_misc.o: ../../h/config.h +tb_misc.o: ../../h/ll_log.h +tb_p1.o: tb_p1.c +tb_p1.o: ../../h/util.h +tb_p1.o: ../../h/config.h +tb_p1.o: ../../h/ll_log.h +tb_p1.o: ../../h/adr.h +tb_p1.o: ../../h/list_rchan.h +tb_p1.o: ../../h/chan.h +tb_p1.o: ../../h/table.h +tb_p1.o: ../../h/list_bpt.h +tb_p1.o: ../../h/auth.h +tb_p1.o: ../../h/list_bpt.h +tb_p1.o: ../../h/extension.h +tb_p1.o: ../../h/mta.h +tb_p1.o: ../../h/adr.h +tb_p1.o: ../../h/list_bpt.h +tb_p1.o: ../../h/aparse.h +tb_p1.o: ../../h/ap.h +tb_p1.o: ../../h/util.h +tb_p1.o: ../../h/or.h +tb_p1.o: ../../h/chan.h +tb_p1.o: ../../h/auth.h +tb_p1.o: ../../h/list_rchan.h +tb_p1.o: ../../h/tb_com.h +tb_p1.o: ../../h/tb_p1.h +tb_p1.o: ../../h/extension.h +tb_p3prm.o: tb_p3prm.c +tb_p3prm.o: ../../h/util.h +tb_p3prm.o: ../../h/config.h +tb_p3prm.o: ../../h/ll_log.h +tb_p3prm.o: ../../h/tb_p3prm.h +tb_prm.o: tb_prm.c +tb_prm.o: ../../h/util.h +tb_prm.o: ../../h/config.h +tb_prm.o: ../../h/ll_log.h +tb_prm.o: ../../h/tb_prm.h +tb_prm.o: ../../h/prm.h +tb_q.o: tb_q.c +tb_q.o: ../../h/util.h +tb_q.o: ../../h/config.h +tb_q.o: ../../h/ll_log.h +tb_q.o: ../../h/q.h +tb_q.o: ../../h/adr.h +tb_q.o: ../../h/list_rchan.h +tb_q.o: ../../h/chan.h +tb_q.o: ../../h/table.h +tb_q.o: ../../h/list_bpt.h +tb_q.o: ../../h/auth.h +tb_q.o: ../../h/list_bpt.h +tb_q.o: ../../h/extension.h +tb_q.o: ../../h/mta.h +tb_q.o: ../../h/adr.h +tb_q.o: ../../h/list_bpt.h +tb_q.o: ../../h/aparse.h +tb_q.o: ../../h/ap.h +tb_q.o: ../../h/util.h +tb_q.o: ../../h/or.h +tb_q.o: ../../h/chan.h +tb_q.o: ../../h/auth.h +tb_q.o: ../../h/list_rchan.h +tb_q.o: ../../h/mta.h +tb_q.o: ../../h/tb_q.h +txt2adr.o: txt2adr.c +txt2adr.o: ../../h/util.h +txt2adr.o: ../../h/config.h +txt2adr.o: ../../h/ll_log.h +txt2adr.o: ../../h/adr.h +txt2adr.o: ../../h/list_rchan.h +txt2adr.o: ../../h/chan.h +txt2adr.o: ../../h/table.h +txt2adr.o: ../../h/list_bpt.h +txt2adr.o: ../../h/auth.h +txt2adr.o: ../../h/list_bpt.h +txt2adr.o: ../../h/extension.h +txt2adr.o: ../../h/mta.h +txt2adr.o: ../../h/adr.h +txt2adr.o: ../../h/list_bpt.h +txt2adr.o: ../../h/aparse.h +txt2adr.o: ../../h/ap.h +txt2adr.o: ../../h/util.h +txt2adr.o: ../../h/or.h +txt2adr.o: ../../h/chan.h +txt2adr.o: ../../h/auth.h +txt2adr.o: ../../h/list_rchan.h +txt2adr.o: ../../h/tb_com.h +txt2adr.o: ../../h/tb_a.h +txt2adr.o: ../../h/list_bpt.h +txt2adr.o: ../../h/list_rchan.h +txt2dr.o: txt2dr.c +txt2dr.o: ../../h/util.h +txt2dr.o: ../../h/config.h +txt2dr.o: ../../h/ll_log.h +txt2dr.o: ../../h/dr.h +txt2dr.o: ../../h/extension.h +txt2dr.o: ../../h/mta.h +txt2dr.o: ../../h/adr.h +txt2dr.o: ../../h/list_rchan.h +txt2dr.o: ../../h/chan.h +txt2dr.o: ../../h/table.h +txt2dr.o: ../../h/list_bpt.h +txt2dr.o: ../../h/auth.h +txt2dr.o: ../../h/list_bpt.h +txt2dr.o: ../../h/extension.h +txt2dr.o: ../../h/mta.h +txt2dr.o: ../../h/aparse.h +txt2dr.o: ../../h/ap.h +txt2dr.o: ../../h/util.h +txt2dr.o: ../../h/or.h +txt2dr.o: ../../h/chan.h +txt2dr.o: ../../h/auth.h +txt2dr.o: ../../h/list_rchan.h +txt2dr.o: ../../h/list_bpt.h +txt2dr.o: ../../h/tb_dr.h +txt2dr.o: ../../h/retcode.h +txt2mta.o: txt2mta.c +txt2mta.o: ../../h/util.h +txt2mta.o: ../../h/config.h +txt2mta.o: ../../h/ll_log.h +txt2mta.o: ../../h/mta.h +txt2mta.o: ../../h/adr.h +txt2mta.o: ../../h/list_rchan.h +txt2mta.o: ../../h/chan.h +txt2mta.o: ../../h/table.h +txt2mta.o: ../../h/list_bpt.h +txt2mta.o: ../../h/auth.h +txt2mta.o: ../../h/list_bpt.h +txt2mta.o: ../../h/extension.h +txt2mta.o: ../../h/mta.h +txt2mta.o: ../../h/aparse.h +txt2mta.o: ../../h/ap.h +txt2mta.o: ../../h/util.h +txt2mta.o: ../../h/or.h +txt2mta.o: ../../h/chan.h +txt2mta.o: ../../h/auth.h +txt2mta.o: ../../h/list_rchan.h +txt2mta.o: ../../h/list_bpt.h +txt2mta.o: ../../h/tb_com.h +txt2mta.o: ../../h/tb_p1.h +txt2mta.o: ../../h/tb_a.h +txt2p3.o: txt2p3.c +txt2p3.o: ../../h/util.h +txt2p3.o: ../../h/config.h +txt2p3.o: ../../h/ll_log.h +txt2p3.o: ../../h/mta.h +txt2p3.o: ../../h/adr.h +txt2p3.o: ../../h/list_rchan.h +txt2p3.o: ../../h/chan.h +txt2p3.o: ../../h/table.h +txt2p3.o: ../../h/list_bpt.h +txt2p3.o: ../../h/auth.h +txt2p3.o: ../../h/list_bpt.h +txt2p3.o: ../../h/extension.h +txt2p3.o: ../../h/mta.h +txt2p3.o: ../../h/aparse.h +txt2p3.o: ../../h/ap.h +txt2p3.o: ../../h/util.h +txt2p3.o: ../../h/or.h +txt2p3.o: ../../h/chan.h +txt2p3.o: ../../h/auth.h +txt2p3.o: ../../h/list_rchan.h +txt2p3.o: ../../h/list_bpt.h +txt2p3.o: ../../h/tb_p3prm.h +txt2prm.o: txt2prm.c +txt2prm.o: ../../h/util.h +txt2prm.o: ../../h/config.h +txt2prm.o: ../../h/ll_log.h +txt2prm.o: ../../h/prm.h +txt2prm.o: ../../h/tb_com.h +txt2prm.o: ../../h/tb_prm.h +txt2q.o: txt2q.c +txt2q.o: ../../h/util.h +txt2q.o: ../../h/config.h +txt2q.o: ../../h/ll_log.h +txt2q.o: ../../h/q.h +txt2q.o: ../../h/adr.h +txt2q.o: ../../h/list_rchan.h +txt2q.o: ../../h/chan.h +txt2q.o: ../../h/table.h +txt2q.o: ../../h/list_bpt.h +txt2q.o: ../../h/auth.h +txt2q.o: ../../h/list_bpt.h +txt2q.o: ../../h/extension.h +txt2q.o: ../../h/mta.h +txt2q.o: ../../h/adr.h +txt2q.o: ../../h/list_bpt.h +txt2q.o: ../../h/aparse.h +txt2q.o: ../../h/ap.h +txt2q.o: ../../h/util.h +txt2q.o: ../../h/or.h +txt2q.o: ../../h/chan.h +txt2q.o: ../../h/auth.h +txt2q.o: ../../h/list_rchan.h +txt2q.o: ../../h/mta.h +txt2q.o: ../../h/tb_com.h +txt2q.o: ../../h/tb_q.h +txt2q.o: ../../h/mta.h +ut_a.o: ut_a.c +ut_a.o: ../../h/head.h +ut_a.o: ../../h/util.h +ut_a.o: ../../h/config.h +ut_a.o: ../../h/ll_log.h +ut_a.o: ../../h/retcode.h +ut_a.o: ../../h/adr.h +ut_a.o: ../../h/list_rchan.h +ut_a.o: ../../h/chan.h +ut_a.o: ../../h/table.h +ut_a.o: ../../h/list_bpt.h +ut_a.o: ../../h/auth.h +ut_a.o: ../../h/list_bpt.h +ut_a.o: ../../h/extension.h +ut_a.o: ../../h/mta.h +ut_a.o: ../../h/adr.h +ut_a.o: ../../h/list_bpt.h +ut_a.o: ../../h/aparse.h +ut_a.o: ../../h/ap.h +ut_a.o: ../../h/util.h +ut_a.o: ../../h/or.h +ut_a.o: ../../h/chan.h +ut_a.o: ../../h/auth.h +ut_a.o: ../../h/list_rchan.h +ut_a.o: ../../h/dr.h +ut_a.o: ../../h/extension.h +ut_a.o: ../../h/mta.h +ut_com.o: ut_com.c +ut_com.o: ../../h/util.h +ut_com.o: ../../h/config.h +ut_com.o: ../../h/ll_log.h +ut_dlh.o: ut_dlh.c +ut_dlh.o: ../../h/util.h +ut_dlh.o: ../../h/config.h +ut_dlh.o: ../../h/ll_log.h +ut_dlh.o: ../../h/mta.h +ut_dlh.o: ../../h/adr.h +ut_dlh.o: ../../h/list_rchan.h +ut_dlh.o: ../../h/chan.h +ut_dlh.o: ../../h/table.h +ut_dlh.o: ../../h/list_bpt.h +ut_dlh.o: ../../h/auth.h +ut_dlh.o: ../../h/list_bpt.h +ut_dlh.o: ../../h/extension.h +ut_dlh.o: ../../h/mta.h +ut_dlh.o: ../../h/aparse.h +ut_dlh.o: ../../h/ap.h +ut_dlh.o: ../../h/util.h +ut_dlh.o: ../../h/or.h +ut_dlh.o: ../../h/chan.h +ut_dlh.o: ../../h/auth.h +ut_dlh.o: ../../h/list_rchan.h +ut_dlh.o: ../../h/list_bpt.h +ut_dr.o: ut_dr.c +ut_dr.o: ../../h/util.h +ut_dr.o: ../../h/config.h +ut_dr.o: ../../h/ll_log.h +ut_dr.o: ../../h/dr.h +ut_dr.o: ../../h/extension.h +ut_dr.o: ../../h/mta.h +ut_dr.o: ../../h/adr.h +ut_dr.o: ../../h/list_rchan.h +ut_dr.o: ../../h/chan.h +ut_dr.o: ../../h/table.h +ut_dr.o: ../../h/list_bpt.h +ut_dr.o: ../../h/auth.h +ut_dr.o: ../../h/list_bpt.h +ut_dr.o: ../../h/extension.h +ut_dr.o: ../../h/mta.h +ut_dr.o: ../../h/aparse.h +ut_dr.o: ../../h/ap.h +ut_dr.o: ../../h/util.h +ut_dr.o: ../../h/or.h +ut_dr.o: ../../h/chan.h +ut_dr.o: ../../h/auth.h +ut_dr.o: ../../h/list_rchan.h +ut_dr.o: ../../h/list_bpt.h +ut_fn.o: ut_fn.c +ut_fn.o: ../../h/util.h +ut_fn.o: ../../h/config.h +ut_fn.o: ../../h/ll_log.h +ut_fn.o: ../../h/mta.h +ut_fn.o: ../../h/adr.h +ut_fn.o: ../../h/list_rchan.h +ut_fn.o: ../../h/chan.h +ut_fn.o: ../../h/table.h +ut_fn.o: ../../h/list_bpt.h +ut_fn.o: ../../h/auth.h +ut_fn.o: ../../h/list_bpt.h +ut_fn.o: ../../h/extension.h +ut_fn.o: ../../h/mta.h +ut_fn.o: ../../h/aparse.h +ut_fn.o: ../../h/ap.h +ut_fn.o: ../../h/util.h +ut_fn.o: ../../h/or.h +ut_fn.o: ../../h/chan.h +ut_fn.o: ../../h/auth.h +ut_fn.o: ../../h/list_rchan.h +ut_fn.o: ../../h/list_bpt.h +ut_free.o: ut_free.c +ut_free.o: ../../h/util.h +ut_free.o: ../../h/config.h +ut_free.o: ../../h/ll_log.h +ut_free.o: ../../h/mta.h +ut_free.o: ../../h/adr.h +ut_free.o: ../../h/list_rchan.h +ut_free.o: ../../h/chan.h +ut_free.o: ../../h/table.h +ut_free.o: ../../h/list_bpt.h +ut_free.o: ../../h/auth.h +ut_free.o: ../../h/list_bpt.h +ut_free.o: ../../h/extension.h +ut_free.o: ../../h/mta.h +ut_free.o: ../../h/aparse.h +ut_free.o: ../../h/ap.h +ut_free.o: ../../h/util.h +ut_free.o: ../../h/or.h +ut_free.o: ../../h/chan.h +ut_free.o: ../../h/auth.h +ut_free.o: ../../h/list_rchan.h +ut_free.o: ../../h/list_bpt.h +ut_gldm.o: ut_gldm.c +ut_gldm.o: ../../h/util.h +ut_gldm.o: ../../h/config.h +ut_gldm.o: ../../h/ll_log.h +ut_gldm.o: ../../h/mta.h +ut_gldm.o: ../../h/adr.h +ut_gldm.o: ../../h/list_rchan.h +ut_gldm.o: ../../h/chan.h +ut_gldm.o: ../../h/table.h +ut_gldm.o: ../../h/list_bpt.h +ut_gldm.o: ../../h/auth.h +ut_gldm.o: ../../h/list_bpt.h +ut_gldm.o: ../../h/extension.h +ut_gldm.o: ../../h/mta.h +ut_gldm.o: ../../h/aparse.h +ut_gldm.o: ../../h/ap.h +ut_gldm.o: ../../h/util.h +ut_gldm.o: ../../h/or.h +ut_gldm.o: ../../h/chan.h +ut_gldm.o: ../../h/auth.h +ut_gldm.o: ../../h/list_rchan.h +ut_gldm.o: ../../h/list_bpt.h +ut_gldm.o: ../../h/or.h +ut_mm2p1.o: ut_mm2p1.c +ut_mm2p1.o: ../../h/util.h +ut_mm2p1.o: ../../h/config.h +ut_mm2p1.o: ../../h/ll_log.h +ut_mpduid.o: ut_mpduid.c +ut_mpduid.o: ../../h/util.h +ut_mpduid.o: ../../h/config.h +ut_mpduid.o: ../../h/ll_log.h +ut_mpduid.o: ../../h/mta.h +ut_mpduid.o: ../../h/adr.h +ut_mpduid.o: ../../h/list_rchan.h +ut_mpduid.o: ../../h/chan.h +ut_mpduid.o: ../../h/table.h +ut_mpduid.o: ../../h/list_bpt.h +ut_mpduid.o: ../../h/auth.h +ut_mpduid.o: ../../h/list_bpt.h +ut_mpduid.o: ../../h/extension.h +ut_mpduid.o: ../../h/mta.h +ut_mpduid.o: ../../h/aparse.h +ut_mpduid.o: ../../h/ap.h +ut_mpduid.o: ../../h/util.h +ut_mpduid.o: ../../h/or.h +ut_mpduid.o: ../../h/chan.h +ut_mpduid.o: ../../h/auth.h +ut_mpduid.o: ../../h/list_rchan.h +ut_mpduid.o: ../../h/list_bpt.h +ut_msg.o: ut_msg.c +ut_msg.o: ../../h/head.h +ut_msg.o: ../../h/util.h +ut_msg.o: ../../h/config.h +ut_msg.o: ../../h/ll_log.h +ut_msg.o: ../../h/retcode.h +ut_p12mm.o: ut_p12mm.c +ut_p12mm.o: ../../h/util.h +ut_p12mm.o: ../../h/config.h +ut_p12mm.o: ../../h/ll_log.h +ut_p1_st.o: ut_p1_st.c +ut_p1_st.o: ../../h/util.h +ut_p1_st.o: ../../h/config.h +ut_p1_st.o: ../../h/ll_log.h +ut_p1_st.o: ../../h/mta.h +ut_p1_st.o: ../../h/adr.h +ut_p1_st.o: ../../h/list_rchan.h +ut_p1_st.o: ../../h/chan.h +ut_p1_st.o: ../../h/table.h +ut_p1_st.o: ../../h/list_bpt.h +ut_p1_st.o: ../../h/auth.h +ut_p1_st.o: ../../h/list_bpt.h +ut_p1_st.o: ../../h/extension.h +ut_p1_st.o: ../../h/mta.h +ut_p1_st.o: ../../h/aparse.h +ut_p1_st.o: ../../h/ap.h +ut_p1_st.o: ../../h/util.h +ut_p1_st.o: ../../h/or.h +ut_p1_st.o: ../../h/chan.h +ut_p1_st.o: ../../h/auth.h +ut_p1_st.o: ../../h/list_rchan.h +ut_p1_st.o: ../../h/list_bpt.h +ut_prm.o: ut_prm.c +ut_prm.o: ../../h/util.h +ut_prm.o: ../../h/config.h +ut_prm.o: ../../h/ll_log.h +ut_prm.o: ../../h/prm.h +ut_q.o: ut_q.c +ut_q.o: ../../h/util.h +ut_q.o: ../../h/config.h +ut_q.o: ../../h/ll_log.h +ut_q.o: ../../h/q.h +ut_q.o: ../../h/adr.h +ut_q.o: ../../h/list_rchan.h +ut_q.o: ../../h/chan.h +ut_q.o: ../../h/table.h +ut_q.o: ../../h/list_bpt.h +ut_q.o: ../../h/auth.h +ut_q.o: ../../h/list_bpt.h +ut_q.o: ../../h/extension.h +ut_q.o: ../../h/mta.h +ut_q.o: ../../h/adr.h +ut_q.o: ../../h/list_bpt.h +ut_q.o: ../../h/aparse.h +ut_q.o: ../../h/ap.h +ut_q.o: ../../h/util.h +ut_q.o: ../../h/or.h +ut_q.o: ../../h/chan.h +ut_q.o: ../../h/auth.h +ut_q.o: ../../h/list_rchan.h +ut_q.o: ../../h/mta.h +ut_qid.o: ut_qid.c +ut_qid.o: ../../h/util.h +ut_qid.o: ../../h/config.h +ut_qid.o: ../../h/ll_log.h +ut_qid.o: ../../h/adr.h +ut_qid.o: ../../h/list_rchan.h +ut_qid.o: ../../h/chan.h +ut_qid.o: ../../h/table.h +ut_qid.o: ../../h/list_bpt.h +ut_qid.o: ../../h/auth.h +ut_qid.o: ../../h/list_bpt.h +ut_qid.o: ../../h/extension.h +ut_qid.o: ../../h/mta.h +ut_qid.o: ../../h/adr.h +ut_qid.o: ../../h/list_bpt.h +ut_qid.o: ../../h/aparse.h +ut_qid.o: ../../h/ap.h +ut_qid.o: ../../h/util.h +ut_qid.o: ../../h/or.h +ut_qid.o: ../../h/chan.h +ut_qid.o: ../../h/auth.h +ut_qid.o: ../../h/list_rchan.h +ut_trace.o: ut_trace.c +ut_trace.o: ../../h/util.h +ut_trace.o: ../../h/config.h +ut_trace.o: ../../h/ll_log.h +ut_trace.o: ../../h/mta.h +ut_trace.o: ../../h/adr.h +ut_trace.o: ../../h/list_rchan.h +ut_trace.o: ../../h/chan.h +ut_trace.o: ../../h/table.h +ut_trace.o: ../../h/list_bpt.h +ut_trace.o: ../../h/auth.h +ut_trace.o: ../../h/list_bpt.h +ut_trace.o: ../../h/extension.h +ut_trace.o: ../../h/mta.h +ut_trace.o: ../../h/aparse.h +ut_trace.o: ../../h/ap.h +ut_trace.o: ../../h/util.h +ut_trace.o: ../../h/or.h +ut_trace.o: ../../h/chan.h +ut_trace.o: ../../h/auth.h +ut_trace.o: ../../h/list_rchan.h +ut_trace.o: ../../h/list_bpt.h +wr_stat.o: wr_stat.c +wr_stat.o: ../../h/util.h +wr_stat.o: ../../h/config.h +wr_stat.o: ../../h/ll_log.h +wr_stat.o: ../../h/q.h +wr_stat.o: ../../h/adr.h +wr_stat.o: ../../h/list_rchan.h +wr_stat.o: ../../h/chan.h +wr_stat.o: ../../h/table.h +wr_stat.o: ../../h/list_bpt.h +wr_stat.o: ../../h/auth.h +wr_stat.o: ../../h/list_bpt.h +wr_stat.o: ../../h/extension.h +wr_stat.o: ../../h/mta.h +wr_stat.o: ../../h/adr.h +wr_stat.o: ../../h/list_bpt.h +wr_stat.o: ../../h/aparse.h +wr_stat.o: ../../h/ap.h +wr_stat.o: ../../h/util.h +wr_stat.o: ../../h/or.h +wr_stat.o: ../../h/chan.h +wr_stat.o: ../../h/auth.h +wr_stat.o: ../../h/list_rchan.h +wr_stat.o: ../../h/mta.h +ut_aparse.o: ut_aparse.c +ut_aparse.o: ../../h/aparse.h +ut_aparse.o: ../../h/ap.h +ut_aparse.o: ../../h/util.h +ut_aparse.o: ../../h/config.h +ut_aparse.o: ../../h/ll_log.h +ut_aparse.o: ../../h/or.h +ut_aparse.o: ../../h/chan.h +ut_aparse.o: ../../h/table.h +ut_aparse.o: ../../h/list_bpt.h +ut_aparse.o: ../../h/auth.h +ut_aparse.o: ../../h/list_bpt.h +ut_aparse.o: ../../h/list_rchan.h +ut_aparse.o: ../../h/chan.h +ut_aparse.o: ../../h/auth.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/pp/adr2txt.c b/Lib/pp/adr2txt.c new file mode 100644 index 0000000..1fe21d5 --- /dev/null +++ b/Lib/pp/adr2txt.c @@ -0,0 +1,618 @@ +/* adr2txt.c: converts address structures to text */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/adr2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/adr2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: adr2txt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "adr.h" +#include "tb_com.h" +#include "tb_a.h" + +#define crit2txt(n) rcmd_srch ((n), tbl_crit) + +extern int argv2fp(); +extern int arg2vstr(); +extern void genreset(); +extern void repreq2txt(); +extern char *qb2hex(); +extern char *time2txt(); + +extern CMD_TABLE + tbl_bool [], + tbl_crit [], + tbl_redir [], + atbl_reg_mail [], + atbl_pd_modes [], + atbl_rdm [], + atbl_ctrl_addrs [/* Env-ctrl-addresses */], + atbl_addr [/* address-lines */], + atbl_status [/* recipient-status */], + atbl_mtarreq [/* mta-report-request */], + atbl_usrreq [/* user-report-request */], + atbl_expconversion [/* explicit-conversion */], + atbl_types [/* address-type */], + atbl_subtypes [/* address-subtype */]; + +static char *A_extension(), *A_req_del(), *A_modes2txt(), *A_redir2txt(); + +static char *A_put(), + *A_chanlist2txt(), + *A_outchan2txt(), + *A_outhost2txt(), + *A_no2txt(), + *A_stat2txt(), + *A_adrtype2txt(), + *A_aext (), + *A_adrsubtype2txt(); + +static int A_adrln2txt(); +char *no2txt3(); + + + + +int adr2txt (fp, ap, type) /* Env-ctrl-addresses -> Txt */ +FILE *fp; +ADDR *ap; +int type; +{ + char *argv[200]; + char sbuf[8*BUFSIZ]; + + PP_DBG (("Lib/pp/adr2txt (%d)", type)); + + switch (type) { + case AD_ORIGINATOR: + case AD_RECIPIENT: + argv[0] = rcmd_srch (type, atbl_ctrl_addrs); + if (A_adrln2txt (sbuf, argv, 1, ap) == NOTOK) + return NOTOK; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + return (ferror (fp) ? NOTOK : OK); + } + return (NOTOK); +} + +static int A_adrln2txt (sbuf, argv, argc, adr) /* Address Line -> Txt */ +char *sbuf; +char **argv; +int argc; +ADDR *adr; +{ + extern char *listbpt2txt(); + Redirection *rp; + char *cp; + char buf[8*BUFSIZ], + *lnptr = sbuf; + X400_Extension *ext; + + + genreset(); + + PP_DBG (("Lib/pp/A_adrln2txt (%s)", argv[0])); + + *lnptr = 0; + lnptr = A_put (lnptr, AD_STATUS, A_stat2txt (adr->ad_status), + argv, &argc); + + lnptr = A_put (lnptr, AD_REFORM_DONE, no2txt3 (adr->ad_rcnt, buf), + argv, &argc); + + lnptr = A_put (lnptr, AD_RECIP_NO, A_no2txt (adr->ad_no, buf), + argv, &argc); + + if (adr -> ad_fmtchan) + lnptr = A_chanlist2txt (lnptr, AD_REFORM_LIST, adr->ad_fmtchan, + argv, &argc); + + lnptr = A_outchan2txt (lnptr, AD_OUTCHAN, adr->ad_outchan, argv, + &argc); + + lnptr = A_outhost2txt (lnptr, AD_OUTHOST, adr->ad_outchan, argv, + &argc); + + lnptr = A_put (lnptr, AD_EXTENSION_ID, + A_no2txt (adr->ad_extension, buf), + argv, &argc); + + repreq2txt (adr->ad_resp, adr->ad_mtarreq, + adr->ad_usrreq, argv, &argc); + + if (adr -> ad_explicitconversion != AD_EXP_NONE) + lnptr = A_put (lnptr, + AD_EXPLICITCONVERSION, + rcmd_srch (adr->ad_explicitconversion, + atbl_expconversion), + argv, &argc); + + lnptr = A_put (lnptr, + AD_ADDTYPE, A_adrtype2txt (adr->ad_type), argv, + &argc); + + if (adr -> ad_subtype != AD_NOSUBTYPE) + lnptr = A_put (lnptr, + AD_SUBTYPE, A_adrsubtype2txt (adr->ad_subtype), + argv, &argc); + + if (adr->ad_eit) + lnptr = A_put (lnptr, AD_EITS, listbpt2txt (adr->ad_eit, buf), + argv, &argc); + if (adr->ad_content) + lnptr = A_put (lnptr, AD_CONTENT, adr->ad_content, + argv, &argc); + + + if (adr -> ad_dn) + lnptr = A_put (lnptr, AD_DN, adr -> ad_dn, argv, &argc); + + if (adr -> ad_orig_req_alt) + lnptr = A_put (lnptr, AD_ORIG_REQ_ALT, adr -> ad_orig_req_alt, + argv, &argc); + +#define docritical(x, n) if (x) \ + lnptr = A_put (lnptr, (n), crit2txt ((x)), \ + argv, &argc) + + docritical (adr -> ad_orig_req_alt_crit, AD_ORIG_REQ_ALT_CRIT); + + if (adr -> ad_req_del[0] != AD_RDM_NOTUSED) + lnptr = A_req_del (lnptr, adr -> ad_req_del, argv, &argc); + + docritical (adr -> ad_req_del_crit, AD_REQ_DEL_CRIT); + + if (adr -> ad_phys_forward) + lnptr = A_put (lnptr, AD_PHYS_FORWARD, + rcmd_srch(TRUE, tbl_bool), argv, &argc); + + docritical (adr -> ad_phys_forward_crit, AD_PHYS_FORWARD_CRIT); + + if (adr -> ad_phys_fw_ad_req) + lnptr = A_put (lnptr, AD_PHYS_FW_AD, + rcmd_srch (TRUE, tbl_bool), argv, &argc); + + docritical (adr -> ad_phys_fw_ad_crit, AD_PHYS_FW_AD_CRIT); + + if (adr -> ad_phys_modes) + lnptr = A_modes2txt (lnptr, adr -> ad_phys_modes, + argv, &argc); + + docritical (adr -> ad_phys_modes_crit, AD_PHYS_MODES_CRIT); + + if (adr -> ad_reg_mail_type) + lnptr = A_put (lnptr, AD_REG_MAIL, + rcmd_srch (adr -> ad_reg_mail_type, + atbl_reg_mail), + argv, &argc); + + docritical (adr -> ad_reg_mail_type_crit, AD_REG_MAIL_CRIT); + + if (adr -> ad_recip_number_for_advice) + lnptr = A_put (lnptr, AD_RECIP_NUMBER_ADVICE, + adr -> ad_recip_number_for_advice, + argv, &argc); + docritical (adr -> ad_recip_number_for_advice_crit, + AD_RECIP_NUMBER_ADVICE_CRIT); + + if (adr -> ad_phys_rendition_attribs) + lnptr = A_put (lnptr, AD_PHYS_RENDITION, + sprintoid (adr -> ad_phys_rendition_attribs), + argv, &argc); + + docritical (adr -> ad_phys_rendition_attribs_crit, + AD_PHYS_RENDITION_CRIT); + + if (adr -> ad_pd_report_request) + lnptr = A_put (lnptr, AD_PD_REPORT_REQUEST, + rcmd_srch (TRUE, tbl_bool), + argv, &argc); + + docritical (adr -> ad_pd_report_request_crit, + AD_PD_REPORT_REQUEST_CRIT); + + for (rp = adr -> ad_redirection_history; rp; rp = rp -> rd_next) + lnptr = A_redir2txt (lnptr, rp, argv, &argc); + + docritical (adr -> ad_redirection_history_crit, + AD_REDIRECTION_HISTORY_CRIT); + + if (adr -> ad_message_token) { + lnptr = A_put (lnptr, AD_MESSAGE_TOKEN, + cp = qb2hex (adr -> ad_message_token), + argv, &argc); + free (cp); + } + + docritical (adr -> ad_message_token_crit, + AD_MESSAGE_TOKEN_CRIT); + + if (adr -> ad_content_integrity) { + lnptr = A_put (lnptr, AD_CONTENT_INTEGRITY, + cp = qb2hex (adr -> ad_content_integrity), + argv, &argc); + free (cp); + } + + docritical (adr -> ad_content_integrity_crit, + AD_CONTENT_INTEGRITY_CRIT); + + if (adr -> ad_proof_delivery) + lnptr = A_put (lnptr, AD_PROOF_DELIVERY, + rcmd_srch (TRUE, tbl_bool), + argv, &argc); + + docritical (adr -> ad_proof_delivery_crit, AD_PROOF_DELIVERY_CRIT); + +#undef docritical + for (ext = adr -> ad_per_recip_ext_list; ext; ext = ext -> ext_next) + lnptr = A_extension (lnptr, ext, argv, &argc); + + + lnptr = A_put (lnptr, AD_ORIG, adr->ad_value, argv, &argc); + + lnptr = A_put (lnptr, AD_X400, adr->ad_r400adr, argv, &argc); + + lnptr = A_put (lnptr, AD_822, adr->ad_r822adr, argv, &argc); + + if (adr->ad_r400DR) + lnptr = A_put (lnptr, AD_X400DR, adr->ad_r400DR, argv, &argc); + + if (adr->ad_r822DR) + lnptr = A_put (lnptr, AD_822DR, adr->ad_r822DR, argv, &argc); + + if (adr->ad_r400orig) + lnptr = A_put (lnptr, AD_X400ORIG, adr->ad_r400orig, + argv, &argc); + + lnptr = A_put (lnptr, AD_END, NULLCP, argv, &argc); + + return OK; +} + + + + +/* --- *** --- +outchan contains only one value, this is a temporary measure until +next PP version - then replace with A_chanlist2txt. +--- *** --- */ + +static char *A_outchan2txt (lnptr, type, chanlist, argv, argc) +char *lnptr; +int type; +LIST_RCHAN *chanlist; +char *argv[]; +int *argc; +{ + LIST_RCHAN *fp; + char buf[LINESIZE]; + + + PP_DBG (("Lib/A_outchan2txt()")); + + if (chanlist == NULLIST_RCHAN || chanlist->li_chan == NULLCHAN) { + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + return (lnptr); + } + + buf[0] = '\0'; + + for (fp = chanlist; fp; fp = fp -> li_next) + if (fp -> li_chan) + if (fp -> li_chan -> ch_name) { + (void) strcat (buf, fp -> li_chan -> ch_name); + break; + } + + + if (buf[0] == '\0') + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + else + lnptr = A_put (lnptr, type, buf, argv, argc); + + return (lnptr); +} + + + + +static char *A_chanlist2txt (lnptr, type, chanlist, argv, argc) +char *lnptr; +int type; +LIST_RCHAN *chanlist; +char *argv[]; +int *argc; +{ + LIST_RCHAN *fp; + char buf[LINESIZE]; + + + PP_DBG (("Lib/A_chanlist2txt()")); + + if (chanlist == NULLIST_RCHAN || chanlist->li_chan == NULLCHAN) { + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + return (lnptr); + } + + buf[0] = '\0'; + + for (fp = chanlist; fp; fp = fp -> li_next) + if (fp -> li_chan) + if (fp -> li_chan -> ch_name) { + if (buf[0] != '\0') + (void) strcat (buf, ","); + (void) strcat (buf, fp -> li_chan -> ch_name); + if (fp -> li_dir) { + (void) strcat(buf, "|"); + (void) strcat(buf, fp -> li_dir); + } + } + + + if (buf[0] == '\0') + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + else + lnptr = A_put (lnptr, type, buf, argv, argc); + + return (lnptr); +} + + + + +/* --- *** --- +outhost contains only one value, this is a temporary measure until +next PP version - then redo as a list. +--- *** --- */ + +static char *A_outhost2txt (lnptr, type, hostlist, argv, argc) +char *lnptr; +int type; +LIST_RCHAN *hostlist; +char *argv[]; +int *argc; +{ + LIST_RCHAN *fp; + char buf[LINESIZE]; + + + PP_DBG (("Lib/A_outhost2txt()")); + + if (hostlist == NULLIST_RCHAN || hostlist->li_mta == NULLCP) { + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + return (lnptr); + } + + buf[0] = '\0'; + + for (fp = hostlist; fp; fp = fp -> li_next) + if (fp -> li_mta) { + (void) strcat (buf, fp -> li_mta); + break; + } + + if (buf[0] == '\0') + lnptr = A_put (lnptr, type, NULLCP, argv, argc); + else + lnptr = A_put (lnptr, type, buf, argv, argc); + + return (lnptr); +} + + + + +static char *A_put (lnptr, key, val, argv, argc) +char *lnptr; +int key; +char *val; +char *argv[]; +int *argc; +{ + + char *lnbegin=lnptr; + int n = *argc; + + if (key != AD_END) + argv[n++] = "="; + + argv[n++] = rcmd_srch (key, atbl_addr); + + if (key != AD_END) { + argv[n++] = lnptr; + if (val == NULLCP || *val == '\0') + lnptr = Bf_put (lnptr, EMPTY); + else + lnptr = Bf_put (lnptr, val); + + *lnptr++ = '\0'; + } + + argv[n] = NULLCP; + *argc = n; + PP_DBG (("Lib/pp/A_put (%.999s)", lnbegin)); + + return (lnptr); +} + + +static char *A_no2txt (val, buf) /* Number -> Txt */ +int val; +char *buf; +{ + (void) sprintf (buf, "%d", val); + return buf; +} + + +char *no2txt3 (value, buf) /* Number -> Txt (max of 3 chars) */ +int value; +char *buf; +{ + char *bufstart = buf, + temp[100]; + int maxlen=3, + i, j, + diff, + len; + + PP_DBG (("Lib/pp/no2txt3 (%d)", value)); + + (void) sprintf (&temp[0], "%d", value); + len = strlen (&temp[0]); + + if (len == maxlen) + for (i=j=0; i maxlen) + (void) sprintf (buf, "%s", "999"); + else if (len < maxlen) { + diff = maxlen - len; + for (i=0; i < diff; buf[i]='0', i++); + for (i=diff, j=0; i Txt */ +int value; +{ + char *keywd; + + PP_DBG (("Lib/pp/A_adrtype2txt (%d)", value)); + + if ((keywd = rcmd_srch (value, atbl_types)) == NULLCP) + keywd = rcmd_srch (AD_ANY_TYPE, atbl_types); + return (keywd); +} + + +static char* A_adrsubtype2txt (value) /* Txt -> Address subtype */ +int value; +{ + char *keywd; + + PP_DBG (("Lib/pp/A_adrsubtype2txt (%d)", value)); + + keywd = rcmd_srch (value, atbl_subtypes); + return (keywd); +} + +static char *A_extension (lnptr, ext, argv, argcp) +char *lnptr; +X400_Extension *ext; +char **argv; +int *argcp; +{ + char extbuf[8*BUFSIZ]; + char buf[20]; + char *av[5]; + + av[0] = A_no2txt (ext -> ext_int, buf); + av[1] = ext -> ext_oid ? sprintoid (ext -> ext_oid) : ""; + av[2] = qb2hex (ext -> ext_value); + av[3] = rcmd_srch (ext -> ext_criticality, tbl_crit); + av[4] = NULLCP; + + if (arg2vstr (0, sizeof extbuf, extbuf, av) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("A_extension: arg2vstr failed")); + + free (av[2]); + return A_put (lnptr, AD_EXTENSION, extbuf, argv, argcp); +} + +static char *A_redir2txt (lnptr, rp, argv, argcp) +char *lnptr; +Redirection *rp; +char *argv[]; +int *argcp; +{ + char *av[5]; + char redbuf[BUFSIZ]; + + av[0] = rp -> rd_addr ? rp -> rd_addr : ""; + av[1] = rp -> rd_dn ? rp -> rd_dn : ""; + av[2] = time2txt (rp -> rd_time); + av[3] = rcmd_srch (rp -> rd_reason, tbl_redir); + av[4] = NULLCP; + + if (arg2vstr (0, sizeof redbuf, redbuf, av) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("A_redir2txt: arg2vstr failed")); + return A_put (lnptr, AD_REDIRECTION_HISTORY, redbuf, argv, argcp); +} + +static char *A_modes2txt (lnptr, md, argv, argcp) +char *lnptr; +int md; +char *argv[]; +int *argcp; +{ + char modebuf[BUFSIZ]; + int i, n; + char *av[20]; + + for (i = 1, n = 0; i <= AD_PM_MAX; i <<= 2) { + if (md & i) + av[n++] = rcmd_srch (i, atbl_pd_modes); + } + av[n] = NULLCP; + + if (arg2vstr (0, sizeof modebuf, modebuf, av) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("A_modes2txt: arg2vstr failed")); + + return A_put (lnptr, AD_PHYS_MODES, modebuf, argv, argcp); +} + +static char *A_req_del (lnptr, rdm, argv, argcp) +char *lnptr; +int rdm[]; +char *argv[]; +int *argcp; +{ + char *av[AD_RDM_MAX+1]; + char rdmbuf[BUFSIZ]; + int n = 0, i; + + for (i = 0; i < AD_RDM_MAX; i++) { + if (rdm[i] == AD_RDM_NOTUSED) + break; + + av[n++] = rcmd_srch (rdm[i], atbl_rdm); + } + + argv[n] = NULLCP; + if (arg2vstr (0, sizeof rdmbuf, rdmbuf, av) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("A_req_del: arg2vstr failed")); + return A_put (lnptr, AD_REQ_DEL, rdmbuf, argv, argcp); +} diff --git a/Lib/pp/chan_acheck.c b/Lib/pp/chan_acheck.c new file mode 100644 index 0000000..c124127 --- /dev/null +++ b/Lib/pp/chan_acheck.c @@ -0,0 +1,120 @@ +/* chan_acheck.c: apply channel address checking */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/chan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/chan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: chan_acheck.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "qmgr.h" + +int chan_acheck (ap, mychan, first, mta) +ADDR *ap; +CHAN *mychan; +int first; +char **mta; +{ + LIST_RCHAN *chan; + int i; + int donealready = 0; + + switch (ap -> ad_status) { + case AD_STAT_PEND: + break; + + case AD_STAT_DONE: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + + case AD_STAT_DRWRITTEN: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + return NOTOK; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("adr_checks - wrong status")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + for (chan = ap -> ad_fmtchan, i = 0; i < ap -> ad_rcnt && chan; + chan = chan -> li_next, i++) { + if (strcmp (chan -> li_chan -> ch_name, + mychan -> ch_name) == 0) + donealready = 1; + } + if (chan == NULL) + chan = ap -> ad_outchan; + + if (strcmp (chan -> li_chan -> ch_name, mychan -> ch_name) != 0) { + if (donealready) { + PP_NOTICE (("Done channel %s already", + mychan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + } + PP_LOG (LLOG_EXCEPTIONS, + ("adr %d not ready for channel %s yet", + ap -> ad_no, mychan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (mychan->ch_chan_type != CH_SHAPER && ap -> ad_resp == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("responsibility bit not set for addr %d", + ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (mta == NULLVP) /* mta check not required */ + return OK; + + if (mychan -> ch_mta) { + *mta = strdup (mychan -> ch_mta); + return OK; + } + + if (ap -> ad_outchan -> li_mta == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No mta for address %d", ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (*mta == NULLCP) + *mta = strdup (ap -> ad_outchan -> li_mta); + else if (strcmp (*mta, ap -> ad_outchan -> li_mta) != 0) { + if (first) { /* ok to change here */ + free (*mta); + *mta = strdup (ap -> ad_outchan -> li_mta); + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("Mta changed from %s to %s", *mta, + ap -> ad_outchan -> li_mta)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + } + return OK; +} diff --git a/Lib/pp/conf.c b/Lib/pp/conf.c new file mode 100644 index 0000000..210c60d --- /dev/null +++ b/Lib/pp/conf.c @@ -0,0 +1,53 @@ +/* conf.c: basic configuration information */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/conf.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/conf.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: conf.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#ifndef TAILOR +#define TAILOR "." +#endif + +#ifndef CMDDIR +#define CMDDIR "." +#endif + +#ifndef LOGDIR +#define LOGDIR "." +#endif + +#ifndef QUEDIR +#define QUEDIR "." +#endif + +#ifndef TBLDIR +#define TBLDIR "." +#endif + +#ifndef NIFTPQUEDIR +#define NIFTPQUEDIR "." +#endif + +#ifndef NIFTPCPF +#define NIFTPCPF "." +#endif + + +char *pptailor = TAILOR; +char *cmddfldir = CMDDIR; +char *logdfldir = LOGDIR; +char *quedfldir = QUEDIR; +char *tbldfldir = TBLDIR; +char *niftpquedir = NIFTPQUEDIR; +char *niftpcpf = NIFTPCPF; diff --git a/Lib/pp/dchan_acheck.c b/Lib/pp/dchan_acheck.c new file mode 100644 index 0000000..6fe3d27 --- /dev/null +++ b/Lib/pp/dchan_acheck.c @@ -0,0 +1,163 @@ +/* dchan_acheck.c: address checking for a channel allowing DR's */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/dchan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/dchan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: dchan_acheck.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "qmgr.h" + +int dchan_acheck (ap, asp, thechan, first, mta) +ADDR *ap, *asp; +CHAN *thechan; +int first; +char **mta; +{ + ADDR *ac; + LIST_RCHAN *chan; + int i; + int donealready = 0; + static int drwr = 0; + static int pend = 0; + + if (first) + drwr = pend = 0; + + switch (ap -> ad_status) { + case AD_STAT_PEND: + if (drwr) { + PP_LOG (LLOG_EXCEPTIONS, + ("Recips have diff status")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + ac = ap; + break; + + case AD_STAT_DONE: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + + case AD_STAT_DRWRITTEN: + if (pend) { + PP_LOG (LLOG_EXCEPTIONS, + ("Recips have diff status")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + if (first) + drwr = ap->ad_no; + else if (drwr != ap->ad_no) { + PP_LOG (LLOG_EXCEPTIONS, + ("Mismatch on DR's %d & %d", + ap->ad_no, drwr)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + ac = asp; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("adr_checks - wrong status")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + for (chan = ac -> ad_fmtchan, i = 0; i < ac -> ad_rcnt && chan; + chan = chan -> li_next, i++) { + if (strcmp (chan->li_chan->ch_name, thechan->ch_name) == 0) + donealready = 1; + } + + if (chan == NULL) + chan = ac -> ad_outchan; + + + if (chan -> li_chan == NULLCHAN || + chan->li_chan->ch_name == NULLCP || + thechan->ch_name == NULLCP) + { + PP_NOTICE (("Unable to compare channels - nullchan found")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + + if (strcmp (chan -> li_chan -> ch_name, thechan -> ch_name) != 0) { + if (donealready) { + PP_NOTICE (("Done channel %s already", + thechan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + } + PP_LOG (LLOG_EXCEPTIONS, + ("adr %d not ready for channel %s yet", + ap -> ad_no, thechan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (ap -> ad_resp == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("responsibility bit not set for addr %d", + ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (mta == NULLVP) /* mta check not required */ + return OK; + + if (thechan -> ch_mta) { + *mta = strdup (thechan -> ch_mta); + return OK; + } + + if (ac -> ad_outchan -> li_mta == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No mta for address %d", ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (*mta == NULLCP) + *mta = strdup (ac -> ad_outchan -> li_mta); + else if (strcmp (*mta, ac -> ad_outchan -> li_mta) != 0) { + if (first) { /* ok to change here */ + free (*mta); + *mta = strdup (ac -> ad_outchan -> li_mta); + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("Mta changed from %s to %s", *mta, + ac -> ad_outchan -> li_mta)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + } + return OK; +} + diff --git a/Lib/pp/dr2txt.c b/Lib/pp/dr2txt.c new file mode 100644 index 0000000..d600c16 --- /dev/null +++ b/Lib/pp/dr2txt.c @@ -0,0 +1,317 @@ +/* dr2txt.c: convert dr structure to text encooding */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/dr2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/dr2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: dr2txt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "dr.h" +#include "tb_dr.h" + +#define crit2txt(n) rcmd_srch ((n), tbl_crit) +static int rr2txt (); +static void drredir2txt (); + +extern char *qb2hex (); +extern char *int2txt (); +extern char *time2txt (); +extern void genreset (); +extern void mpduid2txt (); +extern int argv2fp (); +extern void trace2txt (); +extern void dlexp2txt (); +extern void fname2txt (); +extern int extension2txt (); +extern void encodedinfo2txt (); + +extern CMD_TABLE + tbl_redir [], + rr_rcode[], + rr_dcode [], + tbl_crit[], + rrtbl [], + drtbl []; + + +/* ------------------- Memory -> Text File ------------------------------ */ + + +int dr2txt (fp, dr) /* DeliveryReport -> Txt */ +FILE *fp; +DRmpdu *dr; +{ + char *argv[100]; + int argc; + Trace *trace; + DLHistory *dlh; + X400_Extension *ext; + Rrinfo *rr; + + PP_DBG (("Lib/pp/dr2txt()")); + + genreset (); + + if (dr -> dr_mpduid) { + argv[0] = rcmd_srch (DR_MSGID, drtbl); + argc = 1; + mpduid2txt (dr -> dr_mpduid, argv, &argc); + if (argc > 1) { + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + } + + argv[0] = rcmd_srch (DR_TRACE, drtbl); + for (trace = dr -> dr_trace; trace; trace = trace -> trace_next) { + argc = 1; + trace2txt (trace, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (DR_SI_TRACE, drtbl); + for (trace = dr -> dr_subject_intermediate_trace; trace; + trace = trace -> trace_next) { + argc = 1; + trace2txt (trace, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (DR_DL_EXP_HIST, drtbl); + for (dlh = dr -> dr_dl_history; dlh; dlh = dlh -> dlh_next) { + argc = 1; + dlexp2txt (dlh, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (dr -> dr_dl_history_crit) { + argv[0] = rcmd_srch (DR_DL_EXP_HIST_CRIT, drtbl); + argv[1] = crit2txt (dr -> dr_dl_history_crit); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (dr -> dr_reporting_dl_name) { + argv[0] = rcmd_srch (DR_REPORTING_DL_NAME, drtbl); + argc = 1; + fname2txt (dr -> dr_reporting_dl_name, + dr -> dr_reporting_dl_name_crit, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (dr -> dr_security_label) { + argv[0] = rcmd_srch (DR_SECURITY_LABEL, drtbl); + argv[1] = qb2hex (dr -> dr_security_label); + argv[2] = crit2txt (dr -> dr_security_label_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (dr -> dr_reporting_mta_certificate) { + argv[0] = rcmd_srch (DR_REPORTING_MTA_CERTIFICATE, drtbl); + argv[1] = qb2hex (dr -> dr_reporting_mta_certificate); + argv[2] = crit2txt (dr -> dr_reporting_mta_certificate_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (dr -> dr_report_origin_auth_check) { + argv[0] = rcmd_srch (DR_REPORT_ORIGIN_AUTH_CHECK, drtbl); + argv[1] = qb2hex (dr -> dr_report_origin_auth_check); + argv[2] = crit2txt (dr -> dr_report_origin_auth_check_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + argv[0] = rcmd_srch (DR_PER_ENVELOPE_EXTENSIONS, drtbl); + for (ext = dr -> dr_per_envelope_extensions; ext; + ext = ext -> ext_next) { + argc = 1; + if (extension2txt (ext, fp, argv, &argc) == NOTOK) + return NOTOK; + } + + + argv[0] = rcmd_srch (DR_PER_REPORT_EXTENSIONS, drtbl); + for (ext = dr -> dr_per_report_extensions; ext; + ext = ext -> ext_next) { + argc = 1; + if (extension2txt (ext, fp, argv, &argc) == NOTOK) + return NOTOK; + } + (void) fprintf (fp, "%s\n", rcmd_srch (DR_END_HDR, drtbl)); + + for (rr = dr -> dr_recip_list; rr; rr = rr -> rr_next) + if (rr2txt (rr, fp) == NOTOK) + return NOTOK; + (void) fprintf (fp, "%s\n", rcmd_srch (RR_END, rrtbl)); + (void) fflush (fp); + return ferror(fp) ? NOTOK : OK; +} + +static int rr2txt (rr, fp) +Rrinfo *rr; +FILE *fp; +{ + char *argv[30]; + int argc; + Redirection *redir; + X400_Extension *ext; + + genreset (); + + argv[0] = rcmd_srch (RR_RECIP, rrtbl); + argv[1] = int2txt (rr -> rr_recip); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + + if (rr -> rr_report.rep_type == DR_REP_SUCCESS) { + argv[0] = rcmd_srch (RR_SUCCESS, rrtbl); + argv[1] = time2txt (rr -> rr_report.rep.rep_dinfo.del_time); + argv[2] = int2txt (rr -> rr_report.rep.rep_dinfo.del_type); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (rr -> rr_report.rep_type == DR_REP_FAILURE) { + argv[0] = rcmd_srch (RR_FAILURE, rrtbl); + argv[1] = rcmd_srch (rr -> rr_report.rep.rep_ndinfo.nd_rcode, + rr_rcode); + argv[2] = rcmd_srch (rr -> rr_report.rep.rep_ndinfo.nd_dcode, + rr_dcode); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (rr -> rr_converted) { + argv[0] = rcmd_srch (RR_CONVERTED, rrtbl); + argc = 1; + encodedinfo2txt (rr -> rr_converted, argv, &argc); + argv[argc] = NULLCP; + if (argc != 1) + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (rr -> rr_originally_intended_recip) { + argv[0] = rcmd_srch (RR_ORIGINALLY_INTENDED_RECIP, rrtbl); + argc = 1; + fname2txt (rr -> rr_originally_intended_recip, 0, + argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (rr -> rr_supplementary) { + argv[0] = rcmd_srch (RR_SUPPLEMENTARY, rrtbl); + argv[1] = rr -> rr_supplementary; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (RR_REDIRECT_HISTORY, rrtbl); + for (redir = rr -> rr_redirect_history; redir; + redir = redir -> rd_next) { + argc = 1; + drredir2txt (redir, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (rr -> rr_redirect_history_crit) { + argv[0] = rcmd_srch (RR_REDIRECT_HISTORY_CRIT, rrtbl); + argv[1] = crit2txt (rr -> rr_redirect_history_crit); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (rr -> rr_physical_fwd_addr) { + argv[0] = rcmd_srch (RR_PHYSICAL_FWD, rrtbl); + fname2txt (rr -> rr_physical_fwd_addr, + rr -> rr_physical_fwd_addr_crit, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (rr -> rr_recip_certificate) { + argv[0] = rcmd_srch (RR_RECIP_CERTIFICATE, rrtbl); + argv[1] = qb2hex (rr -> rr_recip_certificate); + argv[2] = crit2txt (rr -> rr_recip_certificate_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (rr -> rr_report_origin_authentication_check) { + argv[0] = rcmd_srch (RR_REPORT_ORIGIN_CHECK, rrtbl); + argv[1] = qb2hex (rr -> rr_report_origin_authentication_check); + argv[2] = + crit2txt (rr -> rr_report_origin_authentication_check_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (rr -> rr_arrival) { + argv[0] = rcmd_srch (RR_ARRIVAL, rrtbl); + argv[1] = time2txt (rr -> rr_arrival); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (RR_PER_RECIP_EXTENSIONS, rrtbl); + for (ext = rr -> rr_per_recip_extensions; ext; ext = ext -> ext_next) { + argc = 1; + if (extension2txt (ext, fp, argv, &argc) == NOTOK) + return NOTOK; + } + (void) fprintf (fp, "%s\n", rcmd_srch (RR_END_RECIP, rrtbl)); + return ferror (fp) ? NOTOK : OK; +} + +static void drredir2txt (rp, argv, argcp) +Redirection *rp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + argv[n++] = rp -> rd_addr ? rp -> rd_addr : ""; + argv[n++] = rp -> rd_dn ? rp -> rd_dn : ""; + argv[n++] = rcmd_srch (rp -> rd_reason, tbl_redir); + *argcp = n; +} diff --git a/Lib/pp/get_dr.c b/Lib/pp/get_dr.c new file mode 100644 index 0000000..49d5141 --- /dev/null +++ b/Lib/pp/get_dr.c @@ -0,0 +1,52 @@ +/* get_dr.c: get a delivery report given a reference */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/get_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/get_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: get_dr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "q.h" +#include "dr.h" +#include "retcode.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + +extern char *dr_file; + +int get_dr (dno, msg_name, drmpdu) +int dno; +char *msg_name; +DRmpdu *drmpdu; +{ + char file[MAXPATHLENGTH]; + FILE *fp; + int retval; + + (void) sprintf (file, "%s/%s%d", msg_name, dr_file, dno); + + if ((fp = fopen (file, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, file, + ("Can't read DR")); + return RP_BAD; + } + + retval = rd_dr (drmpdu, fp); + (void) fclose (fp); + return (retval); +} diff --git a/Lib/pp/lchan_acheck.c b/Lib/pp/lchan_acheck.c new file mode 100644 index 0000000..8f49201 --- /dev/null +++ b/Lib/pp/lchan_acheck.c @@ -0,0 +1,134 @@ +/* lchan_acheck.c: apply local channel address checking */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/lchan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/lchan_acheck.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: lchan_acheck.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "qmgr.h" + +int lchan_acheck (ap, mychan, first, recip) +ADDR *ap; +CHAN *mychan; +int first; +char **recip; +{ + LIST_RCHAN *chan; + char *to; + int i; + int donealready = 0; + + switch (ap -> ad_status) { + case AD_STAT_PEND: + break; + + case AD_STAT_DONE: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + + case AD_STAT_DRWRITTEN: + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_positiveDR); + return NOTOK; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("adr_checks - wrong status")); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + for (chan = ap -> ad_fmtchan, i = 0; i < ap -> ad_rcnt && chan; + chan = chan -> li_next, i++) { + if (strcmp (chan -> li_chan -> ch_name, + mychan -> ch_name) == 0) + donealready = 1; + } + if (chan == NULL) + chan = ap -> ad_outchan; + + if (strcmp (chan -> li_chan -> ch_name, mychan -> ch_name) != 0) { + if (donealready) { + PP_NOTICE (("Done channel %s already", + mychan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_success); + return NOTOK; + } + PP_LOG (LLOG_EXCEPTIONS, + ("adr %d not ready for channel %s yet", + ap -> ad_no, mychan -> ch_name)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (ap -> ad_resp == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("responsibility bit not set for addr %d", + ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (recip == NULLVP) /* mta check not required */ + return OK; + + switch (ap -> ad_type) { + case AD_822_TYPE: + to = ap -> ad_r822adr; + break; + + case AD_X400_TYPE: + to = ap -> ad_r400adr; + break; + + default: + case AD_ANY_TYPE: + PP_LOG (LLOG_EXCEPTIONS, ("Bad address type %d", + ap -> ad_type)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (to == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("No recipient for address %d", ap -> ad_no)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + + if (*recip == NULLCP) + *recip = strdup (to); + else if (strcmp (*recip, to) != 0) { + if (first) { /* ok to change here */ + free (*recip); + *recip = strdup (to); + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("Mta changed from %s to %s", *recip, + to)); + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_messageFailure); + return NOTOK; + } + } + return OK; +} diff --git a/Lib/pp/list_bpt.c b/Lib/pp/list_bpt.c new file mode 100644 index 0000000..a75d28f --- /dev/null +++ b/Lib/pp/list_bpt.c @@ -0,0 +1,139 @@ +/* list_bpt.c: utility routines for Body Part Types */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/list_bpt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/list_bpt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: list_bpt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "list_bpt.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* +Creates a new list structure +*/ + +LIST_BPT* list_bpt_new (value) +char *value; +{ + register LIST_BPT *list; + + + PP_DBG (("Lib/pp/list_bpt_new (%s)", value)); + + if (value == NULLCP) + return (NULLIST_BPT); + + list = (LIST_BPT *)smalloc (sizeof *list); + + list -> li_next = NULL; + list -> li_name = strdup (value); + + return (list); + +} + + + + +/* +Duplicates +*/ + +LIST_BPT *list_bpt_dup (list) +LIST_BPT *list; +{ + LIST_BPT *retlist = NULLIST_BPT; + register LIST_BPT *new; + + for (; list != NULLIST_BPT; list = list->li_next) { + new = (LIST_BPT *) smalloc (sizeof *list); + new -> li_name = strdup (list->li_name); + new -> li_next = NULL; + list_bpt_add (&retlist, new); + } + + return (retlist); +} + +/* +Adds item onto the end of base +*/ + +void list_bpt_add (base, new) +LIST_BPT **base, + *new; +{ + register LIST_BPT *ep = *base; + + if (ep == NULLIST_BPT) + *base = new; + else { + while (ep->li_next != NULLIST_BPT) + ep = ep->li_next; + ep->li_next = new; + } +} + + +/* +Finds a specified item within a list +*/ + +LIST_BPT *list_bpt_find (list, item) +LIST_BPT *list; +char *item; +{ + register LIST_BPT *lp; + + PP_DBG (("Lib/pp/list_bpt_find (%s)", item)); + + for (lp = list; lp != NULLIST_BPT; lp = lp->li_next) + if (lexequ (lp -> li_name, item) == 0) + return (lp); + + return (NULLIST_BPT); +} + +LIST_BPT *list_bpt_nfind (list, item, len) +LIST_BPT *list; +char *item; +int len; +{ + register LIST_BPT *lp; + + PP_DBG (("Lib/pp/list_bpt_find (%s)", item)); + + for (lp = list; lp != NULLIST_BPT; lp = lp->li_next) + if (lexnequ (lp -> li_name, item, len) == 0) + return (lp); + + return (NULLIST_BPT); +} + +void list_bpt_free (list) +LIST_BPT *list; +{ + if (list == NULLIST_BPT) return; + list_bpt_free (list->li_next); + if (list -> li_name) + free (list->li_name); + free ((char *)list); +} diff --git a/Lib/pp/list_rchan.c b/Lib/pp/list_rchan.c new file mode 100644 index 0000000..1217f4f --- /dev/null +++ b/Lib/pp/list_rchan.c @@ -0,0 +1,141 @@ +/* list_rchan.c: utility routines for struct LIST_REFORMAT */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/list_rchan.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/list_rchan.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: list_rchan.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "list_rchan.h" + + + +/* --------------------- Begin Routines -------------------------------- */ + + +/* +Creates a new list structure +*/ + +LIST_RCHAN* list_rchan_new (site, chan) +char *site; +char *chan; +{ + register LIST_RCHAN *list; + + PP_DBG (("Lib/pp/list_rchan_new (%s, %s)", + site ? site : "", + chan ? chan : "")); + + if (site == NULLCP && chan == NULLCP) + return (NULLIST_RCHAN); + + list = (LIST_RCHAN *) smalloc (sizeof *list); + + if (chan) { + list -> li_chan = ch_nm2struct (chan); + if (list -> li_chan == NULLCHAN) { + PP_LOG (LLOG_EXCEPTIONS, + ("Chan %s not known", chan)); + free ((char *)list); + return (NULLIST_RCHAN); + } + PP_DBG (("Channel '%s' added", list -> li_chan -> ch_name)); + } + else list -> li_chan = NULLCHAN; + + if (site) + list -> li_mta = strdup (site); + else list -> li_mta = NULLCP; + list -> li_auth = NULL; + list -> li_next = NULL; + + return (list); +} + + + +/* +Sets the channel part in the list structure +*/ + +int list_rchan_schan (list, chan) +LIST_RCHAN *list; +char *chan; +{ + + PP_DBG (("Lib/pp/list_rchan_schan (%s)", chan)); + + if (chan == NULLCP) return (NOTOK); + + if ((list -> li_chan = ch_nm2struct (chan)) == NULLCHAN) + return (NOTOK); + + return (OK); +} + + + +/* +Sets the site/mta info of the list structure +*/ + + +int list_rchan_ssite (list, site) +LIST_RCHAN *list; +char *site; +{ + + PP_DBG (("Lib/pp/list_rchan_ssite (%s)", site)); + + if (site == NULLCP) return (NOTOK); + list -> li_mta = strdup (site); + return (OK); +} + + + +/* +Adds item onto the end of base +*/ + +void list_rchan_add (base, new) +LIST_RCHAN **base, + *new; +{ + register LIST_RCHAN *rp = *base; + + if (rp == NULLIST_RCHAN) + *base = new; + else { + while (rp->li_next != NULLIST_RCHAN) + rp = rp->li_next; + rp->li_next = new; + } +} + +/* +Do not free the CHAN ptr because set by ch_all[] +*/ + +void list_rchan_free (list) +LIST_RCHAN *list; +{ + if (list == NULLIST_RCHAN) return; + if (list -> li_next) + list_rchan_free (list->li_next); + if (list -> li_mta) + free (list -> li_mta); + + free ((char *)list); +} diff --git a/Lib/pp/make b/Lib/pp/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/pp/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/pp/msg2file.c b/Lib/pp/msg2file.c new file mode 100644 index 0000000..b190829 --- /dev/null +++ b/Lib/pp/msg2file.c @@ -0,0 +1,36 @@ +/* msg2file: convert message reference into a filename */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/msg2file.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/msg2file.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: msg2file.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + +int n_subdirs = 2; + +/* assume of the form msg.NNNNN-NNN */ + +int msg2file (name, fullname) +char *name, *fullname; +{ + int copyn = 5; + int i = 0; + char *p; + + p = fullname; + for (i = 0; i < n_subdirs; i++, copyn++) { + (void) strncpy (p, name, copyn); + p += copyn; + *p++ = '/'; + *p = '\0'; + } + (void) strcpy (p, name); +} + diff --git a/Lib/pp/mta2txt.c b/Lib/pp/mta2txt.c new file mode 100644 index 0000000..5d303df --- /dev/null +++ b/Lib/pp/mta2txt.c @@ -0,0 +1,402 @@ +/* mta2txt.c: handle text encoding of various mta structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/mta2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/mta2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: mta2txt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" +#include "tb_com.h" +#include "tb_a.h" +#include "tb_p1.h" + +extern char *genstore (); +char *utctime (); +char *int2txt (); +extern int argv2fp (); + +static char *P1_rreq2txt (); +#define crit2txt(n) rcmd_srch ((n), tbl_crit) + +extern CMD_TABLE + p1tbl_mpduid [/* mpdu-identifier */], + p1tbl_trace [/* trace-information */], + p1tbl_globaldomid [/* global-domain-identifier */], + p1tbl_domsinfo [/* domain-supplied-info */], + p1tbl_action [/* domain-supplied-info-action */], + p1tbl_encinfoset [/* encode-info-types-set */], + tbl_crit [], + atbl_addr [/* address-lines */], + tbl_bool [], + atbl_mtarreq [/* mta-report-request */], + atbl_usrreq [/* user-report-request */]; + + +/* --------------------- Memory->Text File ---------------------------- */ + +void globaldomid2txt (); +void encodedinfo2txt (); + +void mpduid2txt (mp, argv, argcp) /* MPDUIdentifier->Txt */ +MPDUid *mp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + PP_DBG (("Lib/pp/mpduid2txt()")); + + if (mp->mpduid_string != NULL) { + argv[n++] = "="; + argv[n++] = rcmd_srch (MPDUID_STRING, p1tbl_mpduid); + argv[n++] = mp->mpduid_string; + *argcp = n; + } + + globaldomid2txt (&mp->mpduid_DomId, argv, argcp); +} + + +void globaldomid2txt (gp, argv, argcp) /* GlobalDomainIdentifier->Txt */ +GlobalDomId *gp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + + PP_DBG (("Lib/pp/golbaldomid2txt (c=%s, a=%s, p=%s)", + gp->global_Country ? gp->global_Country : "notspecified", + gp->global_Admin ? gp->global_Admin : "notspecified", + gp->global_Private && isstr (gp->global_Private) + ? gp->global_Private : "notspecified")); + + if (gp->global_Country != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (GLOBAL_COUNTRY, p1tbl_globaldomid); + argv[n++] = gp->global_Country; + } + + if (gp->global_Admin != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (GLOBAL_ADMIN, p1tbl_globaldomid); + argv[n++] = gp->global_Admin; + } + + if (gp->global_Private != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (GLOBAL_PRIVATE, p1tbl_globaldomid); + argv[n++] = gp->global_Private; + } + *argcp = n; +} + +extern char *time2txt (); + +void domsinfo2txt (sp, argv, argcp) /* DomainSuppliedInfo->Txt */ +DomSupInfo *sp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + + PP_DBG (("Lib/pp/domsinfo2txt()")); + + if (sp->dsi_time != 0) { + argv[n++] = "="; + argv[n++] = rcmd_srch (DSI_TIME, p1tbl_domsinfo); + argv[n++] = time2txt (sp->dsi_time); + } + + if (sp->dsi_deferred != 0) { + argv[n++] = "="; + argv[n++] = rcmd_srch (DSI_DEFERRED, p1tbl_domsinfo); + argv[n++] = time2txt (sp->dsi_deferred); + } + + if (sp->dsi_action == ACTION_RELAYED || + sp->dsi_action == ACTION_ROUTED) + { + argv[n++] = "="; + argv[n++] = rcmd_srch (DSI_ACTION, p1tbl_domsinfo); + argv[n++] = int2txt (sp->dsi_action); + } + + if (sp->dsi_converted.eit_types != NULL || + sp->dsi_converted.eit_g3parms != NULL || + sp->dsi_converted.eit_tTXparms != NULL || + sp->dsi_converted.eit_presentation != NULL) + { + argv[n++] = rcmd_srch (DSI_CONVERTED, p1tbl_domsinfo); + encodedinfo2txt (&sp->dsi_converted, argv, &n); + } + + + if (sp->dsi_attempted_md.global_Country != NULLCP || + sp->dsi_attempted_md.global_Admin != NULLCP || + sp->dsi_attempted_md.global_Private != NULLCP) { + argv[n++] = rcmd_srch (DSI_ATTEMPTED, p1tbl_domsinfo); + globaldomid2txt (&sp->dsi_attempted_md, argv, &n); + } + *argcp = n; +} + + +void action2txt (fp, pvkey, action) /*DomainSuppliedInfo (action)->Txt */ +FILE *fp; +char *pvkey; +int action; +{ + char *keywd; + + PP_DBG (("Lib/pp/action2txt(%s %d)", pvkey, action)); + + keywd = rcmd_srch (action, p1tbl_action); + (void) fprintf (fp, "%s%s\n", pvkey, keywd); +} + + +void encodedinfo2txt (ep, argv, argcp) /* EncodedInformationTypes->Txt */ +EncodedIT *ep; +char *argv[]; +int *argcp; +{ + char buf[LINESIZE]; + int n = *argcp; + extern char *listbpt2txt (); + + PP_DBG (("Lib/encodedinfo2txt('%d' '%d' '%d')", + ep->eit_g3parms, ep->eit_tTXparms, + ep->eit_presentation)); + + (void) listbpt2txt (ep -> eit_types, buf); + if (buf[0]) { + PP_DBG (("Lib/listbpt2txt ('%s')", buf)); + argv[n++] = "="; + argv[n++] = rcmd_srch (EI_BIT_STRING, p1tbl_encinfoset); + argv[n++] = genstore(buf); + } + + if (ep->eit_g3parms != 0){ + argv[n++] = "="; + argv[n++] = rcmd_srch (EI_G3NONBASIC, p1tbl_encinfoset); + argv[n++] = int2txt ((int)ep -> eit_g3parms); + } + if (ep->eit_tTXparms != 0){ + argv[n++] = "="; + argv[n++] = rcmd_srch (EI_TELETEXNONBASIC, p1tbl_encinfoset); + argv[n++] = int2txt ((int)ep -> eit_tTXparms); + } + if (ep->eit_presentation != 0){ + argv[n++] = "="; + argv[n++] = rcmd_srch (EI_PRESENTATION, p1tbl_encinfoset); + argv[n++] = int2txt ((int)ep->eit_presentation); + } + *argcp = n; +} + + +char *listbpt2txt (bpt, buf) +LIST_BPT *bpt; +char *buf; +{ + LIST_BPT *list; + + PP_DBG (("Lib/pp/listbpt2txt()")); + buf[0] = 0; + for (list = bpt; list; list = list->li_next) { + if (list->li_name == NULLCP) + continue; + (void) strcat (buf, list->li_name); + if (list->li_next) + (void) strcat (buf, ","); + } + return buf; +} + +void trace2txt (tp, argv, argcp) /* TraceInformation->Txt */ +Trace *tp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + PP_DBG (("Lib/pp/trace2txt()")); + + if (tp->trace_mta != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (TRACE_MTA, p1tbl_trace); + argv[n++] = tp->trace_mta; + *argcp = n; + } + globaldomid2txt (&tp->trace_DomId, argv, argcp); + domsinfo2txt (&tp->trace_DomSinfo, argv, argcp); + n = *argcp; + argv[n++] = rcmd_srch (EOB, p1tbl_trace); + *argcp = n; +} + + +/* ReportRequest->Txt */ +void repreq2txt (resp, mta, usr, argv, argcp) +int resp; +int mta; +int usr; +char *argv[]; +int *argcp; +{ + char *p; + int n = *argcp; + + if ((p = P1_rreq2txt (AD_RESPONSIBILITY, resp)) != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (AD_RESPONSIBILITY, atbl_addr); + argv[n++] = p; + } + if ((p = P1_rreq2txt (AD_MTA_REP_REQ, mta)) != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (AD_MTA_REP_REQ, atbl_addr); + argv[n++] = p; + } + if ((p = P1_rreq2txt (AD_USR_REP_REQ, usr)) != NULLCP) { + argv[n++] = "="; + argv[n++] = rcmd_srch (AD_USR_REP_REQ, atbl_addr); + argv[n++] = p; + } + *argcp = n; +} + + +static char* P1_rreq2txt (type, val) /* ReportRequest->Txt */ +int type; +int val; +{ + PP_DBG (("Lib/pp/P1_rreq2txt(%d %d)", type, val)); + + switch (type) { + case AD_RESPONSIBILITY: + switch (val) { + case YES: + case NO: + return rcmd_srch (val, tbl_bool); + default: + return (NULLCP); + } + case AD_MTA_REP_REQ: + switch (val) { + case AD_MTA_NONE: + case AD_MTA_BASIC: + case AD_MTA_CONFIRM: + case AD_MTA_AUDIT_CONFIRM: + return rcmd_srch (val, atbl_mtarreq); + default: + return (NULLCP); + } + case AD_USR_REP_REQ: + switch (val) { + case AD_USR_NONE: + case AD_USR_NOREPORT: + case AD_USR_BASIC: + case AD_USR_CONFIRM: + return rcmd_srch (val, atbl_usrreq); + default: + return (NULLCP); + } + } + return (NULLCP); +} + + +char *time2txt (t) +UTC t; +{ + static char buffer[LINESIZE]; + if (UTC2rfc (t, buffer) == NOTOK) { + UTC ut = utcnow (); + (void) UTC2rfc (ut, buffer); + free ((char *)ut); + } + return buffer; +} + + +char *int2txt (val) +int val; +{ + char buf[LINESIZE]; + + (void) sprintf (buf, "%ld", val); + return genstore (buf); +} + +char *qb2hex (qb) +struct qbuf *qb; +{ + char *hexbuf; + char *str; + + hexbuf = smalloc (2 *qb -> qb_len + 1); + str = qb2str(qb); + + hexbuf[explode (hexbuf, (u_char *)str, qb -> qb_len)] = 0; + free (str); + + return hexbuf; +} + +void dlexp2txt (dlp, argv, argcp) +DLHistory *dlp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + + argv[n++] = dlp -> dlh_addr ? dlp -> dlh_addr : ""; + argv[n++] = dlp -> dlh_dn ? dlp -> dlh_dn : ""; + argv[n++] = dlp -> dlh_time ? time2txt (dlp -> dlh_time) : ""; + *argcp = n; +} + +void fname2txt (fn, crt, argv, argcp) +FullName *fn; +int crt; +char *argv[]; +int *argcp; +{ + int n = *argcp; + + argv[n++] = fn -> fn_addr ? fn -> fn_addr : ""; + argv[n++] = fn -> fn_dn ? fn -> fn_dn : ""; + if (crt) + argv[n++] = crit2txt (crt); + *argcp = n; +} + +int extension2txt (ext, fp, argv, argcp) +X400_Extension *ext; +FILE *fp; +char *argv[]; +int *argcp; +{ + int n = *argcp; + + argv[n++] = int2txt (ext -> ext_int); + argv[n++] = ext -> ext_oid ? sprintoid (ext -> ext_oid) : ""; + argv[n++] = qb2hex (ext -> ext_value); + argv[n++] = rcmd_srch (ext -> ext_criticality, tbl_crit); + argv[n++] = NULLCP; + + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[2]); + return OK; +} diff --git a/Lib/pp/p32txt.c b/Lib/pp/p32txt.c new file mode 100644 index 0000000..2583e1d --- /dev/null +++ b/Lib/pp/p32txt.c @@ -0,0 +1,87 @@ +/* p32txt.c: converts p3params into text encoding */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/p32txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/p32txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: p32txt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "q.h" +#include "tb_p3prm.h" + +extern int argv2fp (); +extern void mpduid2txt (); + +/* ------------------- Memory -> Text File ------------------------------ */ + +char *qb2hex (); + +extern char *time2txt (); +extern CMD_TABLE p3prm_tbl[]; + +int p32txt (fp, p3) +FILE *fp; +register P3params *p3; +{ + char *argv[100]; + int argc; + + PP_DBG (("Lib/pp/p32txt")); + + + argv[0] = rcmd_srch (P3PRM_MPDUID, p3prm_tbl); + argc = 1; + mpduid2txt (&p3->mpduid, argv, &argc); + if (argc > 1) { + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (p3 -> submit_time) { + argv[0] = rcmd_srch (P3PRM_STIME, p3prm_tbl); + argv[1] = time2txt (p3 -> submit_time); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (p3 -> content_type != NULLCP) { + argv[0] = rcmd_srch (P3PRM_CONTENT, p3prm_tbl); + argv[1] = p3 -> content_type; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (p3 -> originating_mta_certificate) { + argv[0] = rcmd_srch (P3PRM_ORIG_MTA_CERT, p3prm_tbl); + argv[1] = qb2hex (p3 -> originating_mta_certificate); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (p3 -> proof_of_submission) { + argv[0] = rcmd_srch (P3PRM_PROOF_OF_SUB, p3prm_tbl); + argv[1] = qb2hex (p3 -> proof_of_submission); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + (void) fprintf (fp, "%s\n", rcmd_srch (P3PRM_END, p3prm_tbl)); + + (void) fflush (fp); + return (ferror (fp) ? NOTOK : OK); +} diff --git a/Lib/pp/pps_mail.c b/Lib/pp/pps_mail.c new file mode 100644 index 0000000..9351f7f --- /dev/null +++ b/Lib/pp/pps_mail.c @@ -0,0 +1,436 @@ +/* pps_mail.c: simple mail interface */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/pps_mail.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/pps_mail.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: pps_mail.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +/* __________________________________________________________________________ + + +PP Simple interface, sort of equivalent to the MMDF ml_ library. +Works through submit though (as does the newer MMDF). +This code makes several assumptions. + 1) The input will always be RFC-822. + 2) The input will always be a local submission - + i.e. you can't pretend you are a channel. + +___________________________________________________________________________ */ + + + +#include "head.h" +#include +#include "prm.h" +#include "q.h" +#include "adr.h" +#include + + +#define INIT 1 +#define TO 2 +#define CC 3 +#define HEADER 4 +#define BODY 5 + + +extern char *loc_dom_site; +extern char *local_822_chan; +extern char *hdr_822_bp; +extern char *ia5_bp; +static int state = INIT; +static Q_struct qs; +static char *cc[120]; +static char *sender; +static char *subject; +static char *to[120]; +static int cccnt; +static int tocnt; +static struct prm_vars pv; +static UTC start_time; + +/* -- local routines -- */ +int pps_1adr(); +int pps_adr(); +int pps_aend(); +int pps_cc(); +int pps_end(); +int pps_file(); +int pps_hdr(); +int pps_init(); +int pps_tinit(); +int pps_to(); +int pps_txt(); +static int pps_adrhdr(); +static void pps_set(); + + + + +/* --------------------- Start of Routines ------------------------------ */ + + + + +int pps_init (subj, rp) +char *subj; /* the subject field - or not */ +RP_Buf *rp; +{ + struct passwd *pwd; + LIST_BPT *new; + ADDR *ap; + UTC now, utclocalise (); + + if (start_time) + free ((char *)start_time); + now = utcnow (); + start_time = utclocalise (now); + free ((char *)now); + + if (state != INIT) + (void) pps_end (NOTOK, rp); + tocnt = cccnt = 0; + if (subj) + subject = strdup (subj); + else + subject = NULLCP; + + if (rp_isbad (io_init(rp))) + return (pps_end (NOTOK, rp)); + + if (rp_isbad (io_wprm (&pv, rp))) + return (pps_end (NOTOK, rp)); + + q_init (&qs); + qs.inbound = list_rchan_new (loc_dom_site, local_822_chan); + + qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp); + new = list_bpt_new (ia5_bp); + list_bpt_add (&qs.encodedinfo.eit_types, new); + + + if (rp_isbad (io_wrq (&qs, rp))) + return (pps_end (NOTOK, rp)); + + if ((pwd = getpwuid (getuid())) == NULL) + return (pps_end (NOTOK, rp)); + + ap = adr_new (pwd->pw_name, AD_822_TYPE, 0); + ap -> ad_status = AD_STAT_DONE; + ap -> ad_resp = NO; + sender = strdup (pwd->pw_name); + + (void) io_wadr (ap, AD_ORIGINATOR, rp); + adr_tfree (ap); + + if (rp_isbad (rp -> rp_val)) + return (pps_end (NOTOK, rp)); + + state = TO; + return (OK); +} + + + + +int pps_adr (adr, rp) +char *adr; +RP_Buf *rp; +{ + ADDR *ap; + int retval; + + if (state != TO && state != CC) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + + + switch (state) { + case TO: + to[tocnt++] = strdup (adr); + break; + case CC: + cc[cccnt++] = strdup (adr); + break; + default: + return (pps_end (NOTOK, rp)); + } + + ap = adr_new (adr, AD_822_TYPE, 1); + retval = io_wadr (ap, AD_RECIPIENT, rp); + adr_tfree (ap); + + if (rp_isbad (retval)) + return (pps_end (NOTOK, rp)); + + return (OK); +} + + + + +int pps_aend(rp) +RP_Buf *rp; +{ + extern UTC utclocalise(); + char buf[BUFSIZ]; + + if (state != TO && state != CC) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + if (rp_isbad (io_adend (rp))) + return (pps_end (NOTOK, rp)); + + if (rp_isbad (io_tinit (rp)) || + rp_isbad (io_tpart ("hdr.822", FALSE, rp))) + return (pps_end (NOTOK, rp)); + + state = HEADER; + + (void) UTC2rfc (start_time, buf); + free ((char *)start_time); + start_time = NULLUTC; + if (pps_hdr ("Date:", buf, rp) == NOTOK || + pps_hdr ("From:", sender, rp) == NOTOK) + return NOTOK; + free (sender); + sender = NULLCP; + + if (tocnt > 0 && pps_adrhdr ("To:", to, tocnt, rp) != OK) + return NOTOK; + if (cccnt > 0 && pps_adrhdr ("Cc:", cc, cccnt, rp) != OK) + return NOTOK; + + if (isstr (subject)) { + if (pps_hdr ("Subject:", subject, rp) == NOTOK) + return NOTOK; + free (subject); + subject = NULLCP; + } + + return (OK); +} + + + + +int pps_tinit(rp) +RP_Buf *rp; +{ + + if (rp_isbad (io_tdata ("\n", 1))) { + pps_set (rp, RP_MECH, "Write error"); + return (NOTOK); + } + if (rp_isbad (io_tdend (rp)) || + rp_isbad (io_tpart ("1.ia5", FALSE, rp))) + return (pps_end (NOTOK, rp)); + state = BODY; + return (OK); +} + + + + +int pps_txt (str, rp) +char *str; +RP_Buf *rp; +{ + if (state != BODY) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + if (rp_isbad (io_tdata (str, strlen (str)))) { + pps_set (rp, RP_FIO, "Bad data transfer"); + return (pps_end (NOTOK, rp)); + } + return (OK); +} + +int pps_file (fp, rp) +FILE *fp; +RP_Buf *rp; +{ + char copybuf[BUFSIZ]; + int n; + + if (state != BODY) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + while (!feof (fp) && !ferror(fp)) { + if ((n = fread (copybuf, sizeof (char), + sizeof (copybuf), fp)) > 0) + if (rp_isbad (io_tdata (copybuf, n))) { + pps_set (rp, RP_FIO, "Bad data transfer"); + return pps_end (NOTOK, rp); + } + } + return (OK); +} + + + + +int pps_end (type, rp) +int type; +RP_Buf *rp; +{ + int i; + + if (type == OK && state == BODY) { + if (rp_isbad (io_tdend (rp))) + return (pps_end (NOTOK, rp)); + if (rp_isbad (io_tend (rp))) + return (pps_end (NOTOK, rp)); + } + + (void) io_end (type); + for (i = 0; i < tocnt; i++) + free (to[i]); + tocnt = 0; + for (i = 0; i < cccnt; i++) + free (cc[i]); + cccnt = 0; + if (subject) free (subject); + if (sender) free (sender); + sender = NULLCP; + subject = NULLCP; + state = INIT; + return (type); +} + + + + +int pps_to(rp) +RP_Buf *rp; +{ + if (state == TO || state == CC) { + state = TO; + return (OK); + } + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); +} + + + + +int pps_cc(rp) +RP_Buf *rp; +{ + if (state == TO || state == CC) { + state = CC; + return (OK); + } + pps_set (rp, RP_MECH, "Out of sync"); + return pps_end(NOTOK, rp); +} + + + + +int pps_hdr (name, contents, rp) +char *name, + *contents; +RP_Buf *rp; +{ + char buffer[LINESIZE]; + + if (state != HEADER) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + (void) sprintf (buffer, "%-10s%s\n", name, contents); + if (rp_isbad (io_tdata (buffer, strlen (buffer)))) { + pps_set (rp, RP_MECH, "Write error"); + return pps_end (NOTOK, rp); + } + return (OK); +} + + + + +int pps_1adr (subj, addr, rp) +char *subj, + *addr; +RP_Buf *rp; +{ + if (pps_init (subj, rp) == OK && + pps_adr (addr, rp) == OK && + pps_aend(rp) == OK && + pps_tinit(rp) == OK) + return (OK); + + return (NOTOK); +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static int pps_adrhdr (field, adr_array, count, rp) +char *field; +char *adr_array[]; +int count; +RP_Buf *rp; +{ + char buffer[LINESIZE]; + int i; + + if (state != HEADER) { + pps_set (rp, RP_MECH, "Out of sync"); + return (pps_end (NOTOK, rp)); + } + + (void) sprintf (buffer, "%-10s", field); + + for (i = 0; i < count; i++) { + (void) strcat (buffer, adr_array[i]); + if (i != count - 1 ) { + if ((int)strlen (buffer) > 64) { + (void) strcat (buffer, ",\n\t"); + (void) io_tdata (buffer, strlen (buffer)); + buffer[0] = '\0'; + } + else (void) strcat (buffer, ", "); + } + } + + if (buffer[0]) + (void) io_tdata (buffer, strlen (buffer)); + + if (rp_isbad (io_tdata ("\n", 1))) { + pps_set (rp, RP_MECH, "Write error"); + return pps_end (NOTOK, rp); + } + + return (OK); +} + +static void pps_set (rp, val, str) +RP_Buf *rp; +int val; +char *str; +{ + rp -> rp_val = val; + (void) strcpy (rp -> rp_line, str); +} diff --git a/Lib/pp/prm2txt.c b/Lib/pp/prm2txt.c new file mode 100644 index 0000000..83b392e --- /dev/null +++ b/Lib/pp/prm2txt.c @@ -0,0 +1,101 @@ +/* tx_prm.c: handles the MessageManagementParameter structures, + see manaul page QUEUE (5). +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/prm2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/prm2txt.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: prm2txt.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "prm.h" +#include "tb_prm.h" + +extern void genreset (); +extern int argv2fp (); + +extern CMD_TABLE + prmtbl_ln [/* message-management-parameters */], + prmtbl_opts [/* options */]; + + +/* ------------------- Memory -> Text File ------------------------------ */ + +static void PRM_opts2txt (); + +int prm2txt (fp, pp) /* MessageManagementParameters -> Txt */ +FILE *fp; +struct prm_vars *pp; +{ + extern char *int2txt (); + char *argv[100]; + int argc; + + genreset (); + PP_DBG (("Lib/pp/prm2txt()")); + + if (pp->prm_logfile != NULLCP) { + argv[0] = rcmd_srch (PRM_LOGFILE, prmtbl_ln); + argv[1] = pp -> prm_logfile; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (pp->prm_loglevel != NULL) { + argv[0] = rcmd_srch (PRM_LOGLEVEL, prmtbl_ln); + argv[1] = int2txt (pp->prm_loglevel); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (pp->prm_opts != NULL) { + argv[0] = rcmd_srch (PRM_OPTS, prmtbl_ln); + argc = 1; + PRM_opts2txt (pp->prm_opts, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (pp -> prm_passwd != NULL) { + argv[0] = rcmd_srch (PRM_PASSWD, prmtbl_ln); + argv[1] = pp -> prm_passwd; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + (void) fprintf (fp, "%s\n", rcmd_srch (PRM_END, prmtbl_ln)); + + return (ferror (fp) ? NOTOK : OK); +} + + +static void PRM_opts2txt (options, argv, argcp) /* Param options -> Txt */ +int options; +char *argv[]; +int *argcp; +{ + int i, narg= *argcp; + + PP_DBG (("Lib/pp/PRM_opts2txt(%d)", options)); + + for (i=0; i < PRM_OPTS_TOTAL; i++) + if (options & (1< +#include "q.h" +#include "tb_com.h" +#include "tb_q.h" +#include "mta.h" + +#define crit2txt(n) rcmd_srch ((n), tbl_crit) +#define txt2int(n) atoi (n) + +extern void genreset (); +extern int argv2fp (); +extern void encodedinfo2txt (); +extern int extension2txt (); +extern void mpduid2txt (); +extern void trace2txt (); +extern char *no2txt3(); + +extern CMD_TABLE + tbl_crit [], + tbl_bool [], + qtbl_que [/* message-envelope-parameters */], + qtbl_mt_type [/* message-type */], + qtbl_con_type [/* content-type */], + qtbl_priority [/* message-priority */]; + + + +/* ------------------- Memory -> Text File ------------------------------ */ + +char *qb2hex (); + +static char *Q_msgtype2txt (), *Q_priority2txt (); +void dlexp2txt (); +void fname2txt (); +extern char *int2txt (); +extern char *time2txt (); + +int q2txt (fp, qp) +FILE *fp; +register Q_struct *qp; +{ + char *argv[100], buf[5]; + int argc; + Trace *trace; + DLHistory *dlexp; + + genreset (); + + PP_DBG (("Lib/pp/q2txt(type=%d, size=%ld)", + qp->msgtype, qp->msgsize)); + + argv[0] = rcmd_srch (Q_MSGTYPE, qtbl_que); + argv[1] = Q_msgtype2txt (qp->msgtype); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + + if (qp -> msgsize != 0) { + argv[0] = rcmd_srch (Q_MSGSIZE, qtbl_que); + argv[1] = int2txt ((int)qp->msgsize); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp->defertime != 0) { + argv[0] = rcmd_srch (Q_DEFERREDTIME, qtbl_que); + argv[1] = time2txt (qp->defertime); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> latest_time) { + argv[0] = rcmd_srch (Q_LATESTTIME, qtbl_que); + argv[1] = time2txt (qp -> latest_time); + argv[2] = crit2txt (qp -> latest_time_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_NWARNS, qtbl_que); + argv[1] = no2txt3((int)qp->nwarns, buf); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + + if (qp -> warninterval != 0) { + argv[0] = rcmd_srch (Q_WARNINTERVAL, qtbl_que); + argv[1] = int2txt (qp->warninterval); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> retinterval != 0) { + argv[0] = rcmd_srch (Q_RETINTERVAL, qtbl_que); + argv[1] = int2txt (qp->retinterval); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> cont_type != NULLCP) { + argv[0] = rcmd_srch (Q_CONTENT_TYPE, qtbl_que); + argv[1] = qp -> cont_type; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_ENCODED_INFO, qtbl_que); + argc = 1; + encodedinfo2txt (&qp->encodedinfo, argv, &argc); + argv[argc] = NULLCP; + if (argc != 1) + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + + argv[0] = rcmd_srch (Q_ORIG_ENCODED_INFO, qtbl_que); + argc = 1; + encodedinfo2txt (&qp->orig_encodedinfo, argv, &argc); + argv[argc] = NULLCP; + if (argc != 1) + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + + if (qp -> priority != PRIO_NORMAL) { + argv[0] = rcmd_srch (Q_PRIORITY, qtbl_que); + argv[1] = Q_priority2txt (qp->priority); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> disclose_recips) { + argv[0] = rcmd_srch (Q_DISCLOSE_RECIPS, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (qp -> implicit_conversion_prohibited) { + argv[0] = rcmd_srch (Q_IMPLICIT_CONVERSION, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (qp -> alternate_recip_allowed) { + argv[0] = rcmd_srch (Q_ALTERNATE_RECIP_ALLOWED, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (qp -> content_return_request) { + argv[0] = rcmd_srch (Q_CONTENT_RETURN_REQUEST, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> recip_reassign_prohibited) { + argv[0] = rcmd_srch (Q_RECIP_REASSIGN_PROHIBITED, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = crit2txt (qp -> recip_reassign_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> dl_expansion_prohibited) { + argv[0] = rcmd_srch (Q_DL_EXP_PROHIBITIED, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = crit2txt (qp -> dl_expansion_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> conversion_with_loss_prohibited) { + argv[0] = rcmd_srch (Q_CONV_WITH_LOSS, qtbl_que); + argv[1] = rcmd_srch (TRUE, tbl_bool); + argv[2] = crit2txt (qp -> conversion_with_loss_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp->ua_id != NULLCP) { + argv[0] = rcmd_srch (Q_UA_ID, qtbl_que); + argv[1] = qp -> ua_id; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> pp_content_correlator) { + argv[0] = rcmd_srch (Q_PP_CONT_CORR, qtbl_que); + argv[1] = qp -> pp_content_correlator; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> general_content_correlator) { + argv[0] = rcmd_srch (Q_GEN_CONT_CORR, qtbl_que); + argv[1] = qb2hex (qp -> general_content_correlator); + argv[2] = crit2txt (qp -> content_correlator_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (qp -> originator_return_address) { + argv[0] = rcmd_srch (Q_ORIG_RETURN_ADDRESS, qtbl_que); + argc = 1; + fname2txt (qp -> originator_return_address, + qp -> originator_return_address_crit, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> forwarding_request != NOTOK) { + argv[0] = rcmd_srch (Q_FORWARDING_REQUEST, qtbl_que); + argv[1] = int2txt (qp -> forwarding_request); + argv[2] = crit2txt (qp -> forwarding_request_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> originator_certificate) { + argv[0] = rcmd_srch (Q_ORIGINATOR_CERT, qtbl_que); + argv[1] = qb2hex (qp -> originator_certificate); + argv[2] = crit2txt (qp -> originator_certificate_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (qp -> algorithm_identifier) { + argv[0] = rcmd_srch (Q_ALGORITHM_ID, qtbl_que); + argv[1] = qb2hex (qp -> algorithm_identifier); + argv[2] = crit2txt (qp -> algorithm_identifier_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (qp -> message_origin_auth_check) { + argv[0] = rcmd_srch (Q_MESSAGE_ORIGIN_AUTH_CHECK, qtbl_que); + argv[1] = qb2hex (qp -> message_origin_auth_check); + argv[2] = crit2txt (qp -> message_origin_auth_check_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (qp -> security_label) { + argv[0] = rcmd_srch (Q_SECURITY_LABEL, qtbl_que); + argv[1] = qb2hex (qp -> security_label); + argv[2] = crit2txt (qp -> security_label_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + free (argv[1]); + } + + if (qp -> proof_of_submission_request) { + argv[0] = rcmd_srch (Q_PROOF_OF_SUB, qtbl_que); + argv[1] = int2txt (qp -> proof_of_submission_request); + argv[2] = crit2txt (qp -> proof_of_submission_crit); + argv[3] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_MESSAGE_EXTENSIONS, qtbl_que); + if (qp -> per_message_extensions) { + X400_Extension *ext; + + for (ext = qp -> per_message_extensions; + ext; ext = ext -> ext_next) { + argc = 1; + if (extension2txt (ext, fp, argv, &argc) == NOTOK) + return NOTOK; + } + } + + if (qp -> inbound && qp -> inbound -> li_chan) { + argv[0] = rcmd_srch (Q_INCHANNEL, qtbl_que); + argv[1] = qp -> inbound -> li_chan -> ch_name; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if ( qp -> inbound && qp -> inbound -> li_mta) { + argv[0] = rcmd_srch (Q_INHOST, qtbl_que); + argv[1] = qp -> inbound -> li_mta; + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_MSGID, qtbl_que); + argc = 1; + mpduid2txt (&qp->msgid, argv, &argc); + if (argc > 1) { + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_TRACE, qtbl_que); + for (trace = qp->trace; trace; trace = trace -> trace_next) { + argc = 1; + trace2txt (trace, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + argv[0] = rcmd_srch (Q_DL_EXP_HISTORY, qtbl_que); + for (dlexp = qp -> dl_expansion_history; dlexp; + dlexp = dlexp -> dlh_next) { + argc = 1; + dlexp2txt (dlexp, argv, &argc); + argv[argc] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + if (qp -> dl_expansion_history_crit) { + argv[0] = rcmd_srch (Q_DL_EXP_HIST_CRIT, qtbl_que); + argv[1] = crit2txt (qp -> dl_expansion_history_crit); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp -> queuetime != 0) { + argv[0] = rcmd_srch (Q_QUEUETIME, qtbl_que); + argv[1] = time2txt (qp->queuetime); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + if (qp->departime != 0) { + argv[0] = rcmd_srch (Q_DEPARTIME, qtbl_que); + argv[1] = time2txt (qp->departime); + argv[2] = NULLCP; + if (argv2fp (fp, argv) == NOTOK) + return NOTOK; + } + + (void) fprintf (fp, "%s\n", rcmd_srch (Q_END, qtbl_que)); + + return (ferror (fp) ? NOTOK : OK); +} + + +static char *Q_msgtype2txt (type) /* Message-type -> Txt */ +int type; +{ + PP_DBG (("Lib/pp/Q_msgtype2txt (%d)", type)); + + switch (type) { + case MT_UMPDU: + case MT_PMPDU: + case MT_DMPDU: + return rcmd_srch (type, qtbl_mt_type); + } + return NULLCP; +} + +static char *Q_priority2txt (type) /* Priority -> Txt */ +int type; +{ + PP_DBG (("Lib/pp/Q_priority2txt('%d')", type)); + + switch (type) { + case PRIO_NORMAL: + case PRIO_NONURGENT: + case PRIO_URGENT: + return rcmd_srch (type, qtbl_priority); + } + return NULLCP; +} diff --git a/Lib/pp/set_1dr.c b/Lib/pp/set_1dr.c new file mode 100644 index 0000000..2eb481d --- /dev/null +++ b/Lib/pp/set_1dr.c @@ -0,0 +1,213 @@ +/* set_1dr.c: Do the necessary stuff to mark one recip as needing a DR */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/set_1dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/set_1dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: set_1dr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "q.h" +#include "dr.h" +#include "retcode.h" +#include + +extern UTC utclocalise (); +extern char *ppversion; +extern CMD_TABLE rr_tcode[], + rr_dcode[], + rr_rcode[]; + +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) + +int set_all_dr (qp, ap, msg, reason, diag, str) +Q_struct *qp; +ADDR *ap; +char *msg; +int reason, diag; +char *str; +{ + for (; ap; ap = ap -> ad_next) + if (set_1dr(qp, ap -> ad_no, msg, reason, diag, str) == NOTOK) + return NOTOK; + return OK; +} + +int set_1dr (qp, no, msg, reason, diag, str) +Q_struct *qp; +int no; +char *msg; +int reason, diag; +char *str; +{ + ADDR *ap; + + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) { + if (ap -> ad_no == no) + break; + } + + if (ap == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, ("set_1dr: address %d not found", + no)); + return NOTOK; + } + + ap -> ad_status = AD_STAT_DRREQUIRED; + + ap -> ad_reason = reason; + ap -> ad_diagnostic = diag; + ap -> ad_add_info = (str == NULLCP) ? NULLCP : strdup(str); + + return wr_dr_stat_log (qp, qp -> Oaddress, ap, msg, + reason == DRR_NO_REASON ? + "positive" : "negative"); +} + + +/* ARGSUSED */ +wr_dr_stat_log (qp, sender, ap, msg, drtype) +Q_struct *qp; +ADDR *sender; +ADDR *ap; +char *msg; +char *drtype; +{ + char *argv[100]; + int argc; + char buffer[BUFSIZ]; + char midbuf[BUFSIZ]; + char tbuf1[BUFSIZ], tbuf2[BUFSIZ]; + char sbuf[40]; + LIST_RCHAN *lastchan; + int arg2vstr (); + static char *eq = "="; + static char *none = "none"; + + argc = 0; + argv[argc ++] = "DR"; + argv[argc++] = drtype; + + if (msg) + argv[argc++] = msg; + else + argv[argc++] = none; + + argv[argc++] = eq; + argv[argc++] = "p1msgid"; + (void) msgid2rfc_aux (&qp -> msgid, midbuf, FALSE); + argv[argc++] = midbuf; + + argv[argc++] = eq; + argv[argc++] = "size"; + (void) sprintf (sbuf, "%d", qp -> msgsize); + argv[argc++] = sbuf; + + argv[argc++] = eq; + argv[argc++] = "inchan"; + argv[argc++] = qp->inbound->li_chan->ch_name; + + argv[argc++] = eq; + argv[argc++] = "dr_dest"; + argv[argc++] = gval(qp->Oaddress); + + argv[argc++] = qp->inbound->li_mta; + + argv[argc++] = eq; + argv[argc++] = "outchan"; + if (ap -> ad_outchan && ap -> ad_outchan -> li_chan) + argv[argc++] = ap->ad_outchan->li_chan->ch_name; + else + argv[argc++] = none; + + argv[argc++] = eq; + argv[argc++] = "dr-src"; + argv[argc++] = gval(ap); + + if (ap -> ad_outchan && ap -> ad_outchan -> li_mta) + argv[argc++] = ap->ad_outchan->li_mta; + else + argv[argc++] = none; + + lastchan = ap -> ad_fmtchan; + if (ap->ad_rcnt != 0) { + int i = 0; + while (i < ap->ad_rcnt && lastchan != NULLIST_RCHAN) { + i++; + lastchan = lastchan->li_next; + } + } + if (lastchan == NULLIST_RCHAN) + lastchan = ap->ad_outchan; + + argv[argc++] = eq; + argv[argc++] = "cur-channel"; + if (lastchan && lastchan -> li_chan) + argv[argc++] = lastchan->li_chan->ch_name; + else argv[argc++] = "submit"; + + if (ap -> ad_reason != DRR_NO_REASON) { + argv[argc ++] = eq; + argv[argc++] = "reason"; + argv[argc++] = rcmd_srch(ap -> ad_reason, rr_rcode); + + argv[argc++] = eq; + argv[argc++] = "diag"; + argv[argc++] = rcmd_srch (ap -> ad_diagnostic, rr_dcode); + + if (ap -> ad_add_info) + argv[argc++] = ap -> ad_add_info; + } + else { + argv[argc++] = eq; + argv[argc++] = "submit-time"; + (void) strcpy (tbuf1, "unknown"); + if (qp -> trace != NULL && + qp -> trace -> trace_DomSinfo.dsi_time) { + UTC ut = utclocalise (qp -> trace -> trace_DomSinfo.dsi_time); + if (ut) { + (void) sprintf (tbuf1, "%d:%d:%d:%02d:%02d", + ut -> ut_mon, ut -> ut_mday, + ut -> ut_hour, ut -> ut_min, + ut -> ut_sec); + free ((char *) ut); + } + + } + argv[argc++] = tbuf1; + + argv[argc++] = eq; + argv[argc++] = "queued-time"; + (void) strcpy (tbuf2, "unknown"); + if (qp -> queuetime) { + UTC ut = utclocalise (qp -> queuetime); + if (ut) { + (void) sprintf (tbuf2, "%d:%d:%d:%02d:%02d", + ut -> ut_mon, ut -> ut_mday, + ut -> ut_hour, ut -> ut_min, + ut -> ut_sec); + free ((char *) ut); + } + + } + argv[argc++] = tbuf2; + + } + argv[argc] = NULL; + + if (arg2vstr (0, sizeof buffer, buffer, argv) == NOTOK) + return NOTOK; + PP_STAT (("%s", buffer)); + return OK; +} diff --git a/Lib/pp/static.c b/Lib/pp/static.c new file mode 100644 index 0000000..b368696 --- /dev/null +++ b/Lib/pp/static.c @@ -0,0 +1,129 @@ +/* static.c: static configuration */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/static.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/static.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: static.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "list_bpt.h" + + +CHAN **ch_all; +Table **tb_all; +LIST_BPT *bodies_all = NULLIST_BPT; +LIST_BPT *headers_all = NULLIST_BPT; + + + +char *aquefile = "addr"; +char *bquedir = "base"; +char *chndfldir = "chans"; +char *formdfldir = "format"; +char *loc_dom_mta = "bogus"; +char *loc_dom_site = "bogus"; +char *loc_or = ""; +char *postmaster = "***INVALID***"; +char *adminstration_req_alt = NULLCP; +char *ppdbm = "ppdbm"; +char *pplogin = "pp"; /* -- login user id of pp -- */ +char *pptsapd_addr = "Internet=localhost+20001"; +char *delim1 = "\1\1\1\1\n"; +char *delim2 = "\1\1\1\1\n"; +char *mboxname = "ppmailbox"; +char *qmgr_hostname = "localhost"; +char *authchannel = "block"; +char *authloglevel = "low"; +char *wrndfldir = "warnings"; /* relative to tbldfldir */ +char *wrnfile = "warning"; /* basename of files containing template warnings */ + +char *x400_mta = NULLCP; + +int return_interval_norm = 24 * 3; /* return after 3 days */ +int return_interval_high = 24 * 1; /* return time 1 day */ +int return_interval_low = 24 * 7; /* return time 7 days */ +int warn_interval = 24 * 1; /* warn after 1 */ +int warn_number = 2; /* 2 warnings */ +int max_hops = 25; /* max number of trace fields */ +int max_loops = 5; /* max times through our MTA */ +int queue_fanout = 0; /* how many sub directories at each level */ +int queue_depth = 0; /* how many depths of sub directory */ +int use_fsync = 1; /* use fsync if available */ +int disk_percent = NOTOK; /* free block percentage */ +int disk_blocks = NOTOK; /* free block count */ + +/* hardwired in names */ +char *submit_prog = "submit"; +char *dr_file = "report."; +char *uucpin_chan = "uucp-in"; +char *local_822_chan = "822-local"; +char *alias_tbl = "aliases"; +char *channel_tbl = "channel"; +char *list_tbl = "list"; +char *user_tbl = "users"; +char *or_tbl = "or"; +char *or2rfc_tbl = "or2rfc"; +char *rfc2or_tbl = "rfc2or"; +char *rfc1148gateway_tbl = "rfc1148gate"; +char *chan_auth_tbl = "auth.channel"; +char *mta_auth_tbl = "auth.mta"; +char *user_auth_tbl = "auth.user"; +char *hdr_prefix = "hdr."; +char *hdr_822_bp = "hdr.822"; +char *hdr_p2_bp = "hdr.p2"; +char *hdr_p22_bp = "hdr.p22"; +char *hdr_ipn_bp = "hdr.ipn"; +char *ia5_bp = "ia5"; +char *qmgr_auth_tbl = "auth.qmgr"; +char *cont_822 = "822"; +char *cont_p2 = "p2"; +char *cont_p22 = "p22"; +char *mailfilter = ".mailfilter"; +char *sysmailfilter = "/usr/local/lib/mailfilter"; +char *submit_addr = NULLCP; +char *dap_user = NULLCP; +char *dap_passwd = NULLCP; + +/* used in distribution list stuff */ +char *loc_dist_prefix = "dist-"; +char *list_tbl_comment = "Comment:"; + +/* used in locking */ +char *lockdir = "/tmp"; +int lockstyle = LOCK_FLOCK; +int lock_break_time = 30 * 60; /* 30 mins grace time */ + +/* -- Logging info -- */ + +static LLog oper_log = { + "oper", NULLCP, NULLCP, + LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, + LLOGCLS | LLOGCRT, NOTOK +}; + +static LLog stat_log = { + "stat", NULLCP, NULLCP, + LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, + LLOGCLS | LLOGCRT, NOTOK +}; + +static LLog norm_log = { + "norm", NULLCP, NULLCP, + LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, + LLOGCRT, NOTOK +}; + +LLog *pp_log_norm = &norm_log; +LLog *pp_log_oper = &oper_log; +LLog *pp_log_stat = &stat_log; diff --git a/Lib/pp/tb_a.c b/Lib/pp/tb_a.c new file mode 100644 index 0000000..9ee4122 --- /dev/null +++ b/Lib/pp/tb_a.c @@ -0,0 +1,201 @@ +/* tb_a.c: Address tables for Address Lines in ADDR Control Files */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_a.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_a.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_a.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "tb_a.h" +#include "adr.h" +#include + + + +/* ------------------------------------------------------------------------ */ + + + +CMD_TABLE atbl_ctrl_addrs[] = { /* Env-ctrl-addresses */ + "Origs", AD_ORIGINATOR, + "Recip", AD_RECIPIENT, + 0, -1 + }; + + +/* sorted - do not reorder */ +CMD_TABLE atbl_addr[] = { /* address-lines */ + "content", AD_CONTENT, + "content_integrity", AD_CONTENT_INTEGRITY, + "content_integrity_crit", AD_CONTENT_INTEGRITY_CRIT, + "dn", AD_DN, + "eits", AD_EITS, + "end-of-addr", AD_END, + "explicit", AD_EXPLICITCONVERSION, + "ext-id", AD_EXTENSION_ID, + "extension", AD_EXTENSION, + "message_token", AD_MESSAGE_TOKEN, + "message_token_crit", AD_MESSAGE_TOKEN_CRIT, + "mta-rreq", AD_MTA_REP_REQ, + "orig", AD_ORIG, + "orig-req-alt", AD_ORIG_REQ_ALT, + "orig-req-alt-crit", AD_ORIG_REQ_ALT_CRIT, + "outchan", AD_OUTCHAN, + "outmta", AD_OUTHOST, + "pd_report_request", AD_PD_REPORT_REQUEST, + "pd_report_request_crit", AD_PD_REPORT_REQUEST_CRIT, + "phys-forward", AD_PHYS_FORWARD, + "phys_forward_crit", AD_PHYS_FORWARD_CRIT, + "phys_fw_ad", AD_PHYS_FW_AD, + "phys_fw_ad_crit", AD_PHYS_FW_AD_CRIT, + "phys_modes", AD_PHYS_MODES, + "phys_modes_crit", AD_PHYS_MODES_CRIT, + "phys_rendition", AD_PHYS_RENDITION, + "phys_rendition_crit", AD_PHYS_RENDITION_CRIT, + "proof_delivery", AD_PROOF_DELIVERY, + "proof_delivery_crit", AD_PROOF_DELIVERY_CRIT, + "recip_number_advice", AD_RECIP_NUMBER_ADVICE, + "recip_number_advice_crit", AD_RECIP_NUMBER_ADVICE_CRIT, + "redirection_history", AD_REDIRECTION_HISTORY, + "redirection_history_crit", AD_REDIRECTION_HISTORY_CRIT, + "reform-done", AD_REFORM_DONE, /* DO NOT CHANGE */ + "reform-list", AD_REFORM_LIST, + "reg_mail", AD_REG_MAIL, + "reg_mail_crit", AD_REG_MAIL_CRIT, + "req_del", AD_REQ_DEL, + "req_del_crit", AD_REQ_DEL_CRIT, + "resp", AD_RESPONSIBILITY, + "rfc", AD_822, + "rfcdr", AD_822DR, + "rno", AD_RECIP_NO, /* DO NOT CHANGE */ + "status", AD_STATUS, /* DO NOT CHANGE */ + "subtype", AD_SUBTYPE, + "type", AD_ADDTYPE, + "usr-rreq", AD_USR_REP_REQ, + "x400", AD_X400, + "x400dr", AD_X400DR, + "x400orig", AD_X400ORIG, + 0, -1 + }; +int n_atbl_addr = ((sizeof(atbl_addr)/sizeof(CMD_TABLE)) - 1); + + +CMD_TABLE atbl_status[] = { /* recipient-status */ + "pend", AD_STAT_PEND, + "done", AD_STAT_DONE, + "drrq", AD_STAT_DRREQUIRED, + "dliv", AD_STAT_DRWRITTEN, + "errs", AD_STAT_UNKNOWN, + 0, -1 + }; + + + +CMD_TABLE atbl_mtarreq[] = { /* mta-report-request */ + "undefined", AD_MTA_NONE, + "basic", AD_MTA_BASIC, + "confirmed", AD_MTA_CONFIRM, + "audit-&-confirmed", AD_MTA_AUDIT_CONFIRM, + 0, -1 + }; + + + +CMD_TABLE atbl_usrreq[] = { /* user-report-request */ + "no-report", AD_USR_NOREPORT, + "basic", AD_USR_BASIC, + "confirmed", AD_USR_CONFIRM, + "undefined", AD_USR_NONE, + 0, -1 + }; + + +/* sorted - do not reorder */ +CMD_TABLE atbl_expconversion[] = { /* explicit-conversion */ + "ia52Teletex", AD_EXP_IA5_TEXT_TO_TELETEX, + "ia52g3fax", AD_EXP_IA5_TEXT_TO_G3_FACSIMILE, + "ia52g4fax1", AD_EXP_IA5_TEXT_TO_G4_CLASS_1, + "ia52telex", AD_EXP_IA5_TEXT_TO_TELEX, + "ia5tovideo", AD_EXP_IA5_TEXT_TO_VIDEOTEX, + "teletex2Telex", AD_EXP_TELETEX_TO_TELEX, + "teletex2g3fax", AD_EXP_TELETEX_TO_G3_FACSIMILE, + "teletex2g4fax1", AD_EXP_TELETEX_TO_G4_CLASS_1, + "teletex2ia5", AD_EXP_TELETEX_TO_IA5_TEXT, + "teletex2video", AD_EXP_TELETEX_TO_VIDEOTEX, + "telex2g4fax1", AD_EXP_TELEX_TO_G4_CLASS_1, + "telex2ia5", AD_EXP_TELEX_TO_IA5_TEXT, + "telex2telex", AD_EXP_TELEX_TO_TELETEX, + "telex2video", AD_EXP_TELEX_TO_VIDEOTEX, + "texlex2g3fax", AD_EXP_TELEX_TO_G3_FACSIMILE, + "video2ia5", AD_EXP_VIDEOTEX_TO_IA5_TEXT, + "video2telex", AD_EXP_VIDEOTEX_TO_TELETEX, + "video2telex", AD_EXP_VIDEOTEX_TO_TELEX, + 0, -1 + }; +int n_atbl_expconversion = ((sizeof(atbl_expconversion)/sizeof(CMD_TABLE)) -1); + + +CMD_TABLE atbl_types[] = { /* address-type */ + "x400", AD_X400_TYPE, + "822", AD_822_TYPE, + "any", AD_ANY_TYPE, + 0, -1 + }; + + + +CMD_TABLE atbl_subtypes[] = { /* address-subtype */ + "jnt", AD_JNT, + "real.rfc733", AD_REAL733, + "real.rfc822", AD_REAL822, + "x400-84", AD_X400_84, + "x400-88", AD_X400_88, + 0, -1 + }; + + +CMD_TABLE atbl_reg_mail[] = { + "non-registered", AD_RMT_NON_REG, + "registered", AD_RMT_REG, + "personal", AD_RMT_PERSON, + 0, -1 +}; + +/* sorted - do not reorder */ +CMD_TABLE atbl_pd_modes[] = { + "bureau", AD_PM_CNT_BUREAU, + "counter-collect", AD_PM_CNT, + "counter-collect+telephone", AD_PM_CNT_PHONE, + "counter-collect+teletex", AD_PM_CNT_TTX, + "counter-collect+telex", AD_PM_CNT_TLX, + "express", AD_PM_EXPR, + "ordinary", AD_PM_ORD, + "special", AD_PM_SPEC, + 0, -1 +}; +int n_atbl_pd_modes = ((sizeof(atbl_pd_modes)/sizeof(CMD_TABLE)) -1); + +/* sorted - do not re-order */ +CMD_TABLE atbl_rdm[] = { + "any", AD_RDM_ANY, + "g3fax", AD_RDM_G3, + "g4fax", AD_RDM_G4, + "mhs", AD_RDM_MHS, + "pd", AD_RDM_PD, + "tlx", AD_RDM_TLX, + "ttx", AD_RDM_TTX, + "tty", AD_RDM_TTY, + "vtx", AD_RDM_VTX, + 0, -1 +}; +int n_atbl_rdm = ((sizeof(atbl_rdm)/sizeof(CMD_TABLE)) -1); diff --git a/Lib/pp/tb_bpt84.c b/Lib/pp/tb_bpt84.c new file mode 100644 index 0000000..c32e2bc --- /dev/null +++ b/Lib/pp/tb_bpt84.c @@ -0,0 +1,52 @@ +/* tb_bp.c: table of body parts see manual page BODYPARTS (5) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_bpt84.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_bpt84.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_bpt84.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include +#include "tb_bpt84.h" + + +CMD_TABLE bptbl_body_parts84 [] = { /* PP Body parts */ + + /* + Unique body part types + */ + + "deliv.p2-txt", BPT_P2_DLIV_TXT, + "hdr.ipn", BPT_HDR_IPN, + "hdr.p2", BPT_HDR_P2, + "hdr.822", BPT_HDR_822, + + /* + Repeated body part types + */ + + "encrypted", BPT_ENCRYPTED, + "g3fax", BPT_G3FAX, + "ia5", BPT_IA5, + "ipm", BPT_IPM, + "national", BPT_NATIONAL, + "sfd", BPT_SFD, + "tif0", BPT_TIF0, + "tif1", BPT_TIF1, + "tlx", BPT_TLX, + "ttx", BPT_TTX, + "undefined", BPT_UNDEFINED, + "videotex", BPT_VIDEOTEX, + "voice", BPT_VOICE, + "odif", BPT_ODIF, + 0, -1 + }; diff --git a/Lib/pp/tb_bpt88.c b/Lib/pp/tb_bpt88.c new file mode 100644 index 0000000..41a17e5 --- /dev/null +++ b/Lib/pp/tb_bpt88.c @@ -0,0 +1,55 @@ +/* tb_bp.c: table of body parts see manual page BODYPARTS (5) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_bpt88.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_bpt88.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_bpt88.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include +#include "tb_bpt88.h" + +CMD_TABLE bptbl_body_parts88 [] = { /* PP Body parts */ + + /* + Unique body part types + */ + + "deliv.p2-txt", BPT_P2_DLIV_TXT, + "hdr.ipn", BPT_HDR_IPN, + "hdr.p22", BPT_HDR_P22, + "hdr.p2", BPT_HDR_P2, + "hdr.822", BPT_HDR_822, + + /* + Repeated body part types + */ + + "encrypted", BPT_ENCRYPTED, + "g3fax", BPT_G3FAX, + "ia5", BPT_IA5, + "ipm", BPT_IPM, + "national", BPT_NATIONAL, + "sfd", BPT_SFD, + "tif0", BPT_TIF0, + "tif1", BPT_TIF1, + "tlx", BPT_TLX, + "ttx", BPT_TTX, + "undefined", BPT_UNDEFINED, + "videotex", BPT_VIDEOTEX, + "voice", BPT_VOICE, + "odif", BPT_ODIF, + "iso6937", BPT_ISO6937TEXT, + "bilateral", BPT_BILATERAL, + "external", BPT_EXTERNAL, + 0, -1 + }; diff --git a/Lib/pp/tb_dr.c b/Lib/pp/tb_dr.c new file mode 100644 index 0000000..24cf976 --- /dev/null +++ b/Lib/pp/tb_dr.c @@ -0,0 +1,139 @@ +/* -- tb_dr.c Delivery Report tables, files located in Q/MSG -- */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_dr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "dr.h" +#include "tb_com.h" +#include "tb_dr.h" +#include + + +/* ------------------------------------------------------------------------ */ + +CMD_TABLE drtbl[] = { /* -- delivery-notification -- */ + "Dl-Exp-Hist", DR_DL_EXP_HIST, + "Dl-Exp-Hist-Crit", DR_DL_EXP_HIST_CRIT, + "Msgid", DR_MSGID, + "Per-Envelope-Extension", DR_PER_ENVELOPE_EXTENSIONS, + "Per-Report-Extension", DR_PER_REPORT_EXTENSIONS, + "Report-End", DR_END, + "Report-Hdr-End", DR_END_HDR, + "Report-Origin-Auth-Check", DR_REPORT_ORIGIN_AUTH_CHECK, + "Reporting-Mta-Certificate", DR_REPORTING_MTA_CERTIFICATE, + "Reporting-Name", DR_REPORTING_DL_NAME, + "Security-Label", DR_SECURITY_LABEL, + "Subject-Intermediate-Trace", DR_SI_TRACE, + "Trace", DR_TRACE, + 0, -1 +}; +int n_drtbl = ((sizeof(drtbl)/sizeof(CMD_TABLE)) -1); + +CMD_TABLE rrtbl[] = { + "Arrival-Time", RR_ARRIVAL, + "Converted_Eit", RR_CONVERTED, + "DR-Failure", RR_FAILURE, + "DR-Success", RR_SUCCESS, + "Originally-Intended-Recip", RR_ORIGINALLY_INTENDED_RECIP, + "Per-Recip-Extension", RR_PER_RECIP_EXTENSIONS, + "Physical-Fwd", RR_PHYSICAL_FWD, + "Recip-Certificate", RR_RECIP_CERTIFICATE, + "Recip-No", RR_RECIP, + "Redirect-History", RR_REDIRECT_HISTORY, + "Redirect-History-Crit", RR_REDIRECT_HISTORY_CRIT, + "Report-End", RR_END, + "Report-Origin-Check", RR_REPORT_ORIGIN_CHECK, + "Reported-Recipient-End", RR_END_RECIP, + "Supplementary-Info", RR_SUPPLEMENTARY, + 0, -1 +}; +int n_rrtbl = ((sizeof(rrtbl)/sizeof(CMD_TABLE)) -1); + +CMD_TABLE rr_tcode [] = { /* -- MTS user type codes -- */ + "Public", DRT_PUBLIC, + "Private", DRT_PRIVATE, + "Ms", DRT_MS, + "Dl", DRT_DL, + "Pdau", DRT_PDAU, + "Physical-Recipient", DRT_PHYSICAL_RECIPIENT, + "Other", DRT_OTHER, + 0, -1, + }; + +CMD_TABLE rr_rcode [] = { /* -- reason-codes -- */ + "Conversion-Not-Performed", DRR_CONVERSION_NOT_PERFORMED, + "Directory-Operation-Unsuccessful", DRR_DIRECTORY_OP_UNSUCCESSFUL, + "Phys-Delivery-Not-Performed", DRR_PHYS_DELIVERY_NOT_PERFORMED, + "Phys-Rendition-Not-Performed", DRR_PHYS_RENDITION_NOT_PERFORMED, + "Restricted-Delivery", DRR_RESTRICTED_DELIVERY, + "Transfer-Failure", DRR_TRANSFER_FAILURE, + "Unable-To-Transfer", DRR_UNABLE_TO_TRANSFER, + 0, -1 + }; +int n_rr_rcode = ((sizeof(rr_rcode)/sizeof(CMD_TABLE)) - 1); + +CMD_TABLE rr_dcode [] = { /* -- diagnostic-codes -- */ + "Alphabetic-Character-Loss", DRD_ALPHABETIC_CHARACTER_LOSS, + "Ambiguous-ORName", DRD_AMBIGUOUS_OR, + "Content-Syntax-Error", DRD_CONTENT_SYNTAX_ERROR, + "Content-Too-Long", DRD_CONTENT_TOO_LONG, + "Content-Type-Not-Supported", DRD_CONTENT_TYPE_NOT_SUPPORTED, + "Conversion-Impractical", DRD_CONVERSION_IMPRACTICAL, + "Conversion-Prohibited", DRD_CONVERSION_PROHIBITED, + "Conversion-With-Loss-Prohibited", DRD_CONVERSION_WITH_LOSS_PROHIBITED, + "Dl-Expansion-Failure", DRD_DL_EXPANSION_FAILURE, + "Dl-Expansion-Prohibited", DRD_DL_EXPANSION_PROHIBITED, + "Encoded-Information-Types-Unsupported",DRD_ENCINFOTYPES_NOTSUPPORTED, + "Implicit-Conversion-Not-Registered", DRD_IMPLICITCONV_NOTREGISTERED, + "Invalid-Parameters", DRD_INVALID_PARAMETERS, + "Line-Too-Long", DRD_LINE_TOO_LONG, + "Loop-Detected", DRD_LOOP_DETECTED, + "Maximum-Time-Expired", DRD_MAX_TIME_EXPIRED, + "MTA-Congestion", DRD_MTA_CONGESTION, + "Multiple-Information-Loss", DRD_MULTIPLE_INFORMATION_LOSS, + "No-Bilateral-Agreement", DRD_NO_BILATERAL_AGREEMENT, + "No-Dl-Submit-Permission", DRD_NO_DL_SUBMIT_PERMISSION, + "Page-Split", DRD_PAGE_SPLIT, + "Physical-Rendition-Attributes-Not-Supported", DRD_PHYSICAL_RENDITION_ATTRIBUTES_NOT_SUPPORTED, + "Pictorial-Symbol-Loss", DRD_PICTORIAL_SYMBOL_LOSS, + "Protocol-Violation", DRD_PROTOCOL_VIOLATION, + "Punctuation-Symbol-Loss", DRD_PUNCTUATION_SYMBOL_LOSS, + "Recipient-Reassignment-Prohibited", DRD_RECIPIENT_REASSIGNMENT_PROHIBITED, + "Redirection-Loop-Detected", DRD_REDIRECTION_LOOP_DETECTED, + "Secure-Messaging-Error", DRD_SECURE_MESSAGING_ERROR, + "Size-Constraint-Violation", DRD_SIZE_CONSTRAINT_VIOLATION, + "Too-Many-Recipients", DRD_TOO_MANY_RECIPIENTS, + "UA-Unavailable", DRD_UA_UNAVAILABLE, + "Unable-To-Downgrade", DRD_UNABLE_TO_DOWNGRADE, + "Undliv-New-Address-Unknown", DRD_UNDLIV_NEW_ADDRESS_UNKNOWN, + "Undliv-Organization-Expired", DRD_UNDLIV_ORGANIZATION_EXPIRED, + "Undliv-Originator-Prohibited-Forwarding", DRD_UNDLIV_ORIGINATOR_PROHIBITED_FORWARDING, + "Undliv-Pd-Address-Incomplete", DRD_UNDLIV_PD_ADDRESS_INCOMPLETE, + "Undliv-Pd-Address-Incorrect", DRD_UNDLIV_PD_ADDRESS_INCORRECT, + "Undliv-Pd-Office-Incorrect-Or-Invalid",DRD_UNDLIV_PD_OFFICE_INCORRECT_OR_INVALID, + "Undliv-Recipient-Changed-Address-Permanently", DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_PERMANENTLY, + "Undliv-Recipient-Changed-Address-Temporarily", DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_TEMPORARILY, + "Undliv-Recipient-Changed-Temporary-Address", DRD_UNDLIV_RECIPIENT_CHANGED_TEMPORARY_ADDRESS, + "Undliv-Recipient-Deceased", DRD_UNDLIV_RECIPIENT_DECEASED, + "Undliv-Recipient-Did-Not-Claim", DRD_UNDLIV_RECIPIENT_DID_NOT_CLAIM, + "Undliv-Recipient-Did-Not-Want-Forwarding", DRD_UNDLIV_RECIPIENT_DID_NOT_WANT_FORWARDING, + "Undliv-Recipient-Refused-To-Accept", DRD_UNDLIV_RECIPIENT_REFUSED_TO_ACCEPT, + "Undliv-Recipient-Unknown", DRD_UNDLIV_RECIPIENT_UNKNOWN, + "Unrecognised-ORName", DRD_UNRECOGNISED_OR, + "Unsupported-Critical-Function", DRD_UNSUPPORTED_CRITICAL_FUNCTION, + 0, -1 +}; +int n_rr_dcode = ((sizeof(rr_dcode)/sizeof(CMD_TABLE)) - 1); diff --git a/Lib/pp/tb_misc.c b/Lib/pp/tb_misc.c new file mode 100644 index 0000000..e4b9569 --- /dev/null +++ b/Lib/pp/tb_misc.c @@ -0,0 +1,46 @@ +/* tb_misc.c: msic tables */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_misc.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_misc.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_misc.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + + +/* ------------------------------------------------------------------------ */ + +CMD_TABLE tbl_bool[] = { /* boolean values */ + "true", TRUE, + "yes", TRUE, + "false", FALSE, + "no", FALSE, + 0, 0 +}; + +CMD_TABLE tbl_month[] = { /* -- used for rfc-utc time calculations -- */ + "Jan", 0, + "Feb", 1, + "Mar", 2, + "Apr", 3, + "May", 4, + "Jun", 5, + "Jul", 6, + "Aug", 7, + "Sep", 8, + "Oct", 9, + "Nov", 10, + "Dec", 11, + 0, -1 + }; diff --git a/Lib/pp/tb_p1.c b/Lib/pp/tb_p1.c new file mode 100644 index 0000000..4d28c1a --- /dev/null +++ b/Lib/pp/tb_p1.c @@ -0,0 +1,93 @@ +/* tb_p1.c: p1 tables of other P1 keywds found in ADDR Control Files */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_p1.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_p1.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_p1.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "tb_com.h" +#include "tb_p1.h" +#include "extension.h" +#include + + +/* ----------------------------------------------------------------------- */ + + +CMD_TABLE p1tbl_mpduid[] = { /* mpdu-identifier */ + "string", MPDUID_STRING, + 0, -1 + }; + + + +CMD_TABLE p1tbl_trace[] = { /* trace-information */ + "mta", TRACE_MTA, + EOUNIT, EOU, + EOBLOCK, EOB, + 0, -1 + }; + + + +CMD_TABLE p1tbl_globaldomid[] = { /* global-domain-identifier */ + "Country", GLOBAL_COUNTRY, + "Admin", GLOBAL_ADMIN, + "Prmd", GLOBAL_PRIVATE, + 0, -1 + }; + + + +CMD_TABLE p1tbl_domsinfo[] = { /* domain-supplied-info */ + "arrival", DSI_TIME, + "deferred", DSI_DEFERRED, + "action", DSI_ACTION, + "converted", DSI_CONVERTED, + "attempted", DSI_ATTEMPTED, + 0, -1 + }; + + + +CMD_TABLE p1tbl_action[] = { /* domain-supplied-info-action */ + "Relayed", ACTION_RELAYED, + "Rerouted", ACTION_ROUTED, + 0, -1 + }; + + +CMD_TABLE p1tbl_encinfoset[] = { /* encode-info-types-set */ + "EncTypes", EI_BIT_STRING, + "G3NonBasic", EI_G3NONBASIC, + "TeletexNonBasic", EI_TELETEXNONBASIC, + "PresCapabilities", EI_PRESENTATION, + 0, -1 + }; + +CMD_TABLE tbl_crit[] = { + "none", CRITICAL_NONE, + "submission", CRITICAL_SUBMISSION, + "transfer", CRITICAL_TRANSFER, + "delivery", CRITICAL_DELIVERY, + 0, -1 + }; + +CMD_TABLE tbl_redir[] = { + "recip-assigned", RDR_RECIP_ASSIGNED, + "orig-assigned", RDR_ORIG_ASSIGNED, + "md-assigned", RDR_MD_ASSIGNED, + 0, -1 +}; diff --git a/Lib/pp/tb_p3prm.c b/Lib/pp/tb_p3prm.c new file mode 100644 index 0000000..ba31485 --- /dev/null +++ b/Lib/pp/tb_p3prm.c @@ -0,0 +1,35 @@ +/* tb_p3prm.c: P3 paramter keywords */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_p3prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_p3prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_p3prm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "tb_p3prm.h" +#include + + +/* ------------------------------------------------------------------------ */ + + + +CMD_TABLE p3prm_tbl[] = { /* message-management-parameters */ + "P3mpduid", P3PRM_MPDUID, + "P3subtime", P3PRM_STIME, + "P3content", P3PRM_CONTENT, + "P3origcert", P3PRM_ORIG_MTA_CERT, + "P3proofofsub", P3PRM_PROOF_OF_SUB, + "P3end", P3PRM_END, + 0, -1 + }; diff --git a/Lib/pp/tb_prm.c b/Lib/pp/tb_prm.c new file mode 100644 index 0000000..47ef6c7 --- /dev/null +++ b/Lib/pp/tb_prm.c @@ -0,0 +1,43 @@ +/* tb_prm.c: MessageManagementParameter tables the parameter keywords + found in ADDR Control Files. See manual page QUEUE (5). +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_prm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "tb_prm.h" +#include "prm.h" +#include + + +/* ------------------------------------------------------------------------ */ + + + +CMD_TABLE prmtbl_ln[] = { /* message-management-parameters */ + "logfile", PRM_LOGFILE, + "level", PRM_LOGLEVEL, + "options", PRM_OPTS, + "passwd", PRM_PASSWD, + "Start-of-MsgEnvPrm", PRM_END, + 0, -1 + }; + +CMD_TABLE prmtbl_opts[] = { /* options */ + "acceptall", PRM_ACCEPTALL, + "notrace", PRM_NOTRACE, + 0, -1 + }; diff --git a/Lib/pp/tb_q.c b/Lib/pp/tb_q.c new file mode 100644 index 0000000..a0559a8 --- /dev/null +++ b/Lib/pp/tb_q.c @@ -0,0 +1,85 @@ +/* tb_q.c: Queue tables - of the keywds found in ADDR Control Files */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/tb_q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: tb_q.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "tb_q.h" +#include + + +/* ------------------------------------------------------------------------ */ + + + +CMD_TABLE qtbl_que[] = { /* message-envelope-parameters */ + "algorithm-id", Q_ALGORITHM_ID, + "alt-recip-allowed", Q_ALTERNATE_RECIP_ALLOWED, + "cont-return", Q_CONTENT_RETURN_REQUEST, + "content-corr", Q_GEN_CONT_CORR, + "Content-type", Q_CONTENT_TYPE, + "conv-with-loss", Q_CONV_WITH_LOSS, + "Deferred-time", Q_DEFERREDTIME, + "Departure-time", Q_DEPARTIME, + "disclose-recips", Q_DISCLOSE_RECIPS, + "dl-exp-hist-crit", Q_DL_EXP_HIST_CRIT, + "dl-exp-history", Q_DL_EXP_HISTORY, + "dl-exp-prohibited", Q_DL_EXP_PROHIBITIED, + "Encoded-info", Q_ENCODED_INFO, + "forward-req", Q_FORWARDING_REQUEST, + "implicit-conv", Q_IMPLICIT_CONVERSION, + "Inbound-channel", Q_INCHANNEL, + "Inbound-mta", Q_INHOST, + "latest-time", Q_LATESTTIME, + "message-extension", Q_MESSAGE_EXTENSIONS, + "message-origin-auth-check", Q_MESSAGE_ORIGIN_AUTH_CHECK, + "Message-size", Q_MSGSIZE, + "Message-type", Q_MSGTYPE, + "MsgId", Q_MSGID, + "Number-warnings", Q_NWARNS, + "orig-return-addr", Q_ORIG_RETURN_ADDRESS, + "Original-encoded-info", Q_ORIG_ENCODED_INFO, + "originator-certificate", Q_ORIGINATOR_CERT, + "pp-cont-corr", Q_PP_CONT_CORR, + "Priority", Q_PRIORITY, + "proof-of-sub", Q_PROOF_OF_SUB, + "Queued-time", Q_QUEUETIME, + "recip-reassign-prohib", Q_RECIP_REASSIGN_PROHIBITED, + "Return-interval", Q_RETINTERVAL, + "security-label", Q_SECURITY_LABEL, + "Start-of-MsgEnvAddr", Q_END, + "Trace", Q_TRACE, + "Ua-id", Q_UA_ID, + "Warning-interval", Q_WARNINTERVAL, + 0, -1 + }; +int n_qtbl_que = ((sizeof(qtbl_que)/sizeof(CMD_TABLE)) -1); + + +CMD_TABLE qtbl_mt_type[] = { /* message-type */ + "User-Mpdu", MT_UMPDU, + "Probe-Mpdu", MT_PMPDU, + "Deliv-Mpdu", MT_DMPDU, + 0, -1 + }; + + +CMD_TABLE qtbl_priority[] = { /* message-priority */ + "normal", PRIO_NORMAL, + "non-urgent", PRIO_NONURGENT, + "urgent", PRIO_URGENT, + 0, -1 + }; diff --git a/Lib/pp/txt2adr.c b/Lib/pp/txt2adr.c new file mode 100644 index 0000000..2f26966 --- /dev/null +++ b/Lib/pp/txt2adr.c @@ -0,0 +1,573 @@ +/* tx_a.c: handles address structures see manual page QUEUE (5) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2adr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2adr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2adr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include "adr.h" +#include "tb_com.h" +#include "tb_a.h" +#include "list_bpt.h" +#include "list_rchan.h" + +#define txt2crit(n) cmd_srch ((n), tbl_crit) +#define txt2int(n) atoi(n) + +extern CMD_TABLE + tbl_bool [], + tbl_crit [], + tbl_redir[], + atbl_pd_modes [], + atbl_reg_mail [], + atbl_rdm [], + atbl_ctrl_addrs [/* Env-ctrl-addresses */], + atbl_addr [/* address-lines */], + atbl_status [/* recipient-status */], + atbl_mtarreq [/* mta-report-request */], + atbl_usrreq [/* user-report-request */], + atbl_expconversion [/* explicit-conversion */], + atbl_types [/* address-type */], + atbl_subtypes [/* address-subtype */]; + +extern int n_atbl_addr, n_atbl_expconversion, n_atbl_pd_modes, + n_atbl_rdm; + +static int A_txt2adln (); +static int A_txt2address (); + +extern struct qbuf *hex2qb (); +extern X400_Extension *txt2extension (); + +/* ------------------- Text File -> Memory ------------------------------ */ + + + +int txt2adr (base, startlineoffset, argv, argc) /* Txt -> Env-ctrl-addresses */ +register ADDR **base; +long startlineoffset; +char **argv; +int argc; +{ + PP_DBG (("Lib/pp/txt2adr (%s)", argv[0])); + + if (--argc < 1) return (NOTOK); + + switch (cmd_srch (argv[0], atbl_ctrl_addrs)) { + case AD_ORIGINATOR: + case AD_RECIPIENT: + return A_txt2address (base, startlineoffset, + &argv[1], argc); + } + + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/txt2adr Unable to parse '%s'", argv[0])); + + return (NOTOK); +} + + +static int A_txt2address (base, startlineoffset, argv, argc) +ADDR **base; +long startlineoffset; +char **argv; +int argc; +{ + ADDR *adr_new(), + *adr; + int n_args; + + + adr = adr_new (NULLCP, NULL, NULL); + + for (n_args=0; n_args < argc;) { + + PP_DBG (("Lib/pp/A_txt2address (%s)", + argv[n_args + 1] ? argv[n_args + 1] : "")); + + if (argv[n_args] == NULLCP) break; + if (*argv[n_args] == '=') { + if (A_txt2adln (adr, argv[n_args + 1], + argv[n_args + 2]) == NOTOK) + return (NOTOK); + n_args += 3; + } + else { + if (A_txt2adln (adr, argv[n_args], NULLCP) == NOTOK) + return NOTOK; + n_args ++; + } + + } + + /* fixed format: Recip status=XXXX reform-done=999 */ + /* 012345678901234567890123456789012 */ + +/* XXXX Remove after 6.0 */ + if (lexequ(argv[1], "rno") == 0) { /* old format */ + adr->ad_stat_offset = startlineoffset + 21; + adr->ad_rcnt_offset = startlineoffset + 38; + } + else { + adr->ad_stat_offset = startlineoffset + 13; + adr->ad_rcnt_offset = startlineoffset + 30; + } + + adr_add (base, adr); + + return (OK); + +} + +static Redirection *A_txt2redir (); +static int A_txt2stat (); +static int A_txt2fmtchan (); +static int A_txt2adrtype (); +static int A_txt2adrsubtype (); +static int A_txt2req_del (); +static int A_txt2modes (); + +static int A_txt2adln (adr, keywd, val) /* Txt -> Address Line */ +ADDR *adr; +char *keywd; +char *val; +{ + PP_DBG (("Lib/pp/A_txt2adln (%s '%s')", + keywd ? keywd : "", + val ? val : "")); + + switch (cmdbsrch (keywd, atbl_addr, n_atbl_addr)) { + case AD_RECIP_NO: + adr->ad_no = txt2int (val); + return (OK); + case AD_STATUS: + return (A_txt2stat (&adr->ad_status, val)); + case AD_REFORM_DONE: + adr->ad_rcnt = txt2int (val); + return (OK); + case AD_REFORM_LIST: + if (lexequ (val, EMPTY) == 0) + return (OK); + return (A_txt2fmtchan (val, &adr->ad_fmtchan)); + case AD_OUTCHAN: + if (lexequ (val, EMPTY) == 0) + return (OK); + + if (adr->ad_outchan == NULLIST_RCHAN) + adr->ad_outchan = list_rchan_new (NULLCP, val); + else + return list_rchan_schan (adr->ad_outchan, val); + return (OK); + case AD_OUTHOST: + if (lexequ (val, EMPTY) == 0) + return (OK); + + if (adr->ad_outchan == NULLIST_RCHAN) + adr->ad_outchan = list_rchan_new (val, NULLCP); + else + return list_rchan_ssite (adr->ad_outchan, val); + return (OK); + case AD_EXTENSION_ID: + adr->ad_extension = txt2int (val); + return (OK); + case AD_RESPONSIBILITY: + return P1_txt2resp (&adr -> ad_resp, val); + case AD_MTA_REP_REQ: + return P1_txt2mtarreq (&adr->ad_mtarreq, val); + case AD_USR_REP_REQ: + return P1_txt2usrreq (&adr -> ad_usrreq, val); + case AD_EXPLICITCONVERSION: + if (lexequ (val, EMPTY) == 0) { + adr->ad_explicitconversion = NULL; + return (OK); + } + adr->ad_explicitconversion = cmdbsrch (val, + atbl_expconversion, + n_atbl_expconversion); + return (OK); + case AD_ADDTYPE: + return (A_txt2adrtype (&adr->ad_type, val)); + case AD_SUBTYPE: + if (lexequ (val, EMPTY) == 0) { + adr->ad_subtype = AD_NOSUBTYPE; + return (OK); + } + return (A_txt2adrsubtype (&adr->ad_subtype, val)); + case AD_EITS: + return txt2listbpt (&adr->ad_eit, val); + case AD_CONTENT: + adr->ad_content = strdup(val); + return OK; + + case AD_DN: + adr ->ad_dn = strdup (val); + return OK; + + case AD_ORIG_REQ_ALT: + adr -> ad_orig_req_alt = strdup (val); + return OK; + + case AD_ORIG_REQ_ALT_CRIT: + adr -> ad_orig_req_alt_crit = txt2crit(val); + return OK; + + case AD_REQ_DEL: + return A_txt2req_del(adr -> ad_req_del, val); + + case AD_REQ_DEL_CRIT: + adr ->ad_req_del_crit = txt2crit (val); + return OK; + + case AD_PHYS_FORWARD: + adr -> ad_phys_forward = cmd_srch (val, tbl_bool); + return OK; + + case AD_PHYS_FORWARD_CRIT: + adr -> ad_phys_forward_crit = txt2crit (val); + return OK; + + case AD_PHYS_FW_AD: + adr -> ad_phys_fw_ad_req = cmd_srch (val, tbl_bool); + return OK; + + case AD_PHYS_FW_AD_CRIT: + adr -> ad_phys_fw_ad_crit = txt2crit (val); + return OK; + + case AD_PHYS_MODES: + adr -> ad_phys_modes = A_txt2modes (val); + return OK; + + case AD_PHYS_MODES_CRIT: + adr -> ad_phys_modes_crit = txt2crit (val); + return OK; + + case AD_REG_MAIL: + adr -> ad_reg_mail_type = cmd_srch (val, atbl_reg_mail); + return OK; + + case AD_REG_MAIL_CRIT: + adr -> ad_reg_mail_type_crit = txt2crit (val); + return OK; + + case AD_RECIP_NUMBER_ADVICE: + adr -> ad_recip_number_for_advice = strdup (val); + break; + + case AD_RECIP_NUMBER_ADVICE_CRIT: + adr -> ad_recip_number_for_advice_crit = txt2crit(val); + break; + + case AD_PHYS_RENDITION: + adr -> ad_phys_rendition_attribs = oid_cpy (str2oid (val)); + return OK; + + case AD_PHYS_RENDITION_CRIT: + adr -> ad_phys_rendition_attribs_crit = txt2crit (val); + return OK; + + case AD_PD_REPORT_REQUEST: + adr -> ad_pd_report_request = cmd_srch (val, tbl_bool); + return OK; + + case AD_PD_REPORT_REQUEST_CRIT: + adr -> ad_pd_report_request_crit = txt2crit (val); + break; + + case AD_REDIRECTION_HISTORY: + { + Redirection *rp, **rpp; + + rp = A_txt2redir (val); + for (rpp = &adr -> ad_redirection_history; + *rpp; rpp = &(*rpp) -> rd_next) + continue; + *rpp = rp; + } + return OK; + + case AD_REDIRECTION_HISTORY_CRIT: + adr -> ad_redirection_history_crit = txt2crit (val); + return OK; + + case AD_MESSAGE_TOKEN: + adr -> ad_message_token = hex2qb (val); + return OK; + + case AD_MESSAGE_TOKEN_CRIT: + adr -> ad_message_token_crit = txt2crit (val); + return OK; + + case AD_CONTENT_INTEGRITY: + adr -> ad_content_integrity = hex2qb(val); + return OK; + + case AD_CONTENT_INTEGRITY_CRIT: + adr -> ad_content_integrity_crit = txt2crit (val); + return OK; + + case AD_PROOF_DELIVERY: + adr -> ad_proof_delivery = cmd_srch (val, tbl_bool); + return OK; + + case AD_PROOF_DELIVERY_CRIT: + adr -> ad_proof_delivery_crit = txt2crit (val); + return OK; + + case AD_EXTENSION: + { + X400_Extension *ext, **extp, + *A_txt2extension (); + + ext = A_txt2extension (val); + + for (extp = &adr -> ad_per_recip_ext_list; + *extp; extp = &(*extp) -> ext_next) + continue; + *extp = ext; + } + return OK; + + case AD_ORIG: + if (val == NULLCP || *val == '\0') + return (NOTOK); + if (lexequ (val, EMPTY) == 0) return (OK); + adr->ad_value = strdup(val); + return (OK); + case AD_X400: + if (val == NULLCP || *val == '\0') + return (NOTOK); + if (lexequ (val, EMPTY) == 0) { + adr->ad_r400adr = NULLCP; + return (OK); + } + adr->ad_r400adr = strdup (val); + return (OK); + case AD_822: + if (val == NULLCP || *val == '\0') + return NOTOK; + if (lexequ (val, EMPTY) == 0) { + adr->ad_r822adr = NULLCP; + return (OK); + } + adr->ad_r822adr = strdup (val); + return (OK); + + case AD_X400DR: + if (!isstr(val)) + return NOTOK; + if (lexequ (val, EMPTY) == 0) + adr->ad_r400DR = NULLCP; + else + adr->ad_r400DR = strdup(val); + return (OK); + + case AD_822DR: + if (!isstr(val)) + return NOTOK; + if (lexequ (val, EMPTY) == 0) + adr->ad_r822DR = NULLCP; + else + adr->ad_r822DR = strdup(val); + return (OK); + + case AD_X400ORIG: + if (!isstr(val)) + return NOTOK; + if (lexequ (val, EMPTY) == 0) + adr->ad_r400orig = NULLCP; + else + adr->ad_r400orig = strdup(val); + return (OK); + + case AD_END: + return (OK); + } + return NOTOK; +} + + + + +static int A_txt2fmtchan (str, fmt_chan) +char *str; +LIST_RCHAN **fmt_chan; +{ + char *np, *dp, + *cp = str; + int keep_going = TRUE; + LIST_RCHAN *new; + + + PP_DBG (("Lib/A_txt2fmtchan (%s)", str)); + + + /* --- *** --- + Format used: + chan_name1|directory, ... , chan_nameN|directory + + Note: + For ad_fmtchan no site name is specified. + This is only specified for ad_outchan. + --- *** --- */ + + + while (keep_going) { + if ((np = index (cp, ',')) != NULLCP) + *np++ = '\0'; + else + keep_going = FALSE; + if ((dp = index(cp, '|')) != NULLCP) + *dp ++ = '\0'; + + if ((new = list_rchan_new (NULLCP, cp)) == NULLIST_RCHAN) { + list_rchan_free (*fmt_chan); + *fmt_chan = NULLIST_RCHAN; + return (NOTOK); + } + if (dp) + new -> li_dir = strdup(dp); + + list_rchan_add (fmt_chan, new); + + cp = np; + if (cp == NULL || *cp == '\0') + break; + } + + return (OK); +} + + + + +static int A_txt2stat (status, keywd) /* Txt -> Recipient_status */ +int *status; +char *keywd; +{ + PP_DBG (("Lib/pp/A_txt2stat (%s)", keywd)); + + switch (*status = cmd_srch (keywd, atbl_status)) { + case AD_STAT_PEND: + case AD_STAT_DONE: + case AD_STAT_DRREQUIRED: + case AD_STAT_DRWRITTEN: + return (OK); + } + return (NOTOK); +} + + +static int A_txt2adrtype (type, keywd) /* Txt -> Address type */ +int *type; +char *keywd; +{ + PP_DBG (("Lib/pp/A_txt2adrtype (%s)", keywd)); + + switch (*type = cmd_srch (keywd, atbl_types)) { + case AD_X400_TYPE: + case AD_822_TYPE: + case AD_ANY_TYPE: + break; + default: + *type = AD_ANY_TYPE; + } + + PP_DBG (("Lib/pp/A_txt2adrtype (%s %d)", keywd, *type)); + return (OK); +} + + +static int A_txt2adrsubtype (type, keywd) /* Txt -> Address subtype */ +int *type; +char *keywd; +{ + PP_DBG (("Lib/pp/A_txt2adrsubtype (%s)", keywd)); + + if ((*type = cmd_srch (keywd, atbl_subtypes)) == -1) + *type = AD_NOSUBTYPE; + return (OK); +} + +static Redirection *A_txt2redir (str) +char *str; +{ + char *argv[10]; + Redirection *rp; + + if (sstr2arg (str, 10, argv, ", \t\n") != 4) + return NULL; + rp = (Redirection *) smalloc (sizeof *rp); + rp -> rd_addr = isstr (argv[0])? strdup (argv[0]) : NULLCP; + rp -> rd_dn = isstr (argv[1]) ? strdup (argv[1]) : NULLCP; + (void) txt2time (argv[2], &rp -> rd_time); + rp -> rd_reason = cmd_srch (argv[3], tbl_redir); + rp -> rd_next = (Redirection *) NULL; + return rp; +} + +static int A_txt2modes (str) +char *str; +{ + char *argv[20]; + int argc, i, n; + int modes = 0; + + + argc = sstr2arg (str, 20, argv, ", \t\n"); + + for (i = 0; i < argc; i++) + if ((n = cmdbsrch (argv[i], atbl_pd_modes, + n_atbl_pd_modes)) != -1) + modes |= n; + return modes; +} + +static int A_txt2req_del (rdm, str) +int rdm[]; +char *str; +{ + char *argv[10]; + int argc; + int n, rc = 0, i; + + argc = sstr2arg (str, 10, argv, ", \t\n"); + for (i = 0; i < argc && rc < AD_RDM_MAX; i++) + if ((n = cmdbsrch(argv[i], atbl_rdm, n_atbl_rdm)) != -1) + rdm[rc++] = n; + return OK; +} + + + + +X400_Extension *A_txt2extension (str) +char *str; +{ + X400_Extension *ext; + char *argv[10]; + + if (sstr2arg (str, 10, argv, ", \t\n") != 4) + return NULL; + ext = (X400_Extension *)smalloc (sizeof *ext); + ext -> ext_int = txt2int (argv[0]); + ext -> ext_oid = str2oid (argv[1]); + ext -> ext_value = hex2qb (argv[2]); + ext -> ext_criticality = cmd_srch (argv[3], tbl_crit); + + return ext; +} + diff --git a/Lib/pp/txt2dr.c b/Lib/pp/txt2dr.c new file mode 100644 index 0000000..173b4ef --- /dev/null +++ b/Lib/pp/txt2dr.c @@ -0,0 +1,323 @@ +/* txt2dr.c: converts text encoding back to dr structure */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2dr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "dr.h" +#include "tb_dr.h" +#include "retcode.h" + + +#define txt2crit(n) cmd_srch ((n), tbl_crit) +#define txt2int(n) atoi(n) + +extern struct qbuf *hex2qb (); +extern X400_Extension *txt2extension (); + +extern CMD_TABLE + tbl_redir [], + rr_rcode[], + rr_dcode [], + tbl_crit [], + rrtbl [], + drtbl [/* delivery-notification */]; + +extern int n_drtbl, n_rrtbl, n_rr_rcode, n_rr_dcode; + + +/* ------------------- Text File -> Memory ------------------------------ */ + + + +int txt2dr (dr, fp) +DRmpdu *dr; +FILE *fp; +{ + int retval; + char buf[10*BUFSIZ]; + int argc; + char *argv[100]; + + for (;;) { + if (rp_isbad (retval = txt2buf (buf, sizeof buf, fp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("txt2buf failed")); + return retval; + } + if (retval == RP_DONE) + return RP_DONE; + + PP_DBG (("Lib/pp/txt2dr buf='%s'", buf)); + + if ((argc = str2arg (buf, 100, argv)) == 0) + return RP_PARM; + + switch (cmdbsrch (argv[0], drtbl, n_drtbl)) { + case DR_MSGID: + dr -> dr_mpduid = (MPDUid *) + smalloc ( sizeof *dr -> dr_mpduid); + bzero ((char *)dr -> dr_mpduid, + sizeof *dr -> dr_mpduid); + if (txt2mpduid (dr -> dr_mpduid, &argv[1], argc - 1) + == NOTOK) + return RP_BAD; + break; + + case DR_TRACE: + if (txt2trace (&dr -> dr_trace, &argv[1], argc - 1) + == NOTOK) + return RP_BAD; + break; + + case DR_SI_TRACE: + if (txt2trace (&dr -> dr_subject_intermediate_trace, + &argv[1], argc - 1) == NOTOK) + return RP_BAD; + break; + + case DR_DL_EXP_HIST: + if (txt2dlexp (&dr -> dr_dl_history, &argv[1], + argc - 1) == NOTOK) + return RP_BAD; + break; + + case DR_DL_EXP_HIST_CRIT: + dr -> dr_dl_history_crit = txt2int (argv[1]); + break; + + case DR_REPORTING_DL_NAME: + if (txt2fname (&dr -> dr_reporting_dl_name, + &dr -> dr_reporting_dl_name_crit, + &argv[1], argc - 1) == NOTOK) + return RP_BAD; + break; + + case DR_SECURITY_LABEL: + dr -> dr_security_label = hex2qb(argv[1]); + if (argc < 3) break; + dr -> dr_security_label_crit = txt2crit (argv[2]); + break; + + case DR_REPORTING_MTA_CERTIFICATE: + dr -> dr_reporting_mta_certificate = hex2qb (argv[1]); + if (argc < 3) break; + dr -> dr_reporting_mta_certificate_crit = + txt2crit (argv[2]); + break; + + case DR_REPORT_ORIGIN_AUTH_CHECK: + dr -> dr_report_origin_auth_check = hex2qb (argv[1]); + if (argc < 3) break; + dr -> dr_report_origin_auth_check_crit = + txt2crit (argv[2]); + break; + + case DR_PER_REPORT_EXTENSIONS: + { + X400_Extension *ext, **extp; + + ext = txt2extension (&argv[1], argc - 1); + + for (extp = &dr -> dr_per_report_extensions; + *extp; extp = &(*extp) -> ext_next) + continue; + *extp = ext; + } + break; + case DR_PER_ENVELOPE_EXTENSIONS: + { + X400_Extension *ext, **extp; + + ext = txt2extension (&argv[1], argc - 1); + + for (extp = &dr -> dr_per_envelope_extensions; + *extp; extp = &(*extp) -> ext_next) + continue; + *extp = ext; + } + break; + + case DR_END_HDR: + return rr2txt (&dr -> dr_recip_list, fp); + + case DR_END: + return RP_DONE; + } + } +} + +int rr2txt (rrp, fp) +Rrinfo **rrp; +FILE *fp; +{ + Rrinfo *rr = NULL; + int retval; + char buf[10*BUFSIZ]; + int argc; + char *argv[100]; + int type; + + for (;;) { + if (rp_isbad (retval = txt2buf (buf, sizeof buf, fp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("txt2buf failed")); + return retval; + } + if (retval == RP_DONE) + return RP_DONE; + + PP_DBG (("Lib/pp/txt2rr buf='%s'", buf)); + + if ((argc = str2arg (buf, 100, argv)) == 0) + return RP_PARM; + + type = cmdbsrch (argv[0], rrtbl, n_rrtbl); + if (type == RR_END) + return RP_DONE; + + if (rr == NULL) { + rr = (Rrinfo *) smalloc (sizeof *rr); + bzero ((char *)rr, sizeof *rr); + *rrp = rr; + } + switch (type) { + case RR_RECIP: + rr -> rr_recip = txt2int (argv[1]); + break; + + case RR_SUCCESS: + rr -> rr_report.rep_type = DR_REP_SUCCESS; + if (txt2time (argv[1], + &rr -> rr_report.rep.rep_dinfo.del_time) == NOTOK) + return RP_BAD; + if (argc < 3) break; + rr -> rr_report.rep.rep_dinfo.del_type = + txt2int (argv[2]); + break; + + case RR_FAILURE: + rr -> rr_report.rep_type = DR_REP_FAILURE; + rr -> rr_report.rep.rep_ndinfo.nd_rcode = + cmdbsrch (argv[1], rr_rcode, n_rr_rcode); + if (argc < 3) break; + rr -> rr_report.rep.rep_ndinfo.nd_dcode = + cmdbsrch (argv[2], rr_dcode, n_rr_dcode); + break; + + case RR_CONVERTED: + rr -> rr_converted = + (EncodedIT *) + smalloc (sizeof *rr -> rr_converted); + bzero ((char *)rr -> rr_converted, + sizeof *rr -> rr_converted); + if (txt2encodedinfo (rr -> rr_converted, &argv[1], + argc - 1) == NOTOK) + return RP_BAD; + break; + + case RR_ORIGINALLY_INTENDED_RECIP: + { + char junk; + if (txt2fname (&rr -> rr_originally_intended_recip, + &junk, &argv[1], argc - 1) == NOTOK) + return RP_BAD; + } + break; + + case RR_SUPPLEMENTARY: + rr -> rr_supplementary = strdup (argv[1]); + break; + + case RR_REDIRECT_HISTORY: + { + Redirection *rp, **rpp, + *txt2redir (); + + rp = txt2redir (&argv[1], argc - 1); + for (rpp = &rr -> rr_redirect_history; + *rpp; rpp = &(*rpp) -> rd_next) + continue; + *rpp = rp; + } + break; + + case RR_REDIRECT_HISTORY_CRIT: + rr -> rr_redirect_history_crit = txt2crit (argv[1]); + break; + + case RR_PHYSICAL_FWD: + if (txt2fname (&rr -> rr_physical_fwd_addr, + &rr -> rr_physical_fwd_addr_crit, + &argv[1], argc - 1) == NOTOK) + return RP_BAD; + break; + + case RR_RECIP_CERTIFICATE: + rr -> rr_recip_certificate = hex2qb (argv[1]); + if (argc < 3) break; + rr -> rr_recip_certificate_crit = txt2crit (argv[2]); + break; + + case RR_REPORT_ORIGIN_CHECK: + rr -> rr_report_origin_authentication_check = + hex2qb (argv[1]); + if (argc < 3) break; + rr -> rr_report_origin_authentication_check_crit = + txt2crit (argv[2]); + break; + + case RR_ARRIVAL: + if (txt2time (argv[1], &rr -> rr_arrival) == NOTOK) + return RP_BAD; + break; + + case RR_PER_RECIP_EXTENSIONS: + { + X400_Extension *ext, **extp; + + ext = txt2extension (&argv[1], argc - 1); + for (extp = &rr -> rr_per_recip_extensions; + *extp; extp = &(*extp) -> ext_next) + continue; + *extp = ext; + } + break; + + case RR_END_RECIP: + return rr2txt (&rr -> rr_next, fp); + + case RR_END: + return RP_DONE; + } + } +} + +Redirection *txt2redir (argv, argc) +char *argv[]; +int argc; +{ + Redirection *rp; + + rp = (Redirection *) smalloc (sizeof *rp); + bzero ((char *)rp, sizeof *rp); + + if (argc < 1) return rp; + rp -> rd_addr = isstr (argv[0]) ? strdup (argv[0]) : NULLCP; + rp -> rd_dn =isstr (argv[1]) ? strdup (argv[1]) : NULLCP; + rp -> rd_reason = cmd_srch (argv[2], tbl_redir); + return rp; +} diff --git a/Lib/pp/txt2mta.c b/Lib/pp/txt2mta.c new file mode 100644 index 0000000..ce98c92 --- /dev/null +++ b/Lib/pp/txt2mta.c @@ -0,0 +1,477 @@ +/* txt2p1.c: handle text to varios mta structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2mta.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2mta.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2mta.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" +#include "tb_com.h" +#include "tb_p1.h" +#include "tb_a.h" + +#define txt2int(n) atoi(n) + +extern char *genstore (); +char *utctime (); +extern struct qbuf *hex2qb (); +extern LIST_BPT *bodies_all, *headers_all; + +extern CMD_TABLE + tbl_crit [], + p1tbl_mpduid [/* mpdu-identifier */], + p1tbl_trace [/* trace-information */], + p1tbl_globaldomid [/* global-domain-identifier */], + p1tbl_domsinfo [/* domain-supplied-info */], + p1tbl_action [/* domain-supplied-info-action */], + p1tbl_encinfoset [/* encode-info-types-set */], + atbl_addr [/* address-lines */], + tbl_bool [], + atbl_mtarreq [/* mta-report-request */], + atbl_usrreq [/* user-report-request */]; +extern int n_atbl_addr; + +/* --------------------- Text File->Memory ---------------------------- */ + + + + +int txt2trace (trp, argv, argc) /* Txt->TraceInformation */ +Trace **trp; +char **argv; +int argc; +{ + int key; + int count = 0, n; + register Trace *new, + *tp; + + PP_DBG (("Lib/pp/txt2trace(%s)", argv[0])); + + + if (--argc < 1) + return (NOTOK); + + + /* -- create a new Trace struct -- */ + new = (Trace*) smalloc (sizeof (*new)); + bzero ((char*)new, sizeof (*new)); + + + /* -- put the new Trace struct into the appropriate place -- */ + if ((tp = *trp) == (Trace *)NULL) + *trp = tp = new; + else { + /* -- point to current and put new in trace_next -- */ + for (; tp->trace_next; tp=tp->trace_next); + tp->trace_next = new; + tp = tp -> trace_next; + } + + + while (argc > 1) { + if (*argv[0] != '=') { + if (cmd_srch(argv[0], p1tbl_trace) == EOB) + count ++; + break; + } + key = cmd_srch (argv[1], p1tbl_trace); + + switch (key) { + case TRACE_MTA: + tp->trace_mta = strdup (argv[2]); + n = 3; + break; + + case EOB: + case EOU: + return count > 0 ? count : 0; + + default: + n = txt2globaldomid (&tp->trace_DomId, + &argv[0], argc); + if (n != NOTOK) { + break; + } + n = txt2domsinfo (&tp->trace_DomSinfo, + &argv[0], argc); + if (n == NOTOK) + return count > 0 ? count : NOTOK; + break; + } + argc -= n; + argv += n; + count += n; + } + return count > 0 ? count : NOTOK; +} + + +int txt2globaldomid (gp, argv, argc) /* Txt->GlobalDomainIdentifier */ +GlobalDomId *gp; +char **argv; +int argc; +{ + int count = 0; + int n; + + PP_DBG (("Lib/pp/txt2globaldomid(%s %d)", + argv[1], argc)); + + while (argc > 0) { + if (*argv[0] != '=') + break; + + switch (cmd_srch (argv[1], p1tbl_globaldomid)) { + case GLOBAL_COUNTRY: + gp->global_Country = strdup (argv[2]); + n = 3; + break; + + case GLOBAL_ADMIN: + gp->global_Admin = strdup (argv[2]); + n = 3; + break; + case GLOBAL_PRIVATE: + gp->global_Private = strdup (argv[2]); + n = 3; + break; + default: + return count > 0 ? count : NOTOK; + } + count += n; + argc -= n; + argv += n; + } + return (count > 0 ? count : NOTOK); +} + + +int txt2domsinfo (di, argv, argc) /* Txt->DomainSuppliedInfo */ +DomSupInfo *di; +char **argv; +int argc; +{ + int n, count = 0; + char *p; + PP_DBG (("Lib/pp/txt2domsinfo(%s)", argv[0])); + + while (argc > 0) { + if (*argv[0] == '=') + p = argv[1]; + else p = argv[0]; + switch (cmd_srch (p, p1tbl_domsinfo)) { + case DSI_TIME: + if (txt2time (argv[2], &di->dsi_time) == NOTOK) + di -> dsi_time = utcnow (); + n = 3; + break; + case DSI_DEFERRED: + if (txt2time (argv[2], &di->dsi_deferred) == NOTOK) + di -> dsi_deferred = utcnow (); + n = 3; + break; + case DSI_ACTION: + di->dsi_action = txt2int (argv[2]); + n = 3; + break; + case DSI_CONVERTED: + n = txt2encodedinfo(&di->dsi_converted, &argv[1], + argc - 1); + if (n == NOTOK) + return n; + n ++; + break; + case DSI_ATTEMPTED: + n = txt2globaldomid (&di->dsi_attempted_md, &argv[1], + argc - 1); + if (n == NOTOK) + return n; + n ++; + break; + default: + return count > 0 ? count : NOTOK; + } + argc -= n; + argv += n; + count += n; + } + return (count > 0 ? count : NOTOK); +} + + +int txt2encodedinfo (ep, argv, argc) /* Txt->EncodedInformationTypes */ +EncodedIT *ep; +char **argv; +int argc; +{ + int count = 0, n; + + + PP_DBG (("Lib/pp/txt2encodedinfo('%s', %d)", argv[0], argc)); + + while (argc > 0) { + if (*argv[0] != '=') + return NOTOK; + + switch (cmd_srch (argv[1], p1tbl_encinfoset)) { + case EI_G3NONBASIC: + ep->eit_g3parms = txt2int (argv[2]); + n = 3; + break; + case EI_TELETEXNONBASIC: + ep->eit_tTXparms = txt2int (argv[2]); + n = 3; + break; + case EI_PRESENTATION: + ep->eit_presentation = txt2int (argv[2]); + n = 3; + break; + case EI_BIT_STRING: + if (txt2listbpt (&ep->eit_types, argv[2]) == NOTOK) + return NOTOK; + n = 3; + break; + default: + return count > 0 ? count : NOTOK; + } + argc -= n; + argv += n; + count += n; + } + return (count > 0 ? count : NOTOK); +} + + +int txt2listbpt (bpt, str) /* Txt -> A List of BodyPartTypes */ +LIST_BPT **bpt; +char *str; +{ + LIST_BPT *np; + int i, + j; + char *buf[30]; + + PP_DBG (("Lib/pp/txt2listbpt(%s)", str)); + + /* + read string which is delimitted by ',' + example: tlx,ia5, etc... + */ + + j = sstr2arg (str, 30, buf, ","); + + for (i = 0; i < j; i++) { +#ifdef notdef + if (list_bpt_find(bodies_all, buf[i]) == NULLIST_BPT) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown bodypart type '%s'", buf[i])); + return NOTOK; + } +#endif + np = list_bpt_new (buf[i]); + list_bpt_add (bpt, np); + } + + return (OK); + +} + +extern char *hdr_prefix; + +int txthdr2listbpt (bpt, str) /* Txt -> A List of BodyPartTypes */ +LIST_BPT **bpt; +char *str; +{ + LIST_BPT *np; + int i, + j; + char *buf[30]; + char buffer[BUFSIZ]; + + PP_DBG (("Lib/pp/txthdr2listbpt(%s)", str)); + + /* + read string which is delimitted by ',' + example: 822,ipn, etc.. + */ + + j = sstr2arg (str, 30, buf, ","); + + for (i = 0; i < j; i++) { + (void) strcpy (buffer, hdr_prefix); + (void) strcat (buffer, buf[i]); +#ifdef notdef + if (list_bpt_find(headers_all, buffer) == NULLIST_BPT) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown header type '%s' ('%s')", + buf[i], buffer)); + return NOTOK; + } +#endif + np = list_bpt_new (buffer); + list_bpt_add (bpt, np); + } + return (OK); + +} + +int txt2mpduid (mep, argv, argc) /* Txt->MPDUIdentifier */ +register MPDUid *mep; +char **argv; +int argc; +{ + int n, count = 0; + PP_DBG (("Lib/pp/txt2mpduid(%s)", argv[0])); + + while (argc > 0) { + if (*argv[0] != '=') + break; + + switch (cmd_srch (argv[1], p1tbl_mpduid)) { + case MPDUID_STRING: + mep->mpduid_string = strdup (argv[2]); + n = 3; + break; + default: + n = txt2globaldomid (&mep->mpduid_DomId, + &argv[0], argc); + if (n == NOTOK) + return count > 0 ? count : NOTOK; + break; + } + argc -= n; + argv += n; + count += n; + } + return count > 0 ? count : NOTOK; +} + + +/* Txt->Responsibility, Mta-report-request & User-report-request */ + +int txt2repreq (field, argv, argc) +int *field; +char **argv; +int argc; +{ + int val; + + PP_DBG (("Lib/pp/txt2repreq(%s %d)", argv[0], argc)); + + if (--argc < 1) return (NOTOK); + if (*argv[0] != '=') return NOTOK; + + switch (cmdbsrch (argv[1], atbl_addr, n_atbl_addr)) { + case AD_RESPONSIBILITY: + if (P1_txt2resp (&val, argv[2]) == NOTOK) + return (NOTOK); + break; + case AD_MTA_REP_REQ: + if (P1_txt2mtarreq (&val, argv[2]) == NOTOK) + return (NOTOK); + break; + case AD_USR_REP_REQ: + if (P1_txt2usrreq (&val, argv[2]) == NOTOK) + return (NOTOK); + break; + default: + return (NOTOK); + } + + PP_DBG (("Lib/pp/txt2repreq(%s %d)", argv[1], val)); + + *field = val; + return (3); +} + + +int P1_txt2resp (val, keywd) /* Txt->Responsibility */ +int *val; +char *keywd; +{ + PP_DBG (("Lib/pp/P1_txt2resp(%s)", keywd)); + + switch (*val = cmd_srch (keywd, tbl_bool)) { + case YES: + case NO: + return (OK); + default: + return (NOTOK); + } +} + + +int P1_txt2mtarreq (val, keywd) /* Txt->Mta-report-request */ +int *val; +char *keywd; +{ + PP_DBG (("Lib/pp/P1_txt2mtarreq(%s)", keywd)); + + switch (*val = cmd_srch (keywd, atbl_mtarreq)) { + case AD_MTA_NONE: + *val = AD_MTA_BASIC; + case AD_MTA_BASIC: + case AD_MTA_CONFIRM: + case AD_MTA_AUDIT_CONFIRM: + return (OK); + default: + return (NOTOK); + } +} + + +int P1_txt2usrreq (val, keywd) /* Txt->Usr-report-request */ +int *val; +char *keywd; +{ + PP_DBG (("Lib/pp/txt2usrreq(%s)", keywd)); + + switch (*val = cmd_srch (keywd, atbl_usrreq)) { + case AD_USR_NONE: + *val = AD_USR_BASIC; + case AD_USR_NOREPORT: + case AD_USR_BASIC: + case AD_USR_CONFIRM: + return (OK); + default: + return (NOTOK); + } +} + + +int txt2time (str, tp) +char *str; +UTC *tp; +{ + return (rfc2UTC (str, tp)); +} + +X400_Extension *txt2extension (argv, argc) +char *argv[]; +int argc; +{ + X400_Extension *ext; + + if (argc <= 3) + return NULL; + ext = (X400_Extension *)smalloc (sizeof *ext); + ext -> ext_int = txt2int (argv[0]); + ext -> ext_oid = str2oid (argv[1]); + ext -> ext_value = hex2qb (argv[2]); + ext -> ext_criticality = cmd_srch (argv[3], tbl_crit); + + return ext; +} diff --git a/Lib/pp/txt2p3.c b/Lib/pp/txt2p3.c new file mode 100644 index 0000000..58c676f --- /dev/null +++ b/Lib/pp/txt2p3.c @@ -0,0 +1,67 @@ +/* tx2p3.c: txt format to p3params structure */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2p3.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2p3.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2p3.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "mta.h" +#include "tb_p3prm.h" + +extern int argv2fp (); +extern struct qbuf *hex2qb (); +extern CMD_TABLE p3prm_tbl[]; + + +int txt2p3prm (p3, argv, argc) +P3params *p3; +char **argv; +int argc; +{ + int key; + + PP_DBG(("Lib/pp/txt2p3.c(%s)", argv[0])); + + + key = cmd_srch (argv[0], p3prm_tbl); + + if (argc < 1 && key != P3PRM_END) + return NOTOK; + + switch (key) { + case P3PRM_MPDUID: + if (txt2mpduid (&p3 -> mpduid, &argv[1], argc - 1) == NOTOK) + return NOTOK; + return OK; + case P3PRM_STIME: + if (!isstr(argv[1])) return OK; + return txt2time (argv[1], &p3 -> submit_time); + case P3PRM_CONTENT: + if (!isstr(argv[1])) return OK; + p3 -> content_type = strdup (argv[1]); + return OK; + case P3PRM_ORIG_MTA_CERT: + if (!isstr(argv[1])) return OK; + p3 -> originating_mta_certificate = hex2qb (argv[1]); + return OK; + case P3PRM_PROOF_OF_SUB: + if (!isstr(argv[1])) return OK; + p3 -> proof_of_submission = hex2qb (argv[1]); + return OK; + case P3PRM_END: + return P3PRM_END; + } + return NOTOK; +} diff --git a/Lib/pp/txt2prm.c b/Lib/pp/txt2prm.c new file mode 100644 index 0000000..52f043c --- /dev/null +++ b/Lib/pp/txt2prm.c @@ -0,0 +1,100 @@ +/* tx_prm.c: handles the MessageManagementParameter structures, + see manaul page QUEUE (5). +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2prm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "prm.h" +#include "tb_com.h" +#include "tb_prm.h" + +#define txt2int(n) atoi(n) + +extern CMD_TABLE + prmtbl_ln [/* message-management-parameters */], + prmtbl_opts [/* options */]; + + + + +/* ------------------- Text File -> Memory ------------------------------ */ + +static int PRM_txt2opts (); + + +int txt2prm (pp, argv, argc) /* Txt -> MessageManagementParameters */ +struct prm_vars *pp; +char **argv; +int argc; +{ + int key; + + + PP_DBG (("Lib/pp/txt2prm(%s)", argv[0])); + + key = cmd_srch (argv[0], prmtbl_ln); + + if (--argc < 1) + if (key != PRM_END) + return (NOTOK); + + switch (key) { + case PRM_LOGFILE: + pp->prm_logfile = strdup (argv[1]); + return (OK); + case PRM_LOGLEVEL: + pp->prm_loglevel = txt2int(argv[1]); + return (OK); + case PRM_PASSWD: + pp->prm_passwd = strdup (argv[1]); + return (OK); + case PRM_OPTS: + return (PRM_txt2opts (argc, &argv[1], &pp->prm_opts)); + case PRM_END: + return (PRM_END); + } + + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/txt2prm Unable to parse '%s'", argv[0])); + return (NOTOK); +} + + +static int PRM_txt2opts (argc, argv, options) /* Txt -> Praram options */ +char **argv; +int argc; +int *options; +{ + + int i; + int type; + + PP_DBG (("Lib/pp/txt2opts(%s)", argv[0])); + + /* read string - delimitted by ',' e.g nocheck etc... */ + *options = 0; + for (i=0; i < argc; i++) { + if ((type = cmd_srch (argv[i], prmtbl_opts))==NOTOK) + continue; + else + *options |= type; + } + PP_DBG (("options = 0x%x", *options)); + return (OK); +} + diff --git a/Lib/pp/txt2q.c b/Lib/pp/txt2q.c new file mode 100644 index 0000000..3e5e0fb --- /dev/null +++ b/Lib/pp/txt2q.c @@ -0,0 +1,384 @@ +/* txt2q.c: text encoding into Q struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/txt2q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: txt2q.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "q.h" +#include "tb_com.h" +#include "tb_q.h" +#include "mta.h" + +#define txt2crit(n) cmd_srch ((n), tbl_crit) +#define txt2int(n) atoi (n) + +extern CMD_TABLE + tbl_bool [], + tbl_crit [], + qtbl_que [/* message-envelope-parameters */], + qtbl_mt_type [/* message-type */], + qtbl_con_type [/* content-type */], + qtbl_priority [/* message-priority */]; + +extern int n_qtbl_que; +extern struct qbuf *hex2qb (); +extern X400_Extension *txt2extension (); +static int Q_txt2msgtype (); +static int Q_txt2priority (); + +/* ------------------- Text File -> Memory ------------------------------ */ + + +int txt2q (qp, startlineoffset, argv, argc) /* Txt -> MessageEnvelopePrarmeters */ +Q_struct *qp; +long startlineoffset; +char **argv; +int argc; +{ + int key; + + PP_DBG (("Lib/pp/txt2q('%s' %d)", argv[0], argc)); + + key = cmdbsrch (argv[0], qtbl_que, n_qtbl_que); + + switch (key) { + case Q_MSGTYPE: + return (Q_txt2msgtype (&qp->msgtype, argv[1])); + + case Q_MSGSIZE: + if (!isstr (argv[1])) return OK; + qp->msgsize = atoi (argv[1]); + return OK; + + case Q_DEFERREDTIME: + if (!isstr (argv[1])) return OK; + return (txt2time (argv[1], &qp->defertime)); + + case Q_LATESTTIME: + if (!isstr (argv[1])) return OK; + if (txt2time (argv[1], &qp ->latest_time) == NOTOK) + return NOTOK; + if (!isstr (argv[2])) return OK; + qp -> latest_time_crit = txt2crit (argv[2]); + return OK; + + case Q_NWARNS: + if (!isstr (argv[1])) return OK; + qp->nwarns = atoi (argv[1]); + qp->nwarns_offset = startlineoffset + strlen(argv[0]) + 1; + return OK; + + case Q_WARNINTERVAL: + if (!isstr (argv[1])) return OK; + qp->warninterval = atoi (argv[1]); + return OK; + + case Q_RETINTERVAL: + if (!isstr (argv[1])) return OK; + qp->retinterval = atoi (argv[1]); + return OK; + + case Q_CONTENT_TYPE: + if (!isstr (argv[1])) return OK; + qp->cont_type = strdup(argv[1]); + return OK; + + case Q_ENCODED_INFO: + if (!isstr (argv[1])) return OK; + if (txt2encodedinfo (&qp->encodedinfo, &argv[1], argc - 1) + == NOTOK) return NOTOK; + return OK; + + case Q_ORIG_ENCODED_INFO: + if (!isstr (argv[1])) return OK; + if (txt2encodedinfo (&qp->orig_encodedinfo, &argv[1], argc - 1) + == NOTOK) return NOTOK; + return OK; + + case Q_PRIORITY: + if (!isstr (argv[1])) return OK; + return (Q_txt2priority (&qp->priority, argv[1])); + + case Q_DISCLOSE_RECIPS: + if (!isstr (argv[1])) return OK; + qp -> disclose_recips = cmd_srch (argv[1], tbl_bool); + return OK; + + case Q_IMPLICIT_CONVERSION: + if (!isstr(argv[1])) return OK; + qp -> implicit_conversion_prohibited = cmd_srch (argv[1], tbl_bool); + return OK; + + case Q_ALTERNATE_RECIP_ALLOWED: + if (!isstr(argv[1])) return OK; + qp -> alternate_recip_allowed = cmd_srch (argv[1], tbl_bool); + return OK; + + case Q_CONTENT_RETURN_REQUEST: + if (!isstr(argv[1])) return OK; + qp -> content_return_request = cmd_srch (argv[1], tbl_bool); + return OK; + + case Q_RECIP_REASSIGN_PROHIBITED: + if (!isstr (argv[1])) return OK; + qp -> recip_reassign_prohibited = cmd_srch (argv[1], tbl_bool); + if (!isstr (argv[2])) return OK; + qp -> recip_reassign_crit = txt2crit (argv[2]); + return OK; + + case Q_DL_EXP_PROHIBITIED: + if (!isstr (argv[1])) return OK; + qp -> dl_expansion_prohibited = cmd_srch (argv[1], tbl_bool); + if (!isstr (argv[2])) return OK; + qp -> dl_expansion_crit = txt2crit (argv[2]); + return OK; + + case Q_CONV_WITH_LOSS: + if (!isstr (argv[1])) return OK; + qp -> conversion_with_loss_prohibited = + cmd_srch (argv[1], tbl_bool); + if (!isstr (argv[2])) return OK; + qp -> conversion_with_loss_crit = + txt2crit (argv[2]); + return OK; + + case Q_UA_ID: + if (!isstr (argv[1])) return OK; + qp->ua_id = strdup (argv[1]); + return OK; + + case Q_PP_CONT_CORR: + if (!isstr (argv[1])) return OK; + qp -> pp_content_correlator = strdup (argv[1]); + return OK; + + case Q_GEN_CONT_CORR: + if (!isstr(argv[1])) return OK; + qp -> general_content_correlator = hex2qb (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> content_correlator_crit = txt2crit (argv[2]); + return OK; + + case Q_ORIG_RETURN_ADDRESS: + return txt2fname (&qp -> originator_return_address, + &qp -> originator_return_address_crit, + argv + 1, argc -1); + + case Q_FORWARDING_REQUEST: + if (!isstr (argv[0])) return OK; + qp -> forwarding_request = txt2int (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> forwarding_request_crit = txt2crit (argv[2]); + return OK; + + case Q_ORIGINATOR_CERT: + if (!isstr (argv[1])) return OK; + qp -> originator_certificate = hex2qb (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> originator_certificate_crit = txt2crit (argv[2]); + return OK; + + case Q_ALGORITHM_ID: + if (!isstr (argv[1])) return OK; + qp -> algorithm_identifier = hex2qb (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> algorithm_identifier_crit = txt2crit (argv[2]); + return OK; + + case Q_MESSAGE_ORIGIN_AUTH_CHECK: + if (!isstr (argv[1])) return OK; + qp -> message_origin_auth_check = hex2qb (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> message_origin_auth_check_crit = txt2crit (argv[2]); + return OK; + + case Q_SECURITY_LABEL: + if (!isstr (argv[1])) return OK; + qp -> security_label = hex2qb (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> security_label_crit = txt2crit (argv[2]); + return OK; + + case Q_PROOF_OF_SUB: + if (!isstr (argv[1])) return OK; + qp -> proof_of_submission_request = txt2int (argv[1]); + if (!isstr (argv[2])) return OK; + qp -> proof_of_submission_crit = txt2crit (argv[2]); + return OK; + + case Q_MESSAGE_EXTENSIONS: + { + X400_Extension *ext, **extp; + + ext = txt2extension (&argv[1], argc - 1); + + for (extp = &qp-> per_message_extensions; + *extp; extp = &(*extp) -> ext_next) + continue; + *extp = ext; + } + return OK; + + case Q_INCHANNEL: + if (!isstr (argv[1])) return NOTOK; + if (qp -> inbound == NULL) + qp->inbound = list_rchan_new (NULLCP, argv[1]); + else return list_rchan_schan (qp->inbound, argv[1]); + return OK; + + case Q_INHOST: + if (!isstr (argv[1])) return NOTOK; + if (qp -> inbound == NULL) + qp -> inbound = list_rchan_new (argv[1], NULLCP); + else return list_rchan_ssite (qp -> inbound, argv[1]); + return OK; + + case Q_MSGID: + if (txt2mpduid (&qp->msgid, &argv[1], argc - 1) == NOTOK) + return NOTOK; + return OK; + case Q_TRACE: + if (txt2trace (&qp->trace, &argv[1], argc - 1) == NOTOK) + return NOTOK; + return OK; + + case Q_DL_EXP_HISTORY: + return txt2dlexp (&qp -> dl_expansion_history, + argv + 1, argc - 1); + + case Q_DL_EXP_HIST_CRIT: + if (!isstr (argv[1])) return OK; + qp -> dl_expansion_history_crit = txt2int (argv[1]); + return OK; + + case Q_QUEUETIME: + if (!isstr (argv[1])) return OK; + return (txt2time (argv[1], &qp->queuetime)); + + case Q_DEPARTIME: + if (!isstr (argv[1])) return OK; + return (txt2time (argv[1], &qp->departime)); + + case Q_END: + return Q_END; + } + + + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/txt2q Unable to parse '%s'", argv[0])); + return NOTOK; +} + + +static int Q_txt2msgtype (msgtype, keywd) /* Txt -> Message-type */ +int *msgtype; +char *keywd; +{ + PP_DBG (("Lib/pp/Q_txt2msgtype(%s)", keywd)); + + switch (*msgtype = cmd_srch (keywd, qtbl_mt_type)) { + case MT_UMPDU: + case MT_PMPDU: + case MT_DMPDU: + return OK; + } + return NOTOK; +} + + + +static int Q_txt2priority (priority, keywd) /* Txt -> Priority */ +int *priority; +char *keywd; +{ + PP_DBG (("Lib/pp/Q_txt2priority(%s)", keywd)); + + switch (*priority = cmd_srch (keywd, qtbl_priority)) { + case PRIO_NORMAL: + case PRIO_NONURGENT: + case PRIO_URGENT: + return OK; + } + return NOTOK; +} + +struct qbuf *hex2qb (hexstr) +char *hexstr; +{ + char *str; + int n; + struct qbuf *qb; + + str = smalloc ((n = strlen (hexstr)) / 2); + n = implode ((unsigned char *)str, hexstr, n); + + qb = str2qb (str, n, 1); + free (str); + return qb; +} + +int txt2fname (fname, crit, argv, argc) +FullName **fname; +char *crit; +char **argv; +int argc; +{ + FullName *fn; + + *fname = fn = (FullName *) smalloc (sizeof *fn); + if (argc < 1) return OK; + if (*argv) + fn -> fn_addr = strdup (*argv); + argv ++; argc --; + + if (argc < 1) return OK; + if (*argv) + fn -> fn_dn = strdup (*argv); + argv ++; argc --; + + if (argc < 1) return OK; + if (*argv) + *crit = txt2crit (*argv); + return OK; +} + +int txt2dlexp (dlp, argv, argc) +DLHistory **dlp; +char **argv; +int argc; +{ + if (argc < 1) + return OK; + for (;*dlp; dlp = &(*dlp) -> dlh_next) + continue; + + *dlp = (DLHistory *) smalloc (sizeof **dlp); + bzero ((char *)*dlp , sizeof **dlp); + + if (argc < 1) return OK; + if (*argv) + (*dlp) -> dlh_addr = strdup (*argv); + argv ++; argc --; + + if (argc < 1) return OK; + if (*argv) + (*dlp) -> dlh_dn = strdup (*argv); + argv ++; argc --; + + if (argc < 1) return OK; + + return txt2time (*argv, &(*dlp) -> dlh_time); +} diff --git a/Lib/pp/ut_a.c b/Lib/pp/ut_a.c new file mode 100644 index 0000000..73f70d8 --- /dev/null +++ b/Lib/pp/ut_a.c @@ -0,0 +1,151 @@ +/* ut_a.c: Address utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_a.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_a.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_a.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "adr.h" +#include "dr.h" + +extern void extensions_free (); + +ADDR *adr_new (orig, type, rno) /* create new addr struct */ +char *orig; +int type; +int rno; +{ + register ADDR *ap; + + PP_DBG (( + "Lib/pp/ut_a.c/adr_new ('addr-orig=%s', 'type=%d' 'rno=%d')", + orig ? orig : "", + type, rno)); + + ap = (ADDR *) smalloc (sizeof(ADDR)); + adr_init (ap); + + /* set values for orig, type and rno if given */ + if (orig != NULLCP) + ap->ad_value = strdup(orig); + if (type) + ap->ad_type = type; + if (rno) { + ap->ad_extension = rno; + ap->ad_no = rno; + } + + ap->aparse = aparse_new(); + ap->aparse->ad_type = ap->ad_type; + + return(ap); +} + +void adr_init (ap) +ADDR *ap; +{ + int i; + + bzero ((char *) ap, sizeof (*ap)); + ap->ad_status = AD_STAT_PEND; /* recipient status */ + ap->ad_resp = YES; /* responsibility flag */ + ap->ad_mtarreq = AD_MTA_BASIC; /* mta-rep-req PRFlag */ + ap->ad_usrreq = AD_USR_BASIC; /* usr-rep-req PRFlag */ + ap->ad_type = AD_ANY_TYPE; /* address-type */ + ap->ad_reason = DRR_NO_REASON; /* no reason */ + ap->ad_parse_stat = RP_AOK; /* addr parsing error status*/ + ap->ad_explicitconversion = AD_EXP_NONE; +#ifdef notdef /* these should not be set - unless the element is there */ + ap->ad_phys_modes = AD_PM_ORD; + ap->ad_reg_mail_type = AD_RMT_UNSPECIFIED; +#endif + for (i = 0; i < AD_RDM_MAX; i++) + ap -> ad_req_del[i] = AD_RDM_NOTUSED; +} + +void adr_add (base, new) +ADDR **base; +ADDR *new; +{ + ADDR *ap = *base; + + PP_DBG (("Lib/pp/ut_a.c/adr_add ()")); + + if (ap == NULLADDR) + *base = new; + else { + while (ap->ad_next != NULLADDR) + ap = ap->ad_next; + ap->ad_next = new; + } +} + +void adr_tfree (addr) /* remove adr and recurse down the links */ +ADDR *addr; +{ + ADDR *ap; + + for (; addr; addr = ap) { + ap = addr -> ad_next; + adr_free (addr); + free ((char *)addr); + } +} + + +void adr_free (ap) +register ADDR *ap; +{ + PP_DBG (("Lib/pp/ut_a.c/UA_afree()")); + + if (ap->ad_value != NULLCP) + free (ap->ad_value); + if (ap->ad_r822adr != NULLCP) + free (ap->ad_r822adr); + if (ap->ad_r400adr != NULLCP) + free (ap->ad_r400adr); + if (ap->ad_add_info != NULLCP) + free (ap->ad_add_info); + if (ap->ad_content != NULLCP) + free (ap->ad_content); + if (ap->ad_parse_message != NULLCP) + free(ap->ad_parse_message); + if (ap->ad_outchan) + list_rchan_free (ap->ad_outchan); + if (ap->ad_fmtchan) + list_rchan_free (ap->ad_fmtchan); + if (ap -> ad_eit) + list_bpt_free (ap -> ad_eit); + + if (ap -> ad_dn) + free (ap -> ad_dn); + if (ap -> ad_orig_req_alt) + free (ap -> ad_orig_req_alt); + if (ap -> ad_recip_number_for_advice) + free (ap -> ad_recip_number_for_advice); + if (ap -> ad_phys_rendition_attribs) + oid_free (ap -> ad_phys_rendition_attribs); + if (ap -> ad_redirection_history) + redirection_free (ap -> ad_redirection_history); + + if (ap -> ad_message_token) + qb_free (ap -> ad_message_token); + if (ap -> ad_content_integrity) + qb_free (ap -> ad_content_integrity); + if (ap -> ad_per_recip_ext_list) + extensions_free (ap -> ad_per_recip_ext_list); + if (ap -> aparse) + aparse_free(ap -> aparse); +} + diff --git a/Lib/pp/ut_aparse.c b/Lib/pp/ut_aparse.c new file mode 100644 index 0000000..cb750c3 --- /dev/null +++ b/Lib/pp/ut_aparse.c @@ -0,0 +1,196 @@ +/* ut_aparse.c: utility routines for the aparse structure */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_aparse.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_aparse.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_aparse.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + +#include "aparse.h" + +static void aparse_init(); + +Aparse_ptr aparse_new () +{ + Aparse_ptr ret; + + ret = (Aparse_ptr) (smalloc (sizeof(Aparse))); + aparse_init(ret); + return ret; +} + +static void aparse_init(ap) +Aparse_ptr ap; +{ + bzero((char *) ap, sizeof (*ap)); + ap->orname = (ORName *) calloc(1, sizeof(ORName)); +} + +void aparse_free (ap) +Aparse_ptr ap; +{ + if (ap->ap_tree) + (void) ap_sqdelete (ap->ap_tree, NULLAP); + if (ap->r822_str) + free(ap->r822_str); + if (ap->r822_local) + free(ap->r822_local); + if (ap->r822_error) + free(ap->r822_error); + + if (ap->orname) + ORName_free(ap->orname); + if (ap->x400_dn) + free(ap->x400_dn); + if (ap->x400_str) + free(ap->x400_str); + if (ap->x400_local) + free(ap->x400_local); + if (ap->x400_error) + free(ap->x400_error); + + if (ap->aliases) + aparse_freeAliasList(ap->aliases); + + if (ap->local_hub_name) + free(ap->local_hub_name); +} + +/* */ + +void aparse_rewindx400(ap) +Aparse_ptr ap; +{ + if (ap->orname->on_or) { + or_free(ap->orname->on_or); + ap->orname->on_or = NULLOR; + } + if (ap->orname->on_dn) { + ; + } + + if (ap->x400_dn) { + free (ap->x400_dn); + ap->x400_dn = NULLCP; + } + if (ap->x400_str) { + free (ap->x400_str); + ap->x400_str = NULLCP; + } + if (ap->x400_local) { + free (ap->x400_local); + ap->x400_local = NULLCP; + } +} + +void aparse_rewindr822(ap) +Aparse_ptr ap; +{ + if (ap->ap_tree) { + (void) ap_sqdelete (ap->ap_tree, NULLAP); + ap->ap_tree = NULLAP; + ap->ap_group = NULLAP; + ap->ap_name = NULLAP; + ap->ap_local = NULLAP; + ap->ap_domain = NULLAP; + ap->ap_route = NULLAP; + } + + if (ap->r822_str) { + free (ap->r822_str); + ap->r822_str = NULLCP; + } + if (ap->r822_local) { + free (ap->r822_local); + ap->r822_local = NULLCP; + } +} + + +void aparse_rewindlocal(ap) +Aparse_ptr ap; +{ + if (ap->local_hub_name) { + free(ap->local_hub_name); + ap->local_hub_name=NULLCP; + } +} + +void aparse_copy_for_recursion(to, from) +Aparse_ptr to, from; +{ + to->dmnorder = from->dmnorder; + to->full = from->full; + to->percents = from->percents; + to->recurse_count = from->recurse_count+1; + to->aliases = aparse_aliasDup(from->aliases); + to->normalised = from->normalised; + to->dont_use_aliases = from->dont_use_aliases; +} + +/* */ + +/* alias list stuff */ + +void aparse_freeAliasList(list) +aliasList *list; +{ + if (list->alias) free(list->alias); + if (list->next) aparse_freeAliasList(list->next); + free((char *) list); +} + +static aliasList *newAliasList(alias) +char *alias; +{ + aliasList *ret = (aliasList *) calloc(1, sizeof(*ret)); + ret->alias = strdup(alias); + return ret; +} + +void aparse_addToAliasList(alias, plist) +char *alias; +aliasList **plist; +{ + aliasList *tmp = newAliasList(alias); + if (*plist == NULL) + *plist = tmp; + else { + tmp->next = *plist; + *plist = tmp; + } +} + +int aparse_inAliasList(alias, list) +char *alias; +aliasList *list; +{ + aliasList *ix = list; + + while (ix != NULL && strcmp(ix->alias, alias) != 0) + ix = ix->next; + + if (ix != NULL) + return OK; + return NOTOK; +} + +aliasList *aparse_aliasDup(list) +aliasList *list; +{ + aliasList *ret = NULL; + + if (list) { + ret = newAliasList(list->alias); + ret->next = aparse_aliasDup(list->next); + } + return ret; +} + diff --git a/Lib/pp/ut_com.c b/Lib/pp/ut_com.c new file mode 100644 index 0000000..7a41432 --- /dev/null +++ b/Lib/pp/ut_com.c @@ -0,0 +1,74 @@ +/* ut_com.c Buffer utilities used by all the tx_*.c files */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_com.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_com.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_com.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + + +/* --------------------- General Routines ------------------------------ */ + + + + +char *Bf_put (buf, str) /* cat str LWSP > buf */ +char *buf; +char *str; +{ + while (*buf++ = *str++); + return (buf); +} + + +extern int arg2vstr (); + +int argv2fp (fp, argv) +FILE *fp; +char **argv; +{ + extern int protocol_mode; + char buffer[10*BUFSIZ]; + + if (arg2vstr (protocol_mode ? 0 : 72, sizeof buffer, buffer, argv) == NOTOK) + return NOTOK; + PP_DBG (("argv2fp(%d) -> '%.199s'", protocol_mode, buffer)); + (void) fputs (buffer, fp); + (void) putc ('\n', fp); + return ferror(fp) ? NOTOK : OK; +} + + + + +static char genbuf[10*BUFSIZ]; +static char *_genbuf; + + +void genreset () +{ + _genbuf = genbuf; +} + + + +char *genstore (str) +char *str; +{ + char *p = _genbuf; + while (*_genbuf++ = *str++) + continue; + return p; +} diff --git a/Lib/pp/ut_dlh.c b/Lib/pp/ut_dlh.c new file mode 100644 index 0000000..0656be1 --- /dev/null +++ b/Lib/pp/ut_dlh.c @@ -0,0 +1,75 @@ +/* ut_dlh.c: utility routines for distribution list history */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_dlh.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_dlh.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_dlh.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +DLHistory *dlh_new (addr, dn, utc) +char *addr, *dn; +UTC utc; +{ + DLHistory *dlh; + + dlh = (DLHistory *) smalloc (sizeof *dlh); + + dlh -> dlh_addr = addr ? strdup (addr) : NULLCP; + dlh -> dlh_dn = dn ? strdup (dn) : NULLCP; + dlh -> dlh_time = utc ? utcdup(utc) : utcnow (); + dlh -> dlh_next = NULL; + return dlh; +} + +void dlh_add (base, dlh) +DLHistory **base, *dlh; +{ + DLHistory **dlp; + + for (dlp = base; *dlp; dlp = &(*dlp) -> dlh_next) + continue; + *dlp = dlh; +} + +DLHistory *dlh_dup (dlh) +DLHistory *dlh; +{ + DLHistory *new = NULL; + DLHistory *dlp; + + for (dlp = dlh; dlp; dlp = dlp->dlh_next) { + dlh_add (&new, dlh_new (dlp -> dlh_addr, + dlp -> dlh_dn, + dlp -> dlh_time)); + } + return new; +} + +void dlh_free (dlh) +DLHistory *dlh; +{ + if (dlh == NULL) + return; + if (dlh -> dlh_next) + dlh_free (dlh -> dlh_next); + if (dlh -> dlh_addr) + free (dlh -> dlh_addr); + if (dlh -> dlh_dn) + free (dlh -> dlh_dn); + if (dlh -> dlh_time) + free ((char *) dlh -> dlh_time); + free ((char *)dlh); +} + diff --git a/Lib/pp/ut_dr.c b/Lib/pp/ut_dr.c new file mode 100644 index 0000000..258f2e7 --- /dev/null +++ b/Lib/pp/ut_dr.c @@ -0,0 +1,93 @@ +/* ut_dr.c: DR utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_dr.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_dr.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "dr.h" + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void dr_init (dreport) +register DRmpdu *dreport; +{ + PP_DBG (("Lib/pp/dr_init()")); + bzero ((char *)dreport, sizeof(*dreport)); +} + + + + +void dr_free (dr) +register DRmpdu *dr; +{ + PP_DBG (("Lib/pp/dr_free()")); + + /* -- the envelope part is set from Q_struct - so not freed -- */ + + if (dr->dr_mpduid) + MPDUid_free (dr->dr_mpduid); + if (dr->dr_trace) + trace_free (dr->dr_trace); + if (dr->dr_subject_intermediate_trace) + trace_free (dr->dr_subject_intermediate_trace); + if (dr -> dr_dl_history) + dlh_free (dr -> dr_dl_history); + if (dr -> dr_reporting_dl_name) + fn_free (dr -> dr_reporting_dl_name); + if (dr -> dr_security_label) + qb_free (dr -> dr_security_label); + if (dr -> dr_reporting_mta_certificate) + qb_free (dr -> dr_reporting_mta_certificate); + if (dr -> dr_report_origin_auth_check) + qb_free (dr -> dr_report_origin_auth_check); + if (dr -> dr_per_report_extensions) + extensions_free (dr -> dr_per_report_extensions); + if (dr->dr_recip_list) + rrinfo_free(dr -> dr_recip_list); + + dr_init (dr); +} + +void rrinfo_free (rr) /* -- ReportedRecipientInfo -- */ +Rrinfo *rr; +{ + if (rr == (Rrinfo *) NULL) return; + + rrinfo_free (rr->rr_next); + + if (rr -> rr_originally_intended_recip) + fn_free (rr -> rr_originally_intended_recip); + if (rr->rr_supplementary != NULLCP) + free (rr->rr_supplementary); + if (rr -> rr_redirect_history) + redirection_free (rr -> rr_redirect_history); + if (rr -> rr_physical_fwd_addr) + fn_free (rr -> rr_physical_fwd_addr); + if (rr -> rr_recip_certificate) + qb_free (rr -> rr_recip_certificate); + if (rr -> rr_report_origin_authentication_check) + qb_free (rr -> rr_report_origin_authentication_check); + if (rr -> rr_arrival) + free ((char *)rr->rr_arrival); + if (rr -> rr_per_recip_extensions) + extensions_free (rr -> rr_per_recip_extensions); + free ((char *) rr); +} diff --git a/Lib/pp/ut_fn.c b/Lib/pp/ut_fn.c new file mode 100644 index 0000000..158986b --- /dev/null +++ b/Lib/pp/ut_fn.c @@ -0,0 +1,52 @@ +/* ut_fn.c: FullName support routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_fn.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_fn.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_fn.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +FullName *fn_new (addr, dn) +char *addr; +char *dn; +{ + FullName *fn; + + fn = (FullName *) smalloc (sizeof *fn); + + fn -> fn_addr = addr ? strdup (addr) : NULLCP; + fn -> fn_dn = dn ? strdup (dn) : NULLCP; + return fn; +} + +void fn_free (fn) +FullName *fn; +{ + if (fn == NULL) + return; + + if (fn -> fn_addr) + free (fn -> fn_addr); + if (fn -> fn_dn) + free (fn -> fn_dn); + free ((char *)fn); +} + +FullName *fn_dup (fn) +FullName *fn; +{ + return fn_new (fn -> fn_addr, fn -> fn_dn); +} + diff --git a/Lib/pp/ut_free.c b/Lib/pp/ut_free.c new file mode 100644 index 0000000..e700daf --- /dev/null +++ b/Lib/pp/ut_free.c @@ -0,0 +1,86 @@ +/* ut_free.c: Freeing utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_free.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_free.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_free.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + + +/* --------------------- Begin Routines -------------------------------- */ + +void encodedinfo_free (ep) /* EncodedInfoTypes */ +EncodedIT *ep; +{ + if (ep == (EncodedIT *)NULL) + return; + + if (ep->eit_types) + list_bpt_free (ep->eit_types); + bzero ((char *)ep, sizeof *ep); +} + +void DomSupInfo_free (dp) /* DomainSuppliedInfo */ +DomSupInfo *dp; +{ + if (dp == NULL) + return; + + if (dp->dsi_time) + free ((char *)dp->dsi_time); + + if (dp->dsi_deferred) + free ((char *)dp->dsi_deferred); + + encodedinfo_free (&dp -> dsi_converted); + GlobalDomId_free (&dp->dsi_attempted_md); + + if (dp -> dsi_attempted_mta) + free (dp -> dsi_attempted_mta); + + bzero ((char *)dp, sizeof *dp); +} + +void redirection_free (rp) +Redirection *rp; +{ + Redirection *rq; + + for (; rp; rp = rq) { + rq = rp -> rd_next; + if (rp -> rd_addr) + free (rp -> rd_addr); + if (rp -> rd_dn) + free (rp -> rd_dn); + free ((char *)rp); + } +} + +void extensions_free (ext) +X400_Extension *ext; +{ + if (ext == NULL) + return; + if (ext -> ext_next) + extensions_free (ext -> ext_next); + if (ext -> ext_oid) + oid_free (ext -> ext_oid); + if (ext -> ext_value) + qb_free (ext -> ext_value); + free ((char *) ext); +} + + + diff --git a/Lib/pp/ut_gldm.c b/Lib/pp/ut_gldm.c new file mode 100644 index 0000000..6ce925e --- /dev/null +++ b/Lib/pp/ut_gldm.c @@ -0,0 +1,53 @@ +/* ut_p1_st.c: Deals with new p1 structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_gldm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_gldm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_gldm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include "or.h" +#include + + +extern GlobalDomId Myglobalname; + + + +/* --------------------- Begin Routines -------------------------------- */ + + +void GlobalDomId_new (gp) /* generate a new global id */ +GlobalDomId *gp; +{ + PP_DBG (("Lib/pp/new_GlobalDomId()")); + + or_myinit (); + gp->global_Country = strdup(Myglobalname.global_Country); + gp->global_Admin = strdup(Myglobalname.global_Admin); + if(Myglobalname.global_Private) + gp->global_Private = strdup(Myglobalname.global_Private); +} + +void GlobalDomId_free (gp) +GlobalDomId *gp; +{ + if (gp -> global_Country) + free (gp -> global_Country); + if (gp -> global_Private) + free (gp -> global_Private); + if (gp -> global_Admin) + free (gp -> global_Admin); + bzero ((char *)gp, sizeof *gp); +} diff --git a/Lib/pp/ut_mm2p1.c b/Lib/pp/ut_mm2p1.c new file mode 100644 index 0000000..677627e --- /dev/null +++ b/Lib/pp/ut_mm2p1.c @@ -0,0 +1,76 @@ +/* ut_mm2p1.c: Deals with conversions between memory -> p1 structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_mm2p1.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_mm2p1.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_mm2p1.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + + +/* --------------------- Memory -> Field -------------------------------- */ + + + +int mem2prf (resp, mta, usr) /* creates a PerRecipientFlag from Memory */ +int resp; +int mta; +int usr; +{ + int field = 0; + + PP_DBG (("Lib/mem2prf (%d %d %d)", resp, mta, usr)); + + /* -- set the responsibility field -- */ + field |= resp; + + + /* -- set the report request field -- */ + switch (mta) { + case 0: + break; + case 1: + field |= (1 << 2); + break; + case 2: + field |= (1 << 1); + break; + case 3: + field |= (1 << 1); + field |= (1 << 2); + break; + } + + + /* -- set the user report request field -- */ + switch (usr) { + case 0: + break; + case 1: + field |= (1 << 4); + break; + case 2: + field |= (1 << 3); + break; + case 3: + field |= (1 << 3); + field |= (1 << 4); + break; + } + + + PP_DBG (("Lib/mem2prf returns (%d)", field)); + + return (field); +} diff --git a/Lib/pp/ut_mpduid.c b/Lib/pp/ut_mpduid.c new file mode 100644 index 0000000..437496c --- /dev/null +++ b/Lib/pp/ut_mpduid.c @@ -0,0 +1,50 @@ +/* ut_mpduid.c: utilities for mpduid's */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_mpduid.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_mpduid.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_mpduid.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" + +void MPDUid_new (mp) +MPDUid *mp; +{ + extern char *loc_dom_mta; + time_t t, time(); + struct tm *tp; + char tbuf[LINESIZE]; + + PP_DBG (("Lib/pp/new_MPDUid()")); + + t = time((time_t *)0); + tp = gmtime(&t); + (void) sprintf(tbuf, "%.10s.%03d:%02d.%02d.%02d.%02d.%02d.%02d", + loc_dom_mta, (getpid()%1000), + tp->tm_mday, tp->tm_mon, (tp->tm_year%100), + tp->tm_hour, tp->tm_min, tp->tm_sec); + mp->mpduid_string = strdup(tbuf); + GlobalDomId_new (&mp->mpduid_DomId); +} + +void MPDUid_free (mp) +MPDUid *mp; +{ + if (mp == NULL) + return; + + if (mp -> mpduid_string) + free (mp -> mpduid_string); + GlobalDomId_free (&mp -> mpduid_DomId); +} diff --git a/Lib/pp/ut_msg.c b/Lib/pp/ut_msg.c new file mode 100644 index 0000000..fae9d8b --- /dev/null +++ b/Lib/pp/ut_msg.c @@ -0,0 +1,356 @@ +/* ut_msg.c: library of routines to read a message directory struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_msg.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_msg.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_msg.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include +#include + + +#define NULLDIR ((DIR*)0) +#define NULLDCT ((struct dirent *)0) + +extern CMD_TABLE + qtbl_con_type [/* content-type */]; + +extern char *quedfldir; +extern int errno; +static int fcmp(); + +static DIR *ST_dir = NULLDIR; +static char *ST_array[BUFSIZ]; +static char *ST_name = NULLCP; +static int ST_curr = NULL; +static int ST_level = NULL; +static int ST_no = NULL; + +int msg_rend (); + +static void UM_array_free (); +static struct dirent *UM_readdir (); +static int UM_isdir (); +static int UM_rfile (); +static void UM_push (); +static struct dirent *UM_pop (); +static int fcmp (); +static int recur_fcmp (); + +/* ------------------------ External Routines -------------------------- */ + + + +static int basedir_len; + +int msg_rinit (dir) +char *dir; +{ + PP_DBG (("Lib/pp/msg_rinit: (%s)", dir)); + + if (ST_dir) (void) msg_rend(); + + ST_level = 0; + ST_name = malloc (LINESIZE); + bzero (ST_name, LINESIZE); + + (void) strcpy (ST_name, dir); + + + if (!UM_isdir (ST_name)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/msg_rinit: %s is not a dir", ST_name)); + return (RP_FOPN); + } + + if ((ST_dir = opendir (ST_name)) == NULLDIR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/msg_rinit: unable to open %s", ST_name)); + return (RP_FOPN); + } + + basedir_len = strlen(ST_name); + + return (RP_OK); + +} + + +int msg_rfile (buf) +char *buf; +{ + char *ptr; + + PP_DBG (("Lib/pp/msg_rfile: (%s)", ST_name)); + + if (ST_no == NULL) { + while (UM_rfile (buf) == RP_OK) { + ptr = strdup (buf); + ST_array [ST_no] = ptr; + ++ST_no; + } + + qsort ((char *)ST_array, + ST_no, + (sizeof (ST_array[0])), + fcmp); + + } + + if (ST_curr < ST_no) { + (void) strcpy (buf, ST_array[ST_curr]); + ++ST_curr; + return (RP_OK); + } + + return (RP_DONE); +} + + +int msg_rend() +{ + PP_DBG (("Lib/pp/msg_rend: (%s)", ST_name)); + + if (ST_dir) { + (void) closedir (ST_dir); + ST_dir = NULLDIR; + } + + if (ST_name) { + free (ST_name); + ST_name = NULLCP; + } + + if (ST_no) + UM_array_free(); + + ST_level = NULL; + return (RP_OK); +} + + +static int fcmp (f1, f2) +register char **f1, **f2; +{ + char *stripedf1, + *stripedf2; + + stripedf1 = (*f1)+basedir_len+1; + stripedf2 = (*f2)+basedir_len+1; + + return recur_fcmp(stripedf1,stripedf2); +} + +static int recur_fcmp(f1,f2) +register char *f1, + *f2; +{ + /* atoi stops at the first non digit */ + int f1digit = atoi(f1); + int f2digit = atoi(f2); + + if (f1digit < f2digit) + return -1; + + else if (f1digit > f2digit) + return 1; + else { + int f1isdir, f2isdir; + char *ixf1, *ixf2; + /* dificult case may have to recurse */ + f1isdir = ((ixf1 = index(f1,'/')) != NULL); + f2isdir = ((ixf2 = index(f2,'/')) != NULL); + if (f1isdir && f2isdir) + return recur_fcmp(++ixf1,++ixf2); + return 0; + } + +} + + + + +/* -------------------------- Static Routines -------------------------- */ + + + + +static int UM_rfile (buf) +char *buf; +{ + struct dirent *dp; + + if (ST_dir == NULLDIR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/UM_rfile: opendir not performed")); + return (RP_DONE); + } + + + dp = UM_readdir (NULLCP); + + if (dp == NULLDCT) + if (ST_level == 0) + return (RP_DONE); + else + if ((dp = UM_pop()) == NULLDCT) + return (RP_DONE); + + if (UM_isdir (dp->d_name)) { + /* + new subdir + */ + UM_push (dp->d_name); + return (UM_rfile (buf)); + } + + + if (isstr (ST_name)) + (void) sprintf (buf, "%s/%s", ST_name, dp->d_name); + else + (void) strcpy (buf, dp->d_name); + + return (RP_OK); + +} + + +static struct dirent *UM_pop() +{ + char tbuf[LINESIZE], + *ptr; + struct dirent *dp; + + --ST_level; + ptr = rindex (ST_name, '/'); + (void) strcpy (tbuf, ++ptr); + *--ptr = '\0'; + + PP_DBG (("Lib/pp/UM_pop: (%s, %d)", ST_name, ST_level)); + + (void) closedir (ST_dir); + ST_dir = opendir (ST_name); + + dp = UM_readdir (&tbuf[0]); + + if (dp) + return (dp); + + if (ST_level) + return (UM_pop()); + + return (NULLDCT); +} + + +static void UM_push (name) +char *name; +{ + char tbuf[LINESIZE]; + + (void) sprintf (tbuf, "%s/%s", ST_name, name); + + (void) strcpy (ST_name, tbuf); + + (void) closedir (ST_dir); + + PP_DBG (("Lib/pp/UM_push: (%s, %d)", ST_name, ST_level+1)); + + if ((ST_dir = opendir (ST_name)) == NULLDIR) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/UM_push: Unable to open %s", ST_name)); + return; + } + + ++ST_level; +} + + +static int UM_isdir (name) +char *name; +{ + struct stat st_rec; + char tbuf[LINESIZE]; + + if (!isstr (name)) + return (FALSE); + + (void) strcpy (&tbuf[0], ST_name); + + if (strcmp (ST_name, name) != 0) { + (void) strcat (&tbuf[0], "/"); + (void) strcat (&tbuf[0], name); + } + + if (stat (&tbuf[0], &st_rec) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, tbuf, + ("Lib/pp/UM_isdir: Unable to stat")); + return (FALSE); + } + + switch (st_rec.st_mode & S_IFMT) { + case S_IFDIR: + PP_DBG (("Lib/pp/UM_isdir (%s = TRUE)", &tbuf[0])); + return (TRUE); + default: + PP_DBG (("Lib/pp/UM_isdir (%s = FALSE)", &tbuf[0])); + return (FALSE); + } +} + + +static struct dirent *UM_readdir (current) +char *current; +{ + struct dirent *dp; + int passed_current = FALSE; + + if (current) + PP_DBG (("Lib/pp/UM_readdir (current = %s)", current)); + + for (dp=readdir(ST_dir); dp != NULLDCT; dp=readdir(ST_dir)) { + if (strcmp (dp->d_name, ".") == 0) continue; + if (strcmp (dp->d_name, "..") == 0) continue; + if (current) + if (strcmp (dp->d_name, current) == 0) { + passed_current = TRUE; + continue; + } + else if (passed_current == FALSE) + continue; + break; + } + + if (dp) + PP_DBG (("Lib/pp/UM_readdir (%s)", dp->d_name)); + + return (dp); +} + + + +static void UM_array_free () +{ + int i; + + for (i=0; i < ST_no; i++) + if (ST_array[i]) { + free (ST_array [i]); + ST_array[i] = NULLCP; + } + + ST_no = NULL; + ST_curr = NULL; +} diff --git a/Lib/pp/ut_p12mm.c b/Lib/pp/ut_p12mm.c new file mode 100644 index 0000000..85855fd --- /dev/null +++ b/Lib/pp/ut_p12mm.c @@ -0,0 +1,63 @@ + /* ut_p12mm.c: Deals with conversions between p1 structures -> memory */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_p12mm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_p12mm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_p12mm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + + + +/* --------------------- Field -> Memory -------------------------------- */ + + + + +void prf2mem (prf, resp, mta, usr) /* PerRecipientFlag -> Mem */ +int prf; +int *resp; +int *mta; +int *usr; +{ + int i; + + PP_DBG (("Lib/pp/prf2mem(%d)", prf)); + + *resp = *mta = *usr = 0; + + for (i = 0; i < 5; i++) + if (prf & (1 << i)) + switch (i) { + case 0: + *resp = 1; + break; + case 1: + *mta |= 2; + break; + case 2: + *mta |= 1; + break; + case 3: + *usr |= 2; + break; + case 4: + *usr |= 1; + break; + } + + + PP_DBG (("Lib/pp/prf2mem returns %d (%d %d %d)", + prf, *resp, *mta, *usr)); +} diff --git a/Lib/pp/ut_p1_st.c b/Lib/pp/ut_p1_st.c new file mode 100644 index 0000000..c1a7b41 --- /dev/null +++ b/Lib/pp/ut_p1_st.c @@ -0,0 +1,96 @@ +/* ut_p1_st.c: Deals with new p1 structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_p1_st.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_p1_st.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_p1_st.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include + + +extern GlobalDomId Myglobalname; +extern char *loc_dom_mta; +extern char *loc_dom_site; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +new_GlobalDomId (gp) /* generate a new global id */ +GlobalDomId *gp; +{ + PP_DBG (("Lib/pp/new_GlobalDomId()")); + + gp->global_Country = strdup(Myglobalname.global_Country); + gp->global_Admin = strdup(Myglobalname.global_Admin); + if(Myglobalname.global_Private) + gp->global_Private = strdup(Myglobalname.global_Private); +} + +GlobalDomId_dup(new, old) +GlobalDomId *new, *old; +{ + if (old->global_Country) + new->global_Country = strdup(old->global_Country); + if (old->global_Admin) + new->global_Admin = strdup(old->global_Admin); + if (old->global_Private) + new->global_Private = strdup(old->global_Private); +} + +new_MPDUid(mp) +MPDUid *mp; +{ + time_t t, time(); + struct tm *tp; + char tbuf[LINESIZE]; + + PP_DBG (("Lib/pp/new_MPDUid()")); + + t = time((time_t *)0); + tp = gmtime(&t); + (void) sprintf(tbuf, "%s.%d:%02d.%02d.%02d.%02d.%02d.%02d", + loc_dom_mta, getpid(), + tp->tm_mday, tp->tm_mon, tp->tm_year+70, + tp->tm_hour, tp->tm_min, tp->tm_sec); + mp->mpduid_string = strdup(tbuf); + new_GlobalDomId(&mp->mpduid_DomId); +} + + + +new_Trace_add (tpp) +register Trace **tpp; +{ + Trace *new, + *tp = *tpp; + + + PP_DBG (("new_trace_add()")); + + new = (Trace *) smalloc (sizeof (*new)); + bzero ((char *) new, sizeof (*new)); + new->trace_mta = strdup (loc_dom_mta); + new_GlobalDomId (&new->trace_DomId); + new->trace_DomSinfo.dsi_time = utcnow (); + + if (tp != (Trace *)0) + new->trace_next = tp; + + *tpp = new; + return (OK); +} diff --git a/Lib/pp/ut_postie.c b/Lib/pp/ut_postie.c new file mode 100644 index 0000000..4364063 --- /dev/null +++ b/Lib/pp/ut_postie.c @@ -0,0 +1,84 @@ +/* ut_postmaster.c: utility routines to get at postmaster address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_postie.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_postie.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_postie.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "adr.h" +#include "chan.h" +#include "retcode.h" + +static ADDR *postmasterAddr; +extern char *postmaster; +char *getpostmaster(type) +int type; +{ + if (postmasterAddr == NULLADDR) { + RP_Buf rp; + postmasterAddr = adr_new(postmaster, AD_822_TYPE, 0); + postmasterAddr -> ad_resp = NO; +#ifdef UKORDER + if (rp_isbad(ad_parse(postmasterAddr, &rp, CH_UK_PREF))) { +#else + if (rp_isbad(ad_parse(postmasterAddr, &rp, CH_USA_PREF))) { +#endif + PP_LOG(LLOG_EXCEPTIONS, + ("Postmaster address '%s' does not parse [%s]", + postmaster, postmasterAddr->ad_parse_message)); + adr_free(postmasterAddr); + postmasterAddr = NULLADDR; + return NULLCP; + } + } + switch (type) { + case AD_822_TYPE: + return postmasterAddr->ad_r822adr; + case AD_X400_TYPE: + return postmasterAddr->ad_r400adr; + default: + return postmasterAddr->ad_value; + } +} + +static ADDR *admin_Req_AltAddr; +extern char *adminstration_req_alt; +char *getadmin_Req_Alt(type) +int type; +{ + if (admin_Req_AltAddr == NULLADDR) { + RP_Buf rp; + admin_Req_AltAddr = adr_new(adminstration_req_alt, + AD_822_TYPE, 0); + admin_Req_AltAddr -> ad_resp = NO; +#ifdef UKORDER + if (rp_isbad(ad_parse(admin_Req_AltAddr, &rp, CH_UK_PREF))) { +#else + if (rp_isbad(ad_parse(admin_Req_AltAddr, &rp, CH_USA_PREF))) { +#endif + PP_LOG(LLOG_EXCEPTIONS, + ("adminstration_req_alt address '%s' does not parse [%s]", + adminstration_req_alt, admin_Req_AltAddr->ad_parse_message)); + adr_free(admin_Req_AltAddr); + admin_Req_AltAddr = NULLADDR; + return NULLCP; + } + } + switch (type) { + case AD_822_TYPE: + return admin_Req_AltAddr->ad_r822adr; + case AD_X400_TYPE: + return admin_Req_AltAddr->ad_r400adr; + default: + return admin_Req_AltAddr->ad_value; + } +} diff --git a/Lib/pp/ut_prm.c b/Lib/pp/ut_prm.c new file mode 100644 index 0000000..90e175f --- /dev/null +++ b/Lib/pp/ut_prm.c @@ -0,0 +1,44 @@ +/* ut_prm.c: MessageManagementParameter utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_prm.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_prm.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "prm.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void prm_init (pp) +struct prm_vars *pp; +{ + PP_DBG (("Lib/pp/ut_prm.c/prm_init()")); + bzero ((char *) pp, sizeof (*pp)); +} + + +void prm_free (pp) +struct prm_vars *pp; +{ + PP_DBG (("Lib/pp/ut_prm.c/prm_free()")); + + if (pp->prm_logfile != NULLCP) free (pp->prm_logfile); + prm_init (pp); +} diff --git a/Lib/pp/ut_q.c b/Lib/pp/ut_q.c new file mode 100644 index 0000000..a77c697 --- /dev/null +++ b/Lib/pp/ut_q.c @@ -0,0 +1,159 @@ +/* ut_q.c: Queue utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_q.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_q.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void q_init (qp) +Q_struct *qp; +{ + PP_DBG (("Lib/pp/q_init()")); + bzero ((char *)qp, sizeof(*qp)); + qp->msgtype = MT_UMPDU; + qp -> nwarns = NOTOK; + qp -> disclose_recips = FALSE; + qp -> forwarding_request = NOTOK; +} + +void q_free (qp) +Q_struct *qp; +{ + PP_DBG (("Lib/pp/q_free()")); + + if (qp->defertime) + free ((char *)qp -> defertime); + if (qp -> latest_time) + free ((char *)qp -> latest_time); + if (qp -> cont_type) + free (qp -> cont_type); + encodedinfo_free (&qp->encodedinfo); + encodedinfo_free (&qp -> orig_encodedinfo); + if (qp->ua_id != NULLCP) + free (qp->ua_id); + if (qp -> pp_content_correlator) + free (qp -> pp_content_correlator); + if (qp -> general_content_correlator) + qb_free (qp -> general_content_correlator); + if (qp -> originator_return_address) + fn_free (qp -> originator_return_address); + if (qp -> originator_certificate) + qb_free (qp -> originator_certificate); + if (qp -> algorithm_identifier) + qb_free (qp -> algorithm_identifier); + if (qp -> message_origin_auth_check) + qb_free (qp -> message_origin_auth_check); + if (qp -> security_label) + qb_free (qp -> security_label); + if (qp -> per_message_extensions) + extensions_free (qp -> per_message_extensions); + if (qp->Oaddress) + adr_tfree (qp->Oaddress); + if (qp->Raddress) + adr_tfree (qp->Raddress); + if (qp->inbound != NULL) + list_rchan_free(qp -> inbound); + MPDUid_free (&qp->msgid); + if (qp->trace) + trace_free (qp->trace); + if (qp -> dl_expansion_history) + dlh_free (qp -> dl_expansion_history); + if (qp->queuetime) + free ((char *)qp -> queuetime); + if (qp->departime) + free ((char *)qp -> departime); + q_init (qp); +} + +void eit_dup(to, from) +EncodedIT *to, *from; +{ + to->eit_g3parms = from->eit_g3parms; + to->eit_tTXparms = from->eit_g3parms; + to->eit_presentation = from->eit_presentation; + to->eit_types = list_bpt_dup(from->eit_types); +} + +void q_almost_dup (to, from) +Q_struct *to, *from; +{ + if (from->latest_time != NULLUTC) + to -> latest_time = utcdup(from -> latest_time); + to->latest_time_crit = from->latest_time_crit; + + if (from->cont_type != NULLCP) + to->cont_type = strdup(from->cont_type); + eit_dup(&(to->orig_encodedinfo), &(from->orig_encodedinfo)); + to->priority = from->priority; + + to->disclose_recips = from->disclose_recips; + to->implicit_conversion_prohibited = from->implicit_conversion_prohibited; + to->alternate_recip_allowed = from->alternate_recip_allowed; + to->content_return_request = from->content_return_request; + + to->recip_reassign_prohibited = from->recip_reassign_prohibited; + to->recip_reassign_crit = from->recip_reassign_crit; + + to->dl_expansion_prohibited = from->dl_expansion_prohibited; + to->dl_expansion_crit = from->dl_expansion_crit; + + to->conversion_with_loss_prohibited = from->conversion_with_loss_prohibited; + to->conversion_with_loss_crit = from->conversion_with_loss_crit; + + if (from->ua_id) + to->ua_id = strdup(from->ua_id); + if (from->pp_content_correlator) + to->pp_content_correlator = strdup(from->pp_content_correlator); +/* need to duplicate qbufs */ +/* general_content_correlator */ + to->content_correlator_crit = from->content_correlator_crit; + +/* originator_return_address */ + to->originator_return_address_crit = + from->originator_return_address_crit; + + to->forwarding_request = from->forwarding_request; + to->forwarding_request_crit = from->forwarding_request_crit; + +/* originator_certificate */ + to->originator_certificate_crit = from->originator_certificate_crit; + +/* algorithm_identifier */ + to->algorithm_identifier_crit = from->algorithm_identifier_crit; + +/* message_origin_auth_check */ + to->message_origin_auth_check_crit = + from->message_origin_auth_check_crit; + +/* security_label */ + to->security_label_crit = from->security_label_crit; + + to->proof_of_submission_request = from->proof_of_submission_request; + to->proof_of_submission_crit = from->proof_of_submission_crit; + +/* per_message_extensions */ + + to->dl_expansion_history = dlh_dup (from->dl_expansion_history); + +} diff --git a/Lib/pp/ut_qid.c b/Lib/pp/ut_qid.c new file mode 100644 index 0000000..9810ac4 --- /dev/null +++ b/Lib/pp/ut_qid.c @@ -0,0 +1,157 @@ +/* ut_qid.c: A qid2dir mapping utility */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_qid.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_qid.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_qid.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include + +extern char *quedfldir; /* -- "/usr/spool/pp/queues" -- */ +extern char *bquedir; /* -- "base" -- */ + +static int QID_adr_chks (); +static int QID_get_dirname (); + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* converts qid + reformatter list into directory with message in */ + +int qid2dir (qid, ap, exists, cpp) +char *qid; /* -- queue id (given) -- */ +ADDR *ap; /* -- recipient address (given) -- */ +int exists; /* -- the directory should exist (complain if not) */ +char **cpp; /* -- malloced to contain the dir name (updated) -- */ +{ + struct stat st; + PP_DBG (("Lib/pp/qid2dir (%s)", qid)); + + if (*cpp) free (*cpp); + *cpp = NULLCP; + + + /* -- checks that a valid recipient address has been specified -- */ + + if (ap == NULLADDR || ap -> ad_status == AD_STAT_DONE) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/qid2dir: %s", + ap ? "bad address status" : + "no address!")); + return (NOTOK); + } + + + /* -- *** --- + gets the current dir for that msg version associated with that + recipient address + --- *** --- */ + + + if (QID_get_dirname (ap, qid, cpp) == NOTOK) + return (NOTOK); + + + /* -- checks that the directory exists by stat ing it -- */ + + if (exists == TRUE && (stat(*cpp, &st) == NOTOK || + (st.st_mode & S_IFMT) != S_IFDIR)) { + PP_SLOG (LLOG_EXCEPTIONS, *cpp, + ("Lib/qid2dir:Missing directory")); + if (*cpp) free (*cpp); + *cpp = NULLCP; + return (NOTOK); + } + return (OK); +} + + + +/* --------------------- Static Routines ------------------------------- */ + +static int QID_get_dirname (ap, msg_dir, cpp) +ADDR *ap; +char *msg_dir, **cpp; +{ + char buf[MAXPATHLENGTH], *cp; + LIST_RCHAN *rp = ap->ad_fmtchan; + int i; + + + PP_DBG (("Lib/pp/QID_get_dirname()")); + + if (ap->ad_rcnt == 0) { + *cpp = malloc ((unsigned) (strlen (msg_dir) + 1 + + 1 + strlen (bquedir))); + (void) sprintf (*cpp, "%s/%s", msg_dir, bquedir); + return (OK); + } + else if (rp == NULLIST_RCHAN && ap->ad_rcnt != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/QID_get_dirname - missing reformatters")); + return (NOTOK); + } + + cp = NULLCP; + for (i = ap -> ad_rcnt; i > 0; i --) /* find current formatter */ + if (rp == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/QID_get_dirname (rfmt err)")); + return NOTOK; + } + else { + cp = rp -> li_dir; + rp = rp -> li_next; + } + + if (cp) { /* new style format */ + *cpp = malloc ((unsigned) (strlen(msg_dir) + 1 + + strlen (cp) + 1)); + (void) sprintf(*cpp, "%s/%s", msg_dir, cp); + return OK; + } + + /* old style long names - 14 chars is sooo restrictive - sigh */ + + rp = ap -> ad_fmtchan; + cp = buf; + + + for (i=ap->ad_rcnt; i > 0; i--) + if (rp) { + if (cp != buf) + *cp ++ = '.'; + (void) strcpy (cp, rp->li_chan->ch_name); + cp += strlen(cp); + rp = rp->li_next; + } + else { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp/QID_get_dirname missing reformatters")); + return (NOTOK); + } + + + + *cpp = (char *) malloc ((unsigned) (strlen (msg_dir) + 1 + + 1 + strlen (bquedir) + + 1 + strlen (buf))); + (void) sprintf (*cpp, "%s/%s.%s", msg_dir, bquedir, buf); + + + return (OK); +} diff --git a/Lib/pp/ut_redirect.c b/Lib/pp/ut_redirect.c new file mode 100644 index 0000000..4801b66 --- /dev/null +++ b/Lib/pp/ut_redirect.c @@ -0,0 +1,98 @@ +/* ut_redirect.c: utility routines for redirections */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_redirect.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_redirect.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_redirect.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "adr.h" + +extern UTC utclocalise(), utcnow(); + +Redirection *redirect_new(addr, dn, utc, reason) +char *addr; +char *dn; +UTC utc; +int reason; +{ + Redirection *ret; + + ret = (Redirection *) smalloc (sizeof *ret); + ret->rd_addr = isstr(addr) ? strdup(addr) : NULLCP; + ret->rd_dn = isstr(dn) ? strdup(dn) : NULLCP; + if (utc == NULLUTC) { + /* redirect now */ + UTC utcn; + utcn = utcnow(); + ret -> rd_time = utclocalise(utcn); + free((char *) utcn); + } else + ret -> rd_time = utclocalise(utc); + ret->rd_reason = reason; + ret->rd_next = (Redirection *) NULL; + return ret; +} + +void redirect_add(base, redirect) +Redirection **base, *redirect; +{ + Redirection **ix; + + for (ix = base; *ix; ix = &(*ix) -> rd_next) + continue; + *ix = redirect; +} + +void redirect_free(redirect) +Redirection *redirect; +{ + if (redirect == (Redirection *) NULL) + return; + if (redirect -> rd_next) + redirect_free(redirect -> rd_next); + if (redirect -> rd_addr) + free(redirect -> rd_addr); + if (redirect -> rd_dn) + free(redirect -> rd_dn); + if (redirect -> rd_time) + free((char *) redirect -> rd_time); + free((char *) redirect); +} + +void redirect_rewind(base, to) +Redirection **base, *to; +{ + Redirection **ix; + + for (ix = base; *ix && *ix != to; ix = &(*ix) -> rd_next) + continue; + if (*ix) { + redirect_free(*ix); + *ix = (Redirection *) NULL; + } +} + +/* check to see in newRedirect in list */ +int redirect_before (base, newRedirect) +Redirection *base, *newRedirect; +{ + for (;base != (Redirection *) NULL; base = base->rd_next) { + if (base->rd_addr && newRedirect -> rd_addr + && lexequ(base->rd_addr,newRedirect->rd_addr) == 0) + return TRUE; + if (base->rd_dn && newRedirect->rd_dn + && lexequ(base->rd_dn, newRedirect->rd_dn) == 0) + return TRUE; + } + + return FALSE; +} diff --git a/Lib/pp/ut_trace.c b/Lib/pp/ut_trace.c new file mode 100644 index 0000000..8ce372d --- /dev/null +++ b/Lib/pp/ut_trace.c @@ -0,0 +1,118 @@ +/* ut_trace.c: Deals trace structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_trace.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/ut_trace.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: ut_trace.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "mta.h" +#include + +extern char *loc_dom_mta; + +Trace *trace_new () +{ + Trace *tp; + + tp = (Trace *) smalloc (sizeof *tp); + + bzero ((char *)tp, sizeof *tp); + + tp -> trace_mta = strdup (loc_dom_mta); + GlobalDomId_new (&tp -> trace_DomId); + tp -> trace_DomSinfo.dsi_time = utcnow (); + return tp; +} + +Trace *trace_dup(old) +Trace *old; +{ + Trace *ret; + + if (old == NULL) + return NULL; + + ret = (Trace *) smalloc (sizeof *ret); + bzero ((char *)ret, sizeof *ret); + + if (old->trace_mta) + ret->trace_mta = strdup(old->trace_mta); + GlobalDomId_dup(&ret->trace_DomId, &old -> trace_DomId); + ret->trace_DomSinfo.dsi_time = utcdup(old->trace_DomSinfo.dsi_time); + trace_add(&ret, trace_dup(old->trace_next)); + return ret; +} + +void trace_add (base, new) +Trace **base, *new; +{ + Trace **tp; + + for (tp = base; *tp; tp = &(*tp) -> trace_next) + continue; + + *tp = new; +} + +void trace_free (tp) +Trace *tp; +{ + if (tp == NULL) + return; + + if (tp -> trace_next) + trace_free (tp -> trace_next); + if (tp -> trace_mta) + free (tp -> trace_mta); + + GlobalDomId_free (&tp -> trace_DomId); + DomSupInfo_free (&tp -> trace_DomSinfo); + free ((char *)tp); +} + +int trace_equ(one, two) +Trace *one, *two; +{ + if (one == NULL + || two == NULL) + return 1; + + if (one->trace_mta == NULLCP + || two->trace_mta == NULLCP) + return 1; + + if (one->trace_mta && two->trace_mta + && lexequ (one->trace_mta, two->trace_mta) != 0) + return 1; + + if (lexequ (one -> trace_DomId.global_Country, + two -> trace_DomId.global_Country) != 0) + return 1; + if (lexequ (one -> trace_DomId.global_Admin, + two -> trace_DomId.global_Admin) != 0) + return 1; + if (one -> trace_DomId.global_Private == NULLCP + && two -> trace_DomId.global_Private == NULLCP) + return 0; + if (one -> trace_DomId.global_Private == NULLCP + || two -> trace_DomId.global_Private == NULLCP) + return 1; + if (lexequ (one -> trace_DomId.global_Private, + two -> trace_DomId.global_Private) != 0) + return 1; + + return 0; +} + + diff --git a/Lib/pp/wr_stat.c b/Lib/pp/wr_stat.c new file mode 100644 index 0000000..731073f --- /dev/null +++ b/Lib/pp/wr_stat.c @@ -0,0 +1,112 @@ +/* wr_stat.c: write out some stats about a message being delivered */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/pp/RCS/wr_stat.c,v 6.0 1991/12/18 20:49:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/pp/RCS/wr_stat.c,v 6.0 1991/12/18 20:49:15 jpo Rel $ + * + * $Log: wr_stat.c,v $ + * Revision 6.0 1991/12/18 20:49:15 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "q.h" + +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) +UTC utclocalise (); + +wr_stat (ap, qp, msg, size) +ADDR *ap; +Q_struct *qp; +char *msg; +int size; +{ + char *argv[100]; + int argc = 0; + char buffer[BUFSIZ]; + char midbuf[BUFSIZ]; + char tbuf[BUFSIZ]; + char tbuf2[BUFSIZ]; + static char *eq = "="; + char sbuf[40]; + + argv[argc++] = "Deliv"; + argv[argc++] = msg; + + argv[argc++] = qp -> inbound -> li_chan -> ch_name; + argv[argc++] = "->"; + if (ap -> ad_outchan && ap -> ad_outchan -> li_chan) + argv[argc++] = ap -> ad_outchan -> li_chan -> ch_name; + else + argv[argc++] = "none"; + + argv[argc++] = eq; + argv[argc++] = "p1msgid"; + (void) msgid2rfc_aux (&qp -> msgid, midbuf, FALSE); + argv[argc++] = midbuf; + + argv[argc++] = eq; + argv[argc++] = "size"; + (void) sprintf (sbuf, "%d", size); + argv[argc++] = sbuf; + + argv[argc++] = eq; + argv[argc++] = "sender"; + argv[argc++] = (qp -> inbound -> li_chan -> ch_in_ad_type == AD_X400_TYPE) ? qp -> Oaddress -> ad_r400adr : qp -> Oaddress -> ad_r822adr; + + argv[argc++] = qp -> inbound -> li_mta; + + argv[argc++] = eq; + argv[argc++] = "recip"; + argv[argc++] = gval(ap); + + if (ap -> ad_outchan && ap -> ad_outchan -> li_mta) + argv[argc++] = ap -> ad_outchan -> li_mta; + else + argv[argc++] = "none"; + + argv[argc++] = eq; + argv[argc++] = "submit-time"; + (void) strcpy (tbuf, "unknown"); + if (qp -> trace != NULL && + qp -> trace -> trace_DomSinfo.dsi_time) { + UTC ut = utclocalise (qp -> trace -> trace_DomSinfo.dsi_time); + if (ut) { + (void) sprintf (tbuf, "%d:%d:%d:%02d:%02d", + ut -> ut_mon, ut -> ut_mday, + ut -> ut_hour, ut -> ut_min, + ut -> ut_sec); + free ((char *) ut); + } + + } + argv[argc++] = tbuf; + + argv[argc++] = eq; + argv[argc++] = "queued-time"; + (void) strcpy (tbuf2, "unknown"); + if (qp -> queuetime) { + UTC ut = utclocalise (qp -> queuetime); + if (ut) { + (void) sprintf (tbuf2, "%d:%d:%d:%02d:%02d", + ut -> ut_mon, ut -> ut_mday, + ut -> ut_hour, ut -> ut_min, + ut -> ut_sec); + free ((char *) ut); + } + + } + argv[argc++] = tbuf2; + + argv[argc] = NULLCP; + + if (arg2vstr (0, sizeof buffer, buffer, argv) == NOTOK) + return NOTOK; + PP_STAT (("%s", buffer)); + return OK; +} diff --git a/Lib/qmgr/Makefile b/Lib/qmgr/Makefile new file mode 100644 index 0000000..8496479 --- /dev/null +++ b/Lib/qmgr/Makefile @@ -0,0 +1,264 @@ +# Makefile to build the 822 addressing stuff +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/Makefile,v 6.0 1991/12/18 20:23:58 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:23:58 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = Qmgr-ops.c Qmgr_tables.c chan_control.c submit2qmgr.c \ + chan_debug.c qstruct2qmgr.c recipstate.c \ + comms.c consblk.c cons-misc.c op_chan.c op_msg.c \ + op_mta.c op_que.c order.c op_filter.c +OBJS = Qmgr-ops.o chan_control.o \ + chan_debug.o qstruct2qmgr.o recipstate.o \ + submit2qmgr.o Qmgr_tables.o \ + comms.o consblk.o cons-misc.o op_chan.o op_msg.o \ + op_mta.o op_que.o order.o op_filter.o + +HEADERS = ../../h + +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = qmgr-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(SHADOW) + +$(SHADOW): $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +Qmgr-ops.c Qmgr-ops.h Qmgr-asn.py: qmgr.ry + $(ROSY) -pepsy $(RYFLAGS) -o $@ qmgr.ry + -cmp -s Qmgr-ops.h $(HEADERS)/Qmgr-ops.h || cp Qmgr-ops.h $(HEADERS) + +Qmgr-types.h: Qmgr_tables.c + +Qmgr_tables.o: Qmgr_tables.c + +Qmgr_tables.c Qmgr-types.h: Qmgr-asn.py + $(PEPSY) $(POFLAGS) -A -h -f Qmgr-asn.py + -cmp -s Qmgr-types.h $(HEADERS)/Qmgr-types.h || \ + cp Qmgr-types.h $(HEADERS)/Qmgr-types.h + -if [ -f Qmgr_defs.h ]; \ + then cmp -s Qmgr_defs.h $(HEADERS)/Qmgr_defs.h || \ + cp Qmgr_defs.h $(HEADERS)/Qmgr_defs.h; \ + fi + -if [ -f Qmgr_pre_defs.h ]; \ + then cmp -s Qmgr_pre_defs.h $(HEADERS)/Qmgr_pre_defs.h || \ + cp Qmgr_pre_defs.h $(HEADERS)/Qmgr_pre_defs.h; \ + fi + +Qmgr-ops.o: Qmgr-ops.c + $(CC) $(CFLAGS) -DPERFORMER -DINVOKER -c Qmgr-ops.c + +lintlib: llib-lqmgr.ln +llib-lqmgr.ln: $(SRCS) + $(LINT) -Cqmgr $(LLFLAGS) $(SRCS) + +install:; + +lint: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +clean: tidy + rm -f $(OBJS) QMGR-* llib-lqmgr.ln + rm -f Qmgr-asn.py Qmgr-ops.c Qmgr-ops.h Qmgr-ops.o + rm -f Qmgr-stubs.c Qmgr-stubs.o Qmgr-types.h Qmgr-types.py + rm -f Qmgr_* + rm -f $(HEADERS)/Qmgr-ops.h $(HEADERS)/Qmgr-types.h \ + $(HEADERS)/Qmgr_defs.h $(HEADERS)/Qmgr_pre_defs.h + +tidy: + rm -f core $(SHADOW) *.old *.BAK *.ph + +define: + $(DEFINE) Makefile + +depend: $(SRCS) + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of building rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +Qmgr-ops.o: Qmgr-ops.c +Qmgr-ops.o: Qmgr-types.h +Qmgr-ops.o: Qmgr-ops.h +Qmgr_tables.o: Qmgr_tables.c +Qmgr_tables.o: Qmgr-types.h +chan_control.o: chan_control.c +chan_control.o: ../../h/qmgr.h +chan_control.o: ../../h/Qmgr-types.h +chan_control.o: ../../h/Qmgr-ops.h +chan_control.o: ../../h/retcode.h +chan_control.o: ../../h/ll_log.h +submit2qmgr.o: submit2qmgr.c +submit2qmgr.o: ../../h/head.h +submit2qmgr.o: ../../h/util.h +submit2qmgr.o: ../../h/config.h +submit2qmgr.o: ../../h/ll_log.h +submit2qmgr.o: ../../h/retcode.h +submit2qmgr.o: ../../h/qmgr.h +submit2qmgr.o: ../../h/Qmgr-types.h +submit2qmgr.o: ../../h/Qmgr-ops.h +submit2qmgr.o: ../../h/q.h +submit2qmgr.o: ../../h/adr.h +submit2qmgr.o: ../../h/list_rchan.h +submit2qmgr.o: ../../h/chan.h +submit2qmgr.o: ../../h/table.h +submit2qmgr.o: ../../h/list_bpt.h +submit2qmgr.o: ../../h/auth.h +submit2qmgr.o: ../../h/list_bpt.h +submit2qmgr.o: ../../h/extension.h +submit2qmgr.o: ../../h/mta.h +submit2qmgr.o: ../../h/adr.h +submit2qmgr.o: ../../h/list_bpt.h +submit2qmgr.o: ../../h/aparse.h +submit2qmgr.o: ../../h/ap.h +submit2qmgr.o: ../../h/util.h +submit2qmgr.o: ../../h/or.h +submit2qmgr.o: ../../h/chan.h +submit2qmgr.o: ../../h/auth.h +submit2qmgr.o: ../../h/list_rchan.h +submit2qmgr.o: ../../h/mta.h +submit2qmgr.o: ../../h/prm.h +chan_debug.o: chan_debug.c +chan_debug.o: ../../h/util.h +chan_debug.o: ../../h/config.h +chan_debug.o: ../../h/ll_log.h +chan_debug.o: ../../h/qmgr.h +chan_debug.o: ../../h/Qmgr-types.h +chan_debug.o: ../../h/Qmgr-ops.h +qstruct2qmgr.o: qstruct2qmgr.c +qstruct2qmgr.o: ../../h/util.h +qstruct2qmgr.o: ../../h/config.h +qstruct2qmgr.o: ../../h/ll_log.h +qstruct2qmgr.o: Qmgr-types.h +qstruct2qmgr.o: ../../h/q.h +qstruct2qmgr.o: ../../h/adr.h +qstruct2qmgr.o: ../../h/list_rchan.h +qstruct2qmgr.o: ../../h/chan.h +qstruct2qmgr.o: ../../h/table.h +qstruct2qmgr.o: ../../h/list_bpt.h +qstruct2qmgr.o: ../../h/auth.h +qstruct2qmgr.o: ../../h/list_bpt.h +qstruct2qmgr.o: ../../h/extension.h +qstruct2qmgr.o: ../../h/mta.h +qstruct2qmgr.o: ../../h/adr.h +qstruct2qmgr.o: ../../h/list_bpt.h +qstruct2qmgr.o: ../../h/aparse.h +qstruct2qmgr.o: ../../h/ap.h +qstruct2qmgr.o: ../../h/util.h +qstruct2qmgr.o: ../../h/or.h +qstruct2qmgr.o: ../../h/chan.h +qstruct2qmgr.o: ../../h/auth.h +qstruct2qmgr.o: ../../h/list_rchan.h +qstruct2qmgr.o: ../../h/mta.h +qstruct2qmgr.o: ../../h/prm.h +recipstate.o: recipstate.c +recipstate.o: ../../h/util.h +recipstate.o: ../../h/config.h +recipstate.o: ../../h/ll_log.h +recipstate.o: ../../h/qmgr.h +recipstate.o: ../../h/Qmgr-types.h +recipstate.o: ../../h/Qmgr-ops.h +comms.o: comms.c +comms.o: ../../h/util.h +comms.o: ../../h/config.h +comms.o: ../../h/ll_log.h +comms.o: ../../h/qmgr-int.h +comms.o: Qmgr-types.h +comms.o: Qmgr-ops.h +comms.o: ../../h/qmgr.h +comms.o: ../../h/Qmgr-types.h +comms.o: ../../h/Qmgr-ops.h +comms.o: consblk.h +consblk.o: consblk.c +consblk.o: ../../h/util.h +consblk.o: ../../h/config.h +consblk.o: ../../h/ll_log.h +consblk.o: consblk.h +cons-misc.o: cons-misc.c +cons-misc.o: ../../h/util.h +cons-misc.o: ../../h/config.h +cons-misc.o: ../../h/ll_log.h +cons-misc.o: ../../h/qmgr-int.h +cons-misc.o: Qmgr-types.h +op_chan.o: op_chan.c +op_chan.o: ../../h/util.h +op_chan.o: ../../h/config.h +op_chan.o: ../../h/ll_log.h +op_chan.o: ../../h/qmgr-int.h +op_chan.o: consblk.h +op_chan.o: Qmgr-types.h +op_msg.o: op_msg.c +op_msg.o: ../../h/util.h +op_msg.o: ../../h/config.h +op_msg.o: ../../h/ll_log.h +op_msg.o: ../../h/qmgr-int.h +op_msg.o: consblk.h +op_msg.o: Qmgr-types.h +op_mta.o: op_mta.c +op_mta.o: ../../h/util.h +op_mta.o: ../../h/config.h +op_mta.o: ../../h/ll_log.h +op_mta.o: ../../h/qmgr-int.h +op_mta.o: consblk.h +op_mta.o: Qmgr-types.h +op_que.o: op_que.c +op_que.o: ../../h/util.h +op_que.o: ../../h/config.h +op_que.o: ../../h/ll_log.h +op_que.o: consblk.h +op_que.o: ../../h/qmgr-int.h +op_que.o: Qmgr-types.h +order.o: order.c +order.o: ../../h/util.h +order.o: ../../h/config.h +order.o: ../../h/ll_log.h +order.o: ../../h/qmgr-int.h +op_filter.o: op_filter.c +op_filter.o: ../../h/util.h +op_filter.o: ../../h/config.h +op_filter.o: ../../h/ll_log.h +op_filter.o: ../../h/qmgr-int.h +op_filter.o: consblk.h +op_filter.o: Qmgr-types.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/qmgr/chan_control.c b/Lib/qmgr/chan_control.c new file mode 100644 index 0000000..48ed9d4 --- /dev/null +++ b/Lib/qmgr/chan_control.c @@ -0,0 +1,435 @@ +/* channel_control.c: control the channel process */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/chan_control.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/chan_control.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: chan_control.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include +#include +#include "qmgr.h" +#include "retcode.h" +#include +#include "ll_log.h" + +static jmp_buf toplevel; + + +static IFP startfnx; +static IFP stopfnx; +static IFP initchfnx; +static struct type_Qmgr_DeliveryStatus *(*workfnx)(); + +static int ros_init (), ros_work (), ros_lose (); +static int ros_worker (), error (), ureject (); +static void adios (); +static void acs_advise (); +static void ros_adios (), ros_advise (); +static void ros_indication (); + +#ifdef notdef +static char *myservice = "pp channel"; +#endif +extern struct RyOperation table_Qmgr_Operations[]; + +int channel_control (argc, argv, init, work, finish) +int argc; +char **argv; +IFP init; +struct type_Qmgr_DeliveryStatus *(*work)(); +IFP finish; +{ + AEI aei = NULLAEI; + struct TSAPdisconnect tds; + struct TSAPdisconnect *td = &tds; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + PP_DBG (("starting")); + + workfnx = work; + initchfnx = init; + stopfnx = finish; + + if (RyDispatch (NOTOK, table_Qmgr_Operations, + operation_Qmgr_processmessage, + ros_worker, roi) == NOTOK) + ros_adios (rop, "processmessage"); + if (RyDispatch (NOTOK, table_Qmgr_Operations, + operation_Qmgr_channelInitialise, + ros_worker, roi) == NOTOK) + ros_adios (rop, "channelInitialise"); + + if (isodeserver (argc, argv, aei, ros_init, ros_work, ros_lose, td) + == NOTOK) { + if (td -> td_cc > 0) + adios (NULLCP, "isodeserver: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, + td -> td_data); + else + adios (NULLCP, "isodeserver: [%s]", + TErrString (td -> td_reason)); + } + + return 0; +} + +static int ros_result (sd, val, rox, roi) +int sd; +struct type_Qmgr_DeliveryStatus *val; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (val == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) val, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + return OK; +} + +static int ros_worker (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_DeliveryStatus *status; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + switch (ryo -> ryo_op) { + case operation_Qmgr_channelInitialise: + switch ((*initchfnx) (in)) { + case OK: + if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, + ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + return OK; + + case NOTOK: + default: + return error (sd, error_Qmgr_protocol, (caddr_t) NULL, + rox, roi); + } + + case operation_Qmgr_processmessage: + status = (*workfnx) (in); + return ros_result (sd, status, rox, roi); + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: operation %s not expected", + sd, ryo -> ryo_name)); + return error (sd, error_Qmgr_protocol, (caddr_t) NULL, + rox, roi); + } +} + +/* */ + +static int ros_init (vecp, vec) +int vecp; +char **vec; +{ + int reply, + result, + sd; + struct AcSAPstart acss; + register struct AcSAPstart *acs = &acss; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + register struct PSAPstart *ps = &acs -> acs_start; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (AcInit (vecp, vec, acs, aci) == NOTOK) { + acs_advise (aca, "initialization fails"); + return NOTOK; + } + PP_DBG (("A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>", + acs -> acs_sd, sprintoid (acs -> acs_context), + sprintaei (&acs -> acs_callingtitle), + sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo)); + + sd = acs -> acs_sd; + + for (vec++; *vec; vec++) + PP_LOG (LLOG_EXCEPTIONS, ("unknown argument \"%s\"", *vec)); + + reply = startfnx ? (*startfnx) (sd, acs) : ACS_ACCEPT; + + result = AcAssocResponse (sd, reply, + reply != ACS_ACCEPT ? ACS_USER_NOREASON : ACS_USER_NULL, + NULLOID, NULLAEI, NULLPA, NULLPC, ps -> ps_defctxresult, + ps -> ps_prequirements, ps -> ps_srequirements, SERIAL_NONE, + ps -> ps_settings, &ps -> ps_connect, NULLPEP, 0, aci); + + ACSFREE (acs); + + if (result == NOTOK) { + acs_advise (aca, "A-ASSOCIATE.RESPONSE"); + return NOTOK; +} + if (reply != ACS_ACCEPT) + return NOTOK; + + if (RoSetService (sd, RoPService, roi) == NOTOK) + ros_adios (rop, "set RO/PS fails"); + + return sd; +} + +/* */ + +static int ros_work (fd) +int fd; +{ + int result; + caddr_t out; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + (*stopfnx) (); + case DONE: + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + return NOTOK; + } + + switch (result = RyWait (fd, NULLIP, &out, OK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + case OK: + case DONE: + ros_indication (fd, roi); + break; + + default: + adios (NULLCP, "unknown return from RoWaitRequest=%d", result); + } + + return OK; +} + +/* */ + +static void ros_indication (sd, roi) +int sd; +register struct RoSAPindication *roi; +{ + int reply, + result; + + switch (roi -> roi_type) { + case ROI_INVOKE: + case ROI_RESULT: + case ROI_ERROR: + adios (NULLCP, "unexpected indication type=%d", roi -> roi_type); + break; + + case ROI_UREJECT: + { + register struct RoSAPureject *rou = &roi -> roi_ureject; + + if (rou -> rou_noid) + PP_LOG (LLOG_EXCEPTIONS, ("RO-REJECT-U.INDICATION/%d: %s", + sd, RoErrString (rou -> rou_reason))); + else + PP_LOG (LLOG_EXCEPTIONS, + ("RO-REJECT-U.INDICATION/%d: %s (id=%d)", + sd, RoErrString (rou -> rou_reason), + rou -> rou_id)); + } + break; + + case ROI_PREJECT: + { + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (ROS_FATAL (rop -> rop_reason)) + ros_adios (rop, "RO-REJECT-P.INDICATION"); + ros_advise (rop, "RO-REJECT-P.INDICATION"); + } + break; + + case ROI_FINISH: + { + register struct AcSAPfinish *acf = &roi -> roi_finish; + struct AcSAPindication acis; + register struct AcSAPabort *aca = &acis.aci_abort; + + PP_TRACE (("A-RELEASE.INDICATION/%d: %d", + sd, acf -> acf_reason)); + + result = AcRelResponse (sd, reply = ACS_ACCEPT, + ACR_NORMAL, NULLPEP, 0, &acis); + + ACFFREE (acf); + + if (result == NOTOK) + acs_advise (aca, "A-RELEASE.RESPONSE"); + else + if (reply != ACS_ACCEPT) + break; + + if (stopfnx) + (*stopfnx)(); + + longjmp (toplevel, DONE); + } + /* NOTREACHED */ + + default: + adios (NULLCP, "unknown indication type=%d", roi -> roi_type); + } +} + +/* */ + +static int ros_lose (td) +struct TSAPdisconnect *td; +{ + if (td -> td_cc > 0) + PP_LOG (LLOG_EXCEPTIONS, ("TNetAccept: [%s] %*.*s", + TErrString (td -> td_reason), td -> td_cc, td -> td_cc, + td -> td_data)); + else + PP_LOG (LLOG_EXCEPTIONS, ("TNetAccept: [%s]", + TErrString (td -> td_reason))); +} + +/* ERRORS */ + +static void ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + longjmp (toplevel, NOTOK); +} + + +static void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s", event, buffer)); +} + +/* */ + +static void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s (source %d)", event, buffer, + aca -> aca_source)); +} + +/* */ + +#ifndef lint + +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_oper, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + +/* ERROR */ + +static int error (sd, err, param, rox, roi) +int sd, + err; +caddr_t param; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (RyDsError (sd, rox -> rox_id, err, param, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "ERROR"); + + return OK; +} + +static int ureject (sd, reason, rox, roi) +int sd, + reason; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "U-REJECT"); + + return OK; +} diff --git a/Lib/qmgr/chan_debug.c b/Lib/qmgr/chan_debug.c new file mode 100644 index 0000000..03b96d2 --- /dev/null +++ b/Lib/qmgr/chan_debug.c @@ -0,0 +1,153 @@ +/* chan_debug.c: stub version of chan_control for debugging channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/chan_debug.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/chan_debug.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: chan_debug.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "qmgr.h" +static void pdeliverystatus (), pindividualdeliverystatus (); + + +/* ARGSUSED */ +int debug_channel_control (argc, argv, init, work, finish) +int argc; +char **argv; +IFP init; +struct type_Qmgr_DeliveryStatus *(*work)(); +IFP finish; +{ + char channel[BUFSIZ], + buf[BUFSIZ]; + int cont = TRUE, + num; + struct type_Qmgr_ProcMsg arg; + struct type_Qmgr_UserList *temp = NULL, + *tail = NULL; + struct type_Qmgr_DeliveryStatus *result; + + if (isatty (2)) + pp_log_norm -> ll_stat |= LLOGTTY; + /* input channel structure */ + printf("Input channel name : "); + if (scanf(" %s",channel) != 1) + return NOTOK; + arg.channel = str2qb(channel,strlen(channel),1); + arg.qid = NULL; + arg.users = NULL; + + if ((*init)(arg.channel) == OK) { + printf("Channel initialised\n"); + while(cont == TRUE) { + if (arg.users != NULL) free_Qmgr_UserList(arg.users); + arg.users = NULL; + if (arg.qid != NULL) qb_free(arg.qid); + arg.qid = NULL; + + temp = tail = NULL; + + printf("Input message id : "); + if (scanf(" %s",buf) != 1) + return NOTOK; + + arg.qid = str2qb(buf,strlen(buf),1); + + printf("Input recipient numbers to pass to channel terminated by -1\n\t : "); + if (scanf(" %d",&num) != 1) + return NOTOK; + + while (num != -1) { + temp = (struct type_Qmgr_UserList *) calloc(1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) calloc(1,sizeof(*(temp->RecipientId))); + temp->RecipientId->parm = num; + if (arg.users == NULL) + arg.users = tail = temp; + else { + tail->next = temp; + temp = temp; + } + if (scanf("%d",&num) != 1) + return NOTOK; + } + + result = (*work) (&arg); + pdeliverystatus(result); + + printf("Do you want to continue "); + do { + printf("(y/n) ? "); + if (scanf("%s", buf) != 1) + return NOTOK; + } while (index("yn",*buf) == NULL); + cont = (*buf == 'y') ? TRUE : FALSE; + } + if (finish != NULLIFP) + (*finish) (); + } else + printf("Channel initialisation failed\n"); + return OK; +} + +static void pdeliverystatus (status) +struct type_Qmgr_DeliveryStatus *status; +{ + printf ("Delivery status\n"); + if (status == NULL) + printf ("Complete failure\n"); + else { + struct type_Qmgr_DeliveryStatus *ix = status; + while (ix != NULL) + { + pindividualdeliverystatus(ix->IndividualDeliveryStatus); + ix = ix->next; + } + } +} + +static void pindividualdeliverystatus(status) +struct type_Qmgr_IndividualDeliveryStatus *status; +{ + printf ("Recipient %d: ", status->recipient->parm); + + switch (status->status) { + case int_Qmgr_status_success: + printf ("success"); + break; + case int_Qmgr_status_successSharedDR: + printf ("successSharedDR"); + break; + case int_Qmgr_status_failureSharedDR: + printf ("failureSharedDR"); + break; + case int_Qmgr_status_negativeDR: + printf ("negativeDR"); + break; + case int_Qmgr_status_positiveDR: + printf ("positiveDR"); + break; + case int_Qmgr_status_messageFailure: + printf ("message failure"); + break; + case int_Qmgr_status_mtaFailure: + printf ("mta failure"); + break; + case int_Qmgr_status_mtaAndMessageFailure: + printf ("mta and message failure"); + break; + default: + printf ("unknown"); + break; + } + (void) putchar ('\n'); +} diff --git a/Lib/qmgr/comms.c b/Lib/qmgr/comms.c new file mode 100644 index 0000000..ad842ef --- /dev/null +++ b/Lib/qmgr/comms.c @@ -0,0 +1,623 @@ +/* comm.c: ROS communication routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/comms.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/comms.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: comms.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" +#include "Qmgr-types.h" +#include "Qmgr-ops.h" +#include "qmgr.h" +#include +#include "consblk.h" + +#define PP_SERVICE "pp qmgr" + +static void advise(), ros_advise(), acs_advise(); + +static int general_error(); + +typedef struct client_dispatch { + char *ds_name; + int ds_operation; + IFP ds_argument; + modtyp *ds_fr_mod; + int ds_fr_index; + IFP ds_result; + IFP ds_error; + char *ds_help; +} Client_dispatch; + +/* CLIENT STRUCTURE */ + +extern int arg_channelread(), res_channelread(); +#define channelread_error general_error + +extern int arg_channelcontrol(), res_channelcontrol(); +#define channelcontrol_error general_error + +extern int arg_mtaread(), res_mtaread(); +#define mtaread_error general_error + +extern int arg_mtacontrol(), res_mtacontrol(); +#define mtacontrol_error general_error + +extern int arg_readchannelmtamessage(), res_readchannelmtamessage(); +#define readchannelmtamessage_error general_error + +extern int arg_msgcontrol(), res_msgcontrol(); +#define msgcontrol_error general_error + +extern int arg_quecontrol(), res_quecontrol(); +#define quecontrol_error general_error + +extern int res_qmgrStatus(); +#define qmgrStatus_error general_error + +extern int arg_filter (); +#define filter_error general_error + +static int arg_quit(); + +struct client_dispatch client_dispatches[] = { +{ + "channelread", operation_Qmgr_channelread, + arg_channelread, &_ZUNIV_mod, _ZUTCTimeUNIV, + res_channelread, channelread_error, + "read information on channels" +}, +{ + "channelcontrol", operation_Qmgr_channelcontrol, + arg_channelcontrol, &_ZQmgr_mod, _ZChannelControlQmgr, + res_channelcontrol, channelcontrol_error, + "control channel" +}, +{ + "mtaread", operation_Qmgr_mtaread, + arg_mtaread, &_ZQmgr_mod, _ZMtaReadQmgr, + res_mtaread, mtaread_error, + "read information on mtas" +}, +{ + "mtacontrol", operation_Qmgr_mtacontrol, + arg_mtacontrol, &_ZQmgr_mod, _ZMtaControlQmgr, + res_mtacontrol, mtacontrol_error, + "control mta" +}, +{ + "readchannelmtamessage", operation_Qmgr_readChannelMtaMessage, + arg_readchannelmtamessage, &_ZQmgr_mod, _ZMsgReadQmgr, + res_readchannelmtamessage, readchannelmtamessage_error, + "read a set of messages" +}, +{ + "msgcontrol", operation_Qmgr_msgcontrol, + arg_msgcontrol, &_ZQmgr_mod, _ZMsgControlQmgr, + res_msgcontrol, msgcontrol_error, + "control msg" +}, +{ + "quecontrol", operation_Qmgr_qmgrControl, + arg_quecontrol, &_ZQmgr_mod, _ZQMGRControlQmgr, + res_quecontrol, quecontrol_error, + "control qmgr" +}, +{ + "qmgrStatus", operation_Qmgr_qmgrStatus, NULLIFP, + &_ZQmgr_mod, _ZQmgrStatusQmgr, + res_qmgrStatus, qmgrStatus_error, + "control qmgr" +}, +{ + "readmsginfo", operation_Qmgr_readmsginfo, arg_filter, + &_ZQmgr_mod, _ZReadMessageArgumentQmgr, + res_readchannelmtamessage, filter_error, + "read messages" +}, +{ + "quit", 0, arg_quit, + NULL, 0, NULLIFP, NULLIFP, + "terminate the association and exit" +}, +{ + NULL +} +}; + +static struct client_dispatch *get_dispatch(id) +{ + struct client_dispatch *ix; + + for (ix = client_dispatches; + NULL != ix && NULLCP != ix->ds_name; + ix++) + if (id == ix -> ds_operation) + return ix; + return (struct client_dispatch *) NULL; +} + + +/* */ + +int initiate_op (ad, op_id, args, pid, fnx, errbuf) +int ad; +int op_id; +char **args; +int *pid; +IFP fnx; +char errbuf[]; +{ + int result, id; + caddr_t in = NULL; + struct RoSAPindication rois; + struct client_dispatch *ds; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + in = NULL; + + if ((ds = get_dispatch(op_id)) == NULL) { + advise(errbuf, "Unknown dispatch number [%d]", + op_id); + return NOTOK; + } + + if (ds -> ds_argument + && (*ds -> ds_argument) (ad, args, &in) == NOTOK) + return NOTOK; + + id = RyGenID (ad); + if (pid) *pid = id; + switch (result = RyStub (ad, + table_Qmgr_Operations, + ds -> ds_operation, + id, + NULLIP, + in, + ds -> ds_result, + ds -> ds_error, + ROS_ASYNC, + roi)) { + case NOTOK: /* failure */ + if (ROS_FATAL(rop->rop_reason)) { + ros_advise (errbuf, rop, "STUB"); + result = DONE; + } + break; + + case OK: /* should get a result/error response */ + (void) newcopblk (ad, id, fnx); + break; + + case DONE: /* got RO-END? */ + advise (errbuf, "%s", "got RO-END.INDICATION"); + break; + default: + advise (errbuf, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + result = NOTOK; + break; + } + + if (ds -> ds_fr_mod && in) + (void) fre_obj (in, + ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod, 1); + return result; +} + +/* */ + +int result_op (ad, pid, errbuf) +int ad; +int *pid; +char errbuf[]; +{ + caddr_t out; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + errbuf[0] = '\0'; + + switch (RyWait (ad, pid, &out, NOTOK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + PP_TRACE (("RyWait returned NOTOK")); + ros_advise (errbuf, rop, "STUB"); + if (ROS_FATAL (rop -> rop_reason)) + return DONE; + break; + + case OK: + PP_TRACE (("RyWait returned OK")); + break; + + case DONE: + return DONE; + } + + return OK; +} + +/* */ + +static PE fillin_passwd(user, passwd, auth, errbuf) +char *user; +char *passwd; +int auth; +char errbuf[]; +{ + PE ret; + struct type_Qmgr_BindArgument *ba; + + ba = (struct type_Qmgr_BindArgument *) + smalloc(sizeof *ba); + switch ((ba->offset = auth)) { + case type_Qmgr_BindArgument_noAuthentication: + default: + break; + case type_Qmgr_BindArgument_weakAuthentication: + ba->un.weakAuthentication = + (struct type_Qmgr_WeakAuthentication *) + smalloc(sizeof(struct type_Qmgr_WeakAuthentication)); + ba->un.weakAuthentication->username = str2qb(user, + strlen(user), + 1); + if (NULLCP != passwd && '\0' != *passwd) + ba->un.weakAuthentication->passwd = str2qb(passwd, + strlen(passwd), + 1); + else + ba->un.weakAuthentication->passwd = NULL; + break; + + } + + if (encode_Qmgr_BindArgument (&ret, 1, NULLCP, 0, ba) == NOTOK) { + advise(errbuf, + "failed to encode BindArgument [%s]", PY_pepy); + free_Qmgr_BindArgument(ba); + return NULLPE; + } + free_Qmgr_BindArgument(ba); + ret->pe_context = 3; + return ret; +} + +static BindResult *convert_BindResult(acc, errbuf) +struct AcSAPconnect *acc; +char *errbuf; +{ + struct type_Qmgr_BindResult *br; + + if (acc->acc_ninfo >= 1) { + if (decode_Qmgr_BindResult (acc->acc_info[0], + 1, NULLIP, NULLVP, &br) == NOTOK) { + advise (errbuf, + "failed to parse BindResult [%s]", + PY_pepy); + return (BindResult *) NOTOK; + } else { + BindResult *ret = (BindResult *) + calloc(1, sizeof(*ret)); + switch (br->result) { + case int_Qmgr_result_acceptedFullAccess: + ret->access = FULL_ACCESS; + break; + case int_Qmgr_result_acceptedLimitedAccess: + default: + ret->access = LIMITED_ACCESS; + break; + } + + if (NULL != br->information) + ret->info = qb2str(br->information); + if (NULL != br->version) + ret->version = qb2str(br->version); + + free_Qmgr_BindResult(br); + return ret; + } + } + return NULL; +} + +void free_BindResult (br) +BindResult *br; +{ + if (br -> info) + free(br -> info); + if (br -> version) + free(br->version); + free((char *) br); +} + +int init_connect (host, user, passwd, auth, pid, errbuf, bindRes) +char *host, *user, *passwd; +int auth; +int *pid; +char errbuf[]; +BindResult **bindRes; +{ + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + AEI aei; + OID ctx, + tmppci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + int result; + PE passwdpep; + + if ((pa = str2paddr (host)) == NULLPA) { + if ((aei = _str2aei (host, PP_SERVICE, QMGR_CTX_OID, + 0, dap_user, dap_passwd)) == NULLAEI) { + advise (errbuf, "%s: unknown entity", + host); + return NOTOK; + } + if ((pa = aei2addr (aei)) == NULLPA) { + advise (errbuf, "%s", "address translation failed"); + return NOTOK; + } + } + if ((ctx = oid_cpy (QMGR_AC)) == NULLOID) { + advise (errbuf, "%s", "out of memory"); + return NOTOK; + } + + if ((tmppci = oid_cpy (QMGR_PCI)) == NULLOID) { + advise (errbuf, "%s", "out of memory"); + return NOTOK; + } + pc -> pc_nctx = 1; + pc -> pc_ctx[0].pc_id = 1; + pc -> pc_ctx[0].pc_asn = tmppci; + pc -> pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (PLocalHostName ())) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + + if ((passwdpep = fillin_passwd(user, passwd, auth, errbuf)) + == NULLPE) + return NOTOK; + + result = AcAsynAssocRequest (ctx, NULLAEI, NULLAEI, NULLPA, + pa, pc, NULLOID, 0, + ROS_MYREQUIRE, + SERIAL_NONE, 0, sf, + &passwdpep, 1, + NULLQOS, acc, aci, 1); + pe_free(passwdpep); + + switch(result) { + case NOTOK: + acs_advise (errbuf, aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; + case CONNECTING_1: + case CONNECTING_2: + *pid = acc->acc_sd; + ACCFREE(acc); + PP_TRACE (("Association initiated")); + return result; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + advise(errbuf, + "Association rejected: [%s]", + AcErrString (acc -> acc_result)); + ACCFREE(acc) + return NOTOK; + } + PP_TRACE (("Association established")); + if (RoSetService (acc->acc_sd, RoPService, roi) == NOTOK) { + ros_advise (errbuf, rop, "set RO/PS fails"); + ACCFREE(acc); + return NOTOK; + } + PP_TRACE (("Service set")); + *pid = acc->acc_sd; + *bindRes = convert_BindResult(acc, errbuf); + ACCFREE(acc); + return DONE; + default: + advise(errbuf, + "Bad response from AcAsynAssocRequest [%d]", + result); + return NOTOK; + } +} + +/* */ + +int retry_connect (id, errbuf, bindRes) +int id; +char errbuf[]; +BindResult **bindRes; +{ + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + PP_TRACE (("acsap_retry(%d)", id)); + switch (result = AcAsynRetryRequest (id, acc, aci)) { + case CONNECTING_1: + case CONNECTING_2: + ACCFREE(acc); + return result; + case NOTOK: + acs_advise (errbuf, aca, "A-ASSOCIATE.REQUEST"); + ACCFREE(acc); + return NOTOK; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + advise(errbuf, + "Association Rejected: [%s]", + AcErrString (acc -> acc_result)); + ACCFREE(acc); + return NOTOK; + } + if (RoSetService (acc->acc_sd, RoPService, roi) == NOTOK) { + ros_advise (errbuf, rop, "set RO/PS fails"); + ACCFREE(acc); + return NOTOK; + } + *bindRes = convert_BindResult(acc, errbuf); + ACCFREE(acc); + return DONE; + default: + advise (errbuf, "%s", "Bad response from AcAsynRetryRequest"); + return NOTOK; + } +} + +/* */ + +char errBuf[BUFSIZ]; + +/* ARGSUSED */ +static int arg_quit (ad, args, arg) +int ad; +char **args, **arg; +{ + return release_connect(ad, errBuf); +} + +int release_connect (sd, errbuf) +int sd; +char errbuf[]; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) { + acs_advise (errbuf, aca, "A-RELEASE.REQUEST"); + return DONE; + } + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + advise (errbuf, "Release rejected by peer: %d", + acr -> acr_reason); + } + + ACRFREE (acr); + PP_TRACE (("Association released")); + + return DONE; +} + +/* ARGSUSED */ +static int general_error(ad, id, err, parameter, roi) +int ad, id, err; +caddr_t parameter; +struct RoSAPindication *roi; +{ + struct RyError *rye; + + if (RY_REJECT == err) { + advise(errBuf, "%s", RoErrString ((int) parameter)); + return OK; + } + + if (NULL != (rye = finderrbyerr (table_Qmgr_Errors, err))) + advise(errBuf, "Error: %s", rye -> rye_name); + else + advise(errBuf, "Error: %d", err); + + return OK; +} + +/* */ + +static void ros_advise(buf, rop, event) +char *buf; +struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + if (rop->rop_cc > 0) + (void) sprintf (buffer, + "[%s] %*.*s", + RoErrString (rop->rop_reason), + rop->rop_cc, rop->rop_cc, + rop->rop_data); + else + (void) sprintf (buffer, + "[%s]", + RoErrString(rop->rop_reason)); + advise(buf, "%s: %s", event, buffer); +} + +static void acs_advise (buf, aca, event) +char *buf; +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", + AcErrString (aca -> aca_reason)); + + advise (buf, "%s: %s (source %d)", event, buffer, + aca -> aca_source); +} + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + char *buf; + va_list ap; + + va_start (ap); + + buf = va_arg(ap, char *); + _asprintf(buf, NULLCP, ap); + va_end(ap); +} +#else +/* VARARGS2 */ + +static void advise(what, fmt) +char *what, *fmt; +{ + advise(what, fmt); +} +#endif diff --git a/Lib/qmgr/cons-misc.c b/Lib/qmgr/cons-misc.c new file mode 100644 index 0000000..8cd8d12 --- /dev/null +++ b/Lib/qmgr/cons-misc.c @@ -0,0 +1,200 @@ +/* cons-misc.c: misc routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/cons-misc.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/cons-misc.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: cons-misc.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ +#include "util.h" +#include +#include "qmgr-int.h" +#include "Qmgr-types.h" + + +/* */ + +time_t convert_time(qb) +struct type_UNIV_UTCTime *qb; +{ + char *str; + time_t temp; + if (qb == NULL) + return 0; + str = qb2str(qb); + temp = utc2time_t(str2utct(str, strlen(str))); + free(str); + return temp; +} + +/* */ + +ProcStatus *convert_ProcStatus(pepsy) +register struct type_Qmgr_ProcStatus *pepsy; +{ + ProcStatus *ret = (ProcStatus *) malloc(sizeof(*ret)); + + ret->enabled = pepsy->enabled; + ret->lastAttempt = convert_time(pepsy->lastAttempt); + ret->cachedUntil = convert_time(pepsy->cachedUntil); + ret->lastSuccess = convert_time(pepsy->lastSuccess); + return ret; +} +/* */ + +long parseUnitStr (s, isTime) +char *s; +int isTime; +{ + long n; + if (s == NULLCP || *s == NULL) return 0; + while(*s != NULL && isspace(*s)) s++; + n = 0; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + s++; + } + while (*s != NULL && isspace(*s)) s++; + if (*s != NULL && isalpha(*s)) { + switch (*s) { + case 's': /* seconds */ + case 'S': + break; + case 'm': /* minutes */ + case 'M': /* or millions */ + if (isTime == TRUE) + n *= 60; + else + n *= 1000000; + break; + case 'h': /* hours */ + case 'H': + n *= 3600; + break; + case 'd': /* days */ + case 'D': + n *= 86400; + break; + case 'w': /* weeks */ + case 'W': + n *= 604800; + break; + case 'k': /* kilo */ + case 'K': + n *= 1000; + break; + default: + break; + } + return n + parseUnitStr(s+1, 1); + } + else return n + parseUnitStr(s, 1); +} + +/* */ + +char *unparseUnitStr(n, isTime) +long n; +int isTime; +{ + char buf[BUFSIZ]; + buf[0] = '\0'; + if (isTime == TRUE) { + unsigned long res; + if ((res = n / (60 * 60 * 24)) != 0) { + (void) sprintf(buf, "%d d", res); + n = n % (60 * 60 * 24); + } + if ((res = n / (60 * 60)) != 0) { + (void) sprintf(buf, + ('\0' == buf[0]) ? "%s%d h" : "%s %d h", + buf, res); + n = n % (60 * 60); + } + if ((res = n / 60) != 0) { + (void) sprintf(buf, + ('\0' == buf[0]) ? "%s%d m" : "%s %d m", + buf, res); + n = n % 60; + } + + if (0 != n) + (void) sprintf(buf, + ('\0' == buf[0]) ? "%s%d s" : "%s %d s", + buf, n); + } else { + /* print to largest unit with 2 significant figures */ + long absolute = (n < 0) ? -n : n; + + if (absolute > 1000000) + (void) sprintf(buf, "%s%.2f M", + (n < 0) ? "-" : "", + (double) absolute / 1000000.0); + else if (absolute > 1000) + (void) sprintf(buf, "%s%.2f k", + (n < 0) ? "-" : "", + (double) absolute / 1000.0); + else + (void) sprintf(buf, "%s%d", + (n < 0) ? "-" : "", + absolute); + } + return strdup(buf); +} + +/* */ + +char *mystrtotime(str) +char *str; +{ + UTC utc; + time_t newsecs; + time_t current; + char *retval; + + newsecs = (time_t) parseUnitStr(str, TRUE); + (void) time(¤t); + + current += newsecs; + + utc = time_t2utc(current); + + retval = utct2str(utc); + free((char *) utc); + return strdup(retval); +} + +/* */ + +char *time_t2RFC(in) +time_t in; +{ + char buf[BUFSIZ]; + struct tm *tm; + struct UTCtime uts; +#ifdef SVR4 + extern long timezone; +#else + struct timeval dummy; + struct timezone time_zone; +#endif + + tm = localtime (&in); + tm2ut (tm, &uts); + uts.ut_flags |= UT_ZONE; +#ifdef SVR4 + uts.ut_zone = timezone/60; +#else + (void) gettimeofday(&dummy, &time_zone); + uts.ut_zone = time_zone.tz_minuteswest; +#endif + if (UTC2rfc(&uts, buf) == OK) + return strdup(buf); + return NULLCP; +} diff --git a/Lib/qmgr/consblk.c b/Lib/qmgr/consblk.c new file mode 100644 index 0000000..9d6900b --- /dev/null +++ b/Lib/qmgr/consblk.c @@ -0,0 +1,59 @@ +/* consblk.c: ROS calling routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/consblk.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/consblk.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: consblk.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "consblk.h" + +static struct cons_opblk Heads, *Head; +static int first_time_only; + +struct cons_opblk *newcopblk (fd, id, fnx) +int fd, id; +IFP fnx; +{ + struct cons_opblk *op; + + if (first_time_only == 0) { + first_time_only = 1; + Head = &Heads; + Head -> next = Head -> prev = Head; + } + + op = (struct cons_opblk *) smalloc (sizeof *op); + op -> fd = fd; + op -> id = id; + op -> fnx = fnx; + insque (op, Head -> prev); + return op; +} + +struct cons_opblk *find_copblk (fd, id) +int fd, id; +{ + struct cons_opblk *op; + + for (op = Head -> next; op != Head; op = op -> next) { + if (op -> fd == fd && op -> id == id) + return op; + } + return NULL; +} + +void free_copblk (op) +struct cons_opblk *op; +{ + remque (op); + free ((char *)op); +} diff --git a/Lib/qmgr/consblk.h b/Lib/qmgr/consblk.h new file mode 100644 index 0000000..fa0203f --- /dev/null +++ b/Lib/qmgr/consblk.h @@ -0,0 +1,22 @@ +/* cons.h: console library routines - private */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/consblk.h,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: consblk.h,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + * + */ + +struct cons_opblk { + struct cons_opblk *next, *prev; + int fd; + int id; + IFP fnx; +}; + +struct cons_opblk *newcopblk (); +struct cons_opblk *find_copblk (); +void free_copblk (); diff --git a/Lib/qmgr/make b/Lib/qmgr/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/qmgr/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/qmgr/op_chan.c b/Lib/qmgr/op_chan.c new file mode 100644 index 0000000..808796b --- /dev/null +++ b/Lib/qmgr/op_chan.c @@ -0,0 +1,206 @@ +/* op_chan.c: channel ROS operation routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_chan.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_chan.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: op_chan.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" +#include "consblk.h" +#include "Qmgr-types.h" +#include +#include + +extern char *mystrtotime(); + +static ChannelInfo *convert_ChanReadResult(); +static ChannelInfo *convert_PrioChannelInfos(); + +#define CHAN_READ_INTERVAL 60 + +/* ARGSUSED */ +int arg_channelread (ad, args, arg) +int ad; +char **args; +struct type_UNIV_UTCTime **arg; +{ + char *str; + UTC utc; + + utc = (UTC) malloc (sizeof(struct UTCtime)); + utc->ut_flags = UT_SEC; + + utc->ut_sec = CHAN_READ_INTERVAL; + + str = utct2str(utc); + *arg = str2qb (str, strlen(str), 1); + return OK; +} + +static ChannelInfo *convert_ChanReadResult(); + +/* ARGSUSED */ +int res_channelread (ad, id, dummy, result, roi) +int ad, id, dummy; +register struct type_Qmgr_ChannelReadResult *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx)(convert_ChanReadResult(result), id); + free_copblk(op); + return OK; +} + +/* */ + +static CMD_TABLE control_tbl[] = { + CTRL_ENABLE, type_Qmgr_Control_start, + CTRL_DISABLE, type_Qmgr_Control_stop, + CTRL_CACHECLEAR,type_Qmgr_Control_cacheClear, + CTRL_CACHEADD, type_Qmgr_Control_cacheAdd, + NULLCP, NOTOK + }; + +/* ARGSUSED */ +int arg_channelcontrol (ad, args, arg) +int ad; +char **args; +struct type_Qmgr_ChannelControl **arg; +/* args[0] = channel */ +/* args[1] = stop,start,clear,cacheadd */ +/* args[2] = time */ +{ + int n; + + *arg = (struct type_Qmgr_ChannelControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], strlen(args[0]), 1); + + if ((n = cmd_srch (args[1], control_tbl)) == NOTOK) + return NOTOK; + if (((*arg)->control->offset = n) == type_Qmgr_Control_cacheAdd) { + char *timestr; + + timestr = mystrtotime(args[2]); + (*arg)->control->un.cacheAdd = str2qb(timestr, + strlen(timestr),1); + free(timestr); + } + return OK; +} + +/* ARGSUSED */ +int res_channelcontrol (ad, id, dummy, result, roi) +int ad, id, dummy; +register struct type_Qmgr_PrioritisedChannelList *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx)(convert_PrioChannelInfos(result), id); + free_copblk(op); + return OK; +} + +/* */ + +static ChannelInfo *convert_ChannelInfo(pepsy) +register struct type_Qmgr_ChannelInfo *pepsy; +{ + ChannelInfo *ret; + + if (pepsy == (struct type_Qmgr_ChannelInfo *) NULL) + return (ChannelInfo *) NULL; + + ret = (ChannelInfo *) calloc (1, sizeof(*ret)); + + ret->channelname = qb2str(pepsy->channel); + ret->channeldescrip = qb2str(pepsy->channelDescription); + + ret->oldestMessage = convert_time(pepsy->oldestMessage); + ret->numberMessages = pepsy->numberMessages; + ret->numberReports = pepsy->numberReports; + ret->volumeMessages = pepsy->volumeMessages; + ret->numberMtas = pepsy->numberMtas; + ret->numberActiveProcesses = pepsy->numberActiveProcesses; + ret->status = convert_ProcStatus(pepsy->status); + ret->inbound = bit_test(pepsy->direction, bit_Qmgr_direction_inbound); + ret->outbound = bit_test(pepsy->direction, bit_Qmgr_direction_outbound); + ret->chantype = pepsy->chantype; + ret->maxprocs = pepsy->maxprocs; + ret->numberMtas = pepsy->numberMtas; + + return ret; +} + +static ChannelInfo *convert_PrioChannelInfos(pepsy) +register struct type_Qmgr_PrioritisedChannelList *pepsy; +{ + ChannelInfo *head, *tail, *temp; + + head = tail = (ChannelInfo *) NULL; + + while (pepsy != (struct type_Qmgr_PrioritisedChannelList *) NULL) { + if ((temp = + convert_ChannelInfo(pepsy->PrioritisedChannel->channel)) + == (ChannelInfo *) NULL) { + free_ChannelInfo(head); + return (ChannelInfo *) NULL; + } + temp -> priority = + pepsy -> PrioritisedChannel -> priority -> parm; + if (head == NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + pepsy = pepsy -> next; + } + return head; +} + +static ChannelInfo *convert_ChanReadResult(pepsy) +register struct type_Qmgr_ChannelReadResult *pepsy; +{ + return convert_PrioChannelInfos(pepsy -> channels); +} + +/* */ + +free_ChannelInfo(list) +ChannelInfo *list; +{ + ChannelInfo *temp; + + while (list != (ChannelInfo *) NULL) { + if (list -> channelname) free (list -> channelname); + if (list -> channeldescrip) free (list -> channeldescrip); + if (list -> status) free_ProcStatus (list -> status); + temp = list; + list = list -> next; + free ((char *) temp); + } +} + + diff --git a/Lib/qmgr/op_filter.c b/Lib/qmgr/op_filter.c new file mode 100644 index 0000000..c6a1602 --- /dev/null +++ b/Lib/qmgr/op_filter.c @@ -0,0 +1,165 @@ +/* op_filter.c: filter operations */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_filter.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_filter.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: op_filter.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" +#include "consblk.h" +#include "Qmgr-types.h" +#include + +#define STR2QB(x) str2qb((x), strlen(x), 1) + +static CMD_TABLE filter_keys[] = { +#define F_CONTENT 1 + QFILTER_CONTENT, F_CONTENT, +#define F_EIT 2 + QFILTER_EIT, F_EIT, +#define F_PRIO 3 + QFILTER_PRIO, F_PRIO, +#define F_RECENT 4 + QFILTER_MORERECENT, F_RECENT, +#define F_EARLIER 5 + QFILTER_EARLIER, F_EARLIER, +#define F_MAXSIZE 6 + QFILTER_MAXSIZE, F_MAXSIZE, +#define F_ORIG 7 + QFILTER_ORIG, F_ORIG, +#define F_RECIP 8 + QFILTER_RECIP, F_RECIP, +#define F_CHANNEL 9 + QFILTER_CHANNEL, F_CHANNEL, +#define F_MTA 10 + QFILTER_MTA, F_MTA, +#define F_QUEID 11 + QFILTER_QUEUEID, F_QUEID, +#define F_MPDU 12 + QFILTER_MPDU, F_MPDU, +#define F_UA 13 + QFILTER_UA, F_UA, + NULLCP, NOTOK + }; + + +static int add_filter (key, val, f) +char *key, *val; +struct type_Qmgr_Filter *f; +{ + switch (cmd_srch (key, filter_keys)) { + case F_CONTENT: + if (f->contenttype) + return NOTOK; + f -> contenttype = STR2QB(val); + break; + + case F_EIT: + { + struct type_Qmgr_EncodedInformationTypes *eit; + eit = (struct type_Qmgr_EncodedInformationTypes *) + smalloc (sizeof *eit); + eit -> PrintableString = STR2QB (val); + eit -> next = f -> eit; + } + break; + + case F_PRIO: + if (f -> priority) + return NOTOK; + f -> priority = (struct type_Qmgr_Priority *) + smalloc (sizeof *f->priority); + f -> priority -> parm = atoi (val); + break; + + case F_RECENT: + if (f -> moreRecentThan) + return NOTOK; + f -> moreRecentThan = STR2QB(val); + break; + case F_EARLIER: + if (f -> earlierThan) + return NOTOK; + f -> earlierThan = STR2QB(val); + break; + case F_MAXSIZE: + if (f -> maxSize) + return NOTOK; + f -> maxSize = atoi(val); + break; + case F_ORIG: + if (f -> originator) + return NOTOK; + f -> originator = STR2QB(val); + break; + case F_RECIP: + if (f -> recipient) + return NOTOK; + f -> recipient = STR2QB (val); + break; + case F_CHANNEL: + if (f -> channel) + return NOTOK; + f -> channel = STR2QB (val); + break; + case F_MTA: + if (f -> mta) + return NOTOK; + f -> mta = STR2QB (val); + break; + case F_QUEID: + if (f -> queueid) + return NOTOK; + f -> queueid = STR2QB (val); + break; + case F_UA: + if (f -> uaContentId) + return NOTOK; + f -> uaContentId = STR2QB (val); + break; + case F_MPDU: + default: + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +int arg_filter(ad, args, arg) +int ad; +char **args; /* list of key=value things */ +struct type_Qmgr_ReadMessageArgument **arg; +{ + char *cp; + struct type_Qmgr_Filter *f; + struct type_Qmgr_FilterList *filterl; + + *arg = (struct type_Qmgr_ReadMessageArgument *) + smalloc (sizeof **arg); + (*arg) -> interval = NULL; + (*arg) -> filters = filterl = + (struct type_Qmgr_FilterList *)smalloc (sizeof *filterl); + filterl -> next = NULL; + filterl -> Filter = f = (struct type_Qmgr_Filter *) + smalloc (sizeof *f); + bzero ((char *)f, sizeof *f); + + while (*args) { + if ((cp = index(*args, '=')) == NULLCP) + return NOTOK; + *cp++ = '\0'; + if (add_filter (*args, cp, f) == NOTOK) + return NOTOK; + args ++; + } + return OK; +} diff --git a/Lib/qmgr/op_msg.c b/Lib/qmgr/op_msg.c new file mode 100644 index 0000000..f276694 --- /dev/null +++ b/Lib/qmgr/op_msg.c @@ -0,0 +1,471 @@ +/* op_msg.c msg ROS operation routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_msg.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_msg.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: op_msg.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" +#include "consblk.h" +#include "Qmgr-types.h" +#include +#include + +#define MSG_READ_INTERVAL 60 /* in secs */ + +/* ARGSUSED */ +int arg_readchannelmtamessage (ad, args, arg) +int ad; +char **args; +/* args[0] = chan args[1] = mta or name in case of local chan */ +struct type_Qmgr_MsgRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MsgRead *) malloc(sizeof(**arg)); + bzero ((char *) *arg, sizeof(**arg)); + /* fillin time */ + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MSG_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + if (args[0] != NULLCP) + (*arg)->channel = str2qb(args[0], strlen(args[0]), 1); + if (args[1] != NULLCP) + (*arg)->mta = str2qb(args[1], strlen(args[1]), 1); + return OK; +} + +static MsgList *convert_MsgList(); + +/* ARGSUSED */ +int res_readchannelmtamessage (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_MsgList *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx)(convert_MsgList(result), id); + free_copblk (op); + return OK; +} + +/* */ + +static struct type_Qmgr_UserList *create_userlist(); + +extern char *mystrtotime(); + +static CMD_TABLE control_tbl[] = { + CTRL_ENABLE, type_Qmgr_Control_start, + CTRL_DISABLE, type_Qmgr_Control_stop, + CTRL_CACHECLEAR,type_Qmgr_Control_cacheClear, + CTRL_CACHEADD, type_Qmgr_Control_cacheAdd, + NULLCP, NOTOK + }; + +/* ARGSUSED */ +int arg_msgcontrol (ad, args, arg) +int ad; +char **args; +struct type_Qmgr_MsgControl **arg; +/* args[0] = qid */ +/* args[1] = time */ +/* args[2] = stop, start, clear cacheadd*/ +/* args[3..] = NULL terminated list of users */ +{ + int n; + + *arg = (struct type_Qmgr_MsgControl *) malloc(sizeof(**arg)); + + (*arg)->qid = str2qb(args[0], strlen(args[0]), 1); + + (*arg)->users = create_userlist(&(args[3])); + + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + if ((n = cmd_srch (args[2], control_tbl)) == NOTOK) + return NOTOK; + + if (((*arg)->control->offset = n) == type_Qmgr_Control_cacheAdd) { + char *timestr; + timestr = mystrtotime(args[1]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + } + return OK; +} + +/* ARGSUSED */ +int res_msgcontrol (ad, id, dummy, result, roi) +int ad, id, dummy; +struct type_Qmgr_Pseudo__newmessage *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx) (id); + free_copblk (op); + return OK; +} + +/* */ + +static Strlist *convert_EITs (pepsy) +register struct type_Qmgr_EncodedInformationTypes *pepsy; +{ + Strlist *head, *tail, *temp; + + head = tail = (Strlist *) NULL; + + while (pepsy != (struct type_Qmgr_EncodedInformationTypes *) NULL) { + if (pepsy->PrintableString) { + temp = (Strlist *) calloc (1, sizeof(*temp)); + temp -> str = qb2str (pepsy->PrintableString); + if (head == (Strlist *) NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + } + pepsy = pepsy -> next; + } + return head; +} + +static PerMessageInfo *convert_PerMessageInfo(pepsy) +register struct type_Qmgr_PerMessageInfo *pepsy; +{ + PerMessageInfo *ret; + + if (pepsy == (struct type_Qmgr_PerMessageInfo *) NULL) + return (PerMessageInfo *) NULL; + + ret = (PerMessageInfo *) calloc(1, sizeof(*ret)); + + ret -> qid = qb2str(pepsy->queueid); + + if (pepsy->mpduiden) { + if (pepsy->mpduiden->global) { + if (pepsy->mpduiden->global->country) + ret->country = + qb2str(pepsy->mpduiden-> + global->country -> un.printable); + if (pepsy->mpduiden->global->admd) + ret->admd = + qb2str(pepsy->mpduiden->global-> + admd -> un.printable); + if (pepsy->mpduiden->global->prmd) + ret->prmd = + qb2str(pepsy->mpduiden->global-> + prmd -> un.printable); + } + if (pepsy->mpduiden->local) + ret->local = + qb2str(pepsy->mpduiden->local); + } + + ret->originator = qb2str(pepsy->originator); + if (pepsy->contenttype) + ret->contenttype = qb2str(pepsy->contenttype); + if (pepsy->eit) + ret -> eits = convert_EITs(pepsy->eit); + ret -> priority = pepsy->priority->parm; + ret -> size = pepsy->size; + ret->age = convert_time(pepsy->age); + ret -> warnInterval = pepsy -> warnInterval; + ret -> numberWarningsSent = pepsy ->numberWarningsSent; + if (pepsy -> expiryTime) + ret -> expiryTime = convert_time(pepsy -> expiryTime); + if (pepsy -> deferredTime) + ret -> deferredTime = convert_time(pepsy -> deferredTime); + if (pepsy -> uaContentId) + ret -> uaContentId = qb2str (pepsy -> uaContentId); + if (pepsy -> optionals & opt_Qmgr_PerMessageInfo_errorCount) + ret->errorCount = pepsy->errorCount; + if (pepsy -> inChannel) + ret -> inChannel = qb2str(pepsy -> inChannel); + return ret; +} + +static Strlist *convert_ChannelList (pepsy) +register struct type_Qmgr_ChannelList *pepsy; +{ + Strlist *head, *tail, *temp; + + head = tail = (Strlist *) NULL; + + while (pepsy != (struct type_Qmgr_ChannelList *) NULL) { + if (pepsy->Channel) { + temp = (Strlist *) calloc (1, sizeof(*temp)); + temp -> str = qb2str (pepsy->Channel); + if (head == (Strlist *) NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + } + pepsy = pepsy -> next; + } + return head; +} + +static RecipInfo *convert_RecipientInfo (pepsy) +register struct type_Qmgr_RecipientInfo *pepsy; +{ + RecipInfo *ret; + + if (pepsy == (struct type_Qmgr_RecipientInfo *) NULL) + return (RecipInfo *) NULL; + + ret = (RecipInfo *) calloc (1, sizeof(*ret)); + + ret -> user = qb2str(pepsy->user); + + if (pepsy->id) + ret->id = pepsy->id->parm; + + if (pepsy->mta) + ret->mta = qb2str(pepsy->mta); + + if (pepsy->channelList) + ret->channels = convert_ChannelList(pepsy->channelList); + + ret->channelsDone = pepsy->channelsDone; + ret->status = convert_ProcStatus(pepsy->procStatus); + if (pepsy->info) + ret->info = qb2str(pepsy->info); + return ret; +} + +static RecipInfo *convert_RecipientList (pepsy) +register struct type_Qmgr_RecipientList *pepsy; +{ + RecipInfo *head, *tail, *temp; + + head = tail = (RecipInfo *) NULL; + + while (pepsy != (struct type_Qmgr_RecipientList *) NULL) { + if (pepsy -> RecipientInfo + && ((temp = + convert_RecipientInfo (pepsy -> RecipientInfo)) + != (RecipInfo *) NULL)) { + if (head == (RecipInfo *) NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + } + pepsy = pepsy -> next; + } + return head; +} + +static MsgInfo *convert_MsgStruct(pepsy) +register struct type_Qmgr_MsgStruct *pepsy; +{ + MsgInfo *ret; + + if (pepsy == (struct type_Qmgr_MsgStruct *) NULL) + return (MsgInfo *) NULL; + + ret = (MsgInfo *) calloc (1, sizeof(*ret)); + + ret -> permsginfo = convert_PerMessageInfo (pepsy -> messageinfo); + + ret -> recips = convert_RecipientList (pepsy -> recipientlist); + + return ret; +} + +static MsgInfo *convert_MsgStructList(pepsy) +register struct type_Qmgr_MsgStructList *pepsy; +{ + MsgInfo *head, *tail, *temp; + + head = tail = (MsgInfo *) NULL; + + while (pepsy != (struct type_Qmgr_MsgStructList *) NULL) { + if (pepsy->MsgStruct + && (temp = convert_MsgStruct(pepsy->MsgStruct)) != + (MsgInfo *) NULL) { + if (head == (MsgInfo *) NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + } + pepsy = pepsy -> next; + } + + return head; +} + +static Strlist *convert_QidList (pepsy) +register struct type_Qmgr_QidList *pepsy; +{ + Strlist *head, *tail, *temp; + + head = tail = (Strlist *) NULL; + + while (pepsy != (struct type_Qmgr_QidList *) NULL) { + if (pepsy->QID) { + temp = (Strlist *) calloc (1, sizeof(*temp)); + temp -> str = qb2str (pepsy->QID); + if (head == (Strlist *) NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + } + pepsy = pepsy -> next; + } + return head; +} + +static MsgList *convert_MsgList(pepsy) +register struct type_Qmgr_MsgList *pepsy; +{ + MsgList *ret; + + if (pepsy == (struct type_Qmgr_MsgList *) NULL) + return (MsgList *) NULL; + + ret = (MsgList *) calloc (1, sizeof(*ret)); + + if (pepsy->msgs) + ret->msgs = convert_MsgStructList (pepsy->msgs); + if (pepsy->deleted) + ret->deleted = convert_QidList (pepsy->deleted); + return ret; +} + + +/* */ + +free_MsgList(list) +MsgList *list; +{ + if (list -> msgs) + free_MsgInfo (list -> msgs); + if (list -> deleted) + free_Strlist (list -> deleted); + free((char *) list); +} + +free_Strlist(list) +Strlist *list; +{ + Strlist *temp; + + while (list != (Strlist *) NULL) { + if (list->str) free(list->str); + temp = list; + list = list -> next; + free((char *) temp); + } +} + +free_MsgInfo (info) +MsgInfo *info; +{ + MsgInfo *temp; + + while ((MsgInfo *) NULL != info) { + if (info->permsginfo) + free_PerMessageInfo(info->permsginfo); + if (info->recips) + free_RecipInfo(info->recips); + temp = info; + info = info->next; + free((char *) temp); + } +} + +free_PerMessageInfo (permsg) +PerMessageInfo *permsg; +{ + if (permsg->qid) free(permsg->qid); + if (permsg->country) free(permsg->country); + if (permsg->admd) free(permsg->admd); + if (permsg->prmd) free(permsg->prmd); + if (permsg->local) free(permsg->local); + if (permsg->originator) free(permsg->originator); + if (permsg->contenttype) free(permsg->contenttype); + if (permsg->eits) free_Strlist(permsg->eits); + if (permsg->uaContentId) free(permsg->uaContentId); + if (permsg->inChannel) free(permsg->inChannel); + free((char *) permsg); +} + +free_RecipInfo(recips) +RecipInfo *recips; +{ + RecipInfo *temp; + while (recips) { + if (recips->user) free(recips->user); + if (recips->mta) free(recips->mta); + if (recips->channels) free_Strlist(recips->channels); + if (recips->status) free_ProcStatus (recips->status); + if (recips->info) free(recips->info); + temp = recips; + recips = recips->next; + free((char *) temp); + } +} + +/* */ + +static struct type_Qmgr_UserList *create_userlist(argv) +char **argv; +{ + struct type_Qmgr_UserList *temp, + *head = NULL, + *tail = NULL; + int i = 0; + while (argv[i] != NULL) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) + malloc(sizeof(struct type_Qmgr_RecipientId)); + temp->RecipientId->parm = atoi(argv[i++]); + + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = tail->next; + } + } + + return head; +} diff --git a/Lib/qmgr/op_mta.c b/Lib/qmgr/op_mta.c new file mode 100644 index 0000000..63ea864 --- /dev/null +++ b/Lib/qmgr/op_mta.c @@ -0,0 +1,198 @@ +/* op_mta.c: mta ROS operation routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_mta.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_mta.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: op_mta.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" +#include "consblk.h" +#include "Qmgr-types.h" +#include +#include + +#define MTA_READ_INTERVAL 60 /* in secs */ + +/* ARGSUSED */ +int arg_mtaread (ad, args, arg) +int ad; +char **args; /* args[0] is channel name */ +struct type_Qmgr_MtaRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MtaRead *) malloc(sizeof(**arg)); + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MTA_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + return OK; +} + +static MtaInfo *convert_PrioritisedMtaList(); + +/* ARGSUSED */ +int res_mtaread (ad, id, dummy, result, roi) +int ad, id, dummy; +register struct type_Qmgr_PrioritisedMtaList *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx) (convert_PrioritisedMtaList(result), id); + free_copblk (op); + return OK; +} + +/* */ + +extern char *mystrtotime(); +static CMD_TABLE control_tbl[] = { + CTRL_ENABLE, type_Qmgr_Control_start, + CTRL_DISABLE, type_Qmgr_Control_stop, + CTRL_CACHECLEAR,type_Qmgr_Control_cacheClear, + CTRL_CACHEADD, type_Qmgr_Control_cacheAdd, + NULLCP, NOTOK + }; + +/* ARGSUSED */ +int arg_mtacontrol (ad, args, arg) +int ad; +char **args; +struct type_Qmgr_MtaControl **arg; +/* args[0] = channel */ +/* args[1] = mta */ +/* args[2] = stop,start,clear,cacheadd */ +/* args[3] = time */ +{ + int n; + + *arg = (struct type_Qmgr_MtaControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], strlen(args[0]), 1); + (*arg)->mta = str2qb(args[1], strlen(args[1]), 1); + + if ((n = cmd_srch (args[2], control_tbl)) == NOTOK) + return NOTOK; + + if (((*arg)->control->offset = n) == type_Qmgr_Control_cacheAdd) { + char *timestr; + + timestr = mystrtotime(args[3]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + } + return OK; +} + +static MtaInfo *convert_MtaInfo(); + +/* ARGSUSED */ +int res_mtacontrol (ad, id, dummy, result, roi) +int ad, id, dummy; +register struct type_Qmgr_MtaInfo *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx) (convert_MtaInfo(result), id); + free_copblk(op); + return OK; +} + +/* */ + +static MtaInfo *convert_MtaInfo(pepsy) +register struct type_Qmgr_MtaInfo *pepsy; +{ + MtaInfo *ret; + + if (pepsy == (struct type_Qmgr_MtaInfo *) NULL) + return (MtaInfo *) NULL; + + ret = (MtaInfo *) calloc (1, sizeof(*ret)); + + ret->channel = qb2str(pepsy->channel); + ret->mta = qb2str(pepsy->mta); + ret->oldestMessage = convert_time(pepsy->oldestMessage); + ret->numberMessages = pepsy->numberMessage; + ret->volumeMessages = pepsy->volumeMessages; + ret->status = convert_ProcStatus(pepsy->status); + ret->numberReports = pepsy->numberDRs; + ret->active = pepsy->active; + if (pepsy->info) + ret->info = qb2str(pepsy->info); + + return ret; +} + +static MtaInfo *convert_PrioritisedMtaList(pepsy) +register struct type_Qmgr_PrioritisedMtaList *pepsy; +{ + MtaInfo *head, *tail, *temp; + + head = tail = (MtaInfo *) NULL; + + while (pepsy != (struct type_Qmgr_PrioritisedMtaList *) NULL) { + if ((temp = + convert_MtaInfo(pepsy->PrioritisedMta->mta)) + == (MtaInfo *) NULL) { + free_MtaInfo(head); + return (MtaInfo *) NULL; + } + temp -> priority = + pepsy->PrioritisedMta->priority->parm; + if (head == NULL) + head = tail = temp; + else { + tail -> next = temp; + tail = temp; + } + pepsy = pepsy -> next; + } + return head; +} + +/* */ + +free_MtaInfo(list) +MtaInfo *list; +{ + MtaInfo *temp; + + while (list != (MtaInfo *) NULL) { + if (list -> channel) free (list -> channel); + if (list -> mta) free (list -> mta); + if (list -> status) free_ProcStatus (list -> status); + if (list -> info) free (list -> info); + temp = list; + list = list -> next; + free ((char *) temp); + } +} diff --git a/Lib/qmgr/op_que.c b/Lib/qmgr/op_que.c new file mode 100644 index 0000000..761dcf2 --- /dev/null +++ b/Lib/qmgr/op_que.c @@ -0,0 +1,116 @@ +/* op_que.c: que ROS operation routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_que.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/op_que.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: op_que.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "consblk.h" +#include "qmgr-int.h" +#include "Qmgr-types.h" +#include +#include + +static CMD_TABLE ops_tbl[] = { + QCTRL_ABORT, int_Qmgr_QMGROp_abort, + QCTRL_GRACEFUL, int_Qmgr_QMGROp_gracefulTerminate, + QCTRL_RESTART, int_Qmgr_QMGROp_restart, + QCTRL_REREAD, int_Qmgr_QMGROp_rereadQueue, + QCTRL_DISSUB, int_Qmgr_QMGROp_disableSubmission, + QCTRL_ENASUB, int_Qmgr_QMGROp_enableSubmission, + QCTRL_DISALL, int_Qmgr_QMGROp_disableAll, + QCTRL_ENAALL, int_Qmgr_QMGROp_enableAll, + QCTRL_INCMAX, int_Qmgr_QMGROp_increasemaxchans, + QCTRL_DECMAX, int_Qmgr_QMGROp_decreasemaxchans, + NULLCP, NOTOK +}; + +/* ARGSUSED */ +int arg_quecontrol (ad, args, arg) +int ad; +char **args; +struct type_Qmgr_QMGROp **arg; +{ + *arg = (struct type_Qmgr_QMGROp *) malloc(sizeof(**arg)); + (*arg)->parm = cmd_srch(args[0], ops_tbl); + if ((*arg) -> parm == NOTOK) + return NOTOK; + return OK; +} + +/* ARGSUSED */ +int res_quecontrol (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_Pseudo__qmgrControl *result; +struct RoSAPindication *roi; +{ + return OK; +} + +/* */ + +static QmgrStatus *convert_QmgrStatus(); + +/* ARGSUSED */ +int res_qmgrStatus (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_QmgrStatus *result; +struct RoSAPindication *roi; +{ + struct cons_opblk *op; + + if ((op = find_copblk(ad, id)) == NULL) + return NOTOK; + + if (op -> fnx) + (*op -> fnx) (convert_QmgrStatus(result), id); + free_copblk (op); + return OK; +} + +/* */ + +static QmgrStatus *convert_QmgrStatus(pepsy) +struct type_Qmgr_QmgrStatus *pepsy; +{ + QmgrStatus *ret; + + if ((struct type_Qmgr_QmgrStatus *) NULL == pepsy) + return (QmgrStatus *) NULL; + + ret = (QmgrStatus *) malloc(sizeof(*ret)); + + if (pepsy->boottime) + ret->boottime = convert_time(pepsy->boottime); + else + ret->boottime = 0; + + ret->messagesIn = pepsy->messagesIn; + ret->messagesOut = pepsy->messagesOut; + ret->addrIn = pepsy->addrIn; + ret->addrOut = pepsy->addrOut; + ret->opsPerSec = pepsy->opsPerSec; + ret->runnableChans = pepsy->runnableChans; + ret->msgsInPerSec = pepsy->msgsInPerSec; + ret->msgsOutPerSec = pepsy->msgsOutPerSec; + ret->maxChans = pepsy->maxChans; + ret->currChans = pepsy->currChans; + ret->totalMsgs = pepsy->totalMsgs; + ret->totalVolume = pepsy->totalVolume; + ret->totalDRs = pepsy->totalDrs; + + return ret; +} diff --git a/Lib/qmgr/order.c b/Lib/qmgr/order.c new file mode 100644 index 0000000..19b45a5 --- /dev/null +++ b/Lib/qmgr/order.c @@ -0,0 +1,186 @@ +/* order.c: routines for use in ordering calculations */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/order.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/order.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: order.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "qmgr-int.h" + +/* */ + +/* -1 == MAX */ + +double measure_Channel(chan, measure, currenttime) +register ChannelInfo *chan; +register MeasureInfo *measure; +time_t currenttime; +{ + double average_db = 0.0; + int noFactors = 0; + + if (NULL == measure) + return 0; + + if (0.0 != measure->ub_number) { + if (chan->numberMessages + chan->numberReports >= measure->ub_number) + return -1; + average_db += (chan->numberMessages+chan->numberReports)*100/measure->ub_number; + noFactors++; + } + + if (0.0 != measure->ub_volume) { + if (chan->volumeMessages >= measure->ub_volume) + return -1; + average_db += (chan->volumeMessages*100)/measure->ub_volume; + noFactors++; + } + + if (0.0 != measure->ub_age) { + double age; + if (chan->oldestMessage != 0 + && (chan->numberMessages != 0 + || chan->numberReports != 0)) + age = (currenttime - chan->oldestMessage) / 60.0; + else + age = 0.0; + if (age >= measure -> ub_age) + return -1; + average_db += (age * 100)/measure->ub_age; + noFactors++; + } + + if (0.0 != measure->ub_last) { + double last; + if (0 != chan->status->lastSuccess) + last = (currenttime - chan->status->lastSuccess)/60.0; + else + last = 0.0; + if (last >= measure->ub_last) + return -1; + if (last >= measure->ub_last/2) { + /* only kick in at halfway */ + average_db += (last * 100)/ measure->ub_last; + noFactors++; + } + } + + if (1 < noFactors) + average_db = average_db / noFactors; + + return average_db; +} + +/* */ + +/* -1 == MAX */ + +double measure_Mta(mta, measure, currenttime) +register MtaInfo *mta; +register MeasureInfo *measure; +time_t currenttime; +{ + double average_db = 0.0; + int noFactors = 0; + + if (NULL == measure) + return 0; + + if (0.0 != measure->ub_number) { + if (mta->numberMessages + mta->numberReports >= measure->ub_number) + return -1; + average_db += (mta->numberMessages+mta->numberReports)*100/measure->ub_number; + noFactors++; + } + + if (0.0 != measure->ub_volume) { + if (mta->volumeMessages >= measure->ub_volume) + return -1; + average_db += (mta->volumeMessages*100)/measure->ub_volume; + noFactors++; + } + + if (0.0 != measure->ub_age) { + double age; + if (mta->oldestMessage != 0 + && (mta->numberMessages != 0 + || mta->numberReports != 0)) + age = (currenttime - mta->oldestMessage) / 60.0; + else + age = 0.0; + if (age >= measure -> ub_age) + return -1; + average_db += (age * 100)/measure->ub_age; + noFactors++; + } + + if (0.0 != measure->ub_last) { + double last; + if (0 != mta->status->lastSuccess) + last = (currenttime - mta->status->lastSuccess)/60.0; + else + last = 0.0; + if (last >= measure->ub_last) + return -1; + if (last >= measure->ub_last/2) { + /* only kick in at halfway */ + average_db += (last * 100)/ measure->ub_last; + noFactors++; + } + } + + if (1 < noFactors) + average_db = average_db / noFactors; + + return average_db; +} + +/* */ + +/* -1 == MAX */ + +double measure_Msg(msg, measure, currenttime) +register MsgInfo *msg; +register MeasureInfo *measure; +time_t currenttime; +{ + double average_db = 0.0; + int noFactors = 0; + + if (NULL == measure) + return 0; + + if (msg->permsginfo->expiryTime != 0 + && (currenttime - msg->permsginfo->expiryTime) >= 0) + /* expired so return MAX */ + return -1; + + if (0.0 != measure->ub_age) { + double age; + age = (currenttime - msg->permsginfo->age) / 60.0; + if (age >= measure->ub_age) + return -1; + average_db += (age * 100)/measure->ub_age; + noFactors++; + } + + if (0.0 != measure->ub_volume) { + if (msg->permsginfo->size >= measure->ub_volume) + return -1; + average_db += (msg->permsginfo->size * 100) / measure->ub_volume; + noFactors++; + } + + if (1 < noFactors) + average_db = average_db / noFactors; + return average_db; +} diff --git a/Lib/qmgr/qmgr.ry b/Lib/qmgr/qmgr.ry new file mode 100644 index 0000000..982c979 --- /dev/null +++ b/Lib/qmgr/qmgr.ry @@ -0,0 +1,576 @@ +-- qmgr.ry - Qmgr operation definitions + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/qmgr.ry,v 6.0 1991/12/18 20:23:58 jpo Rel $ +-- +-- $Log: qmgr.ry,v $ +-- Revision 6.0 1991/12/18 20:23:58 jpo +-- Release 6.0 +-- +-- +-- + + +Qmgr +DEFINITIONS ::= +BEGIN + +-- EXPORTS everything + + +-- PORTS +qmgr-use OBJECT + PORTS { newmessage[S], + readmsginfo[S], + msginfo[C], + channelinitialise[C], + processmessage, + channelbegin[S], + readqueue[C], + channelread[S], + channelinfo[C], + channelcontrol[S], + mtaread[S], + mtainfo[C], + mtacontrol[S], + qmgrstatus[S], + readchannelmtamessage[S] } ::= id-pt-qmgr-use + + +activeChannel OBJECT + PORTS { channelinitialise, + processmessage [S] } + ::= id-pt-activeChannel + +passiveChannel OBJECT + PORTS { processmessage[S], + channelbegin[C] } + ::= id-pt-passiveChannel + +submitProcess OBJECT + PORTS { newmessage[C] } + ::= id-pt-submitProcess + +queueReadProcess OBJECT + PORTS { readqueue[S] } + ::= id-pt-queueReadProcess + +managementUA OBJECT + PORTS { processmessage[C], + readmsginfo[C], + msginfo[S], + channelread[C], + channelinfo[S], + channelcontrol[C], + mtaread[C], + mtainfo[S], + mtacontrol[C], + qmgrstatus[C], + readchannelmtamessage[C] } + ::= id-pt-managementUA + +-- OPERATIONS + + -- new message arrived + -- Submit -> QMGR +newmessage OPERATION + ARGUMENT MsgStruct + RESULT NULL + ERRORS { congested, protocol } + ::= 0 + + -- read a message + -- Console -> QMGR + -- QMGR -> QMGR +readmsginfo OPERATION + ARGUMENT ReadMessageArgument + RESULT MsgList + ERRORS { congested, protocol } + LINKED {msginfo} + ::= 1 + + -- QMGR -> Console + -- Incremental update +msginfo OPERATION + ARGUMENT MsgList + ::= 10 + + -- processes a message + -- QMGR -> Channel +processmessage OPERATION + ARGUMENT ProcMsg + RESULT DeliveryStatus + ERRORS { congested, protocol } + ::= 2 + + -- start up a channel + -- Channel -> QMGR +channelbegin OPERATION + ARGUMENT FilterList + -- type of message requested + RESULT FilterList + -- what you are going to get + ERRORS { congested, protocol } + ::= 3 + + -- read the entire queue + -- QMGR -> Q reader +readqueue OPERATION + ARGUMENT NULL + RESULT MsgList + ERRORS { congested, protocol } + ::= 4 + + -- read a channel + -- Console -> QMGR + -- get info at channel level +channelread OPERATION + ARGUMENT UTCTime + RESULT ChannelReadResult + ERRORS { congested, protocol } + LINKED {chaninfo} + ::= 5 + + -- QMGR -> Console + -- Incremental update +chaninfo OPERATION + ARGUMENT ChannelReadResult + -- info on ALL channels + ::= 11 + + -- control a channels behaviour + -- Console -> QMGR +channelcontrol OPERATION + ARGUMENT ChannelControl + RESULT PrioritisedChannelList + ERRORS { congested, protocol, noSuchChannel, illegalOperation, + authenticationFailure} + ::= 6 + + -- read about a mta + -- Console -> QMGR +mtaread OPERATION + ARGUMENT MtaRead + RESULT PrioritisedMtaList + ERRORS { congested, protocol, noSuchChannel } + LINKED {mtainfo} + ::= 7 + + -- QMGR -> Console + -- Incremental update +mtainfo OPERATION + ARGUMENT PrioritisedMtaList + ::= 12 + + -- control a mta + -- Console -> QMGR +mtacontrol OPERATION + ARGUMENT MtaControl + RESULT MtaInfo + ERRORS { congested, noSuchChannel, mtaNotInQueue, + authenticationFailure} + ::= 8 + + -- control a message + -- Console -> QMGR +msgcontrol OPERATION + ARGUMENT MsgControl + RESULT NULL + ERRORS { congested, protocol, noSuchChannel, mtaNotInQueue, + authenticationFailure} + ::= 13 + + -- QMGR -> Channel (process) +channelInitialise OPERATION + ARGUMENT Channel + RESULT NULL + ERRORS { congested, protocol, noSuchChannel} + ::= 9 + +qmgrControl OPERATION + ARGUMENT QMGRControl + RESULT NULL -- always works + ERRORS { congested, protocol, authenticationFailure} + ::= 14 + +readChannelMtaMessage OPERATION + ARGUMENT MsgRead + RESULT MsgList + ERRORS { congested, protocol, noSuchChannel, mtaNotInQueue } + ::= 15 + +qmgrStatus OPERATION + ARGUMENT NULL + RESULT QmgrStatus + ERRORS { congested, protocol } + ::= 16 +-- ERRORS + + -- congestion at the responder +congested ERROR + ::= 0 + + -- unknown channel +noSuchChannel ERROR + ::= 1 + + -- unknown operation +illegalOperation ERROR + ::= 2 + + -- operation on mta makes no sense +mtaNotInQueue ERROR + ::= 3 + + -- error in the protocol +protocol ERROR + ::= 4 + +authenticationFailure ERROR + ::= 5 + +-- Bind Arguments + +BindArgument ::= CHOICE { -- structure used in association request + noAuthentication [0] NULL, + weakAuthentication [1] WeakAuthentication + } + +WeakAuthentication ::= SEQUENCE { + username [0] IA5String, + passwd [1] IA5String OPTIONAL + } + +BindResult ::= SEQUENCE { + result[0] ENUMERATED { -- result from the association request + acceptedLimitedAccess(0), -- accepted limited access + acceptedFullAccess(1) -- accepted full access + }, + information[1] IA5String OPTIONAL, + version[2] IA5String OPTIONAL + } + + +BindError ::= SEQUENCE { + reason[0] ENUMERATED { + badCredentials(0), -- dont know this person + congested(1) -- some system problem + }, + information[1] IA5String OPTIONAL + } + +-- DATA TYPES + +Mta ::= IA5String + +Channel ::= PrintableString + +Priority ::= ENUMERATED {low(0), normal(1), high(2)} + -- Internal priorities COULD be different + -- to external ones + +UAContentId ::= PrintableString + +ContentType ::= PrintableString + +EncodedInformationTypes ::= SEQUENCE OF PrintableString + +QID ::= PrintableString + +User ::= IA5String + -- QMGR just sees users as strings. + -- This is 822 or /= X.400 syntax + -- The caller must get the right form! + + +ReadMessageArgument ::= SEQUENCE { + filters FilterList, + interval UTCTime OPTIONAL + -- interval for control of the LINKED operation + } + +MsgList ::= SEQUENCE { + msgs SEQUENCE OF %[ type_Qmgr_MsgStructList %] + MsgStruct, + deleted SEQUENCE OF %[ type_Qmgr_QidList %] QID OPTIONAL + } + +ProcMsg ::= SEQUENCE { + qid QID, + users UserList, + -- if USER 0, do all outstanding DNs + channel Channel -- Channel to apply + -- must be same for each user! + -- Warning and Expiry channels have "special" behaviour +} + +Control ::= CHOICE { + stop [0] NULL, + start [1] NULL, + cacheClear [2] NULL, + cacheAdd [3] UTCTime } + +ChannelControl ::= SEQUENCE { + channel [0] Channel, + control [1] Control + } + +MtaControl ::= SEQUENCE { + channel [0] Channel, + mta [1] Mta, + control [2] Control + } + +MsgControl ::= SEQUENCE { + qid [0] QID, + users [1] UserList, + control [2] Control + } + +UserList ::= SEQUENCE OF RecipientId + +RecipientId ::= INTEGER + +MsgStruct ::= SEQUENCE { + messageinfo [0] PerMessageInfo, + recipientlist [1] SEQUENCE OF %[ type_Qmgr_RecipientList %] + RecipientInfo + -- only recipients with responsibility bit set + -- AND originator (recipient 0) + -- The originator is needed for DRs + } + + +PerMessageInfo ::= SEQUENCE { + queueid [0] QID, + mpduiden [1] MPDUIdentifier, + originator [2] User, + contenttype [3] ContentType OPTIONAL, + eit [4] EncodedInformationTypes OPTIONAL, + priority [5] Priority, + size [6] INTEGER, + -- size in bytes + age [7] UTCTime, + warnInterval [8] INTEGER, + numberWarningsSent [9] INTEGER, + expiryTime [10] UTCTime, + deferredTime [11] UTCTime OPTIONAL, + uaContentId [12] UAContentId OPTIONAL, + errorCount [13] INTEGER OPTIONAL, + inChannel [14] Channel OPTIONAL + } + +ProcStatus ::= SEQUENCE { + enabled [0] BOOLEAN, + lastAttempt [1] UTCTime OPTIONAL, + cachedUntil [2] UTCTime OPTIONAL, + lastSuccess [3] UTCTime OPTIONAL + } + +RecipientInfo ::= SEQUENCE { + user [0] User, + id [1] RecipientId, + mta [2] Mta, + channelList [3] SEQUENCE OF %[ type_Qmgr_ChannelList %] Channel, + channelsDone [4] INTEGER, + -- Number of channels processed + -- If EQUAL to the number of channels, + -- this implies DN is still pending + procStatus [4] ProcStatus OPTIONAL, + info [5] IA5String OPTIONAL } + + +FilterList ::= SEQUENCE OF Filter + +Filter ::= SEQUENCE { + contenttype [0] ContentType OPTIONAL, + eit [1] EncodedInformationTypes OPTIONAL, + -- message must have only specified types + priority [2] Priority OPTIONAL, + -- messages of this priority and above + moreRecentThan [3] UTCTime OPTIONAL, + earlierThan [4] UTCTime OPTIONAL, + maxSize [5] INTEGER DEFAULT 0, + -- size in bytes + originator [6] User OPTIONAL, + recipient [7] User OPTIONAL, + channel [8] Channel OPTIONAL, + mta [9] Mta OPTIONAL, + queueid [10] QID OPTIONAL, + mpduiden [11] MPDUIdentifier OPTIONAL, + uaContentId [12] UAContentId OPTIONAL } + +ChannelReadResult ::= SEQUENCE { + channels [0] PrioritisedChannelList, + load1 [1] INTEGER DEFAULT 0, + load2 [2] INTEGER DEFAULT 0, + currchans [3] INTEGER DEFAULT 0, + maxchans [4] INTEGER DEFAULT 0} + +PrioritisedChannelList ::= SEQUENCE OF PrioritisedChannel + +PrioritisedChannel ::= SEQUENCE { + channel ChannelInfo, + priority Priority } + +ChannelInfo ::= SEQUENCE { + channel [0] Channel, + channelDescription [1] PrintableString, + oldestMessage [2] UTCTime, + numberMessages [3] INTEGER, -- not including DRs + volumeMessages [4] INTEGER, -- bytes + numberActiveProcesses [5] INTEGER, + status [6] ProcStatus, + numberReports [7] INTEGER, + direction [8] BITSTRING { + inbound (0), -- supports inbound traffic + outbound (1) -- supports outbound traffic + -- both bits on => does both + -- both bits off is internal + }, + chantype [9] ENUMERATED { + mta (0), -- is an MTA level channel + mts (1), -- is an MTS level channel + internal (2), -- is an internal channel (formatter etc) + passive (3) -- responding channel? + }, + maxprocs [10] INTEGER DEFAULT 0, + numberMtas [11] INTEGER DEFAULT 0 + + } + +MtaRead ::= SEQUENCE { + channel Channel, + time UTCTime OPTIONAL + } + +MsgRead ::= SEQUENCE { + channel Channel, + mta Mta, + time UTCTime OPTIONAL + } + +PrioritisedMtaList ::= SEQUENCE OF PrioritisedMta + +PrioritisedMta ::= SEQUENCE { + mta MtaInfo, + priority Priority } + +MtaInfo ::= SEQUENCE { + channel [0] Channel, + mta [1] Mta, + oldestMessage [2] UTCTime, + numberMessage [3] INTEGER, -- not DRs + volumeMessages [4] INTEGER, + status [5] ProcStatus, + numberDRs [6] INTEGER, + active [7] BOOLEAN DEFAULT FALSE, + info [8] IA5String OPTIONAL + } + +DeliveryStatus ::= SEQUENCE OF IndividualDeliveryStatus + + +IndividualDeliveryStatus ::= SEQUENCE { + recipient [0] RecipientId, + status [1] ENUMERATED { + -- The QMGR should treat the following + -- as successful. In the latter cases + -- a DR is processed in conjuction + -- with a different recipient + success (0), + successSharedDR (1), + failureSharedDR (2), + + -- The next set are treated by the + -- QMGR as now having to send a DR + negativeDR (3), -- negative DR + positiveDR (4), -- positive DR + + + -- the final set are different types + -- of transient failure, needing + -- different QMGR retry strategies + messageFailure (5),-- temp failure on the Message (e.g. + -- protocol temp reject) + mtaFailure (6), -- MTA failure (e.g. couldn't connect) + mtaAndMessageFailure (7) -- Both (e.g. connection bust) + }, + info[2] IA5String OPTIONAL + } + + +QMGRControl ::= SEQUENCE { + op [0] QMGROp + } + +QMGROp ::= ENUMERATED { + abort (0), + gracefulTerminate (1), + restart (2), -- as if from cold + rereadQueue (3), -- but don't disguard curent information + disableSubmission (4), -- Don't let processes submit + enableSubmission (5), + disableAll (6), + enableAll (7), + increasemaxchans(8), + decreasemaxchans(9) } + + +QmgrStatus ::= SEQUENCE { + boottime UTCTime, + messagesIn INTEGER, + messagesOut INTEGER, + addrIn INTEGER, + addrOut INTEGER, + opsPerSec INTEGER, -- * 100 + runnableChans INTEGER, -- * 100 + msgsInPerSec INTEGER, -- * 100 + msgsOutPerSec INTEGER, -- * 100 + maxChans INTEGER, + currChans INTEGER, + totalMsgs INTEGER, + totalVolume INTEGER, + totalDrs INTEGER + } + +-- P1 definitions included for ease + + +MPDUIdentifier ::= + [APPLICATION 4] IMPLICIT SEQUENCE { + global GlobalDomainIdentifier, + local IA5String + } +GlobalDomainIdentifier ::= + [APPLICATION 3] + IMPLICIT SEQUENCE { + country CountryName, + admd AdministrationDomainName, + prmd PrivateDomainIdentifier OPTIONAL + } + +CountryName ::= + [APPLICATION 1] + CHOICE { + numeric NumericString, + printable PrintableString + } + +AdministrationDomainName ::= + [APPLICATION 2] + CHOICE { + numeric NumericString, + printable PrintableString + } + +PrivateDomainIdentifier ::= + CHOICE { + numeric NumericString, + + printable PrintableString + } + + + +END diff --git a/Lib/qmgr/qstruct2qmgr.c b/Lib/qmgr/qstruct2qmgr.c new file mode 100644 index 0000000..76c15fb --- /dev/null +++ b/Lib/qmgr/qstruct2qmgr.c @@ -0,0 +1,579 @@ +/* qstruct2qmgr.c: conversion routine from verbose submit struct to concise +qmgr struct */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/qstruct2qmgr.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/qstruct2qmgr.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: qstruct2qmgr.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +/* Qmgr types */ +#include "Qmgr-types.h" + +/* Sumbit types */ +#include "q.h" +#include "prm.h" + +extern CMD_TABLE qtbl_con_type[]; +/* */ +/* Routines */ +extern time_t utctotime(); +static struct type_Qmgr_PerMessageInfo *fillin_messageinfo(); +static struct type_Qmgr_MPDUIdentifier *fillin_mpduiden(); +static struct type_Qmgr_GlobalDomainIdentifier *fillin_gldmdid(); +static struct type_Qmgr_CountryName *fillin_country(); +static struct type_Qmgr_AdministrationDomainName *fillin_admd(); +static struct type_Qmgr_PrivateDomainIdentifier *fillin_prmd(); +static struct type_Qmgr_ContentType *fillin_content(); +static struct type_Qmgr_EncodedInformationTypes *fillin_eit(); +static struct type_Qmgr_Priority *fillin_prio(); +static struct type_UNIV_UTCTime *fillin_age(); +static struct type_UNIV_UTCTime *fillin_expiryTime(); +static struct type_UNIV_UTCTime *fillin_deferredTime(); +static struct type_Qmgr_User *fillin_user(); +static struct type_Qmgr_RecipientList *fillin_reciplist(); +static struct type_Qmgr_RecipientInfo *fillin_recip(); +static struct type_Qmgr_ChannelList *fillin_chans(); + +/* error flag and values */ +int fatal_errors; + +/* */ + +/* routine to initialise a qstruct */ +void qinit (que) +Q_struct *que; +{ + que->inbound = NULL; + que->encodedinfo.eit_types = NULL; + que->orig_encodedinfo.eit_types = NULL; + que->ua_id = NULL; + que->msgid.mpduid_DomId.global_Country = NULL; + que->msgid.mpduid_DomId.global_Admin = NULL; + que->msgid.mpduid_DomId.global_Private = NULL; + que->msgid.mpduid_string = NULL; + que->trace = NULL; + que->Oaddress = NULL; + que->Raddress = NULL; +} + +/* conversion routine */ +struct type_Qmgr_MsgStruct *qstruct2qmgr (file,prm,que,sender,recip,rcount) +char *file; +struct prm_vars *prm; +Q_struct *que; +ADDR *sender; +ADDR *recip; +int rcount; +{ + struct type_Qmgr_MsgStruct *msg; + + /* + if fatal_errors becomes true something missing that must be there + */ + fatal_errors = FALSE; + + msg = (struct type_Qmgr_MsgStruct *) calloc (1, sizeof ( *msg)); + + msg->messageinfo = fillin_messageinfo (file,prm,que,sender); + msg->recipientlist = fillin_reciplist (file,sender,recip,rcount); + +/* if (msg->recipientlist == NULL) { +* PP_LOG(LLOG_NOTICE, +* ("Lib/qmgr/qstruct2qmgr : no recipients for '%s'",file)); +* free_Qmgr_MsgStruct(msg); +* msg = NULL; +* }*/ + + if (fatal_errors == TRUE) { + free_Qmgr_MsgStruct (msg); + msg = NULL; + } + return msg; + +} + +/* */ +/* per message info routines */ + +/* ARGSUSED */ +static struct type_Qmgr_PerMessageInfo *fillin_messageinfo ( + file,prm,que,sender) +char *file; +struct prm_vars *prm; +Q_struct *que; +ADDR *sender; +{ + struct type_Qmgr_PerMessageInfo *qmi; + + qmi = (struct type_Qmgr_PerMessageInfo *) + calloc (1, sizeof ( *qmi)); + + if (file != NULLCP) + qmi->queueid = (struct qbuf *) + str2qb (file, strlen(file), 1); + else { + PP_OPER (file, ("Lib/qmgr/qstruct2qmgr: null queueid")); + fatal_errors = TRUE; + } + qmi->mpduiden = fillin_mpduiden (que->msgid); + qmi->originator = fillin_user (sender,file); + qmi->contenttype = fillin_content (que); + qmi->eit = fillin_eit (que); + qmi->priority = fillin_prio (que); + qmi->size = que->msgsize; + qmi->age = fillin_age (que); + qmi->warnInterval = que->warninterval; + qmi->numberWarningsSent = que->nwarns; + qmi->expiryTime = fillin_expiryTime (que); + qmi->deferredTime = fillin_deferredTime (que); + if (que->ua_id != NULL) + qmi->uaContentId = (struct qbuf *) + str2qb (que->ua_id,strlen (que->ua_id),1); + else qmi->uaContentId = NULL; + if (que -> inbound && que -> inbound -> li_chan) + qmi -> inChannel = + str2qb (que -> inbound -> li_chan -> ch_name, + strlen (que -> inbound -> li_chan -> ch_name), + 1); + return qmi; +} + + + +static struct type_Qmgr_MPDUIdentifier *fillin_mpduiden (msgid) +MPDUid msgid; +{ + struct type_Qmgr_MPDUIdentifier *mpdu; + + mpdu = (struct type_Qmgr_MPDUIdentifier *) + calloc (1, sizeof (*mpdu)); + + mpdu->global = fillin_gldmdid (msgid); + if (msgid.mpduid_string == NULL) { + PP_OPER(NULLCP, + ("Lib/qmgr/qstruct2qmgr: missing MsgId string")); + fatal_errors = TRUE; + + mpdu->local = NULL; + } else + mpdu->local = str2qb (msgid.mpduid_string, + strlen (msgid.mpduid_string), + 1); + + return mpdu; +} + +static struct type_Qmgr_GlobalDomainIdentifier *fillin_gldmdid (msgid) +MPDUid msgid; +{ + struct type_Qmgr_GlobalDomainIdentifier *glid; + + glid = (struct type_Qmgr_GlobalDomainIdentifier *) + calloc (1,sizeof (*glid)); + + glid->country = fillin_country (msgid); + glid->admd = fillin_admd (msgid); + glid->prmd = fillin_prmd (msgid); + return glid; +} + +static struct type_Qmgr_CountryName *fillin_country (msgid) +MPDUid msgid; +{ + struct type_Qmgr_CountryName *country; + + country = (struct type_Qmgr_CountryName *) + calloc (1,sizeof (*country)); + + country->offset = type_Qmgr_CountryName_printable; + if (msgid.mpduid_DomId.global_Country == NULL) { + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr : missing MsgId country")); + fatal_errors = TRUE; + country->un.printable = NULL; + + } else + country->un.printable = str2qb ( + msgid.mpduid_DomId.global_Country, + strlen (msgid.mpduid_DomId.global_Country), + 1); + + return country; +} + +static struct type_Qmgr_AdministrationDomainName *fillin_admd (msgid) +MPDUid msgid; +{ + struct type_Qmgr_AdministrationDomainName *admd; + + admd = (struct type_Qmgr_AdministrationDomainName *) + calloc (1,sizeof (*admd)); + + admd->offset = type_Qmgr_AdministrationDomainName_printable; + if (msgid.mpduid_DomId.global_Admin == NULL) { + PP_OPER(NULLCP, + ("Lib/qmgr/qstruct2 missing MsgId admin domain")); + fatal_errors = TRUE; + admd->un.printable = NULL; + } else + admd->un.printable = str2qb ( + msgid.mpduid_DomId.global_Admin, + strlen (msgid.mpduid_DomId.global_Admin), + 1); + return admd; +} + +static struct type_Qmgr_PrivateDomainIdentifier *fillin_prmd (msgid) +MPDUid msgid; +{ + struct type_Qmgr_PrivateDomainIdentifier *prmd = NULL; + + if (msgid.mpduid_DomId.global_Private != NULL) { + + prmd = (struct type_Qmgr_PrivateDomainIdentifier *) + calloc (1,sizeof (*prmd)); + + prmd->offset = type_Qmgr_PrivateDomainIdentifier_printable; + prmd->un.printable = str2qb ( + msgid.mpduid_DomId.global_Private, + strlen (msgid.mpduid_DomId.global_Private), + 1); + } + return prmd; +} + +static struct type_Qmgr_ContentType *fillin_content (que) +Q_struct *que; +{ + char *str = que->cont_type; + + if (str) + return str2qb (str,strlen (str),1); + return NULL; +} + +static struct type_Qmgr_EncodedInformationTypes *fillin_eit (que) +Q_struct *que; +{ + struct type_Qmgr_EncodedInformationTypes *head = NULL, + *tail = NULL, + *temp = NULL; + LIST_BPT *ix = que->encodedinfo.eit_types; + + while (ix != NULL) { + temp = (struct type_Qmgr_EncodedInformationTypes *) + calloc (1, sizeof (*temp)); + temp->PrintableString = str2qb (ix->li_name, + strlen (ix->li_name), + 1); + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = temp; + } + ix = ix->li_next; + } + return head; +} + +static struct type_Qmgr_Priority *fillin_prio (que) +Q_struct *que; +{ + struct type_Qmgr_Priority *prio; + + prio = (struct type_Qmgr_Priority *) calloc (1,sizeof (*prio)); + prio->parm = que->priority; + return prio; +} + +static struct type_UNIV_UTCTime *fillin_age (que) +Q_struct *que; +{ + struct type_UNIV_UTCTime *ti; + char *str; + + str = utct2str (que->queuetime); + ti = str2qb (str,strlen (str),1); + + return ti; +} + + +static struct type_UNIV_UTCTime *fillin_expiryTime (que) +Q_struct *que; +{ + time_t t; + UTC utc; + char *str; + + /* expiry time = queuetime + retinterval */ + + t = utc2time_t (que -> queuetime); + t += que -> retinterval * 60 * 60; + utc = time_t2utc (t); + str = utct2str (utc); + free ((char *)utc); + return str2qb (str, strlen (str), 1); +} + +static struct type_UNIV_UTCTime *fillin_deferredTime (que) +Q_struct *que; +{ + struct type_UNIV_UTCTime *ti; + char *str; + + if (que -> defertime) + str = utct2str (que->defertime); + else + return NULL; + + ti = str2qb (str, strlen (str), 1); + + return ti; +} + +static struct type_Qmgr_User *fillin_user (usr,file) +ADDR *usr; +char *file; +{ + struct type_Qmgr_User *user = NULL; + switch (usr->ad_type) { + case AD_X400_TYPE: + if (usr->ad_r400adr == NULL) { + PP_OPER(NULLCP, + ("Lib/qmgr/qstruct2qmgr: ad_r400adr = nil in %s",file)); + fatal_errors = TRUE; + } else + user = (struct type_Qmgr_User *) + str2qb (usr->ad_r400adr, strlen (usr->ad_r400adr), 1); + break; + case AD_822_TYPE: + if (usr->ad_r822adr == NULL) { + PP_OPER(NULLCP, + ("Lib/qmgr/qstruct2qmgr: ad_r822adr = nil in %s",file)); + fatal_errors = TRUE; + } else + user = (struct type_Qmgr_User *) + str2qb (usr->ad_r822adr, strlen (usr->ad_r822adr), 1); + break; + case AD_ANY_TYPE: + if (usr->ad_value == NULL) { + PP_OPER(NULLCP, + ("Lib/qmgr/qstruct2qmgr: ad_value = nil in %s",file)); + fatal_errors = TRUE; + } else + user = (struct type_Qmgr_User *) + str2qb (usr->ad_value, strlen (usr->ad_value), 1); + break; + default: + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr: unknown address type in %s", + file)); + fatal_errors = TRUE; + break; + } + return user; +} + +/* */ +/* recip list routines */ +static struct type_Qmgr_RecipientList *fillin_reciplist (file,sender,recip,rcount) +char *file; +ADDR *sender; +ADDR *recip; +int rcount; +{ + struct type_Qmgr_RecipientList *ri, *head, *tail; + int ix; + ADDR *adr; + + head = tail = NULL; + ix = 0; + adr = recip; + + /* deal with sender */ + ri = (struct type_Qmgr_RecipientList *) calloc(1, sizeof(*ri)); + ri->RecipientInfo = fillin_recip(file, sender); + head = tail = ri; + + while (ix++ < rcount && adr != NULLADDR) { + if (adr->ad_status != AD_STAT_DONE) { + /* okay to pass to qmgr */ + + ri = (struct type_Qmgr_RecipientList *) + calloc (1, sizeof (*ri)); + ri->RecipientInfo = fillin_recip (file,adr); + + /* add to list */ + tail->next = ri; + tail = ri; + } + adr = adr->ad_next; + } + if (adr) + PP_LOG(LLOG_NOTICE, + ("qstruct2qmgr/fillin_reciplist: discrepancy between rcount and recip (number in recip list < rcount)")); + return head; +} + +static int countChans(list) +struct type_Qmgr_ChannelList *list; +{ + int count = 0; + while (list != NULL) { + count++; + list = list->next; + } + + return count; +} + + +static struct type_Qmgr_RecipientInfo *fillin_recip (file, recip) +char *file; +ADDR *recip; +{ + struct type_Qmgr_RecipientInfo *ri; + + ri = (struct type_Qmgr_RecipientInfo *) calloc (1,sizeof (*ri)); + ri->user = fillin_user (recip,file); + ri->id = (struct type_Qmgr_RecipientId *) calloc (1, sizeof *ri->id); + ri -> id -> parm = recip->ad_no; + + + /* --- *** --- + Note: if a non DR is to be sent for that recipient then the + output channel and mta is not required as the sender's + info is used instead + BUT mta is not OPTIONAL in ASN.1 so put dummy value in + --- *** --- */ + + + if (recip->ad_outchan + && recip->ad_outchan->li_mta != NULLCP) + ri->mta = (struct type_Qmgr_Mta *) + str2qb (recip->ad_outchan->li_mta, + strlen (recip->ad_outchan->li_mta), 1); + else if (recip->ad_status == AD_STAT_DRWRITTEN) + ri->mta = (struct type_Qmgr_Mta *) + str2qb("Delivery Report Written", + strlen("Delivery Report Written"), 1); + else { + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr: %s '%s'", + "missing recipient mta name in", + file)); + fatal_errors = TRUE; + } + + + ri->channelList = fillin_chans ( + file, + recip->ad_status, + recip->ad_fmtchan, + recip->ad_outchan + ); + if (recip->ad_status == AD_STAT_DRWRITTEN) + ri -> channelsDone = countChans(ri->channelList); + else + ri -> channelsDone = recip -> ad_rcnt; + return ri; +} + + +static struct type_Qmgr_ChannelList *fillin_chans (file,status,fmt,out) +char *file; +int status; +LIST_RCHAN *fmt, + *out; +{ + struct type_Qmgr_ChannelList *head = NULL, *ptr, *tmp; + LIST_RCHAN *ix; + + /* formatters */ + ix = fmt; + while (ix != NULL) { + tmp = (struct type_Qmgr_ChannelList *) + calloc (1,sizeof (*tmp)); + tmp->next = NULL; + if ((ix->li_chan != NULL) + && (ix->li_chan->ch_name != NULL)) + tmp->Channel = (struct type_Qmgr_Channel *) + str2qb (ix->li_chan->ch_name, + strlen (ix->li_chan->ch_name), + 1); + else { + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr: %s '%s'", + "null channel name in", + file)); + fatal_errors = TRUE; + } + + /* add to list */ + if (head == NULL) + head = tmp; + else { + ptr = head; + while (ptr->next != NULL) + ptr = ptr->next; + ptr->next = tmp; + } + ix = ix->li_next; + } + + /* outputters */ + ix = out; + if ((ix == NULL) && (status != AD_STAT_DRWRITTEN)) { + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr: %s '%s'", + "missing out channel in", + file)); + fatal_errors = TRUE; + } + + while (ix != NULL) { + tmp = (struct type_Qmgr_ChannelList *) + calloc (1,sizeof (*tmp)); + tmp->next = NULL; + if ((ix->li_chan != NULL) + && (ix->li_chan->ch_name != NULL)) + tmp->Channel = (struct type_Qmgr_Channel *) + str2qb (ix->li_chan->ch_name, + strlen (ix->li_chan->ch_name), + 1); + else { + PP_OPER (NULLCP, + ("Lib/qmgr/qstruct2qmgr: %s '%s'", + "null out channel name in", + file)); + fatal_errors = TRUE; + } + + /* add to list */ + if (head == NULL) + head = tmp; + else { + ptr = head; + while (ptr->next != NULL) + ptr = ptr->next; + ptr->next = tmp; + } + ix = ix->li_next; + } + return head; +} diff --git a/Lib/qmgr/recipstate.c b/Lib/qmgr/recipstate.c new file mode 100644 index 0000000..504368d --- /dev/null +++ b/Lib/qmgr/recipstate.c @@ -0,0 +1,137 @@ +/* recipstate.c: support for qmgr responses */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/recipstate.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/recipstate.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: recipstate.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "qmgr.h" + +#define STR2QB(s) str2qb((s), strlen((s)), 1) + +struct type_Qmgr_DeliveryStatus *deliverystate; + +struct type_Qmgr_DeliveryStatus *delivery_setstate (rno, val, msg) +int rno, val; +char *msg; +{ + struct type_Qmgr_DeliveryStatus *ds; + + PP_DBG (("delivery_setstate (%d, %d)", rno, val)); + + for (ds = deliverystate; ds; ds = ds -> next) { + if (ds -> IndividualDeliveryStatus -> recipient -> parm == rno) { + ds -> IndividualDeliveryStatus -> status = val; + if (msg) { + if (ds -> IndividualDeliveryStatus -> info) + qb_free (ds -> + IndividualDeliveryStatus -> + info); + ds -> IndividualDeliveryStatus -> info = + STR2QB (msg); + } + } + } + return deliverystate; +} + +struct type_Qmgr_DeliveryStatus *delivery_init (users) +struct type_Qmgr_UserList *users; +{ + struct type_Qmgr_DeliveryStatus **ds; + struct type_Qmgr_IndividualDeliveryStatus *ids; + + PP_DBG (("delivery_init (users)")); + + if (deliverystate) { + free_Qmgr_DeliveryStatus (deliverystate); + deliverystate = NULL; + } + + for (ds = & deliverystate; users; users = users -> next, + ds = &(*ds)->next) { + *ds = (struct type_Qmgr_DeliveryStatus *) + calloc (1, sizeof (**ds)); + ids = (*ds) -> IndividualDeliveryStatus = + (struct type_Qmgr_IndividualDeliveryStatus *) + calloc (1, sizeof (struct type_Qmgr_IndividualDeliveryStatus)); + ids -> recipient = (struct type_Qmgr_RecipientId *) + calloc (1, sizeof *ids -> recipient); + ids -> recipient -> parm = users -> RecipientId -> parm; + ids -> status = -1; + ids -> info = NULL; + } + return deliverystate; +} + +struct type_Qmgr_DeliveryStatus *delivery_setallstate (val, msg) +int val; +char *msg; +{ + struct type_Qmgr_DeliveryStatus *ds; + int first = 1; + + PP_DBG (("delivery_setallstate (%d)", val)); + + if (deliverystate == NULL) + return deliverystate; + + for (ds = deliverystate; ds; ds = ds -> next) { + switch (ds -> IndividualDeliveryStatus -> status) { + case int_Qmgr_status_negativeDR: + case int_Qmgr_status_positiveDR: + case int_Qmgr_status_successSharedDR: + case int_Qmgr_status_failureSharedDR: + break; + default: + ds -> IndividualDeliveryStatus -> status = val; + if (msg && val == int_Qmgr_status_mtaFailure && + first) { + if (ds -> IndividualDeliveryStatus -> info) + qb_free (ds -> IndividualDeliveryStatus + -> info); + ds -> IndividualDeliveryStatus -> info = + STR2QB (msg); + first = 0; + } + break; + } + } + return deliverystate; +} + +struct type_Qmgr_DeliveryStatus *delivery_resetDRs (val) +int val; +{ + struct type_Qmgr_DeliveryStatus *ds; + + PP_DBG (("delivery_resetDRs (%d)", val)); + + if (deliverystate == NULL) + return deliverystate; + + for (ds = deliverystate; ds; ds = ds -> next) { + switch (ds -> IndividualDeliveryStatus -> status) { + case int_Qmgr_status_negativeDR: + case int_Qmgr_status_positiveDR: + case int_Qmgr_status_successSharedDR: + case int_Qmgr_status_failureSharedDR: + ds -> IndividualDeliveryStatus -> status = val; + break; + default: + break; + } + } + return deliverystate; +} diff --git a/Lib/qmgr/submit2qmgr.c b/Lib/qmgr/submit2qmgr.c new file mode 100644 index 0000000..8d6abc5 --- /dev/null +++ b/Lib/qmgr/submit2qmgr.c @@ -0,0 +1,454 @@ +/* submit_interface: interface to qmgr for submit's use */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/submit2qmgr.c,v 6.0 1991/12/18 20:23:58 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/qmgr/RCS/submit2qmgr.c,v 6.0 1991/12/18 20:23:58 jpo Rel $ + * + * $Log: submit2qmgr.c,v $ + * Revision 6.0 1991/12/18 20:23:58 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include + +#include "qmgr.h" + +/* Sumbit types */ +#include "q.h" +#include "prm.h" + +/* Outside routines */ +struct type_Qmgr_MsgStruct *qstruct2qmgr(); + +/* DATA */ +static char *myservice = "pp qmgr"; + +/* OPERATIONS */ +static int newmessage_result(); +static int general_error(); + +#define newmessage_error general_error + +static void acs_log (); +static void ros_log (); +static int getresult (); +static int conn_status; +static char qmgr_addr[] = "qmgr-pa.cache"; + +/* */ +static struct PSAPaddr *get_addr (hostname) +char *hostname; +{ + register struct PSAPaddr *pa; + AEI aei; + char buf[BUFSIZ]; + FILE *fp = NULL; + + if ((fp = fopen (qmgr_addr, "r")) != NULL && + fgets (buf, sizeof buf, fp) != NULL && + (pa = str2paddr (buf)) != NULLPA) { + (void) fclose (fp); + return pa; + } + if (fp) + (void) fclose (fp); + + if ((aei = _str2aei(hostname, myservice, QMGR_CTX_OID, 0, dap_user, + dap_passwd)) == NULLAEI) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_start %s-%s: unknown application-entity", + hostname,myservice)); + return NULLPA; + } + if ((pa = aei2addr(aei)) == NULLPA) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_address translation failed")); + return NULLPA; + } + if ((fp = fopen (qmgr_addr, "w")) != NULL) { + (void) fprintf (fp, "%s\n", _paddr2str (pa, NULLNA, -1)); + (void) fclose (fp); + } + else + PP_SLOG (LLOG_EXCEPTIONS, qmgr_addr, + ("Can't write qmgr addr cache")); + return pa; +} + +/* main interface routines */ + +int qmgr_start(hostname, status, async) +char *hostname; +int *status; +int async; +{ + int sd; + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + OID ctx, + pci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if ((pa = get_addr (hostname)) == NULLPA) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't get paddr of qmgr")); + return NOTOK; + } + + if ((ctx = oid_cpy(QMGR_AC)) == NULLOID) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_start: out of memory")); + return NOTOK; + } + if ((pci = oid_cpy(QMGR_PCI)) == NULLOID) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_start: out of memory")); + return NOTOK; + } + pc->pc_nctx = 1; + pc->pc_ctx[0].pc_id = 1; + pc->pc_ctx[0].pc_asn = pci; + pc->pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref ("submit")) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof(*sf)); + } + + switch (AcAsynAssocRequest (ctx, NULLAEI, NULLAEI, NULLPA, pa, pc, NULLOID, + 0, ROS_MYREQUIRE, SERIAL_NONE, 0, sf, NULLPEP, + 0, NULLQOS, acc, aci, async)) { + case NOTOK: + *status = conn_status = NOTOK; + acs_log(aca,"A-ASSOCIATE.REQUEST"); + return NOTOK; + + case CONNECTING_2: + *status = conn_status = CONNECTING_2; + sd = acc -> acc_sd; + ACCFREE (acc); + return sd; + + case CONNECTING_1: /* if !async - this is OK */ + if (async == 1) { + *status = conn_status = CONNECTING_1; + sd = acc -> acc_sd; + ACCFREE (acc); + return sd; + } + /* otherwise - we are really DONE */ + + case DONE: + if (acc->acc_result != ACS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_start: Association rejected: [%s]", + AcErrString(acc->acc_result))); + return NOTOK; + } + sd = acc->acc_sd; + ACCFREE(acc); + if (RoSetService(sd, RoPService, roi) == NOTOK) { + ros_log(rop,"set RO/PS fails"); + return NOTOK; + } + *status = conn_status = DONE; + return sd; + } + return NOTOK; +} + +int qmgr_retry (fd, status) +int fd; +int *status; +{ + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + PP_DBG (("acsap_retry(%d)", fd)); + if (conn_status == DONE) + return fd; + switch (result = AcAsynRetryRequest (fd, acc, aci)) { + case CONNECTING_1: + case CONNECTING_2: + ACCFREE (acc); + *status = conn_status = result; + return fd; + case NOTOK: + acs_log (aca, "A-ASSOCIATE.REQUEST"); + conn_status = NOTOK; + return NOTOK; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, + ("Association Rejected: [%s]", + AcErrString (acc -> acc_result))); + return NOTOK; + } + ACCFREE (acc); + if (RoSetService (fd, RoPService, roi) == NOTOK) { + ros_log (rop, "set RO/PS fails"); + return NOTOK; + } + *status = conn_status = DONE; + return fd; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Bad response from AcAsynRetryRequest")); + return NOTOK; + } +} + + +static int outstanding = NOTOK; + +int qmgr_end(sd) +int sd; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (outstanding != NOTOK) + if (getresult (sd, outstanding, 60) == NOTOK) + return NOTOK; + + outstanding = NOTOK; +#ifdef CONNECTING_1 + if (AcRelRequest(sd,ACF_NORMAL,NULLPEP,0, NOTOK, acr,aci) == NOTOK) { +#else + if (AcRelRequest(sd,ACF_NORMAL,NULLPEP,0,acr,aci) == NOTOK) { +#endif + acs_log(aca,"A-RELEASE.REQUEST"); + return NOTOK; + } + + if (!acr->acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr_end: Release rejected by peer: %d", + acr->acr_reason)); + return NOTOK; + } + + ACRFREE(acr); + return OK; +} + + +int message_send (sd, file, prm, que, sender, recips, rcount) +int sd; +char *file; +struct prm_vars *prm; +Q_struct *que; +ADDR *sender, + *recips; +int rcount; +{ +/* copied from invoke in ryinitiator */ + int result; + struct type_Qmgr_MsgStruct *in; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi->roi_preject; + + while (conn_status != DONE && conn_status != NOTOK) { + int status = conn_status; + sd = qmgr_retry (sd, &status); + if (conn_status == DONE) + break; + sleep (1); + } + if (sd == NOTOK || conn_status == NOTOK) + return NOTOK; + + if (outstanding != NOTOK) + if (getresult (sd, outstanding, NOTOK) == NOTOK) + return NOTOK; + outstanding = NOTOK; + + if ((in = qstruct2qmgr(file,prm,que,sender,recips,rcount)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("qstruct2qmgr failure for '%s'", + file)); + return NOTOK; + } + if (in->recipientlist == NULL) { + /* no users waiting so no need to pass to qmgr */ + PP_LOG (LLOG_EXCEPTIONS, + ("message_send: No recips for '%s'", + file)); + free_Qmgr_PerMessageInfo(in->messageinfo); + free((char *) in); + return OK; + } + + switch (result = RyStub (sd, table_Qmgr_Operations, + operation_Qmgr_newmessage, + outstanding = RyGenID(sd), NULLIP, + (caddr_t) in, + newmessage_result, + newmessage_error, ROS_ASYNC, roi)) { + case NOTOK: + if (ROS_FATAL(rop->rop_reason)) { + PP_LOG (LLOG_EXCEPTIONS, + ("STUB")); + return outstanding = NOTOK; + } + PP_LOG (LLOG_EXCEPTIONS, + ("message_send:STUB")); + break; + + case OK: + break; + + case DONE: + PP_LOG (LLOG_EXCEPTIONS, + ("got RO-END.INDICATION")); + outstanding = NOTOK; + return qmgr_end(sd); + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("submit_interface unknown return from RyStub=%d",result)); + return outstanding = NOTOK; + } + if (in) + free_Qmgr_MsgStruct(in); + return OK; +} + +/* */ +/* subsiduary routines */ + +/* ARGSUSED */ +static int newmessage_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +struct type_Qmgr_Pseudo__newmessage *result; +struct RoSAPindication *roi; +{ + return OK; +} + +/* ARGSUSED */ +static int general_error (sd, id, error, parameter, roi) +int sd, + id, + error; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + + if (error == RY_REJECT) { + PP_LOG (LLOG_EXCEPTIONS, ("%s", RoErrString ((int) parameter))); + return OK; + } + + if (rye = finderrbyerr (table_Qmgr_Errors, error)) + PP_LOG (LLOG_EXCEPTIONS, ("%s", rye -> rye_name)); + else + PP_LOG (LLOG_EXCEPTIONS, ("Error %d", error)); + + return OK; +} + +/* */ + +static void ros_log (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/qmgr/submit_interface %s: %s", event, buffer)); +} + +/* */ + +static void acs_log (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", + AcErrString (aca -> aca_reason)); + + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/qmgr/submit_interface %s: %s (source %d)", event, buffer, + aca -> aca_source)); +} + +static int getresult (sd, id, delay) +int sd, id, delay; +{ + caddr_t out; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi->roi_preject; + + switch (RyWait (sd, &id, &out, delay, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + ros_log (rop, "RyWait Stub"); + if (ROS_FATAL (rop -> rop_reason)) { + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr-interface failed fatally")); + return NOTOK; + } + break; + case OK: + break; + + case DONE: + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr interface quit")); + return NOTOK; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("qmgr interface - bad response")); + return NOTOK; + } + return OK; +} diff --git a/Lib/table/Makefile b/Lib/table/Makefile new file mode 100644 index 0000000..dc07d50 --- /dev/null +++ b/Lib/table/Makefile @@ -0,0 +1,266 @@ +# Table & database lookup routines. +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/table/RCS/Makefile,v 6.0 1991/12/18 20:24:28 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:24:28 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ch_nm2struct.c tb_1148gate.c tb_checkauth.c tb_dbm.c tb_getalias.c \ + tb_getauth.c tb_getchan.c tb_getdl.c tb_getdomain.c tb_getlocal.c \ + tb_getuser.c tb_k2val.c tb_nm2struct.c tb_rtsparams.c +OBJS = ch_nm2struct.o tb_1148gate.o tb_checkauth.o tb_dbm.o tb_getalias.o \ + tb_getauth.o tb_getchan.o tb_getdl.o tb_getdomain.o tb_getlocal.o \ + tb_getuser.o tb_k2val.o tb_nm2struct.o tb_rtsparams.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = table-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: ${SHADOW} + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +install:; + +lintlib: llib-ltable.ln +llib-ltable.ln: ${SRCS} + $(LINT) -Ctable $(LLFLAGS) ${SRCS} + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +clean: tidy + rm -f ${OBJS} llib-ltable.ln + +tidy: + rm -f core ${SHADOW} *.old a.out *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +tb_dbm.o: tb_dbm.c + $(OLDCC) -c $(CFLAGS) tb_dbm.c + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ch_nm2struct.o: ch_nm2struct.c +ch_nm2struct.o: ../../h/util.h +ch_nm2struct.o: ../../h/config.h +ch_nm2struct.o: ../../h/ll_log.h +ch_nm2struct.o: ../../h/chan.h +ch_nm2struct.o: ../../h/table.h +ch_nm2struct.o: ../../h/list_bpt.h +ch_nm2struct.o: ../../h/list_bpt.h +tb_1148gate.o: tb_1148gate.c +tb_1148gate.o: ../../h/or.h +tb_1148gate.o: ../../h/util.h +tb_1148gate.o: ../../h/config.h +tb_1148gate.o: ../../h/ll_log.h +tb_1148gate.o: ../../h/table.h +tb_checkauth.o: tb_checkauth.c +tb_checkauth.o: ../../h/util.h +tb_checkauth.o: ../../h/config.h +tb_checkauth.o: ../../h/ll_log.h +tb_checkauth.o: ../../h/chan.h +tb_checkauth.o: ../../h/table.h +tb_checkauth.o: ../../h/list_bpt.h +tb_dbm.o: tb_dbm.c +tb_dbm.o: ../../h/head.h +tb_dbm.o: ../../h/util.h +tb_dbm.o: ../../h/config.h +tb_dbm.o: ../../h/ll_log.h +tb_dbm.o: ../../h/retcode.h +tb_dbm.o: ../../h/dbase.h +tb_dbm.o: ../../h/config.h +tb_dbm.o: ../../h/table.h +tb_dbm.o: ../../h/sys.file.h +tb_dbm.o: ../../h/util.h +tb_getalias.o: tb_getalias.c +tb_getalias.o: ../../h/util.h +tb_getalias.o: ../../h/config.h +tb_getalias.o: ../../h/ll_log.h +tb_getalias.o: ../../h/table.h +tb_getalias.o: ../../h/adr.h +tb_getalias.o: ../../h/list_rchan.h +tb_getalias.o: ../../h/chan.h +tb_getalias.o: ../../h/table.h +tb_getalias.o: ../../h/list_bpt.h +tb_getalias.o: ../../h/auth.h +tb_getalias.o: ../../h/list_bpt.h +tb_getalias.o: ../../h/extension.h +tb_getalias.o: ../../h/mta.h +tb_getalias.o: ../../h/adr.h +tb_getalias.o: ../../h/list_bpt.h +tb_getalias.o: ../../h/aparse.h +tb_getalias.o: ../../h/ap.h +tb_getalias.o: ../../h/util.h +tb_getalias.o: ../../h/or.h +tb_getalias.o: ../../h/chan.h +tb_getalias.o: ../../h/auth.h +tb_getalias.o: ../../h/list_rchan.h +tb_getalias.o: ../../h/alias.h +tb_getauth.o: tb_getauth.c +tb_getauth.o: ../../h/head.h +tb_getauth.o: ../../h/util.h +tb_getauth.o: ../../h/config.h +tb_getauth.o: ../../h/ll_log.h +tb_getauth.o: ../../h/retcode.h +tb_getauth.o: ../../h/util.h +tb_getauth.o: ../../h/chan.h +tb_getauth.o: ../../h/table.h +tb_getauth.o: ../../h/list_bpt.h +tb_getauth.o: ../../h/auth.h +tb_getauth.o: ../../h/list_bpt.h +tb_getauth.o: ../../h/list_rchan.h +tb_getauth.o: ../../h/chan.h +tb_getauth.o: ../../h/auth.h +tb_getauth.o: ../../h/adr.h +tb_getauth.o: ../../h/list_rchan.h +tb_getauth.o: ../../h/extension.h +tb_getauth.o: ../../h/mta.h +tb_getauth.o: ../../h/adr.h +tb_getauth.o: ../../h/list_bpt.h +tb_getauth.o: ../../h/aparse.h +tb_getauth.o: ../../h/ap.h +tb_getauth.o: ../../h/util.h +tb_getauth.o: ../../h/or.h +tb_getauth.o: ../../h/chan.h +tb_getauth.o: ../../h/auth.h +tb_getauth.o: ../../h/list_rchan.h +tb_getchan.o: tb_getchan.c +tb_getchan.o: ../../h/util.h +tb_getchan.o: ../../h/config.h +tb_getchan.o: ../../h/ll_log.h +tb_getchan.o: ../../h/list_rchan.h +tb_getchan.o: ../../h/chan.h +tb_getchan.o: ../../h/table.h +tb_getchan.o: ../../h/list_bpt.h +tb_getchan.o: ../../h/auth.h +tb_getchan.o: ../../h/list_bpt.h +tb_getdl.o: tb_getdl.c +tb_getdl.o: ../../h/util.h +tb_getdl.o: ../../h/config.h +tb_getdl.o: ../../h/ll_log.h +tb_getdl.o: ../../h/chan.h +tb_getdl.o: ../../h/table.h +tb_getdl.o: ../../h/list_bpt.h +tb_getdl.o: ../../h/table.h +tb_getdl.o: ../../h/dl.h +tb_getdl.o: ../../h/adr.h +tb_getdl.o: ../../h/list_rchan.h +tb_getdl.o: ../../h/chan.h +tb_getdl.o: ../../h/auth.h +tb_getdl.o: ../../h/list_bpt.h +tb_getdl.o: ../../h/extension.h +tb_getdl.o: ../../h/mta.h +tb_getdl.o: ../../h/adr.h +tb_getdl.o: ../../h/list_bpt.h +tb_getdl.o: ../../h/aparse.h +tb_getdl.o: ../../h/ap.h +tb_getdl.o: ../../h/util.h +tb_getdl.o: ../../h/or.h +tb_getdl.o: ../../h/chan.h +tb_getdl.o: ../../h/auth.h +tb_getdl.o: ../../h/list_rchan.h +tb_getdl.o: ../../h/retcode.h +tb_getdomain.o: tb_getdomain.c +tb_getdomain.o: ../../h/util.h +tb_getdomain.o: ../../h/config.h +tb_getdomain.o: ../../h/ll_log.h +tb_getdomain.o: ../../h/list_rchan.h +tb_getdomain.o: ../../h/chan.h +tb_getdomain.o: ../../h/table.h +tb_getdomain.o: ../../h/list_bpt.h +tb_getdomain.o: ../../h/auth.h +tb_getdomain.o: ../../h/list_bpt.h +tb_getlocal.o: tb_getlocal.c +tb_getlocal.o: ../../h/util.h +tb_getlocal.o: ../../h/config.h +tb_getlocal.o: ../../h/ll_log.h +tb_getlocal.o: ../../h/chan.h +tb_getlocal.o: ../../h/table.h +tb_getlocal.o: ../../h/list_bpt.h +tb_getlocal.o: ../../h/loc_user.h +tb_getuser.o: tb_getuser.c +tb_getuser.o: ../../h/util.h +tb_getuser.o: ../../h/config.h +tb_getuser.o: ../../h/ll_log.h +tb_getuser.o: ../../h/chan.h +tb_getuser.o: ../../h/table.h +tb_getuser.o: ../../h/list_bpt.h +tb_getuser.o: ../../h/list_rchan.h +tb_getuser.o: ../../h/chan.h +tb_getuser.o: ../../h/auth.h +tb_getuser.o: ../../h/list_bpt.h +tb_k2val.o: tb_k2val.c +tb_k2val.o: ../../h/util.h +tb_k2val.o: ../../h/config.h +tb_k2val.o: ../../h/ll_log.h +tb_k2val.o: ../../h/table.h +tb_nm2struct.o: tb_nm2struct.c +tb_nm2struct.o: ../../h/util.h +tb_nm2struct.o: ../../h/config.h +tb_nm2struct.o: ../../h/ll_log.h +tb_nm2struct.o: ../../h/table.h +tb_rtsparams.o: tb_rtsparams.c +tb_rtsparams.o: ../../h/util.h +tb_rtsparams.o: ../../h/config.h +tb_rtsparams.o: ../../h/ll_log.h +tb_rtsparams.o: ../../h/chan.h +tb_rtsparams.o: ../../h/table.h +tb_rtsparams.o: ../../h/list_bpt.h +tb_rtsparams.o: ../../h/rtsparams.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/table/ch_nm2struct.c b/Lib/table/ch_nm2struct.c new file mode 100644 index 0000000..91f67a9 --- /dev/null +++ b/Lib/table/ch_nm2struct.c @@ -0,0 +1,73 @@ +/* ch_nm2struct.c: convert channel name into structure */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/ch_nm2struct.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/ch_nm2struct.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: ch_nm2struct.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "list_bpt.h" + +extern char chrcnv[]; +#define LEXEQU(a,b) (chrcnv[(a)[0]] == chrcnv[(b)[0]] && lexequ((a),(b)) ==0) + +CHAN* ch_nm2struct (name) +register char *name; +{ + register CHAN **chp, *chan; + + if (ch_all == (CHAN **)0) + return (NULLCHAN); + + for (chp = ch_all; (chan = *chp) != NULLCHAN; chp++) + if (LEXEQU (name, chan->ch_name) || + (chan->ch_key && list_bpt_find (chan->ch_key, name) != NULLIST_BPT)) + return (chan); + return (NULLCHAN); +} + +CHAN *ch_mta2struct (name, mta) +register char *name; +char *mta; +{ + register CHAN **cpp, *chan; + CHAN *good_match = NULLCHAN; + /* not actually used just there cos needed */ + char *subdom = NULLCP, chan_key[BUFSIZ], normalised[BUFSIZ]; + + if (ch_all == (CHAN **)0) + return (NULLCHAN); + + for (cpp = ch_all; (chan = *cpp) != NULLCHAN; cpp++) { + if (! LEXEQU (name, chan->ch_name) && + list_bpt_find (chan -> ch_key, name) == NULLIST_BPT) + continue; + + if (chan -> ch_mta_table == NULL) + good_match = chan; + else if (mta && + tb_getdomain_table (chan -> ch_mta_table, + mta, chan_key, normalised, + chan -> ch_ad_order, &subdom) == OK) { + if (subdom) free(subdom); + return chan; + } + if (subdom) { + free(subdom); + subdom = NULLCP; + } + } + + return good_match; +} diff --git a/Lib/table/make b/Lib/table/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/table/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/table/tb_1148gate.c b/Lib/table/tb_1148gate.c new file mode 100644 index 0000000..078e3a5 --- /dev/null +++ b/Lib/table/tb_1148gate.c @@ -0,0 +1,65 @@ +/* tb_1148gate: look up domain in table of 1148 gateways */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_1148gate.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_1148gate.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_1148gate.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "or.h" +#include "util.h" +#include "table.h" + +static Table *tb_1148gateways = NULLTBL; +extern char *rfc1148gateway_tbl, *loc_or, or_error[]; + +int tb_get1148gate (domain, or) +char *domain; +OR_ptr *or; +{ + char *p, buf[LINESIZE]; + + PP_DBG (("Lib/tb_get1148gate (%s)", domain)); + + if (tb_1148gateways == NULLTBL) { + if ((tb_1148gateways = tb_nm2struct (rfc1148gateway_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, ("Lib/tb_get1148gate: rfc1148gateway table NULL!")); + return NOTOK; + } + } + + for (p = domain; *p != '\0';) { + if (tb_k2val (tb_1148gateways, p, buf, TRUE) == OK) + break; + p = index (p, '.'); + if (p == NULLCP) + break; + else + p++; + } + + + if (p == NULLCP || *p == '\0') { + (void) sprintf (or_error, + "Unable to find rfc1148 gateway for '%s'", + domain); + return NOTOK; + } + else { + *or = or_dmn2or (buf); + if (*or == NULLOR) + return or_lose ("format error '%s':'%s'", + p, buf); + } + + return OK; +} diff --git a/Lib/table/tb_checkauth.c b/Lib/table/tb_checkauth.c new file mode 100644 index 0000000..e280729 --- /dev/null +++ b/Lib/table/tb_checkauth.c @@ -0,0 +1,72 @@ +/* tb_checkauth.c: authentication checks for submission */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_checkauth.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_checkauth.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_checkauth.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" + +#define MAX_USER_ARGS 5 +#define MAX_USERIDS 50 + +extern char *crypt (); + +/* --------------------- Begin Routines -------------------------------- */ + +int tb_checkauth (key, channel, username, passwd) +char *key; +CHAN *channel; +char *username; +char *passwd; +{ + int argc, argc2; + char *argv [MAX_USER_ARGS], + *argv2[MAX_USERIDS], + buf [BUFSIZ]; + int i; + + PP_DBG (("Lib/tb_checkauth (%s, %s)", key, channel -> ch_name)); + + if (channel -> ch_auth_tbl == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Warning: Channel %s (%s) doesn't have an authentication table", + channel -> ch_name, channel -> ch_show)); + return OK; + } + + if (tb_k2val (channel -> ch_auth_tbl, key, buf, TRUE) == NOTOK) + return (NOTOK); + + if ((argc = sstr2arg (buf, MAX_USER_ARGS, argv, "|")) == NOTOK) + return (NOTOK); + + if (username && argc > 1) { + if ((argc2 = sstr2arg (argv[1], MAX_USERIDS, argv2, ",")) + == NOTOK) + return NOTOK; + + for (i = 0; i < argc2; i++) + if (lexequ (argv2[i], username) == 0) + return OK; + } + + if (passwd && argc > 2) { + if (strcmp (passwd, crypt (passwd, argv[2])) == 0) + return OK; + } + PP_LOG(LLOG_EXCEPTIONS, ("Username %s not allowed for %s on chan %s", + username, key, channel -> ch_name)); + return (NOTOK); +} diff --git a/Lib/table/tb_dbm.c b/Lib/table/tb_dbm.c new file mode 100644 index 0000000..641f4d4 --- /dev/null +++ b/Lib/table/tb_dbm.c @@ -0,0 +1,212 @@ +/* tb_dbm.c: table lookup routines ([n]dbm based) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_dbm.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_dbm.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_dbm.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "dbase.h" +#include "table.h" +#include "sys.file.h" + +extern char *ppdbm, *tbldfldir; +extern void getfpath (); +extern void err_abrt (); + +#ifndef GCC_DBM_OK + /* GCC_DBM_OK should be declared if you KNOW that your (n)dbm library + * returns structures in the same was as gcc exxpects them. + */ +# ifdef __GNUC__ +#ifdef sparc + #error GCC and sparc architecture dont get on very well with structures compile this file with cc +#endif + /* most pcc based compilers screw up the return of structures. + * They actually return a pointer to a static struct, which is copied. + * Here is a HACK to get such a pcc version of the library to work + * with the gnu structure returning convention. NB: need a cpp which + * allows recursive definitions (such as gcc) + */ +# ifdef NDBM +# ifndef dbm_fetch + # error You are using gcc with ndbm, but have not fixed + # error (or defined GCC_DBM_OK if the dbm library is OK asis) +# endif /* dbm_fetch */ +# else /* NDBM */ +# ifndef fetch + # error You are using gcc with dbm, but have not fixed + # error (or defined GCC_DBM_OK if the dbm library is OK asis) +# endif /* fetch */ +# endif /* NDBM */ +# endif /* __GNUC__ */ +#endif /* GCC_DBM_OK */ + + +/* --------------------- Begin Routines -------------------------------- */ + +static int tb_fetch (); + +/* -- find the value (address), given its key (hostname) -- */ + +int tb_dbmk2val (table, name, buf, first) +register Table *table; +char name[], /* -- name of ch "member" / key -- */ + *buf; /* -- put value in this buffer -- */ +int first; +{ + static Dbvalue dbm; + static Dbptr dp = NULL; + register char *cp; + + if (first) { + if (tb_fetch (name, dbm)) + dp = dbm; + else dp = NULL; + } + else if (dp) + dp ++; + + for (; dp && (cp = dp->db_table) != NULLCP; dp++) { + if (lexequ (cp, table -> tb_name) != 0) + continue; + if (buf != 0) { + if (dp->db_value == NULL) + *buf = '\0'; + else + (void) strcpy (buf, dp->db_value); + } + return (OK); + } + if (buf != 0) + (void) strcpy (buf, " (ERROR)"); + + return (NOTOK); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int tb_fetch (name, dbm) +char *name; /* -- use this key to fetch entry -- */ +Dbvalue dbm; /* -- put the entry here -- */ +{ + static char dbvalue[ENTRYSIZE]; + register Dbptr dp; + datum key, + value; + register char *p, + *cp; + int cnt; + +#ifdef GDBM + static GDBM_FILE thedb; +#else +#ifdef NDBM + static DBM *thedb; +#else + static int savedirf, savepagf; + int tdirf, tpagf; +#endif +#endif + static int dbmopen = FALSE; + + + if (dbmopen == FALSE) { + char filename [BUFSIZ]; + + getfpath (tbldfldir, ppdbm, filename); + +#ifdef GDBM + (void) strcat (filename, ".gdbm"); + if ((thedb = gdbm_open (filename, 0, GDBM_READER, 0, NULL)) == NULL) + err_abrt (RP_FIO, "Error opening database '%s`", + filename); +#else +#ifdef NDBM + if ((thedb = dbm_open (filename, O_RDONLY, 0)) == NULL) + err_abrt (RP_FIO, + "Error opening database '%s'", filename); +#else + if (dbminit (filename) < 0) + err_abrt (RP_FIO, + "Error opening database '%s'", filename); + savedirf = dirf; + savepagf = pagf; +#endif +#endif + dbmopen = TRUE; + } + + + key.dptr = dbvalue; + key.dsize = strlen (name) + 1; + for (cp = dbvalue, p = name; *p; p++) + *cp++ = uptolow (*p); + *cp = 0; + + +#ifdef GDBM + value = gdbm_fetch (thedb, key); +#else +#ifdef NDBM + value = dbm_fetch (thedb, key); +#else + tpagf = pagf; tdirf = dirf; + pagf = savepagf; dirf = savedirf; + value = fetch (key); + pagf = tpagf; dirf = tdirf; +#endif +#endif + + + if (value.dptr == NULL +#ifdef NDBM + || dbm_error (thedb) +#endif NDBM + ) + { +#ifdef NDBM + dbm_clearerr (thedb); +#endif NDBM + + PP_DBG (("Lib/tb_fetch/FALSE (%s, %d)", + key.dptr, key.dsize)); + return (FALSE); + } + + + + (void) strcpy (dbvalue, value.dptr); + + cnt = MAXDBENTRIES-1; + for (p = dbvalue, dp = dbm; *p && cnt ; cnt--, dp++) { + for (dp->db_table = p ; *p ; p++) + if (*p == ' ') { /* get table name */ + *p++ = '\0'; + break; + } + for (dp->db_value = (*p ? p : NULL); *p; p++) + if (*p == FS) { /* get value-part */ + *p++ = '\0'; + break; + } + } + for (; cnt ; cnt--, dp++) + dp->db_table = dp->db_value = NULL; + + return (TRUE); +} diff --git a/Lib/table/tb_getalias.c b/Lib/table/tb_getalias.c new file mode 100644 index 0000000..3ec5c81 --- /dev/null +++ b/Lib/table/tb_getalias.c @@ -0,0 +1,126 @@ +/* tb_getalias.c: grab an alias */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getalias.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getalias.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getalias.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "table.h" +#include "adr.h" +#include "alias.h" + + +#define MAX_ALIAS_ARGS 10 + + +static CMD_TABLE aliastbl_type[] = { + "synonym", ALIAS_SYNONYM, + "alias", ALIAS_PROPER, + 0, -1 + }; + +static CMD_TABLE aliastbl_qual[] = { + "822", AD_822_TYPE, + "x400", AD_X400_TYPE, + "external", ALIAS_EXTERNAL, + 0, -1 + }; + + + +/* --------------------- Begin Routines -------------------------------- */ + + +/* +This routine returns the values: + NOTOK - Table or routine error. + OK - Alias found in Table + DONE - Alias not found in Table (- alias is a proper user name) +*/ + +extern char *alias_tbl; + +int tb_getalias (key, alias, subdom) +char *key; +ALIAS *alias; +char *subdom; +{ + + char *argv [MAX_ALIAS_ARGS], + buf [BUFSIZ], tblname[MAXPATHLENGTH]; + int argc, i, qual; + Table *Alias = NULLTBL; + + + if (subdom == NULLCP || *subdom == '\0') + (void) sprintf(tblname,"%s", alias_tbl); + else + (void) sprintf(tblname,"%s-%s", subdom, alias_tbl); + + PP_DBG (("Lib/tb_getalias (%s)", tblname)); + + + if ((Alias = tb_nm2struct (tblname)) == NULLTBL) { + PP_OPER (NULLCP, ("Lib/tb_getalias (no table '%s')",tblname)); + return (NOTOK); + } + + if (tb_k2val (Alias, key, buf, TRUE) == NOTOK) + return (DONE); + + + /* -- get alias arguments -- */ + + if ((argc = sstr2arg (buf, MAX_ALIAS_ARGS, argv, "\t ")) == NOTOK) + return (NOTOK); + + + switch (alias->alias_type = cmd_srch (argv[0], aliastbl_type)) { + case ALIAS_SYNONYM: + case ALIAS_PROPER: + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getalias (err type=%d)", alias->alias_type)); + return (NOTOK); + } + + + (void) strcpy (&alias->alias_user[0], argv[1]); + + alias->alias_external = 0; + alias->alias_ad_type = AD_ANY_TYPE; + + for (i = 2; i < argc; i++) { + if (!isstr(argv[i])) + continue; + switch ((qual = cmd_srch (argv[i], aliastbl_qual))) { + case AD_X400_TYPE: + case AD_822_TYPE: + alias->alias_ad_type = qual; + break; + case ALIAS_EXTERNAL: + alias->alias_external = qual; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getalias unknown qualifier '%s'", + argv[i])); + return (NOTOK); + + } + } + return (OK); +} diff --git a/Lib/table/tb_getauth.c b/Lib/table/tb_getauth.c new file mode 100644 index 0000000..cd6fa53 --- /dev/null +++ b/Lib/table/tb_getauth.c @@ -0,0 +1,604 @@ +/* tb_getauth.c: retrieve authorisation information */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getauth.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getauth.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getauth.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "chan.h" +#include "auth.h" +#include "list_rchan.h" +#include "adr.h" +#include + + + +/* -- statics -- */ +static Table *Chan_auth = NULLTBL; +static Table *Mta_auth = NULLTBL; +static Table *User_auth = NULLTBL; + + + +/* -- command tables -- */ + +static CMD_TABLE authtbl_chan[] = { + "free", AUTH_CHAN_FREE, + "negative", AUTH_CHAN_NEGATIVE, + "block", AUTH_CHAN_BLOCK, + "none", AUTH_CHAN_NONE, + "warnsender", AUTH_CHAN_WARNS, + "warnrecipient", AUTH_CHAN_WARNR, + "sizelimit", AUTH_CHAN_SIZELIMIT, + "test", AUTH_CHAN_TEST, + 0, -1 + }; + + + +#define AUTH_MTA_DEFAULT 1 +#define AUTH_MTA_REQUIRES 2 +#define AUTH_MTA_EXCLUDES 3 +#define AUTH_MTA_CONTENTEX 4 +#define AUTH_MTA_SIZELIMIT 5 + +static CMD_TABLE authtbl_mta[] = { + "default", AUTH_MTA_DEFAULT, + "requires", AUTH_MTA_REQUIRES, + "excludes", AUTH_MTA_EXCLUDES, + "content-excludes", AUTH_MTA_CONTENTEX, + "bodypart-excludes", AUTH_MTA_CONTENTEX, + "sizelimit", AUTH_MTA_SIZELIMIT, + 0, -1 + }; + + + +#define AUTH_USER_DEFAULT 1 +#define AUTH_USER_CONTENTEX 2 +#define AUTH_USER_SIZELIMIT 3 + +static CMD_TABLE authtbl_user[] = { + "default", AUTH_USER_DEFAULT, + "content-excludes", AUTH_USER_CONTENTEX, + "bodypart-excludes", AUTH_USER_CONTENTEX, + "sizelimit", AUTH_USER_SIZELIMIT, + 0, -1 + }; + + + +CMD_TABLE authtbl_rights[] = { /* NOT static - used in auth.c */ + "in", AUTH_RIGHTS_IN, + "out", AUTH_RIGHTS_OUT, + "both", AUTH_RIGHTS_BOTH, + "none", AUTH_RIGHTS_NONE, + "unset", AUTH_RIGHTS_UNSET, + 0, -1 + }; + + +extern CHAN *ch_inbound; /* -- chan calling submit -- */ +extern char *chan_auth_tbl; +extern char *mta_auth_tbl; +extern char *user_auth_tbl; +extern char *ad_getlocal(); +extern long atol (); + + +/* -- local routines */ +int tb_getauthchan(); +int tb_getauthmta(); +int tb_getauthusr(); +void tb_parse_authchan(); + +static LIST_CHAN_RIGHTS *list_chan_rights_new(); +static LIST_REGEX *list_regex_new(); +static int tb_authrights(); +static void add_cont_excludes(); +static void add_chanrights(); +static void add_regex(); +static void list_chan_rights_add(); +static void list_regex_add(); +static void tb_getauthchan_aux(); +static void tb_parse_authmta(); + + + + +/* --------------------- Begin Routines ------------------------------------ */ + + + + +int tb_getauthchan (ochan) +LIST_AUTH_CHAN *ochan; +{ + char key[MAXPATHLENGTH]; + + + ochan -> li_found = FALSE; + + if (Chan_auth == NULLTBL) + if ((Chan_auth = tb_nm2struct (chan_auth_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getauthchan missing %s", + chan_auth_tbl)); + return OK; + } + + + (void) sprintf (key, "%s->%s", + ch_inbound -> ch_name, ochan -> li_chan -> ch_name); + (void) tb_getauthchan_aux (key, ochan); + if (ochan -> li_found == TRUE) return OK; + + + (void) sprintf (key, "%s->*", ch_inbound -> ch_name); + (void) tb_getauthchan_aux (key, ochan); + if (ochan -> li_found == TRUE) return OK; + + + (void) sprintf (key, "*->%s", ochan -> li_chan -> ch_name); + (void) tb_getauthchan_aux (key, ochan); + + return OK; +} + + + + +void tb_parse_authchan (c, argc, argv) +LIST_AUTH_CHAN *c; +int argc; +char **argv; +{ + int i, retval; + char *p; + + for (i = 0; i < argc; i++) { + if (!isstr(argv[i])) + continue; + if ((p = index (argv[i], '=')) == NULLCP) { + + PP_DBG (("Lib/tb_parse_authchan %s", argv[i])); + + switch (retval = cmd_srch (argv[i], authtbl_chan)) { + case AUTH_CHAN_FREE: + c -> policy = AUTH_CHAN_FREE; + break; + case AUTH_CHAN_NEGATIVE: + c -> policy = AUTH_CHAN_NEGATIVE; + break; + case AUTH_CHAN_BLOCK: + c -> policy = AUTH_CHAN_BLOCK; + break; + case AUTH_CHAN_NONE: + c -> policy = AUTH_CHAN_NONE; + break; + case AUTH_CHAN_TEST: + c -> test = AUTH_CHAN_TEST; + break; + default: + PP_OPER (NULLCP, + ("Lib/tb_parse_authchan error %d %s", + retval, argv[i])); + break; + } + } + else { + *p++ = '\0'; + PP_DBG (("Lib/tb_parse_authchan %s = %s", argv[i], p)); + + switch (retval = cmd_srch (argv[i], authtbl_chan)) { + case AUTH_CHAN_WARNS: + c -> warnsender = strdup (p); + break; + case AUTH_CHAN_WARNR: + c -> warnrecipient = strdup (p); + break; + case AUTH_CHAN_SIZELIMIT: + c -> sizelimit = atol (p); + break; + default: + PP_OPER(NULLCP, + ("Lib/tb_parse_authchan error %d %s %s", + retval, argv[i], p)); + break; + } + } + } +} + + + + +int tb_getauthmta (omta) +LIST_AUTH_MTA *omta; +{ + char *argv [MAX_AUTH_ARGS]; + char buf[BUFSIZ]; + int argc; + + PP_DBG (("Lib/tb_getauthmta (%s)", omta -> li_mta)); + + omta -> li_found = FALSE; + + if (Mta_auth == NULLTBL) + if ((Mta_auth = tb_nm2struct (mta_auth_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getauthmta missing %s", + mta_auth_tbl)); + return OK; + } + + if (tb_k2val (Mta_auth, omta -> li_mta, buf, TRUE) == NOTOK) + return OK; + + if ((argc = sstr2arg (buf, MAX_AUTH_ARGS, argv, " \t,")) == NOTOK) + return OK; + + omta -> li_found = TRUE; + + (void) tb_parse_authmta (omta, argc, argv); + return OK; +} + + + + +int tb_getauthusr (ousr, ad) +AUTH_USER *ousr; +ADDR *ad; +{ + char *argv [MAX_AUTH_ARGS]; + char buf[BUFSIZ]; + char *p, *uname; + int argc, i, rights, retval = RP_BAD, found; + CHAN *c; + + + ousr -> found = FALSE; + + if (User_auth == NULLTBL) + if ((User_auth = tb_nm2struct (user_auth_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getauthusr missing %s", + user_auth_tbl)); + return OK; + } + + found = FALSE; + + if (ad->aparse) { + if (found == FALSE + && ad->aparse->r822_str) { + if (tb_k2val (User_auth, + ad->aparse->r822_str, + buf, TRUE) != NOTOK) { + uname = ad->aparse->r822_str; + found = TRUE; + } + } + if (found == FALSE + && ad->aparse->r822_local) { + if (tb_k2val (User_auth, + ad->aparse->r822_local, + buf, TRUE) != NOTOK) { + uname = ad->aparse->r822_local; + found = TRUE; + } + } + if (found == FALSE + && ad->aparse->x400_str) { + if (tb_k2val (User_auth, + ad->aparse->x400_str, + buf, TRUE) != NOTOK) { + uname = ad->aparse->x400_str; + found = TRUE; + } + } + if (found == FALSE + && ad->aparse->x400_local) { + if (tb_k2val (User_auth, + ad->aparse->x400_local, + buf, TRUE) != NOTOK) { + uname = ad->aparse->x400_local; + found = TRUE; + } + } + } + if (found == FALSE) { + PP_TRACE(("no authorisation entry found for user '%s'", + ad->ad_value)); + return OK; + } + + PP_DBG (("Lib/tb_getauthusr (%s, '%s')", uname, buf)); + + + if ((argc = sstr2arg (buf, MAX_AUTH_ARGS, argv, " \t,")) == NOTOK) + return OK; + + ousr -> found = TRUE; + + + for (i = 0; i < argc; i++) { + if (!isstr(argv[i])) + continue; + + if ((p = index (argv[i], '=')) == NULLCP) { + PP_OPER(NULLCP, + ("Lib/tb_getauthusr error %d %s", + retval, argv[i])); + return NOTOK; + + } + + /* -- all of form xxx=yyy -- */ + *p++ = '\0'; + + PP_DBG (("Lib/tb_getauthusr %s = %s", argv[i], p)); + + switch (retval = cmd_srch (argv[i], authtbl_user)) { + case AUTH_USER_DEFAULT: + if ((rights = tb_authrights (p)) != NOTOK) + ousr -> rights = rights; + break; + case AUTH_USER_CONTENTEX: + add_cont_excludes (&ousr -> content_excludes, + p); + break; + case AUTH_USER_SIZELIMIT: + ousr -> sizelimit = atol (p); + break; + + default: + if ((rights = tb_authrights (p)) != NOTOK) + if ((c = ch_nm2struct (argv[i])) != NULLCHAN) + add_chanrights (&ousr -> li_cr, + c, rights); + break; + } + } + + return OK; +} + + + + +/* --------------------- Static Routines ----------------------------------- */ + + + + +static void tb_getauthchan_aux (str, ochan) +char *str; +LIST_AUTH_CHAN *ochan; +{ + int argc; + char *argv[MAX_AUTH_ARGS]; + char buf[BUFSIZ]; + + PP_DBG (("Lib/tb_getauthchan_aux: try key %s", str)); + + if (tb_k2val (Chan_auth, str, buf, TRUE) == NOTOK) + return; + + if ((argc = sstr2arg (buf, MAX_AUTH_ARGS, argv, " \t,")) == NOTOK) + return; + + ochan -> li_found = TRUE; + (void) tb_parse_authchan (ochan, argc, argv); + + return; +} + + + + +static void tb_parse_authmta (omta, argc, argv) +LIST_AUTH_MTA *omta; +int argc; +char **argv; +{ + int i, retval = NOTOK, rights; + char *p; + CHAN *c; + + for (i = 0; i < argc; i++) { + if (!isstr(argv[i])) + continue; + + if ((p = index (argv[i], '=')) == NULLCP) { + PP_OPER(NULLCP, + ("Lib/tb_parse_authchan error %d %s", + retval, argv[i])); + return; + } + + + /* -- all of form xxx=yyy -- */ + + *p++ = '\0'; + + PP_DBG (("Lib/tb_getauthmta %s = %s", argv[i], p)); + + switch (retval = cmd_srch (argv[i], authtbl_mta)) { + + case AUTH_MTA_DEFAULT: + if ((rights = tb_authrights (p)) != NOTOK) + omta -> rights = rights; + break; + case AUTH_MTA_REQUIRES: + add_regex (&omta -> requires, p); + break; + case AUTH_MTA_EXCLUDES: + add_regex (&omta -> excludes, p); + break; + case AUTH_MTA_CONTENTEX: + add_cont_excludes (&omta -> content_excludes, + p); + break; + case AUTH_MTA_SIZELIMIT: + omta -> sizelimit = atol (p); + break; + + default: + if ((rights = tb_authrights (p)) != NOTOK) + if ((c = ch_nm2struct (argv[i])) != NULLCHAN) + add_chanrights (&omta -> li_cr, + c, rights); + break; + } + } +} + + + + +static int tb_authrights (cp) +char *cp; +{ + int retval; + + retval = cmd_srch (cp, authtbl_rights); + + if (retval == NOTOK) + PP_LOG (LLOG_NOTICE, ("Lib/tb_authrights not known <%s>", cp)); + + PP_DBG (("Lib/tb_authrights for %s returns %d", cp, retval)); + return retval; +} + + + + +static void add_regex (lp, str) +LIST_REGEX **lp; +char *str; /* 1 or more regular expressions */ +{ + char *cp; + + + while (str) { + cp = str; + if (str = index (str, AUTH_SEPERATOR)) + *str++ = '\0'; + list_regex_add (lp, list_regex_new (cp)); + } +} + + + + +static void list_regex_add (list, item) +LIST_REGEX **list; +LIST_REGEX *item; +{ + LIST_REGEX *lp = *list; + + if (lp == NULLIST_REGEX) { + *list = item; + return; + } + + while (lp -> li_next != NULLIST_REGEX) + lp = lp -> li_next; + lp -> li_next = item; +} + + + +static LIST_REGEX *list_regex_new (value) +char *value; +{ + LIST_REGEX *lp; + + if (value == NULLCP) return (NULLIST_REGEX); + + lp = (LIST_REGEX *) malloc (sizeof *lp); + bzero ((char *)lp, sizeof *lp); + lp -> li_regex = strdup (value); + + return (lp); +} + + + + +static void add_cont_excludes (lp, str) +LIST_BPT **lp; +char *str; +{ + char *cp; + + while (str) { + cp = str; + if ((str = index (str, AUTH_SEPERATOR))) + *str++ = '\0'; + list_bpt_add (lp, list_bpt_new (cp)); + } +} + + + + +static void add_chanrights (list, chan, rights) +LIST_CHAN_RIGHTS **list; +CHAN *chan; +int rights; +{ + list_chan_rights_add (list, list_chan_rights_new (chan, rights)); +} + + + + +static void list_chan_rights_add (list, item) +LIST_CHAN_RIGHTS **list; +LIST_CHAN_RIGHTS *item; +{ + LIST_CHAN_RIGHTS *lp = *list; + + if (lp == NULLIST_CHAN_RIGHTS) { + *list = item; + return; + } + + while (lp -> li_next != NULLIST_CHAN_RIGHTS) + lp = lp -> li_next; + lp -> li_next = item; +} + + + +static LIST_CHAN_RIGHTS *list_chan_rights_new (chan, rights) +CHAN *chan; +int rights; +{ + LIST_CHAN_RIGHTS *lp; + + if (chan == NULLCHAN) return (NULLIST_CHAN_RIGHTS); + + lp = (LIST_CHAN_RIGHTS *) malloc (sizeof *lp); + bzero ((char *)lp, sizeof *lp); + lp -> li_rights = AUTH_RIGHTS_UNSET; + lp -> li_chan = chan; + lp -> li_rights = rights; + + return (lp); +} diff --git a/Lib/table/tb_getchan.c b/Lib/table/tb_getchan.c new file mode 100644 index 0000000..291b7d2 --- /dev/null +++ b/Lib/table/tb_getchan.c @@ -0,0 +1,175 @@ +/* tb_getchan.c - maps a Next Hop hostname into its outgoing channel pairs */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getchan.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getchan.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getchan.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "list_rchan.h" + + + +static Table *Channel = NULLTBL; +static int CH_str2rchan (); +static int CH_doparse (); + +/* --------------------- Begin Routines --------------------------------- */ + + + + +/* --- *** Start Description *** --- + +tb_getchan (key, rp) + char *key; + LIST_RCHAN **rp; + +Parameters required: + - The Next Hop hostname (key) + - A pointer to the list of channel pairs used to get to the + Next Hop hostname (rp) + +Example: + key = torch.co.uk + rp = li_mta = ukc.ac.uk li_chan = JANET + li_mta = stl.stc.co.uk li_chan = PSS + +Routine: + - Reads the channel table + - Updates rp + - Returns OK or NOTOK. + + +Note: + - This routine always fills in ad_outchan with hostnames in US order. + + +--- *** End Description *** --- */ + + + + +/* ------------------------------------------------------------------------ */ + + +extern char *channel_tbl; + +int tb_getchan (key, rp) +char *key; +LIST_RCHAN **rp; +{ + char tbuf[BUFSIZ]; + + PP_DBG (("Lib/table/tb_getchan ('%s')", key)); + + if (Channel == NULLTBL) + if ((Channel = tb_nm2struct (channel_tbl)) == NULLTBL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getchan channel table not found")); + return NOTOK ; + } + + if (tb_k2val (Channel, key, tbuf, TRUE) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getchan key '%s' not found.POSSIBLE INTERNAL INCONSISTENCY BETWEEN TABLES", key)); + return NOTOK ; + } + + if (*rp != NULLIST_RCHAN) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/tb_getchan list is already set!")); + return NOTOK ; + } + + /* -- free all memory -- */ + if (CH_str2rchan (rp, tbuf) == NOTOK) { + PP_DBG (("Lib/table/tb_getchan free list!")); + list_rchan_free (*rp); + *rp = NULLIST_RCHAN; + return NOTOK ; + } + + return OK; +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int CH_str2rchan (rp, str) +LIST_RCHAN **rp; +char *str; +{ + LIST_RCHAN *list; + char *host = NULLCP, + *chan = NULLCP, + *next = NULLCP; + int retval; + + + PP_DBG (("Lib/table/CH_str2rchan ('%s')", str)); + + *rp = NULLIST_RCHAN; + + while ((retval = CH_doparse (str, &host, &chan, &next)) == OK) { + if ((list = list_rchan_new(host, chan)) != NULLIST_RCHAN) + list_rchan_add (rp, list); + + if (next) + str = next; + else + break; + } + + if (retval == NOTOK || *rp == NULLIST_RCHAN) + return NOTOK; + return OK; +} + + + +static int CH_doparse (str, host, chan, next) +char *str; +char **host; +char **chan; +char **next; +{ + char *cp; + + PP_DBG (("Lib/table/CH_doparse ('%s')", str)); + + if ((cp = index (str, ',')) == NULLCP) + *next = NULLCP; + else + *next = ++cp; + + *host = str; + if ((cp = index (str, '(')) == NULLCP) + return NOTOK; + if (*host == cp) + *host = NULLCP; + else + *cp = '\0'; + cp++; + *chan = cp; + + if ((cp = index (*chan, ')')) == NULLCP) + return NOTOK; + *cp = '\0'; + + return OK; +} diff --git a/Lib/table/tb_getdl.c b/Lib/table/tb_getdl.c new file mode 100644 index 0000000..5badbbf --- /dev/null +++ b/Lib/table/tb_getdl.c @@ -0,0 +1,328 @@ +/* tb_getdl.c: expand a distribution list */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getdl.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getdl.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getdl.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "table.h" +#include "dl.h" +#include "adr.h" +#include "retcode.h" +#include + +ADDR *tb_getModerator(); +static Table *List = NULLTBL; +static Name *getNames(); +static Name *getNamesFromFile(); +Name *new_Name(); +extern char *compress (); +/* +This routine returns the values: + NOTOK - Table or routine erroe. + OK - List found in Table + DONE - temporary error ? +*/ +char *namefile; + +extern char *list_tbl; + +tb_getdl (key, plist,complain) +char *key; +dl **plist; +int complain; +{ + char buf[BUFSIZ], + *ix, + *start, + mod[MAXPATHLENGTH], + *str; + int retval = OK; + ADDR *adr; + + namefile = NULLCP; + *plist = NULL; + PP_DBG(("tb_getdl (%s)", key)); + + if (List == NULLTBL) + if ((List = tb_nm2struct(list_tbl)) == NULLTBL) { + PP_LOG(LLOG_EXCEPTIONS, ("tb_getdl (no table)")); + return DONE; + } + + if (tb_k2val (List, key, buf, TRUE) == NOTOK) { + if (complain == OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to find entry for %s in list table %s", + key, list_tbl)); + return DONE; + } + return NOTOK; + } + + *plist = (dl *) calloc(1, sizeof(dl)); + (*plist) -> dl_listname = strdup(key); + + start = &(buf[0]); + if ((adr = tb_getModerator(key)) == NULLADDR) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to get moderator for dl '%s'",key)); + retval = DONE; + } else { + (*plist) -> dl_moderator = strdup(adr->ad_value); + adr_free(adr); + } + if ((ix = index(start, ',')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("tb_getdl syntax error for '%s' : listname:[uids],...", key)); + retval = DONE; + } else { + *ix = '\0'; + (void) compress(start,mod); + if (mod[0] != '\0') + (*plist)->dl_uids = getNames(mod, &retval); + else + (*plist)->dl_uids = NULL; + } + + start = ix+1; + if (retval == OK) { + str = start; + ix = index(str, ','); + if (ix != NULL) + *ix++ = '\0'; + (*plist) -> dl_desc = ix; + (*plist) -> dl_list = getNames(str, &retval); + (*plist) -> dl_file = namefile; + } + + return retval; +} + +Name *new_Name(str, file) +char *str; +char *file; +{ + Name *ret = (Name *) calloc(1, sizeof(Name)); + + ret -> name = strdup(str); + if (file) + ret -> file = strdup(file); + return ret; +} + +static Name *getNames(str, pretval) +char *str; +int *pretval; +{ + Name *head = NULL, + *tail = NULL, + *temp = NULL; + char *ix, *start; + + while ((ix = index(str,'|')) != NULL) { + *ix = NULL; + start = str; + while (isspace(*start)) start++; + + if (strncmp(start,"file=",strlen("file=")) == 0) + temp = getNamesFromFile(start, pretval); + else + temp = new_Name(start, NULLCP); + if (head == NULL) + head = tail = temp; + else + tail -> next = temp; + while (tail -> next != NULL) + tail = tail->next; + str = ix + 1; + } + + start = str; + while (isspace(*start)) start++; + + if (strcmp(start,"") != 0) { + if (strncmp(start,"file=",strlen("file=")) == 0) + temp = getNamesFromFile(start,pretval); + else + temp = new_Name(start,NULLCP); + if (head == NULL) + head = tail = temp; + else + tail -> next = temp; + } + return head; +} + +extern char *loc_dist_prefix; + +ADDR *tb_getModerator(list) +char *list; +{ + char moderator[LINESIZE], + *ix; + ADDR *adr; + RP_Buf rp; + extern char *getpostmaster(); + + if ((ix = index(list, '@')) != NULL) + *ix = '\0'; + + if (strncmp(list, loc_dist_prefix, strlen(loc_dist_prefix)) == 0) { + /* attempt to strip of loc_dist_prefix to find moderator */ + (void) sprintf(moderator, + "%s-request", + (list+strlen(loc_dist_prefix))); + adr = adr_new (moderator, AD_822_TYPE, 0); + adr -> ad_resp = NO; +#ifdef UKORDER + if (!rp_isbad(ad_parse(adr, &rp, CH_UK_PREF))) { +#else + if (!rp_isbad(ad_parse(adr, &rp, CH_USA_PREF))) { +#endif + if (ix != NULL) *ix = '@'; + return adr; + } + adr_free(adr); + } + + (void) sprintf(moderator,"%s-request",list); + adr = adr_new (moderator, AD_822_TYPE, 0); + adr -> ad_resp = NO; +#ifdef UKORDER + if (!rp_isbad(ad_parse(adr, &rp, CH_UK_PREF))) +#else + if (!rp_isbad(ad_parse(adr, &rp, CH_USA_PREF))) +#endif + return adr; + adr_free(adr); + + adr = adr_new ((ix = getpostmaster(AD_822_TYPE)), + AD_822_TYPE, 0); + adr -> ad_resp = NO; +#ifdef UKORDER + if (rp_isbad(ad_parse(adr, &rp, CH_UK_PREF))) { +#else + if (rp_isbad(ad_parse(adr, &rp, CH_UK_PREF))) { +#endif + PP_OPER(NULLCP, + ("Failed to parse postmaster '%s' [%s]", + ix, adr->ad_parse_message)); + adr_free(adr); + return NULLADDR; + } + return adr; +} + +static Name *getNamesFromFile(file,pretval) +char *file; +int *pretval; +{ + Name *head = NULL, + *tail = NULL, + *temp; + char entry[LINESIZE], + fullname[MAXPATHLENGTH], + *ix; + struct stat statbuf; + extern char *tbldfldir; + FILE *fd; + int len; + + if ((ix = index(file,'=')) == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("error in parsing '%s'",file)); + return NULL; + } + ix++; + (void) compress(ix,ix); + + if (ix[0] != '/') + (void) sprintf(fullname, "%s/%s", tbldfldir, ix); + else + (void) sprintf(fullname, "%s", ix); + + if (namefile == NULLCP) namefile = strdup(fullname); + + + if (stat (fullname, &statbuf) != OK) { + PP_OPER(fullname, ("unable to stat file")); + *pretval = DONE; + return NULL; + } + + if ((statbuf.st_mode & S_IFMT) != S_IFREG) { + PP_OPER(fullname, ("Not a regular file")); + *pretval = DONE; + return NULL; + } + + if ((fd = fopen(fullname,"r")) == NULL) { + PP_OPER(fullname, ("Can't open file")); + *pretval = DONE; + return NULL; + } + + while (fgets(entry, LINESIZE, fd) != NULL) { + (void) compress(entry, entry); + if (entry[0] == '\n' || entry[0] == '#' || entry[0] == '\0') + continue; + + len = strlen(entry); + if (entry[len-1] == '\n') entry[len-1] = '\0'; + temp = new_Name(entry, fullname); + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = temp; + } + } + (void) fclose(fd); + return head; +} + +name_free(list) +Name *list; +{ + if (list == NULL) + return; + if (list -> next) + name_free(list -> next); + if (list -> name) + free(list -> name); + if (list -> file) + free(list->file); + + free((char *) list); +} + +dl_free(list) +dl *list; +{ + if (list == NULLDL) + return; + if (list -> dl_listname) + free(list -> dl_listname); + if (list -> dl_moderator) + free(list -> dl_moderator); + if (list -> dl_uids) + name_free(list -> dl_uids); + if (list -> dl_list) + name_free(list -> dl_list); + if (list -> dl_file) + free(list -> dl_file); + free((char *) list); +} diff --git a/Lib/table/tb_getdomain.c b/Lib/table/tb_getdomain.c new file mode 100644 index 0000000..df0f29f --- /dev/null +++ b/Lib/table/tb_getdomain.c @@ -0,0 +1,687 @@ +/* +tb_getdomain.c - maps an alias domain into a normalised one and optionally, + maps a normalised domain into its next hop out. +*/ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getdomain.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getdomain.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getdomain.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "list_rchan.h" +#include + +#define MASK_PREFBIT 1 +char *bits2str(); +int str2bits(); +static int scorebits(); +static int dom_lookup (); +static int fillin_results(); + + +/* --------------------- Begin Routines --------------------------------- */ + + + +/* --- *** Start Description *** --- + +tb_getdomain (dom_key, chan_key, normalised, order_pref, ppsubdom) + + dom_key - Could be either an Alias, NRS Short from, + or a Normalised domain name. + chan_key - The Next Hop hostname. This is used + as a key to the channel table. + normalised - Normalised version of (dom_key) + order_pref - UK only, USA only, UK pref, USA pref. + ppsubdom - is this a sub domain - if so which + +Example: + dom_key = blah.torch.co + chan_key = torch.co.uk + normalised = blah.torch.co.uk + order_pref = CH_UK_PREF + +Routine: + - Reads the domain table + - Updates normalised. + - Optionally updates chan_key if ptr given. + - Returns OK or NOTOK. + +Note: + - This Routine always returns the char* normalised in USA order + +--- *** End Description *** --- */ + + + +/* ------------------------------------------------------------------------ */ + +static int loopCount; /* stop infinite recursion for synonyms */ +#define MAXLOOPS 10 + +static int hitTable; +/* */ +/* interface for general parsing */ + +int tb_getdomain (dom_key, chan_key, normalised, order_pref, ppsubdom) +char *dom_key; +char *chan_key; +char *normalised; +int order_pref; +char **ppsubdom; +{ + Table *Domain; + int retval; + + if ((Domain = tb_nm2struct ("domain")) == NULLTBL) { + PP_LOG (LLOG_FATAL, + ("No table 'domain' defined")); + return (NOTOK); + } + + hitTable = FALSE; + loopCount = 0; + if ((retval = tb_getdomain_aux(Domain, dom_key, order_pref, + chan_key, normalised, + ppsubdom)) == NOTOK + && hitTable == FALSE) + /* try for default */ + if ((retval = tb_getdomain_aux(Domain, "*", order_pref, + chan_key, normalised, + ppsubdom)) == OK) { + (void) strcpy(normalised, dom_key); + PP_NOTICE(("Using default route for '%s'", + dom_key)); + } + return retval; +} + +/* */ +/* interface for mtatable identification */ + +int tb_getdomain_table (table, dom_key, chan_key, + normalised, order_pref, ppsubdom) +Table *table; +char *dom_key; +char *chan_key; +char *normalised; +int order_pref; +char **ppsubdom; +{ + loopCount = 0; + return tb_getdomain_aux(table, dom_key, order_pref, + chan_key, normalised, ppsubdom); +} + +/* */ + +int tb_getdomain_aux (table, dom_key, order_pref, + chan_key, normalised, + ppsubdom) +Table *table; /* domain table */ +char *dom_key; /* what we're looking up */ +int order_pref; /* which dmn ordering we allow */ +char *chan_key; /* routing pointer */ +char *normalised; /* normalised dmn */ +char **ppsubdom; /* pointer to local tables */ +{ + char tbuf[BUFSIZ], + usa_norm[BUFSIZ], + usa_chan[BUFSIZ], + uk_norm[BUFSIZ], + uk_chan[BUFSIZ], + *usa_ord[LINESIZE], + *uk_ord[LINESIZE], + *str; + char *uksd = NULLCP, *ussd = NULLCP; + int count, + usa_score, + uk_score; + + if (dom_key == NULLCP) + return NOTOK; + + if (*dom_key == '.' || dom_key [strlen (dom_key) - 1] == '.') + return (NOTOK); + + *ppsubdom = NULLCP; + *normalised = '\0'; + if (chan_key) + *chan_key = '\0'; + + PP_DBG (("Lib/table/tb_getdomain (domain='%s', order_pref=%d)", + dom_key, order_pref)); + + /* -- do not destroy input -- */ + (void) strcpy (tbuf, dom_key); + + + /* -- get things into known order and count parts of name -- */ + if ((order_pref & CH_UK_ONLY) != 0) + count = str2bits (tbuf, '.', uk_ord, usa_ord); + else + count = str2bits (tbuf, '.', usa_ord, uk_ord); + + + /* -- look up the usa order name - exact match -- */ + + str = bits2str (usa_ord, '.'); + /* try for foo.bar */ + if (dom_lookup (table, str, order_pref, + usa_chan, usa_norm, ppsubdom, + 0, TRUE, usa_ord, count) == OK || + /* try for *.foo.bar */ + dom_lookup (table, str, order_pref, + usa_chan, usa_norm, ppsubdom, + 0, FALSE, usa_ord, count) == OK) { + fillin_results(usa_norm, usa_chan, normalised, chan_key); + return OK; + } + /* -- ok, if the other way around is allowed - try it -- */ + if ((order_pref & MASK_PREFBIT) != 0) { + str = bits2str (uk_ord, '.'); + /* try for bar.foo */ + if (dom_lookup (table, str, order_pref, + uk_chan, uk_norm, ppsubdom, + 0, TRUE, uk_ord, count) == OK || + /* try for *.bar.foo */ + dom_lookup(table, str, order_pref, + uk_chan, uk_norm, ppsubdom, + 0, FALSE, uk_ord, count) == OK) { + fillin_results(uk_norm, uk_chan, + normalised, chan_key); + return OK; + } + } + + uksd = ussd = NULLCP; + + /* -- score usa order -count the number of matching bits -- */ + usa_score = scorebits (table, usa_ord, count, + usa_norm, usa_chan, + &ussd, order_pref); + + /* -- also score the reverse order if appropriate -- */ + if ((order_pref & MASK_PREFBIT) != 0) + uk_score = scorebits (table, uk_ord, count, + uk_norm, uk_chan, + &uksd, order_pref); + else + uk_score = -1; + + /* -- no matches - can't normalise this thing -- */ + if (uk_score == -1 && usa_score == -1) { + if (uksd) free(uksd); + if (ussd) free(ussd); + return NOTOK; + } + + + /* -- usa order is the best fit -- */ + if (usa_score >= uk_score) { + *ppsubdom = ussd; + if (uksd) free(uksd); + fillin_results(usa_norm, usa_chan, normalised, chan_key); + } else { + /* -- uk order is the best fit -- */ + *ppsubdom = uksd; + if (ussd) free(ussd); + fillin_results(uk_norm, uk_chan, normalised, chan_key); + } + return OK; +} + +/* */ +/* find best match ( -1 == no match ) */ + +static int scorebits (table, comps, numComps, norm, chan, subdom, order_pref) +Table *table; +char *comps[]; +int numComps; +char norm[]; +char chan[]; +char **subdom; +int order_pref; +{ + int i; + char *tbuf[LINESIZE], *str, **ptr; + + PP_DBG (("Lib/table/scorebits()")); + + for (i = 0, ptr = comps; *ptr != NULL; ptr++) + tbuf[i++] = *ptr; + + tbuf[i] = NULLCP; + + /* numComps -1 cos already looked up whole domain */ + for (i = numComps-1; i > 0; i--) { + str = bits2str (&tbuf[numComps - i], '.'); + switch (dom_lookup(table, str, order_pref, + chan, norm, subdom, + numComps - i, FALSE, + comps, numComps)) { + case OK: + case DONE: + /* decreasing i so best hit first hit */ + return i; + default: + break; + } + } + + /* no hits */ + norm[0] = '\0'; + if (chan) + chan[0] = '\0'; + return NOTOK; +} + +/* */ + +static int check_rule(); + +static int dom_lookup (table, name, order_pref, + chan, norm, subdom, nbits, + full, comps, numComps) +Table *table; /* table */ +char *name; /* what we're looking up */ +int order_pref; /* which dmn ordering we allow */ +char *chan; /* routing pointer */ +char *norm; /* normalised dmn */ +char **subdom; /* pointer to local tables */ +int nbits; /* number of non matched subdomains */ +int full; /* looking for * or exact */ +char *comps[]; /* components of dmn */ +int numComps; /* number of components */ +{ + char *vec[10]; + int vecp, i; + int first = TRUE; + char buf[BUFSIZ], pnorm[BUFSIZ]; + char value[BUFSIZ]; + + norm[0] = '\0'; + chan[0] = '\0'; + *subdom = NULLCP; + + /* fillin * if not full */ + if (full == TRUE) + (void) strcpy(buf, name); + else if (name != NULLCP) + (void) sprintf (buf, "*.%s", name); + else + /* default route */ + (void) strcpy(buf, "*"); + + for (;;) { + if (tb_k2val (table, buf, value, first) == NOTOK) + return NOTOK; + + first = 0; + hitTable = TRUE; + + /* split into different rules */ + if ((vecp = sstr2arg (value, 10, vec, "|")) < 1) + return NOTOK; + + for (i = 0; i < vecp; i++) { + switch (check_rule(table, vec[i], buf, + pnorm, chan, subdom, + nbits, full)) { + case OK: + reconstruct_dom(norm, pnorm, numComps - nbits, + comps, numComps); + return OK; + case DONE: + if (++loopCount > MAXLOOPS) { + PP_LOG(LLOG_EXCEPTIONS, + ("possible synonym loop '%s' in table '%s'", + buf, table->tb_name)); + return NOTOK; + } + if (pnorm[0] == '*') { + char *ix; + ix = pnorm + strlen("*."); + reconstruct_dom(buf, ix, + numComps - nbits, + comps, numComps); + } else + (void) strcpy(buf, pnorm); + if (tb_getdomain_aux(table, buf, + order_pref, + chan, norm, + subdom) == OK) + return OK; + break; + default: + break; + } + } + } +} + +/* */ + +/* check one rule */ + +#define KEY_NORM 1 +#define KEY_KEY 2 +#define KEY_NORMKEY 3 +#define KEY_LOCAL 4 +#define KEY_VALID 5 +#define KEY_MAX 6 +#define KEY_MIN 7 +#define KEY_SYNONYM 8 + +static CMD_TABLE tbl_domainKeys[] = { + "norm", KEY_NORM, + "mta", KEY_KEY, + "norm+mta", KEY_NORMKEY, + "mta+norm", KEY_NORMKEY, + "local", KEY_LOCAL, + "valid", KEY_VALID, + "max", KEY_MAX, + "min", KEY_MIN, + "synonym", KEY_SYNONYM, + 0, -1 + }; + +static int check_rule (table, rule, lhs, norm, chan, subdom, nbits, full) +Table *table; +char *rule, *lhs, + *norm, *chan, **subdom; +int nbits, full; +{ + int maxsub, minsub; + int vecp; + char *vec[10], *val; + int synon, i, canUse, normSet; + + synon = FALSE; + canUse = FALSE; + normSet = FALSE; + + /* set default upper and lower bounds */ + if (full == TRUE) + maxsub = minsub = 0; + else { + maxsub = NOTOK; + minsub = 1; + } + + if ((vecp = sstr2arg (rule, 10, vec, " \t")) < 1) + return NOTOK; + + for (i = 0; i < vecp; i++) { + + if (!isstr(vec[i])) + continue; + + if ((val = index(vec[i], '=')) != NULLCP) + *val++ = '\0'; + + switch (cmd_srch(vec[i], tbl_domainKeys)) { + case KEY_SYNONYM: + if (val == NULLCP || *val == '\0') + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': No value given with key '%s'", + table->tb_name, lhs, vec[i])); + else { + (void) strcpy(norm, val); + normSet = TRUE; + synon = TRUE; + canUse = TRUE; + } + break; + + case KEY_NORM: + case KEY_VALID: + if (val != NULLCP && *val != '\0') { + (void) strcpy(norm, val); + normSet = TRUE; + } + canUse = TRUE; + break; + + case KEY_NORMKEY: + if (val != NULLCP && *val != '\0') { + (void) strcpy(norm, val); + (void) strcpy(chan, val); + } else { + /* use lhs as key */ + char *ix; + if (lhs[0] == '*' + && lhs[1] == '.') + ix = &(lhs[2]); + else + ix = &(lhs[0]); + (void) strcpy(norm, ix); + (void) strcpy(chan, ix); + } + normSet = TRUE; + canUse = TRUE; + break; + + case KEY_KEY: + if (val == NULLCP || *val == '\0') { + /* use lhs as key */ + char *ix; + if (lhs[0] == '*' + && lhs[1] == '.') + ix = &(lhs[2]); + else + ix = &(lhs[0]); + (void) strcpy(chan, ix); + } else + (void) strcpy(chan, val); + canUse = TRUE; + break; + + case KEY_LOCAL: + if (val == NULLCP || *val == '\0') + *subdom = strdup(""); + else + *subdom = strdup(val); + canUse = TRUE; + break; + + case KEY_MAX: + if (full == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': invalid specification of 'max' with exact match", + table->tb_name, lhs)); + norm[0] = '\0'; + chan[0] = '\0'; + *subdom = NULLCP; + return NOTOK; + } + if (val == NULLCP || *val == '\0') + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': No value given with key '%s'", + table->tb_name, lhs, vec[i])); + else { + if (val[0] == '*') + maxsub = NOTOK; + else if (isdigit(val[0])) + maxsub = atoi(val); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': Non numeric string as value for key '%s'", + table->tb_name, lhs, vec[i])); + } + break; + + case KEY_MIN: + if (full == TRUE) { + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': invalid specification of 'min' with exact match", + table->tb_name, lhs)); + norm[0] = '\0'; + chan[0] = '\0'; + *subdom = NULLCP; + return NOTOK; + } + if (val == NULLCP || *val == '\0') + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': No value given with key '%s'", + table->tb_name, lhs, vec[i])); + else { + if (val[0] == '*') + minsub = NOTOK; + else if (isdigit(val[0])) + minsub = atoi(val); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Illegal format in table '%s' for '%s': Non numeric string as value for key '%s'", + table->tb_name, lhs, vec[i])); + } + break; + + default: + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown key '%s' in table '%s' for entry '%s'", + vec[i], table->tb_name, lhs)); + break; + } + + } + if (canUse == FALSE) + PP_LOG(LLOG_EXCEPTIONS, + ("entry '%s' in table '%s' has no useful keys (mta,key,local)", + lhs, table->tb_name)); + else if ((maxsub == NOTOK || maxsub >= nbits) + && (minsub == NOTOK || minsub <= nbits)) { + + if (normSet == FALSE) { + /* use lhs */ + char *ix; + if (lhs[0] == '*' + && lhs[1] == '.') + ix = &(lhs[2]); + else + ix = &(lhs[0]); + (void) strcpy(norm, ix); + } + + if (synon == TRUE) + return DONE; + else + return OK; + } + return NOTOK; +} + +/* */ + +static int fillin_results(innorm, inchan, + outnorm, outchan) +char *innorm, *inchan, + *outnorm, *outchan; +{ + if (outnorm) + (void) strcpy(outnorm, innorm); + if (outchan) { + if (inchan[0] != '\0') + (void) strcpy(outchan, inchan); + else + /* no norm given */ + outchan[0] = '\0'; + } +} + +/* */ + +/* reconstruct full domain by adding unmatched components to norm'd */ +reconstruct_dom(into, norm, hits, comps, numComps) +char *into; +char *norm; +int hits; +char *comps[]; +int numComps; +{ + int i; + + into[0] = '\0'; + + for (i = 0; i < numComps - hits; i++) { + if (into[0] != '\0') + (void) strcat (into, "."); + (void) strcat (into, comps[i]); + } + if (into[0] != '\0') + (void) strcat (into, "."); + (void) strcat(into, norm); +} + + +/* */ + +char *bits2str (ptr, sep) +register char **ptr; +register char sep; +{ + char silly[2]; + static char tbuf[LINESIZE]; + + PP_DBG (("Lib/table/bits2str ('%s')", *ptr)); + + silly[0] = sep; + silly[1] = '\0'; + + (void) strcpy (tbuf, *ptr++); + + while (*ptr != NULLCP) { + (void) strcat (tbuf, silly); + (void) strcat (tbuf, *ptr++); + } + + return (tbuf); +} + + +/* +This routine takes a hostname in a string and returns two +arrays of pointers into the string. The string is "chopped up" +with '\0'. The number of elements in the hostname is returned. +*/ + +int str2bits (str, sep, forward, reverse) +register char *str; +register char sep; +register char **forward; +register char **reverse; +{ + register int i, + j; + + PP_DBG (("Lib/table/str2bits(%s)", str)); + + *forward++ = str; + for (i = 1; *str != '\0'; str++) + if (*str == sep) { + *str = '\0'; + *forward++ = &str[1]; + i++; + } + + *forward-- = NULLCP; + + if (reverse != NULL) { + for (j = 0; j < i; j++) + *reverse++ = *forward--; + *reverse = NULLCP; + } + + return (i); +} diff --git a/Lib/table/tb_getlocal.c b/Lib/table/tb_getlocal.c new file mode 100644 index 0000000..06b9c3b --- /dev/null +++ b/Lib/table/tb_getlocal.c @@ -0,0 +1,319 @@ +/* tb_getlocal.c: convert address to user reference */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getlocal.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getlocal.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getlocal.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "loc_user.h" +#include +#include +#include + +#define MAX_USER_ARGS 50 +extern char *mboxname, *mailfilter, *sysmailfilter; +extern CMD_TABLE tbl_bool[]; + +static CMD_TABLE key_tbl[] = { +#define T_UID 1 + "uid", T_UID, +#define T_GID 2 + "gid", T_GID, +#define T_USERNAME 3 +#define T_START T_USERNAME /* start backwards compat */ + "username", T_USERNAME, +#define T_DIRECTORY 4 + "directory", T_DIRECTORY, +#define T_MAILBOX 5 +#define T_FINISH T_MAILBOX /* end backwards compat */ + "mailbox", T_MAILBOX, +#define T_SHELL 6 + "shell", T_SHELL, +#define T_HOME 7 + "home", T_HOME, +#define T_MAILFORMAT 8 + "mailformat", T_MAILFORMAT, +#define T_RESTRICTED 9 + "restricted", T_RESTRICTED, +#define T_MAILFILTER 10 + "mailfilter", T_MAILFILTER, + "usermailfilter",T_MAILFILTER, +#define T_SYSMAILFILTER 11 + "sysmailfilter",T_SYSMAILFILTER, +#define T_SEARCHPATH 12 + "searchpath", T_SEARCHPATH, + "PATH", T_SEARCHPATH, +#define T_OPTS 13 + "opts", T_OPTS, + 0, -1 + }; + +static CMD_TABLE mf_tbl[] = { + "pp", MF_PP, + "mmdf", MF_PP, + "sendmail", MF_UNIX, + "unix", MF_UNIX, + "auto", MF_AUTO, + 0, -1 +}; + + +static char def[] = "default"; +static char none[] = "none"; +static int parse_entry (); + +extern void getfpath (); +/* --------------------- Begin Routines -------------------------------- */ + +LocUser *tb_getlocal (key, channel) +char *key; +CHAN *channel; +{ + LocUser *loc; + char buf [BUFSIZ]; + + + PP_DBG (("Lib/tb_getlocal (%s, %s)", key, channel -> ch_name)); + + if (channel -> ch_table == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("Channel %s (%s) doesn't have a table", + channel -> ch_name, channel -> ch_show)); + return NULL; + } + + loc = (LocUser *) smalloc (sizeof *loc); + bzero ((char *)loc, sizeof *loc); + loc -> restricted = FALSE; + loc -> mailformat = MF_PP; + + if (tb_k2val (channel -> ch_table, def, buf, TRUE) == OK) + if (parse_entry (loc, buf, def) == NOTOK) { + free_loc_user (loc); + return NULL; + } + + + if (lexequ (def, key) == 0) + return loc; + + if (tb_k2val (channel -> ch_table, key, buf, TRUE) == NOTOK) { + free_loc_user (loc); + return NULL; + } + + if (parse_entry (loc, buf, key) == NOTOK) { + free_loc_user (loc); + return NULL; + } + + /* see if the result is valid */ + if (loc -> directory == NULLCP) { + if (loc -> home) + loc -> directory = strdup(loc->home); + else { + PP_LOG (LLOG_EXCEPTIONS, + ("No directory or home specified for %s", key)); + free_loc_user (loc); + return NULL; + } + } + if (loc -> home == NULLCP) + loc -> home = strdup(loc->directory); + + if (loc->mailfilter == NULLCP) + loc -> mailfilter = strdup (mailfilter); + if (lexequ(loc -> mailfilter, none) == 0) { + free (loc -> mailfilter); + loc -> mailfilter = NULLCP; + } + else if (strcmp (loc->directory, loc -> home) != 0) { + getfpath (loc -> home, loc -> mailfilter, buf); + free (loc -> mailfilter); + loc -> mailfilter = strdup(buf); + } + if (loc -> sysmailfilter == NULLCP) + loc -> sysmailfilter = strdup (sysmailfilter); + if (lexequ(loc -> sysmailfilter, none) == 0) { + free (loc -> sysmailfilter); + loc -> sysmailfilter = NULLCP; + } + + return loc; +} + +void free_loc_user (loc) +LocUser *loc; +{ + if (loc -> username) + free (loc->username); + if (loc -> directory) + free (loc -> directory); + if (loc -> mailbox) + free (loc -> mailbox); + if (loc -> shell) + free (loc -> shell); + if (loc -> home) + free (loc -> home); + if (loc -> mailfilter) + free (loc -> mailfilter); + if (loc -> sysmailfilter) + free (loc -> sysmailfilter); + if (loc -> searchpath) + free (loc -> searchpath); + if (loc -> opts) + free (loc -> opts); + free ((char *) loc); +} + +static int parse_entry (loc, buf, key) +LocUser *loc; +char *buf; +char *key; +{ + int count = T_START - 1; + int state; + int argc; + int val; + char *argvl[MAX_USER_ARGS], **argv; + int seenuid = 0, seengid = 0; + char *p; + + if ((argc = sstr2arg (buf, MAX_USER_ARGS, argvl, " \t,")) == NOTOK) + return (NOTOK); + + for(argv = argvl; argc > 0; argc--, argv++) { + char ** resp = NULLVP; + + if (!isstr(*argv)) + continue; + + if ((p = index (*argv, '=')) == NULL) { + if (++count > T_FINISH) { + PP_LOG (LLOG_EXCEPTIONS, + ("Info string `%s' for %s not in key=val format", + *argv, key)); + return NOTOK; + } + state = count; + p = *argv; + } + else { + *p++ = '\0'; + state = cmd_srch (*argv, key_tbl); + } + + switch (state) { + case T_UID: + loc -> uid = atoi(p); + seenuid = 1; + continue; + case T_GID: + loc -> gid = atoi(p); + seengid = 1; + continue; + case T_USERNAME: + resp = &(loc -> username); + break; + case T_DIRECTORY: + resp = &(loc -> directory); + break; + case T_MAILBOX: + resp = &(loc -> mailbox); + break; + case T_SHELL: + resp = &(loc -> shell); + break; + case T_HOME: + resp = &(loc -> home); + break; + case T_MAILFORMAT: + if ((val = cmd_srch (p, mf_tbl)) != NOTOK) + loc -> mailformat = val; + else + PP_LOG (LLOG_EXCEPTIONS, + ("Bad value for mailformat %s in %s", + p, key)); + continue; + case T_RESTRICTED: + if ((val = cmd_srch (p, tbl_bool)) != NOTOK) + loc -> restricted = val; + else + PP_LOG (LLOG_EXCEPTIONS, + ("Bad value for restricted %s in %s", + p, key)); + continue; + case T_MAILFILTER: + resp = &(loc -> mailfilter); + break; + case T_SYSMAILFILTER: + resp = &(loc -> sysmailfilter); + break; + case T_SEARCHPATH: + resp = &(loc -> searchpath); + break; + case T_OPTS: + resp = &(loc -> opts); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown key in user info for %s '%s' (%s)", + key, *argv, p)); + continue; + } + if (resp) + { + if (*resp) + free (*resp); + *resp = strdup(p); + } + } + /* start fixing up special cases */ + if (loc -> mailbox == NULLCP) + loc -> mailbox = strdup (mboxname); + + + if (loc -> username) { + if (isdigit (*loc -> username) && + (p = index (loc -> username, '/'))) { + *p ++ = NULL; + loc -> uid = atoi (loc -> username); + loc -> gid = atoi (p); + free (loc -> username); + loc -> username = NULLCP; + } + else { + struct passwd *pwd; + + if ((pwd = getpwnam (loc -> username)) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, + ("No such local user %s", loc -> username)); + return NOTOK; + } + + if (seenuid == 0) + loc -> uid = pwd -> pw_uid; + if (seengid == 0) + loc -> gid = pwd -> pw_gid; + if (loc -> home == NULLCP) + loc -> home = strdup (pwd -> pw_dir); + if (loc -> shell == NULLCP) + loc -> shell = strdup (pwd -> pw_shell); + if (loc -> directory == NULLCP) + loc -> directory = strdup (pwd -> pw_dir); + } + } + return OK; +} diff --git a/Lib/table/tb_getuser.c b/Lib/table/tb_getuser.c new file mode 100644 index 0000000..068f3dc --- /dev/null +++ b/Lib/table/tb_getuser.c @@ -0,0 +1,89 @@ +/* tb_getuser.c: grab an user */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getuser.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_getuser.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_getuser.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "list_rchan.h" + + +#define MAX_ALTERNATIVE_CHANS 20 +#define MAX_USER_ARGS 5 + +/* --------------------- Begin Routines -------------------------------- */ + + +extern char *user_tbl, *loc_dom_mta; + +LIST_RCHAN *tb_getuser (key, subdom) +char *key; +char *subdom; +{ + char *argv [MAX_ALTERNATIVE_CHANS], + *subargv[MAX_USER_ARGS], + buf [BUFSIZ], + tblname[MAXPATHLENGTH]; + int argc, i; + Table *User = NULLTBL; + LIST_RCHAN *chans = NULLIST_RCHAN, *tmp; + + if (subdom == NULLCP || *subdom == '\0') + (void) sprintf(tblname,"%s", user_tbl); + else + (void) sprintf(tblname,"%s-%s", subdom, user_tbl); + + + PP_DBG (("Lib/tb_getuser (%s)", tblname)); + + + if ((User = tb_nm2struct (tblname)) == NULLTBL) { + PP_OPER (NULLCP, ("Lib/tb_getuser (no table '%s')", tblname)); + return (NULLIST_RCHAN); + } + + if (tb_k2val (User, key, buf, TRUE) == NOTOK) + return (NULLIST_RCHAN); + + if ((argc = sstr2arg (buf, MAX_ALTERNATIVE_CHANS, argv, ",")) == NOTOK) + return (NULLIST_RCHAN); + + for (i = 0; i < argc; i++) { + if (!isstr(argv[i])) + continue; + + if ((sstr2arg (argv[i], MAX_USER_ARGS, subargv, " ")) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to parse delivery channels for '%s' in the user table '%s'", + key, tblname)); + list_rchan_free(chans); + return NULLIST_RCHAN; + } + if ((tmp = list_rchan_new ((subargv[1] == NULLCP || + *subargv[1] == '\0') ? + loc_dom_mta : subargv[1], + NULLCP)) == NULLIST_RCHAN) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to find delivery channel '%s' for '%s' in the user table '%s'", + argv[0], key, tblname)); + list_rchan_free(chans); + return NULLIST_RCHAN; + } + tmp -> li_chan = ch_nm2struct(subargv[0]); + list_rchan_add (&chans, tmp); + } + return (chans); +} + diff --git a/Lib/table/tb_k2val.c b/Lib/table/tb_k2val.c new file mode 100644 index 0000000..ad84f2d --- /dev/null +++ b/Lib/table/tb_k2val.c @@ -0,0 +1,191 @@ +/* tb_k2val.c: primitive routine - convert key to value */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_k2val.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_k2val.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_k2val.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "table.h" + + +#define MAXF 80 + + +/* +All the tables with open files +*/ + +static Table *tb_xall [MAXF]; +static int curclose; +extern char *tbldfldir; +static int tblosearch (); + + + +/* --------------------- Start Routines -------------------------------- */ + +int tb_k2val (tbl, key, val, first) +register Table *tbl; +char *key; +char *val; +int first; +{ + FILE *f; + char linebuf[LINESIZE], + value[LINESIZE]; + int i, status; + + + PP_DBG (("Lib/tb_k2val (%s)", key)); + + if (tbl -> tb_override && + tblosearch (tbl, key, val, first) == OK) + return OK; + + if (TB_SRC (tbl -> tb_flags) == TB_DBM) + return (tb_dbmk2val (tbl, key, val, first)); + + + if (tbl -> tb_fp == NULLFILE) { + /* + Must open the file.... + */ + if (*tbl -> tb_file != '/') { + (void) sprintf (linebuf, "%s/%s", + tbldfldir, tbl -> tb_file); + f = fopen (linebuf, "r"); + } + else + f = fopen (tbl -> tb_file, "r"); + + if (f == NULLFILE) { + PP_OPER (tbl -> tb_file, ("Cannot open")); + return (NOTOK); + } + + tbl -> tb_fp = f; + + for (i = 0 ; i < MAXF ; i++) + if (tb_xall [(i+curclose) % MAXF] == NULL) { + tb_xall [(i+curclose) % MAXF] = tbl; + goto got; + } + + (void) fclose (tb_xall [curclose] -> tb_fp); + tb_xall [curclose] -> tb_fp = NULLFILE; + tb_xall [curclose++] = tbl; + curclose %= MAXF; + + got:; + } + + f = tbl -> tb_fp; + if (first) + rewind (f); + while ((status = tab_fetch (f, linebuf, value)) != DONE) { + if (status == NOTOK) + continue; + if (lexequ (linebuf, key) == 0) { + /* + Found now return it + */ + if (val == NULL) + return (OK); + (void) strcpy (val, value); + return (OK); + } + } + return (NOTOK); +} + + +int tab_fetch (f, key, val) +register FILE *f; +char *key; +char *val; +{ + register char *cp; + int c; + + while ((c = getc(f)) != EOF && isspace (c)) + continue; + + if (c == '#') { + while ((c = getc(f)) != EOF && c != '\n') + continue; + return tab_fetch (f, key, val); + } + + cp = key; + do { + if (c == '\n') { + *cp = '\0'; + PP_LOG (LLOG_EXCEPTIONS, + ("no value - missing ':' key=%s", key)); + return NOTOK; + } + if (c == ':') { + if (cp > key && cp[-1] == '\\') + cp [-1] = c; + else break; + } + else *cp ++ = c; + if (key - cp > LINESIZE) { + *cp = '\0'; + PP_LOG (LLOG_EXCEPTIONS, ("Key too long '%s'", key)); + return NOTOK; + } + } while ((c = getc (f)) != EOF); + if (c == EOF) + return DONE; + *cp = '\0'; + + while ((c = getc(f)) != EOF && c != '\n' && isspace (c)) + continue; + + cp = val; + do { + if (c == '\n') + break; + else + *cp ++ = c; + if (val - cp > LINESIZE) { + *cp = '\0'; + PP_LOG (LLOG_EXCEPTIONS, ("Value too long %s:%s", + key, val)); + return NOTOK; + } + } while ((c = getc (f)) != EOF); + if (c == EOF) + return DONE; + *cp = '\0'; + return OK; +} + +/* ARGSUSED */ +static int tblosearch (tbl, key, val, first) +Table *tbl; +char *key; +char *val; +int first; /* may do something with this someday */ +{ + TableOverride *to; + + for (to = tbl -> tb_override; to; to = to -> tbo_next) + if (lexequ (key, to -> tbo_key) == 0) { + (void) strcpy (val, to -> tbo_value); + return OK; + } + return NOTOK; +} diff --git a/Lib/table/tb_nm2struct.c b/Lib/table/tb_nm2struct.c new file mode 100644 index 0000000..a0b04aa --- /dev/null +++ b/Lib/table/tb_nm2struct.c @@ -0,0 +1,36 @@ +/* tb_nm2struct: convert a table name to a struct pointer */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_nm2struct.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_nm2struct.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_nm2struct.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "table.h" + + +Table * +tb_nm2struct(name) +char *name; +{ + register Table **tbl; + + if (tb_all == (Table **)0) + return( (Table *)0); + + for(tbl = tb_all ; *tbl != (Table *)0 ; tbl++) + if(lexequ(name, (*tbl)->tb_name) == 0) + return(*tbl); + + return( (Table *)0); +} diff --git a/Lib/table/tb_rtsparams.c b/Lib/table/tb_rtsparams.c new file mode 100644 index 0000000..fd3c6b4 --- /dev/null +++ b/Lib/table/tb_rtsparams.c @@ -0,0 +1,323 @@ +/* tb_rtsparams.c: fetch X.400 RTS parameters */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_rtsparams.c,v 6.0 1991/12/18 20:24:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/table/RCS/tb_rtsparams.c,v 6.0 1991/12/18 20:24:28 jpo Rel $ + * + * $Log: tb_rtsparams.c,v $ + * Revision 6.0 1991/12/18 20:24:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include "rtsparams.h" +#include +#include + + +CMD_TABLE rts_tbl[] = { +#define RTSP_LMTA 1 + "lmta", RTSP_LMTA, +#define RTSP_RMTA 2 + "rmta", RTSP_RMTA, +#define RTSP_LPASS 3 + "lpass", RTSP_LPASS, +#define RTSP_RPASS 4 + "rpass", RTSP_RPASS, +#define RTSP_RPPNAME 5 + "rname", RTSP_RPPNAME, +#define RTSP_MDINFO 6 + "mdinfo", RTSP_MDINFO, +#define RTSP_LPSAP 7 + "lpsap", RTSP_LPSAP, +#define RTSP_RPSAP 8 + "rpsap", RTSP_RPSAP, +#define RTSP_MODE 9 + "mode", RTSP_MODE, +#define RTSP_TYPE 10 + "type", RTSP_TYPE, +#define RTSP_OTHER 11 + "other", RTSP_OTHER, +#define RTSP_INFO 12 + "info", RTSP_INFO, +#define RTSP_TRYNEXT 13 + "trynext", RTSP_TRYNEXT, +#define RTSP_TRACE 14 + "tracing", RTSP_TRACE, +#define RTSP_FIXORIG 15 + "fix-orig", RTSP_FIXORIG, + NULLCP, -1 +}; + + + + +CMD_TABLE rts_info[] = { +#define RTSINFO_MODE 1 + "mode", RTSINFO_MODE, +#define RTSINFO_UNDEFINED 2 + "undefined", RTSINFO_UNDEFINED, + NULLCP, -1 +}; + + + + +static char def[] = "default"; + +static int conv_entry(), conv_info(); + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +RtsParams *tb_rtsparams(tbl, remote_site) +Table *tbl; +char *remote_site; +{ + RtsParams *rp = NULL; + char buffer[BUFSIZ]; + + if (tbl == NULLTBL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No incomming table specified for %s", remote_site)); + return NULL; + } + + /* --- initialisation --- */ + rp = (RtsParams *) smalloc(sizeof *rp); + bzero((char *) rp, sizeof *rp); + rp->rts_mode = RTS_MONOLOGUE; + rp->type = RTSP_1984; + rp->trace_type = RTSP_TRACE_ALL; + rp->our_passwd = strdup(""); + rp->our_name = strdup(""); + + + /* --- retrieve & convert the default entry --- */ + if (tb_k2val(tbl, def, buffer, TRUE) == OK) + if (conv_entry(rp, buffer, def) == NOTOK) + goto tb_rtsparams_error; + + if (lexequ(def, remote_site) == 0) + return rp; + + + /* --- retrieve & convert the actual remote site entry --- */ + if (tb_k2val(tbl, remote_site, buffer, TRUE) == NOTOK) + goto tb_rtsparams_error; + + if (conv_entry(rp, buffer, remote_site) == NOTOK) + goto tb_rtsparams_error; + + return rp; + + +tb_rtsparams_error:; + RPfree(rp); + return NULL; +} + + + + +static int conv_entry(rp, buffer, remote_site) +RtsParams *rp; +char *buffer; +char *remote_site; +{ + int argc; + char *argv[100]; + int n; + + if ((argc = str2arg(buffer, 100, argv)) < 2) { + PP_LOG(LLOG_EXCEPTIONS, + ("Badly formatted table entry for %s (%s)", + remote_site, buffer)); + return NOTOK; + } + + + for (n = 0; n < argc;) { + if (strcmp(argv[n], "=") != 0) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad value %s for %s", argv[n], remote_site)); + n++; + continue; + } + n++; + switch (cmd_srch(argv[n], rts_tbl)) { + case RTSP_LMTA: + if (rp->our_name) + free(rp->our_name); + rp->our_name = strdup(argv[n + 1]); + break; + case RTSP_RMTA: + if (rp->their_name) + free(rp->their_name); + rp->their_name = strdup(argv[n + 1]); + break; + case RTSP_LPASS: + if (rp->our_passwd) + free(rp->our_passwd); + rp->our_passwd = strdup(argv[n + 1]); + break; + case RTSP_RPASS: + if (rp->their_passwd) + free(rp->their_passwd); + rp->their_passwd = strdup(argv[n + 1]); + break; + case RTSP_RPPNAME: + if (rp->their_internal_ppname) + free(rp->their_internal_ppname); + rp->their_internal_ppname = strdup(argv[n + 1]); + break; + case RTSP_MDINFO: + if (rp->md_info) + free(rp->md_info); + rp->md_info = strdup(argv[n + 1]); + break; + case RTSP_LPSAP: + if (rp->our_address) + free(rp->our_address); + rp->our_address = strdup(argv[n + 1]); + break; + case RTSP_RPSAP: + if (rp->their_address) + free(rp->their_address); + rp->their_address = strdup(argv[n + 1]); + break; + case RTSP_MODE: + if (lexequ(argv[n + 1], "twa") == 0) + rp->rts_mode = RTS_TWA; + else if (lexequ(argv[n + 1], "mon") == 0) + rp->rts_mode = RTS_MONOLOGUE; + break; + case RTSP_TYPE: + if (lexequ(argv[n + 1], "1988-X410") == 0) + rp->type = RTSP_1988_X410MODE; + else if (lexequ(argv[n + 1], "1988-NORMAL") == 0 || + lexequ(argv[n + 1], "1988") == 0) + rp->type = RTSP_1988_NORMAL; + else if (lexequ(argv[n + 1], "1984") == 0) + rp->type = RTSP_1984; + break; + + case RTSP_OTHER: + case RTSP_INFO: + if (conv_info (rp, argv[n + 1], remote_site) == NOTOK) + return NOTOK; + break; + + case RTSP_TRACE: + if (lexequ(argv[n + 1], "admd") == 0) + rp->trace_type = RTSP_TRACE_ADMD; + else if (lexequ(argv[n + 1], "nointernal") == 0) + rp->trace_type = RTSP_TRACE_NOINT; + else if (lexequ(argv[n + 1], "local-internal") == 0) + rp->trace_type = RTSP_TRACE_LOCALINT; + else + rp->trace_type = RTSP_TRACE_ALL; + break; + case RTSP_TRYNEXT: + if (rp->try_next) + free(rp->try_next); + rp->try_next = strdup(argv[n + 1]); + break; + case RTSP_FIXORIG: + if (rp->fix_orig) + free(rp->fix_orig); + rp->fix_orig = strdup(argv[n + 1]); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + (" Warning: Unknown keyword %s", argv[n])); + break; + } + n += 2; + } + return OK; +} + + + + +static int conv_info(rp, buffer, remote_site) +RtsParams *rp; +char *buffer; +char *remote_site; +{ + int argc; + char *argv[100]; + int n; + + + if ((argc = str2arg(buffer, 100, argv)) < 2) { + PP_LOG(LLOG_EXCEPTIONS, + ("Badly formatted table entry for %s (%s)", + remote_site, buffer)); + return NOTOK; + } + + + for (n = 0; n < argc;) { + if (strcmp(argv[n], "=") != 0) { + PP_LOG(LLOG_EXCEPTIONS, + ("Bad value %s for %s", argv[n], remote_site)); + n++; + continue; + } + n++; + switch (cmd_srch(argv[n], rts_info)) { + case RTSINFO_MODE: + if (rp->info_mode) + free(rp->info_mode); + rp->info_mode = strdup(argv[n + 1]); + break; + case RTSINFO_UNDEFINED: + if (rp->info_undefined) + free(rp->info_undefined); + rp->info_undefined = strdup(argv[n + 1]); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + (" Warning: Unknown keyword %s", argv[n])); + break; + } + n += 2; + } + return OK; +} + + + + +void RPfree(rp) +RtsParams *rp; +{ + PP_DBG(("RPfree()")); + if (rp == NULL) return; + if (rp->their_name) free(rp->their_name); + if (rp->their_passwd) free(rp->their_passwd); + if (rp->their_internal_ppname) free(rp->their_internal_ppname); + if (rp->their_address) free(rp->their_address); + if (rp->our_name) free(rp->our_name); + if (rp->our_passwd) free(rp->our_passwd); + if (rp->our_address) free(rp->our_address); + if (rp->md_info) free(rp->md_info); + if (rp->try_next) free(rp->try_next); + if (rp->info_mode) free(rp->info_mode); + if (rp->info_undefined) free(rp->info_undefined); + if (rp->fix_orig) free(rp->fix_orig); + free((char *) rp); +} diff --git a/Lib/tai/Makefile b/Lib/tai/Makefile new file mode 100644 index 0000000..2929dd9 --- /dev/null +++ b/Lib/tai/Makefile @@ -0,0 +1,139 @@ +# Tailoring routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/tai/RCS/Makefile,v 6.0 1991/12/18 20:24:59 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:24:59 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = init_chan.c init_tai.c init_uip.c pp_setuserid.c \ + tai_chan.c tai_sys.c tai_tb.c +OBJS = init_chan.o init_tai.o init_uip.o pp_setuserid.o \ + tai_chan.o tai_sys.o tai_tb.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = tai-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../util/llib-lutil.ln \ + ../x400/llib-lx400.ln + + + +############################################################ +# +# Building Rules +# +############################################################ + +default: ${SHADOW} + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + + +install:; + +lintlib:llib-ltai.ln +llib-ltai.ln: ${SRCS} + $(LINT) -Ctai $(LLFLAGS) ${SRCS} + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +clean: tidy + rm -f ${OBJS} llib-ltai.ln +tidy: + rm -f core ${SHADOW} *.old a.out *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +init_chan.o: init_chan.c +init_tai.o: init_tai.c +init_tai.o: ../../h/head.h +init_tai.o: ../../h/util.h +init_tai.o: ../../h/config.h +init_tai.o: ../../h/ll_log.h +init_tai.o: ../../h/retcode.h +init_uip.o: init_uip.c +pp_setuserid.o: pp_setuserid.c +pp_setuserid.o: ../../h/util.h +pp_setuserid.o: ../../h/config.h +pp_setuserid.o: ../../h/ll_log.h +tai_chan.o: tai_chan.c +tai_chan.o: ../../h/head.h +tai_chan.o: ../../h/util.h +tai_chan.o: ../../h/config.h +tai_chan.o: ../../h/ll_log.h +tai_chan.o: ../../h/retcode.h +tai_chan.o: ../../h/chan.h +tai_chan.o: ../../h/table.h +tai_chan.o: ../../h/list_bpt.h +tai_chan.o: ../../h/adr.h +tai_chan.o: ../../h/list_rchan.h +tai_chan.o: ../../h/chan.h +tai_chan.o: ../../h/auth.h +tai_chan.o: ../../h/list_bpt.h +tai_chan.o: ../../h/extension.h +tai_chan.o: ../../h/mta.h +tai_chan.o: ../../h/adr.h +tai_chan.o: ../../h/list_bpt.h +tai_chan.o: ../../h/aparse.h +tai_chan.o: ../../h/ap.h +tai_chan.o: ../../h/util.h +tai_chan.o: ../../h/or.h +tai_chan.o: ../../h/chan.h +tai_chan.o: ../../h/auth.h +tai_chan.o: ../../h/list_rchan.h +tai_sys.o: tai_sys.c +tai_sys.o: ../../h/head.h +tai_sys.o: ../../h/util.h +tai_sys.o: ../../h/config.h +tai_sys.o: ../../h/ll_log.h +tai_sys.o: ../../h/retcode.h +tai_sys.o: ../../h/list_bpt.h +tai_tb.o: tai_tb.c +tai_tb.o: ../../h/util.h +tai_tb.o: ../../h/config.h +tai_tb.o: ../../h/ll_log.h +tai_tb.o: ../../h/retcode.h +tai_tb.o: ../../h/table.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/tai/init_chan.c b/Lib/tai/init_chan.c new file mode 100644 index 0000000..f19edd6 --- /dev/null +++ b/Lib/tai/init_chan.c @@ -0,0 +1,21 @@ +/* init_chan.c: initialisation for channel programs */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_chan.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_chan.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: init_chan.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + +void chan_init (pname) +char *pname; +{ + (void) sys_init (pname); +} diff --git a/Lib/tai/init_tai.c b/Lib/tai/init_tai.c new file mode 100644 index 0000000..6c60b3e --- /dev/null +++ b/Lib/tai/init_tai.c @@ -0,0 +1,370 @@ +/* init_tai.c: tailoring initialisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_tai.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_tai.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: init_tai.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include +#include +#include + +#define MAXTAIARGS 100 +#define COMMENTCHAR '#' + + +extern char *pptailor, + *isodelogpath, + *tbldfldir, + *logdfldir; + +static char *getlines(); +static void pp_tailor_export (); +static void pp_log_init (); +extern void err_abrt (); +static void pp_log_export (); +static int tai_read(); +extern void siginit (); +extern char chrcnv[]; + +/* --------------------- Begin Routines -------------------------------- */ + +#define LEXEQU(a,b) (chrcnv[(a[0])] == chrcnv[(b[0])] && lexequ((a),(b))== 0) + + +int sys_init (name) +char *name; +{ + return pp_initialise (name, TAI_ALL); +} + +pp_initialise (name, flags) +char *name; +int flags; +{ + char buf[BUFSIZ], + *args[MAXTAIARGS], + *lineptr, + *rname; + static char onceonly = 0; + int ac; + + + if ((rname = rindex (name, '/')) != NULLCP) + rname ++; + if (rname == NULLCP || *rname == 0) + rname = name; + + + ll_hdinit (pp_log_oper, rname); + ll_hdinit (pp_log_stat, rname); + ll_hdinit (pp_log_norm, rname); + isodetailor (rname, 0); + + if (onceonly ++) + return OK; + + if (flags & TAI_SIGNALS) + siginit(); + + pp_log_init (flags); + + (void) sprintf (buf, "%s/", logdfldir); + isodelogpath = strdup (buf); + + + if (tai_read (pptailor) == NOTOK) + err_abrt (RP_FIO, + "Lib/init_tai.c: Cannot open tailor file '%s'", + pptailor); + + while ((lineptr = getlines ()) != NULLCP) { + if (*lineptr == '\0') + continue; + PP_DBG (("tailor line='%s'", buf)); + if ((ac = sstr2arg (lineptr, MAXTAIARGS, + args, " \t,")) == NOTOK) + err_abrt (RP_MECH, + "Lib/init_tai.c: too many tailor params"); + + if (ac <= 1) + continue; + + + if (LEXEQU (args[0], "chan") && + chan_tai (ac, args) == OK) + continue; + + if (LEXEQU (args[0], "tbl") && + tbl_tai (ac, args) == OK) + continue; + + if (sys_tai (ac, args) == OK) + continue; + + if (LEXEQU (rname, args[0])) { + PP_DBG (("Adding tailor %s for %s", + args[1], rname)); + (void) sys_tai (ac - 1, &args[1]); + } + } + + pp_tailor_export (flags); + if (flags & TAI_LOGS) + pp_log_export (); + return OK; +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void pp_tailor_export (flags) +int flags; +{ + extern char *cmddfldir, *chndfldir, *formdfldir, + *quedfldir, + *ppdbm, *wrndfldir, *x400_mta, *loc_dom_mta; + extern char *dupfpath(); + char buf[BUFSIZ]; + + + if (flags & TAI_LOGS) { + if (isodelogpath) + free (isodelogpath); + + (void) sprintf (buf, "%s/", logdfldir); + isodelogpath = strdup (buf); + } + isodexport (NULLCP); + + chndfldir = dupfpath (cmddfldir, chndfldir); + formdfldir = dupfpath (cmddfldir, formdfldir); + ppdbm = dupfpath (tbldfldir, ppdbm); + wrndfldir = dupfpath (tbldfldir, wrndfldir); + if (x400_mta == NULLCP) + x400_mta = strdup (loc_dom_mta); +} + +static char *pp_tailor_str, *ppt_ptr; +static int tlineno; + +static int tai_read (file) +char *file; +{ + int fd; + struct stat st; + + tlineno = 1; + if ((fd = open (file, O_RDONLY, 0)) == NOTOK) + return NOTOK; + if (fstat (fd, &st) == NOTOK) { + (void) close (fd); + return NOTOK; + } + ppt_ptr = pp_tailor_str = smalloc ((int)st.st_size + 1); + if (read (fd, pp_tailor_str, (int)st.st_size) != st.st_size) { + (void) close (fd); + return NOTOK; + } + pp_tailor_str[st.st_size] = 0; + (void) close (fd); + return OK; +} + + + +static char *getlines () +{ + register char *p = ppt_ptr; + char *base; + register char *lastp; + +#define skipto(x) while(*p && *p != (x)) p ++; + + while (*p == COMMENTCHAR || *p == '\n') { + skipto ('\n'); + tlineno ++; + if (p) p++; + } + + if (*p == '\0') { + ppt_ptr = p; + return NULLCP; + } + + base = p; + lastp = NULLCP; + while (1) { + skipto ('\n'); + tlineno ++; + if (*p == '\n') + *p = ' '; + else break; + if (lastp == NULLCP) lastp = p; + if (p[1] == COMMENTCHAR) { + continue; + } else if (p[1] == ' ' || p[1] == '\t') { + if (lastp) + while (lastp < p) *lastp++ = ' '; + lastp = NULLCP; + continue; + } + break; + } +#undef skipto + if (p && *p) *p++ = '\0'; + if (lastp) *lastp = '\0'; + ppt_ptr = p; + return base; +} + + +static void tai_def_eh (str) +char *str; +{ + PP_LOG (LLOG_EXCEPTIONS, ("%s", str)); +} + +static VFP teh = tai_def_eh; + +void tai_seterrorhandler (fnx) +VFP fnx; +{ + if (fnx == NULLVFP) + teh = tai_def_eh; + else + teh = fnx; +} + +#ifdef lint +/* VARARGS1 */ +void tai_error (fmt) +char *fmt; +{ + tai_error (fmt); +} +#else +void tai_error (va_alist) +va_dcl +{ + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + va_list ap; + + va_start (ap); + _asprintf (buf, NULLCP, ap); + (void) sprintf (buf2, "Tailor error in entry ending line %d: %s\n", + tlineno, buf); + (teh)(buf2); + va_end (ap); +} +#endif +/* ------------------------------------------------------------------ */ +struct logpairs { + LLog **isode_log; + LLog **isode_save; + char *name; + char *level; +}; + + +#define NULLOG ((LLog **)0) + +static LLog +#ifdef X25 + *log_x25, +#endif + *log_acsap, + *log_addr, + *log_compat, + *log_psap, + *log_psap2, + *log_rosap, + *log_rtsap, + *log_ssap, + *log_tsap; + +static struct logpairs logpairs[] = { + &acsap_log, &log_acsap, "acsap", "acsaplevel", + &addr_log, &log_addr, "addr", "addrlevel", + &compat_log, &log_compat, "compat", "compatlevel", + &psap2_log, &log_psap2, "psap2", "psap2level", + &psap_log, &log_psap, "psap", "psaplevel", + &rosap_log, &log_rosap, "rosap", "rosaplevel", + &rtsap_log, &log_rtsap, "rtsap", "rtsaplevel", + &ssap_log, &log_ssap, "ssap", "ssaplevel", + &tsap_log, &log_tsap, "tsap", "tsaplevel", +#ifdef X25 + &x25_log, &log_x25, "x25", "x25level", +#endif + 0 +}; + +static LLog zdummy = { + "dummy.log", NULLCP, NULLCP, + LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, + LLOGCLS | LLOGCRT | LLOGZER, NOTOK +}; +static LLog *dummy = &zdummy; + + +static void pp_log_init (flags) +int flags; +{ + struct logpairs *lp; + + for (lp = logpairs; lp -> name; lp ++) { + if (flags & TAI_LOGS) + **(lp -> isode_log) = *pp_log_norm; + *(lp -> isode_save) = *(lp -> isode_log); + if (flags & TAI_LOGS) + *(lp -> isode_log) = dummy; + } +} + +static void pp_log_export() +{ + struct logpairs *lp; + + for (lp = logpairs; lp -> name; lp++) + *(lp -> isode_log) = *(lp -> isode_save); +} + +void pp_setlog (argv, argc) +char *argv[]; +int argc; +{ + struct logpairs *lp; + + if (argc < 1) + return; + + for (lp = logpairs; lp -> name; lp ++) { + if (lexequ (argv[0], lp -> level) == 0) + break; + } + + if (lp -> name == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, ("level %s not found", + argv[0])); + return; + } + log_tai (*(lp -> isode_save), &argv[1], argc - 1); +} diff --git a/Lib/tai/init_uip.c b/Lib/tai/init_uip.c new file mode 100644 index 0000000..bae3003 --- /dev/null +++ b/Lib/tai/init_uip.c @@ -0,0 +1,21 @@ +/* init_uip.c: user interface initialisation (none at present) */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_uip.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/init_uip.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: init_uip.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + +void uip_init (pname) +char *pname; +{ + (void) sys_init (pname); +} diff --git a/Lib/tai/make b/Lib/tai/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/tai/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/tai/pp_setuserid.c b/Lib/tai/pp_setuserid.c new file mode 100644 index 0000000..75ca8b4 --- /dev/null +++ b/Lib/tai/pp_setuserid.c @@ -0,0 +1,46 @@ +/* pp_setuserid.c: set user id to pp owner */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/pp_setuserid.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/pp_setuserid.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: pp_setuserid.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + + +extern char *pplogin; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int pp_setuserid() +{ + struct passwd *pwd; + + if ((pwd = getpwnam(pplogin)) == (struct passwd *)0) + return (NOTOK); + + if (setuid (pwd->pw_uid) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Lib/pp_setuserid.c/Can't set uid to %d(%s)", + pwd -> pw_uid, pplogin)); + return (NOTOK); + } + return (OK); +} diff --git a/Lib/tai/tai_chan.c b/Lib/tai/tai_chan.c new file mode 100644 index 0000000..3ca697c --- /dev/null +++ b/Lib/tai/tai_chan.c @@ -0,0 +1,525 @@ +/* tai_chan.c: channel specific tailoring code */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_chan.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_chan.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: tai_chan.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include "chan.h" +#include "adr.h" + + + +extern void err_abrt (); +extern void tai_error (); +extern CMD_TABLE qtbl_con_type[], + atbl_types[], + atbl_subtypes[]; +static char chn_str[] = "chan"; +static int ch_numchans = 0; +static int ch_maxchans = 0; + +/* tables */ +#define CH_NAME 1 +#define CH_PROGNAME 2 +#define CH_SHOW 3 +#define CH_CHAN_TYPE 4 +#define CH_CONTENT_IN 5 +#define CH_DRCHAN 6 +#define CH_CONTENT_OUT 7 +#define CH_COST 8 +#define CH_SORT 9 +#define CH_IN_INFO 10 +#define CH_AD_TYPE 11 +#define CH_AD_SUBTYPE 12 +#define CH_AD_ORDER 13 +#define CH_BPT_IN 14 +#define CH_BPT_OUT 15 +#define CH_HDR_IN 16 +#define CH_HDR_OUT 17 +#define CH_TABLE 18 +#define CH_XMTA 19 +#define CH_ACCESS 20 +#define CH_PROBE 21 +#define CH_AUTHTBL 22 +#define CH_DOMPARSE 23 +#define CH_CONV 24 +#define CH_MAXPROC 25 +#define CH_KEY 26 +#define CH_OUT_INFO 27 +#define CH_OUT_AD_TYPE 28 +#define CH_IN_AD_TYPE 29 +#define CH_IN_SUBTYPE 30 +#define CH_OUT_SUBTYPE 31 +#define CH_MTA_TABLE 32 +#define CH_TRACE_TYPE 33 +#define CH_IN_TABLE 34 +#define CH_SOLO_PROC 35 +#define CH_BADSENDER_POLICY 36 +#define CH_CHECK_MODE 37 + +static CMD_TABLE chtbl_key[] = { + "access", CH_ACCESS, + "adr", CH_AD_TYPE, + "adr-order", CH_AD_ORDER, + "auth-tbl", CH_AUTHTBL, + "bad-sender-policy", CH_BADSENDER_POLICY, + "bptin", CH_BPT_IN, + "bptout", CH_BPT_OUT, + "check", CH_CHECK_MODE, + "content-in", CH_CONTENT_IN, + "content-out", CH_CONTENT_OUT, + "conv", CH_CONV, + "cost", CH_COST, + "domain-norm", CH_DOMPARSE, + "drchan", CH_DRCHAN, + "hdrin", CH_HDR_IN, + "hdrout", CH_HDR_OUT, + "in-info", CH_IN_INFO, + "ininfo", CH_IN_INFO, + "inadr", CH_IN_AD_TYPE, + "insubadr", CH_IN_SUBTYPE, + "intable", CH_IN_TABLE, + "key", CH_KEY, + "maxproc", CH_MAXPROC, + "mta", CH_XMTA, + "mtatable", CH_MTA_TABLE, + "name", CH_NAME, + "out-info", CH_OUT_INFO, + "outinfo", CH_OUT_INFO, + "outadr", CH_OUT_AD_TYPE, + "outsubadr", CH_OUT_SUBTYPE, + "outtable", CH_TABLE, + "probe", CH_PROBE, + "prog", CH_PROGNAME, + "show", CH_SHOW, + "solo-proc", CH_SOLO_PROC, + "sort", CH_SORT, + "subadr", CH_AD_SUBTYPE, + "trace", CH_TRACE_TYPE, + "type", CH_CHAN_TYPE, + 0, -1 + }; +#define N_CHANTBLENT ((sizeof(chtbl_key)/sizeof(CMD_TABLE)) - 1) + + + +static CMD_TABLE chtbl_types[] = { + "both", CH_BOTH, + "debris", CH_DEBRIS, + "delete", CH_DELETE, + "in", CH_IN, + "out", CH_OUT, + "qmgrload", CH_QMGR_LOAD, + "shaper", CH_SHAPER, + "split", CH_SPLITTER, + "timeout", CH_TIMEOUT, + "warn", CH_WARNING, + 0, -1 + }; +#define N_CHANTYPES ((sizeof(chtbl_types)/sizeof(CMD_TABLE)) - 1) + + +static CMD_TABLE chtbl_sort[] = { + "mta", CH_SORT_MTA, + "priority", CH_SORT_PRIORITY, + "size", CH_SORT_SIZE, + "time", CH_SORT_TIME, + "user", CH_SORT_USR, + "none", CH_SORT_NONE, + 0, -1 + }; +#define N_CHANSORT ((sizeof(chtbl_sort)/sizeof(CMD_TABLE)) - 1) + +static CMD_TABLE chtbl_ad_order[] = { + "usa", CH_USA_ONLY, + "uk", CH_UK_ONLY, + "usapref", CH_USA_PREF, + "ukpref", CH_UK_PREF, + 0, -1 + }; + +static CMD_TABLE chtbl_access[] = { + "mta", CH_MTA, + "mts", CH_MTS, + 0, -1 + }; + +static CMD_TABLE chtbl_domparse[] = { + "full", CH_DOMAIN_NORM_ALL, + "partial", CH_DOMAIN_NORM_PARTIAL, + 0, -1 + }; + +static CMD_TABLE chtbl_conv[] = { + "none", CH_CONV_NONE, + "1148", CH_CONV_1148, + "conv", CH_CONV_CONVERT, + "loss", CH_CONV_WITHLOSS, + 0, -1 + }; + +static CMD_TABLE chtbl_trace[] = { + "via", CH_TRACE_VIA, + "received", CH_TRACE_RECEIVED, + "x400", CH_TRACE_X400, + 0, -1 + }; + +static CMD_TABLE chtbl_badsender_policy[] = { + "strict", CH_BADSENDER_STRICT, + "sloppy", CH_BADSENDER_SLOPPY, + 0, -1 + }; + +static CMD_TABLE chtbl_check[] = { + "strict", CH_STRICT_CHECK, + "sloppy", CH_SLOPPY_CHECK, + NULLCP, NOTOK + }; + +/* --------------------- Begin Routines -------------------------------- */ + +chan_tai (argc, argv) +int argc; +char **argv; +{ + register CHAN *cp; + char *arg, + *p, + *ch_sort_arg[CH_MAX_SORT]; + int ind, + val, + i, j, + n_ch_sort; + + + PP_DBG (("chan_tai()")); + + if (argc < 2 || lexequ (argv[0], chn_str) != 0) return (NOTOK); + + arg = *++argv; + + if (ch_maxchans == 0) { + ch_maxchans = 10; + ch_all = (CHAN **)smalloc (sizeof(CHAN *) * ch_maxchans); + } + else if (ch_numchans + 1 == ch_maxchans) { + ch_maxchans += 10; + ch_all = (CHAN **)realloc ((char *)ch_all, + (unsigned) sizeof (CHAN *) * ch_maxchans); + if (ch_all == NULL) + err_abrt (RP_MECH, "Out of space for channels"); + } + ch_all[ch_numchans++] = cp = (CHAN *) smalloc ((sizeof (CHAN))); + ch_all[ch_numchans] = NULLCHAN; + + + /* -- Initialize the malloc'd channel -- */ + bzero ((char *)cp, sizeof(*cp)); +/* cp -> ch_sort[1] = CH_SORT_TIME; */ + cp -> ch_name = arg; + cp -> ch_access = CH_MTA; + cp -> ch_ad_order = CH_USA_ONLY; + cp -> ch_in_ad_type = AD_822_TYPE; + cp -> ch_out_ad_type = AD_822_TYPE; + cp -> ch_domain_norm = CH_DOMAIN_NORM_PARTIAL; + cp -> ch_conversion = CH_CONV_NONE; + cp -> ch_badSenderPolicy = CH_BADSENDER_STRICT; + + argc -= 2; + argv++; + + for (ind = 0; ind < argc; ind++) { + + if ((p = index (argv[ind], '=')) == NULLCP) + continue; + + *p++ = '\0'; + PP_DBG (("tai/tai_chan %s = %s", argv[ind], p)); + + switch (cmdbsrch (argv[ind], chtbl_key, N_CHANTBLENT)) { + + case CH_NAME: + cp->ch_name = p; + break; + + case CH_PROGNAME: + cp->ch_progname = p; + break; + + case CH_SHOW: + cp->ch_show = p; + break; + + case CH_KEY: + if (txt2listbpt (&cp -> ch_key, p) == NOTOK) + tai_error ("bad keys %s for %s", + p, cp -> ch_name); + break; + + case CH_CHAN_TYPE: + val = cmdbsrch (p, chtbl_types, N_CHANTYPES); + if (val == NOTOK) + tai_error ("Unknown type %s in chan %s", + p, cp->ch_name); + else + cp -> ch_chan_type = val; + break; + + case CH_DRCHAN: + cp->ch_drchan = p; + break; + + case CH_COST: + cp->ch_cost = atoi(p); + break; + + case CH_SORT: + n_ch_sort = sstr2arg + (p, CH_MAX_SORT, ch_sort_arg, " "); + + if (n_ch_sort < 0 || n_ch_sort > CH_MAX_SORT) { + tai_error ("Too many sort keys for %s", + cp -> ch_name); + n_ch_sort = CH_MAX_SORT; + } + + for (i=j=0; i < n_ch_sort; i++) { + val = cmdbsrch (ch_sort_arg[i], + chtbl_sort, N_CHANSORT); + if (val == NOTOK) + tai_error ("%s bad sort key for %s", + ch_sort_arg[i], + cp -> ch_name); + else cp->ch_sort[j++] = val; + } + break; + + case CH_IN_INFO: + cp->ch_in_info = p; + break; + + case CH_OUT_INFO: + cp->ch_out_info = p; + break; + + case CH_CONTENT_IN: + cp->ch_content_in = p; + break; + + case CH_CONTENT_OUT: + cp->ch_content_out = p; + break; + + case CH_AD_TYPE: + val = cmd_srch (p, atbl_types); + if (val == NOTOK) + tai_error ("Unknown adr type %s in chan %s", + p, cp->ch_name); + cp -> ch_in_ad_type = + cp -> ch_out_ad_type = val; + break; + + case CH_IN_AD_TYPE: + val = cmd_srch (p, atbl_types); + if (val == NOTOK) + tai_error ("Unknown inadr type %s in chan %s", + p, cp->ch_name); + else + cp -> ch_in_ad_type = val; + break; + + case CH_OUT_AD_TYPE: + val = cmd_srch (p, atbl_types); + if (val == NOTOK) + tai_error ("Unknown adr out type %s in chan %s", + p, cp->ch_name); + + else + cp -> ch_out_ad_type = val; + break; + + case CH_AD_SUBTYPE: + val = cmd_srch (p, atbl_subtypes); + if (val == NOTOK) + tai_error ("Unknown ad subtype %s in chan %s", + p, cp->ch_name); + + else + cp -> ch_in_ad_subtype = + cp -> ch_out_ad_subtype = val; + break; + + case CH_IN_SUBTYPE: + val = cmd_srch (p, atbl_subtypes); + if (val == NOTOK) + tai_error ("Unknown adr insubtype %s in chan %s", + p, cp->ch_name); + else + cp -> ch_in_ad_subtype = val; + break; + + case CH_OUT_SUBTYPE: + val = cmd_srch (p, atbl_subtypes); + if (val == NOTOK) + tai_error ("Unknown adr outsubtype %s in chan %s", + p, cp->ch_name); + else + cp -> ch_out_ad_subtype = val; + break; + + case CH_AD_ORDER: + val = cmd_srch (p, chtbl_ad_order); + if (val == NOTOK) + tai_error ("Unknown adr-order %s in chan %s", + p, cp->ch_name); + + else + cp -> ch_ad_order = val; + break; + + + case CH_BPT_IN: + if (txt2listbpt (&cp -> ch_bpt_in, p) == NOTOK) + tai_error ("Bad body part in for %s", + cp -> ch_name); + break; + + case CH_BPT_OUT: + if (txt2listbpt (&cp -> ch_bpt_out, p) == NOTOK) + tai_error ("Bad body part out for %s", + cp -> ch_name); + break; + + case CH_HDR_IN: + if (txthdr2listbpt (&cp -> ch_hdr_in, p) == NOTOK) + tai_error ("Bad hdr part in for %s", + cp -> ch_name); + break; + + case CH_HDR_OUT: + if (txthdr2listbpt (&cp -> ch_hdr_out, p) == NOTOK) + tai_error ("Bad hdr part out for %s", + cp -> ch_name); + break; + + case CH_TABLE: + if ((cp -> ch_table = tb_nm2struct (p)) == NULLTBL) + tai_error ("Unknown table %s for %s", + p, cp -> ch_name); + break; + + case CH_MTA_TABLE: + if ((cp -> ch_mta_table = tb_nm2struct (p)) == NULLTBL) + tai_error ("Unknown table %s for %s", + p, cp -> ch_name); + break; + case CH_IN_TABLE: + if ((cp -> ch_in_table = tb_nm2struct (p)) == NULLTBL) + tai_error ("Unknown table %s for %s", + p, cp -> ch_name); + break; + + case CH_AUTHTBL: + if ((cp -> ch_auth_tbl = tb_nm2struct (p)) == NULLTBL) + tai_error ("Unknown table %s for %s", + p, cp -> ch_name); + break; + + case CH_XMTA: + cp -> ch_mta = p; + break; + + case CH_ACCESS: + val = cmd_srch (p, chtbl_access); + if (val != NOTOK) + cp -> ch_access = val; + else + tai_error ("Unknown access type %s in chan %s", + p, cp->ch_name); + + break; + + case CH_PROBE: + if (*p == 'y') + cp -> ch_probe = TRUE; + break; + + case CH_DOMPARSE: + val = cmd_srch (p, chtbl_domparse); + if (val != NOTOK) + cp -> ch_domain_norm = val; + else + tai_error ("Unknown domparse %s in chan %s", + p, cp->ch_name); + + break; + + case CH_MAXPROC: + cp -> ch_maxproc = atoi (p); + break; + case CH_CONV: + val = cmd_srch (p, chtbl_conv); + if (val != NOTOK) + cp -> ch_conversion = val; + else + tai_error ("Unknown conv type %s in chan %s", + p, cp->ch_name); + + break; + case CH_TRACE_TYPE: + val = cmd_srch (p, chtbl_trace); + + if (val != NOTOK) + cp -> ch_trace_type = val; + else + tai_error ("Unknown trace type %s in chan %s", + p, cp->ch_name); + + break; + + case CH_SOLO_PROC: + if (*p == 'y') + cp -> ch_solo_proc = TRUE; + break; + + case CH_BADSENDER_POLICY: + val = cmd_srch (p, chtbl_badsender_policy); + + if (val != NOTOK) + cp -> ch_badSenderPolicy = val; + else + tai_error ("Unknown bad sender policy '%s' for chan %s", + p, cp->ch_name); + break; + + case CH_CHECK_MODE: + val = cmd_srch (p, chtbl_check); + if (val != NOTOK) + cp -> ch_strict_mode = val; + else val = CH_STRICT_CHECK; + break; + + default: + tai_error("Unknown key '%s' for %s", + argv[ind], cp -> ch_name); + } + + } + + + return (OK); +} diff --git a/Lib/tai/tai_sys.c b/Lib/tai/tai_sys.c new file mode 100644 index 0000000..95cc2a8 --- /dev/null +++ b/Lib/tai/tai_sys.c @@ -0,0 +1,487 @@ +/* tai_sys.c: system tailoring routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_sys.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_sys.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: tai_sys.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include "list_bpt.h" +#include + +extern void err_abrt (); +extern void pp_setlog (); +extern void tai_error (); +extern int arg2vstr (); + +extern char + *chndfldir, + *cmddfldir, + *dap_user, + *dap_passwd, + *formdfldir, + *lckdfldir, + *lockdir, + *loc_dom_mta, + *loc_dom_site, + *loc_or, + *logdfldir, + *mboxname, + *niftpcpf, + *niftpquedir, + *postmaster, + *adminstration_req_alt, + *pp_isodetailor, + *ppdbm, + *pplogin, + *pptsapd_addr, + *qmgr_hostname, + *quedfldir, + *tbldfldir, + *delim1, + *delim2, + *authchannel, + *authloglevel, + *submit_addr, + *sysmailfilter, + *mailfilter, + *x400_mta, + *wrndfldir; + +extern LLog + *pp_log_norm, + *pp_log_oper, + *pp_log_stat; + +extern LIST_BPT + *bodies_all, + *headers_all; + +extern int + lockstyle, + warn_interval, + warn_number, + max_hops, + max_loops, + queue_depth, + queue_fanout, + use_fsync, + disk_percent, + disk_blocks, + return_interval_low, + return_interval_norm, + return_interval_high; + + + +extern CMD_TABLE tbl_bool[]; + +#define MAUTHLOG 1 +#define MBODY_TYPES 2 +#define MBOXNAME 3 +#define MCHANDIR 4 +#define MCMDDIR 5 +#define MDBM 6 +#define MFORMDIR 7 +#define MISODELOG 8 +#define MISOTAILOR 9 +#define MLOC_DOM_MTA 10 +#define MLOC_DOM_SITE 11 +#define MLOC_OR 12 +#define MLOGDIR 13 +#define MNORMLOG 14 +#define MOPERLOG 15 +#define MPOSTMASTER 16 +#define MPPLOGIN 17 +#define MPPTSAPD_ADDR 18 +#define MQMGR_HOST 19 +#define MQUEDIR 20 +#define MTBLDIR 21 +#define MDELIM1 22 +#define MDELIM2 23 +#define MAUTHCHANNEL 24 +#define MAUTHLOGLEVEL 25 +#define MWRNDFLDIR 26 +#define LOCKSTYLE 27 +#define LOCKDIR 28 +#define WARN_INTERVAL 29 +#define WARN_NUMBER 30 +#define RETURN_INTERVAL 31 +#define MAILFILTER 32 +#define SYSMAILFILTER 33 +#define MAXLOOPS 34 +#define MAXHOPS 35 +#define X400MTA 36 +#define MHDR_TYPES 37 +#define SUBMIT_ADDR 38 +#define DAPUSER 39 +#define DAPPASSWD 40 +#define QUEUE_STRUCTURE 41 +#define USE_FSYNC 42 +#define DISK_USE 43 +#define MADMINASIGALT 44 + +/* this array is sorted - be careful if you change it! */ +static CMD_TABLE cmdtab[] = { + "adminstration_assigned_alternate_recipient", MADMINASIGALT, + "authchannel", MAUTHCHANNEL, + "authlog", MAUTHLOG, + "authloglevel", MAUTHLOGLEVEL, + "bodypart", MBODY_TYPES, + "chandir", MCHANDIR, + "cmddir", MCMDDIR, + "dap_passwd", DAPPASSWD, + "dap_user", DAPUSER, + "dbm", MDBM, + "delim1", MDELIM1, + "delim2", MDELIM2, + "diskuse", DISK_USE, + "formdir", MFORMDIR, + "fsync", USE_FSYNC, + "headertype", MHDR_TYPES, + "isode", MISOTAILOR, + "isodelog", MISODELOG, + "lockdir", LOCKDIR, + "lockstyle", LOCKSTYLE, + "loc_dom_mta", MLOC_DOM_MTA, + "loc_dom_site", MLOC_DOM_SITE, + "loc_or", MLOC_OR, + "logdir", MLOGDIR, + "mailfilter", MAILFILTER, + "maxhops", MAXHOPS, + "maxloops", MAXLOOPS, + "mboxname", MBOXNAME, + "normlog", MNORMLOG, + "nwarnings", WARN_NUMBER, + "operlog", MOPERLOG, + "postmaster", MPOSTMASTER, + "pplogin", MPPLOGIN, + "pptsapd_addr", MPPTSAPD_ADDR, + "qmgrhost", MQMGR_HOST, + "quedir", MQUEDIR, + "queuestruct", QUEUE_STRUCTURE, + "returntime", RETURN_INTERVAL, + "submit_addr", SUBMIT_ADDR, + "sysmailfilter", SYSMAILFILTER, + "tbldir", MTBLDIR, + "warninterval", WARN_INTERVAL, + "wrndfldir", MWRNDFLDIR, + "x400mta", X400MTA, + 0, -1 + }; +#define N_CMDENT ((sizeof(cmdtab)/sizeof(CMD_TABLE)) - 1) + + + +/* --------------------- Begin Routines -------------------------------- */ + + +static void do_isode_tailor(); +static void add_bodies(), add_hdrs(); +static char *argbak2str(); + +static CMD_TABLE tbl_lock_styles[] = { + "flock", LOCK_FLOCK, + "fcntl", LOCK_FCNTL, + "file", LOCK_FILE, + "lockf", LOCK_LOCKF, + 0, -1 + }; + +int sys_tai (argc, argv) /* do system wide initialisations */ +int argc; +char **argv; +{ + char *arg; + int val; + + if (argc < 2) + return (NOTOK); + arg = argv[1]; + + PP_DBG (("tai/sys_tai %s %s", argv[0], arg)); + + switch (cmdbsrch (argv[0], cmdtab, N_CMDENT)) { + case MAUTHLOG: + log_tai (pp_log_stat, &argv[1], argc-1); + break; + case MBODY_TYPES: + add_bodies (&argv[1], argc - 1); + break; + case MHDR_TYPES: + add_hdrs (&argv[1], argc - 1); + break; + case MBOXNAME: + mboxname = arg; + break; + case MCHANDIR: + chndfldir = arg; + break; + case MCMDDIR: + cmddfldir = arg; + break; + case MDBM: + ppdbm = arg; + break; + case MFORMDIR: + formdfldir = arg; + break; + case MISODELOG: + pp_setlog (&argv[1], argc - 1); + break; + case MISOTAILOR: + do_isode_tailor (&argv[1], argc-1); + break; + case MLOC_DOM_MTA: + loc_dom_mta = arg; + break; + case MLOC_DOM_SITE: + loc_dom_site = arg; + break; + case MLOC_OR: + loc_or = arg; + break; + case MLOGDIR: + logdfldir = arg; + break; + case MNORMLOG: + log_tai (pp_log_norm, &argv[1], argc-1); + break; + case MOPERLOG: + log_tai (pp_log_oper, &argv[1], argc-1); + break; + case MPOSTMASTER: + postmaster = arg; + break; + case MADMINASIGALT: + adminstration_req_alt = arg; + break; + case MPPLOGIN: + pplogin = arg; + break; + case MPPTSAPD_ADDR: + pptsapd_addr = arg; + break; + case MQMGR_HOST: + qmgr_hostname = arg; + break; + case MQUEDIR: + quedfldir = arg; + break; + case MTBLDIR: + tbldfldir = arg; + break; + case MDELIM1: + delim1 = arg; + break; + case MDELIM2: + delim2 = arg; + break; + case MAUTHCHANNEL: + authchannel = argbak2str(&argv[1]); + break; + case MAUTHLOGLEVEL: + authloglevel = arg; + break; + case MWRNDFLDIR: + wrndfldir = arg; + break; + case LOCKSTYLE: + lockstyle = cmd_srch (arg, tbl_lock_styles); + if (lockstyle == -1) { + tai_error ("Unknown lockstyle setting %s", + arg); + lockstyle = LOCK_FLOCK; + } + break; + case LOCKDIR: + lockdir = arg; + break; + + case WARN_INTERVAL: + if ((val = atoi(arg)) > 0) + warn_interval = val; + else + tai_error ("Bad warning interval %d", val); + break; + case WARN_NUMBER: + if ((val = atoi(arg)) >= 0) + warn_number = val; + else + tai_error ("Bad warning number %d", val); + break; + case RETURN_INTERVAL: + if ((val = atoi(arg)) > 0) + return_interval_norm = val; + else + tai_error ("Bad return interval time %d", val); + return_interval_high = return_interval_norm / 2; + return_interval_low = return_interval_norm * 2; + if (argc >= 3 ) { + if ((val = atoi (argv[2])) > 0) + return_interval_high = val; + else tai_error ("Bad high priority return time %d", + val); + } + if (argc >= 4) { + if ((val = atoi(argv[3])) > 0) + return_interval_low = val; + else + tai_error ("Bad low priority return time %d", + val); + } + break; + case MAILFILTER: + mailfilter = arg; + break; + case SYSMAILFILTER: + sysmailfilter = arg; + break; + case MAXHOPS: + if ((val = atoi(arg)) > 1) + max_hops = val; + else tai_error ("Bad max hops value %d", val); + break; + case MAXLOOPS: + if ((val = atoi(arg)) > 1) + max_loops = val; + else tai_error ("Bad max loops value %d", val); + break; + case X400MTA: + x400_mta = arg; + break; + case SUBMIT_ADDR: + submit_addr = arg; + break; + case DAPUSER: + dap_user = arg; + break; + case DAPPASSWD: + dap_passwd = arg; + break; + case QUEUE_STRUCTURE: + queue_depth = 1; + if ((val = atoi(arg)) > 0) + queue_fanout = val; + else + tai_error ("Bad queue fanout param %d", val); + if (argc >= 3) { + if ((val = atoi(arg)) > 0) + queue_depth = val; + else + tai_error ("Bad queue depth value %d", val); + } + break; + case USE_FSYNC: + if ((val = cmd_srch (arg, tbl_bool)) == NOTOK) + tai_error ("Bad boolean value for fsync %s", arg); + else + use_fsync = val; + break; + case DISK_USE: + if ((val = atoi(arg)) >= 0) + disk_blocks = val; + else tai_error ("Bad disk use parameter %d", val); + if (argc >= 3) { + if ((val = atoi(argv[2])) >= 0) + disk_percent = val; + else + tai_error ("Bad disk percentage figure %d", + val); + } + break; + default: + PP_DBG (("Lib/tai_sys.c/default=%s", arg)); + return (NOTOK); + } + return (OK); +} + + +/* ------------------------------------------------------------------ */ + +static void do_isode_tailor (av, ac) +char **av; +int ac; +{ + char buffer[BUFSIZ]; + int i; + + buffer[0] = 0; + for (i = 1; i < ac; i++) { + (void) strcat (buffer, av[i]); + (void) strcat (buffer, " "); + } + + if (isodesetvar (av[0], strdup (buffer), 1) == NOTOK) + tai_error ("Unknown isode variable %s", av[0]); +} + +/* ------------------------------------------------------------------ */ + +static void add_bodies (av, ac) +char **av; +int ac; +{ + int i; + LIST_BPT *new; + + for (i = 0; i < ac; i++, av ++) { + if (!isstr (*av)) + continue; + new = list_bpt_new (*av); + if (new == NULLIST_BPT) + err_abrt (RP_MECH, "Out of memory"); + list_bpt_add (&bodies_all, new); + } +} + +extern char *hdr_prefix; + +static void add_hdrs (av, ac) +char **av; +int ac; +{ + int i; + LIST_BPT *new; + char buf[BUFSIZ]; + + for (i = 0; i < ac; i++, av ++) { + if (!isstr (*av)) + continue; + (void) sprintf(buf, "%s%s", hdr_prefix, *av); + new = list_bpt_new (buf); + if (new == NULLIST_BPT) + err_abrt (RP_MECH, "Out of memory"); + list_bpt_add (&headers_all, new); + } +} + +/* ------------------------------------------------------------------ */ + +static char *argbak2str(av) /* convert back to string for now */ +char **av; + +/* The purpose of this is to allow a tailor line to be entered in the same + format as a database entry, or to postpone parsing until a later + time +*/ + +{ + char buffer[BUFSIZ]; + + (void) arg2vstr( 0, BUFSIZ, buffer, av ); /* 0 = no folding */ + PP_DBG (("tai_sys/argbak2str '%s'", buffer)); + return strdup( buffer ); +} diff --git a/Lib/tai/tai_tb.c b/Lib/tai/tai_tb.c new file mode 100644 index 0000000..3c19691 --- /dev/null +++ b/Lib/tai/tai_tb.c @@ -0,0 +1,162 @@ +/* tai_tb.c: table tailoring info */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_tb.c,v 6.0 1991/12/18 20:24:59 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/tai/RCS/tai_tb.c,v 6.0 1991/12/18 20:24:59 jpo Rel $ + * + * $Log: tai_tb.c,v $ + * Revision 6.0 1991/12/18 20:24:59 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include +#include "table.h" + + +extern void err_abrt (); +extern void tai_error (); + +static int tb_numtables = 0; +static int tb_maxtb; +static char tbl_str[] = "tbl"; + +#define CMDTNAME 1 +#define CMDTFILE 2 +#define CMDTSHOW 3 +#define CMDTFLAGS 4 +#define CMDTOVER 5 + +static CMD_TABLE tb_cmdtbl[] = { + "file", CMDTFILE, + "flags", CMDTFLAGS, + "name", CMDTNAME, + "override", CMDTOVER, + "show", CMDTSHOW, + 0, -1 +}; +#define N_TBCMDS ((sizeof(tb_cmdtbl)/sizeof(CMD_TABLE))-1) + + +#define CMDTFLINEAR 1 +#define CMDTFDBM 2 + + +static CMD_TABLE tb_flags[] = { + "linear", CMDTFLINEAR, + "dbm", CMDTFDBM, + 0, -1 +}; + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +int tbl_tai (argc, argv) +int argc; +char **argv; +{ + register Table *tbptr; + char *p, + *arg; + int ind; + + if (argc < 2 || lexequ (argv[0], tbl_str) != 0) + return (NOTOK); + + if (tb_maxtb == 0) { + tb_maxtb = 10; + tb_all = (Table **)smalloc (sizeof(Table *) * tb_maxtb); + } + else if (tb_numtables + 1 == tb_maxtb) { + tb_maxtb += 10; + tb_all = (Table **) realloc ((char *)tb_all, + (unsigned)sizeof (Table *) * tb_maxtb); + if (tb_all == NULL) + err_abrt (RP_MECH, "Out of space for tables"); + } + + + argc--; + arg = *++argv; + tb_all[tb_numtables++] = tbptr = (Table *) smalloc (sizeof (Table)); + tb_all [tb_numtables] = NULLTBL; + tbptr -> tb_name = arg; + tbptr -> tb_show = arg; + tbptr -> tb_file = arg; + tbptr -> tb_fp = NULLFILE; + tbptr -> tb_flags = TB_DBM; + tbptr -> tb_override = NULL; + argv++; + argc--; + + for (ind = 0 ; ind < argc ; ind++) { + + if ((p = index (argv[ind], '=')) == NULLCP) + continue; + *p++ = '\0'; + + switch (cmdbsrch (argv[ind], tb_cmdtbl, N_TBCMDS)) { + case CMDTNAME: + tbptr->tb_name = p; + break; + case CMDTFILE: + tbptr->tb_file = p; + break; + case CMDTSHOW: + tbptr->tb_show = p; + break; + case CMDTFLAGS: + switch (cmd_srch (p, tb_flags)) { + case CMDTFDBM: + tbptr->tb_flags = TB_DBM; + break; + case CMDTFLINEAR: + tbptr->tb_flags = TB_LINEAR; + break; + default: + tai_error ("Unknown flag %s for %s", + p, tbptr -> tb_name); + break; + } + break; + case CMDTOVER: + { + char *cp; + TableOverride *to, **tp; + + if ((cp = index(p, ':')) == NULL) + tai_error ("Illegal override syntax '%s' for %s", + p, tbptr -> tb_name); + else { + *cp++ = '\0'; + to = (TableOverride *) + smalloc (sizeof *to); + to -> tbo_key = p; + to -> tbo_value = cp; + to -> tbo_next = NULL; + for (tp = &tbptr -> tb_override; + *tp; tp = &(*tp) -> tbo_next) + continue; + *tp = to; + } + } + break; + + default: + tai_error ("unknown key %s for table %s", + argv[ind], tbptr -> tb_name); + break; + } + } + return (OK); +} diff --git a/Lib/util/Makefile b/Lib/util/Makefile new file mode 100644 index 0000000..fb4af79 --- /dev/null +++ b/Lib/util/Makefile @@ -0,0 +1,208 @@ +# Utility routines & functions +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/util/RCS/Makefile,v 6.0 1991/12/18 20:25:18 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:25:18 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = arg2str.c compress.c err_abrt.c expand.c getfpath.c lock.c \ + multcat.c multcpy.c pe_fragment.c prefix.c rename_log.c \ + rp_valstr.c siginit.c str2arg.c timeout.c timer.c tryfork.c \ + utctime.c check_close.c flip_bits.c sys5_regex.c \ + cmdbsrch.c hier_scanQ.c oid2lstr.c lstr2oid.c recrm.c diskfull.c +OBJS = arg2str.o compress.o err_abrt.o expand.o getfpath.o lock.o \ + multcat.o multcpy.o pe_fragment.o prefix.o rename_log.o \ + rp_valstr.o siginit.o str2arg.o timeout.o timer.o tryfork.o \ + utctime.o check_close.o flip_bits.o sys5_regex.o \ + cmdbsrch.o hier_scanQ.o oid2lstr.o lstr2oid.o recrm.o diskfull.o + +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) $(LCF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +SHADOW = util-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../x400/llib-lx400.ln + + +############################################################ +# +# Building Rules +# +############################################################ + +default: ${SHADOW} + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lintlib: llib-lutil.ln +llib-lutil.ln: ${SRCS} + $(LINT) -Cutil $(LLFLAGS) ${SRCS} + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +install:; + +clean: tidy + rm -f $(OBJS) llib-lutil.ln +tidy: + rm -f core ${SHADOW} *.old *.BAK + + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +arg2str.o: arg2str.c +arg2str.o: ../../h/util.h +arg2str.o: ../../h/config.h +arg2str.o: ../../h/ll_log.h +arg2str.o: ../../h/retcode.h +compress.o: compress.c +compress.o: ../../h/util.h +compress.o: ../../h/config.h +compress.o: ../../h/ll_log.h +err_abrt.o: err_abrt.c +err_abrt.o: ../../h/head.h +err_abrt.o: ../../h/util.h +err_abrt.o: ../../h/config.h +err_abrt.o: ../../h/ll_log.h +err_abrt.o: ../../h/retcode.h +expand.o: expand.c +expand.o: ../../h/util.h +expand.o: ../../h/config.h +expand.o: ../../h/ll_log.h +expand.o: ../../h/expand.h +getfpath.o: getfpath.c +getfpath.o: ../../h/util.h +getfpath.o: ../../h/config.h +getfpath.o: ../../h/ll_log.h +lock.o: lock.c +lock.o: ../../h/util.h +lock.o: ../../h/config.h +lock.o: ../../h/ll_log.h +lock.o: ../../h/sys.file.h +multcat.o: multcat.c +multcat.o: ../../h/util.h +multcat.o: ../../h/config.h +multcat.o: ../../h/ll_log.h +multcpy.o: multcpy.c +pe_fragment.o: pe_fragment.c +prefix.o: prefix.c +prefix.o: ../../h/util.h +prefix.o: ../../h/config.h +prefix.o: ../../h/ll_log.h +rename_log.o: rename_log.c +rename_log.o: ../../h/head.h +rename_log.o: ../../h/util.h +rename_log.o: ../../h/config.h +rename_log.o: ../../h/ll_log.h +rename_log.o: ../../h/retcode.h +rp_valstr.o: rp_valstr.c +rp_valstr.o: ../../h/head.h +rp_valstr.o: ../../h/util.h +rp_valstr.o: ../../h/config.h +rp_valstr.o: ../../h/ll_log.h +rp_valstr.o: ../../h/retcode.h +siginit.o: siginit.c +siginit.o: ../../h/util.h +siginit.o: ../../h/config.h +siginit.o: ../../h/ll_log.h +str2arg.o: str2arg.c +str2arg.o: ../../h/util.h +str2arg.o: ../../h/config.h +str2arg.o: ../../h/ll_log.h +timeout.o: timeout.c +timeout.o: ../../h/util.h +timeout.o: ../../h/config.h +timeout.o: ../../h/ll_log.h +timer.o: timer.c +timer.o: ../../h/util.h +timer.o: ../../h/config.h +timer.o: ../../h/ll_log.h +tryfork.o: tryfork.c +tryfork.o: ../../h/util.h +tryfork.o: ../../h/config.h +tryfork.o: ../../h/ll_log.h +utctime.o: utctime.c +utctime.o: ../../h/util.h +utctime.o: ../../h/config.h +utctime.o: ../../h/ll_log.h +check_close.o: check_close.c +check_close.o: ../../h/util.h +check_close.o: ../../h/config.h +check_close.o: ../../h/ll_log.h +flip_bits.o: flip_bits.c +sys5_regex.o: sys5_regex.c +sys5_regex.o: ../../h/config.h +cmdbsrch.o: cmdbsrch.c +cmdbsrch.o: ../../h/util.h +cmdbsrch.o: ../../h/config.h +cmdbsrch.o: ../../h/ll_log.h +hier_scanQ.o: hier_scanQ.c +hier_scanQ.o: ../../h/util.h +hier_scanQ.o: ../../h/config.h +hier_scanQ.o: ../../h/ll_log.h +oid2lstr.o: oid2lstr.c +oid2lstr.o: ../../h/util.h +oid2lstr.o: ../../h/config.h +oid2lstr.o: ../../h/ll_log.h +lstr2oid.o: lstr2oid.c +lstr2oid.o: ../../h/util.h +lstr2oid.o: ../../h/config.h +lstr2oid.o: ../../h/ll_log.h +recrm.o: recrm.c +recrm.o: ../../h/util.h +recrm.o: ../../h/config.h +recrm.o: ../../h/ll_log.h +diskfull.o: diskfull.c +diskfull.o: ../../h/util.h +diskfull.o: ../../h/config.h +diskfull.o: ../../h/ll_log.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/util/arg2str.c b/Lib/util/arg2str.c new file mode 100644 index 0000000..3803f01 --- /dev/null +++ b/Lib/util/arg2str.c @@ -0,0 +1,172 @@ +/* arg2str: list of arguments to string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/arg2str.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/arg2str.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: arg2str.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" + +extern void err_abrt (); + +/* convert an array of strings to one or more lines of 'arguments'. + * + * this is intended to be used along with the str2arg() routine. + */ + +int arg2vstr (linelen, maxlen, buf, argv) /* convert the list to a string */ + int linelen; + int maxlen; /* length of string */ + char *buf; /* where to put the output string */ + char **argv; /* the argument vector */ +{ + unsigned totlen, /* total length of current line */ + len; /* length of current argument */ + unsigned gotdelim; /* a delimiter char is in arg */ + unsigned gotpair; /* key/value pair */ + char tmpstr[8*BUFSIZ]; /* string under construction */ + register char *src, + *bp, + *dest = NULLCP; + + bp = buf; + for (totlen = gotpair = 0, *bp = '\0'; + *argv != (char *) 0; argv++) + { + if (gotpair == 0 && strcmp ("=", *argv) == 0) + { + dest = tmpstr; + gotpair = 2; /* take the next two arguments */ + continue; + } + + + if(**argv == '\0'){ + gotdelim = TRUE; + goto nextone; + } + for (src = *argv, gotdelim = FALSE; *src != '\0'; src++) + switch (*src) + { + case ' ': + case '\t': + case '=': + case ',': + case ';': + case ':': + case '/': + case '|': + case '.': + case '#': + gotdelim = TRUE; + goto nextone; + } + + nextone: + if (gotpair == 0) + dest = tmpstr; + if (gotdelim) + *dest++ = '"'; + for (src = *argv; *src != '\0'; src++) + { + switch (*src) + { + case '\b': + *dest++ = '\\'; + *dest++ = 'b'; + break; + + case '\t': + *dest++ = '\\'; + *dest++ = 't'; + break; + + case '\f': + *dest++ = '\\'; + *dest++ = 'f'; + break; + + case '\r': + *dest++ = '\\'; + *dest++ = 'r'; + break; + + case '\n': + *dest++ = '\\'; + *dest++ = 'n'; + break; + + case '\\': /* Added by Doug Kingston */ + case '\"': + *dest++ = '\\'; + *dest++ = *src; + break; + + default: + if (iscntrl (*src)) + { + *dest++ = '\\'; + *dest++ = ((*src >> 6) & 07) + '0'; + *dest++ = ((*src >> 3) & 07) + '0'; + *dest++ = (*src & 07) + '0'; + } + else + *dest++ = *src; + } + } + + if (gotdelim) + *dest++ = '"'; + + switch (gotpair) /* handle key/value differently */ + { + case 2: + *dest++ = '='; + gotpair--; + continue; + + case 1: + gotpair = 0; + } + + *dest = '\0'; + len = dest - tmpstr; + + if (totlen != 0) + { + if ((linelen > 0) && ((totlen + len) > linelen)) + { + *bp ++ = '\n'; + *bp ++ = '\t'; + maxlen -= 2; + totlen = 8; + } + else + { + *bp ++ = ' '; + maxlen --; + totlen += 1; + } + *bp = '\0'; + } + if (maxlen < len) + return NOTOK; + maxlen -= len; + for (dest = tmpstr; *dest;) + *bp ++ = *dest++; + *bp = '\0'; + totlen += len; + } + return OK; +} diff --git a/Lib/util/check_close.c b/Lib/util/check_close.c new file mode 100644 index 0000000..3a8e06e --- /dev/null +++ b/Lib/util/check_close.c @@ -0,0 +1,33 @@ +/* check_close.c: close an fopen'd fd with lots of checks. */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/check_close.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/check_close.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: check_close.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" + +extern int use_fsync; + +int check_close (fp) +FILE *fp; +{ + + if (fflush(fp) == EOF || ferror(fp)) + return NOTOK; +#ifdef HAS_FSYNC + if (use_fsync && fsync(fileno(fp)) == NOTOK) + return NOTOK; +#endif + if (fclose (fp) == EOF) + return NOTOK; + return OK; +} diff --git a/Lib/util/cmdbsrch.c b/Lib/util/cmdbsrch.c new file mode 100644 index 0000000..d9225ab --- /dev/null +++ b/Lib/util/cmdbsrch.c @@ -0,0 +1,46 @@ +/* cmdbsrch.c: binary search of tables */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/cmdbsrch.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/cmdbsrch.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: cmdbsrch.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include + + +cmdbsrch (str, cmd, entries) /* binary version of cmdsrch */ +char *str; /* test string */ +CMD_TABLE cmd[]; /* table of known commands */ +int entries; /* size of cmd table */ +{ + register int hi, lo, mid; + register int diff; + char *p; + + hi = entries-1; + lo = 0; + + for (mid=(hi+lo)/2 ; hi >= lo; mid=(hi+lo)/2) + { + p = cmd[mid].cmd_key; + if ((diff = chrcnv[*str] - chrcnv[*p]) == 0 && + (diff = lexequ(str, p))==0) + return(cmd[mid].cmd_value); + + if (diff < 0) + hi = mid - 1; + else + lo = mid+1; + } + + return(cmd[entries].cmd_value); +} diff --git a/Lib/util/compress.c b/Lib/util/compress.c new file mode 100644 index 0000000..09df10c --- /dev/null +++ b/Lib/util/compress.c @@ -0,0 +1,52 @@ +/* compress: compress out redundant, & strip trailing linear white space */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/compress.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/compress.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: compress.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + +char *compress (fromptr, toptr) +register char *fromptr; +register char *toptr; +{ + register char chr; + char *in_toptr = toptr; + /* + init to skip leading spaces + */ + chr = ' '; + + while ((*toptr = *fromptr++) != '\0') { + /* + convert newlines and tabs to only save first space + */ + if (isspace (*toptr)) { + if (chr != ' ') + *toptr++ = chr = ' '; + } + else + chr = *toptr++; + } + + + /* + remove trailing space if any + */ + if ((chr == ' ') + && (toptr != in_toptr)) + *--toptr = '\0'; + return (toptr); +} diff --git a/Lib/util/diskfull.c b/Lib/util/diskfull.c new file mode 100644 index 0000000..db3e4fa --- /dev/null +++ b/Lib/util/diskfull.c @@ -0,0 +1,119 @@ +/* diskfull.c: check available space meets requirements */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/diskfull.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/diskfull.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: diskfull.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" + +#if defined(ultrix) && defined(mips) +#include +#include +#include +#include + +#define FSTATFS fstatfs +#define STAT_FS struct fs_data + +/* +** Function Name : fstatfs +** Description : Get file system statistics. fstatfs returns +** information about the filesystem on which an open +** file resides. See statfs(3) for more information. +** Arguments : fd - open file descriptor +** buffer - ptr to memory to store struct fs_data in +** Returns : Upon successful completion, a value of 0 is returned. +** Otherwise, -1 is returned and the global variable errno +** is set to indicate the error. +** Author : David Bonnell (bonnell@coral.cs.jcu.edu.au) +** : Department of Computer Science, James Cook University +** : 7 October, 1991 +*/ +int +fstatfs(int fd, struct fs_data *buffer) +{ + struct stat buf; + struct fs_data mount[NMOUNT]; + int i, nmount; + + if (fstat(fd, &buf) < 0) return -1; /* get fs dev */ + + i=0; + nmount = getmountent(&i, mount, NMOUNT); /* get sys mount table */ + if (nmount < 0) return -1; + + for (i=0; i +#define STAT_FS struct statfs +#define FSTATFS fstatfs +#else +#ifdef SYS5 /* sys5 is different (of course!) */ +#define CHECKDISK +#include +#define STAT_FS struct statvfs +#define FSTATFS fstatvfs +#endif + /* can't be handled */ +#endif +#endif + + +fdiskfull (fd, blocks, percent) +int fd; +int blocks; +int percent; +{ +#ifdef CHECKDISK + STAT_FS fs; + + if (blocks <= 0 && percent <= 0) + return OK; + + if (FSTATFS (fd, &fs) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "failed", ("%s on %d", FSTATFS, fd)); + return OK; /* and hope... */ + } +#if defined(ultrix) && defined(mips) + if (blocks != NOTOK && fs.fd_req.bfree < blocks) +#else + if (blocks != NOTOK && fs.f_bavail < blocks) +#endif + return NOTOK; + if (percent != NOTOK) { + int tblks; /* total blocks - reserved */ + +#if defined(ultrix) && defined(mips) + tblks = fs.fd_req.btot - (fs.fd_req.bfree - fs.fd_req.bfreen); + if ((fs.fd_req.bfree * 100 / tblks) < percent) +#else + tblks = fs.f_blocks - (fs.f_bfree - fs.f_bavail); + if ((fs.f_bavail * 100 / tblks) < percent) +#endif + return NOTOK; + } +#endif + return OK; /* if we don't have the facility - lie! */ +} diff --git a/Lib/util/err_abrt.c b/Lib/util/err_abrt.c new file mode 100644 index 0000000..2361142 --- /dev/null +++ b/Lib/util/err_abrt.c @@ -0,0 +1,50 @@ +/* err_abrt: abort from an error */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/err_abrt.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/err_abrt.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: err_abrt.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include + +#ifdef lint +/*VARARGS2 */ +void err_abrt(code, fmt) +int code; +char *fmt; +{ + err_abrt (code, fmt); +} +#else + +void err_abrt (va_alist) +va_dcl +{ + va_list ap; + int code; + char tbuf[BUFSIZ]; + + va_start (ap); + + code = va_arg (ap, int); + + _asprintf (tbuf, NULLCP, ap); + + PP_OPER (NULLCP, ("err_abrt (%s) [%s]", tbuf, rp_valstr(code))); + fprintf(stderr, "err_abrt -> %s [%s]\n", tbuf, rp_valstr(code)); + va_end (ap); + + exit(code); +} +#endif diff --git a/Lib/util/expand.c b/Lib/util/expand.c new file mode 100644 index 0000000..49bb10f --- /dev/null +++ b/Lib/util/expand.c @@ -0,0 +1,144 @@ +/* expand.c */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/expand.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/expand.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: expand.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "expand.h" + +/* + * E X P A N D . C + * + * Expand expands a text string expanding macros provided + * in a vector of key and value pairs. + * + * e.g. expand(buf, "$A+$B=$(RESULT)", array) + * with Expand array[] = {"A", "1", + * "B", "2", + * "RESULT", "3", + * 0, 0}; + * gives "1+2=3" in buf. + * + * wja@uk.ac.nott.maths Wed Feb 22 15:00:26 GMT 1984 + * DPK@BRL, 13 Apr 84 Made more portable and changed array usage. + * jpo@cs.nott.ac.uk 18 July 1989 Changed to structure. + * pac@cs.nott.ac.uk Mon Mar 12 19:54:39 1990 + * added expand_dyn + */ + + +static char *exname(), *exlookup(); + +#define INC BUFSIZ + +char *expand_dyn(fmt, macros) +char *fmt; +Expand macros[]; +{ + register char *bp = NULLCP, *cp; + int ix = 0, len = 0; + char name[LINESIZE]; + + bp = (char *) malloc(INC * sizeof(*bp)); + len += INC; + + while (fmt && *fmt) { + if (ix >= len) { + /* resize */ + len += INC; + bp = (char *) realloc(bp, (unsigned)(len*sizeof(char))); + } + if (*fmt != '$') + bp[ix++] = *fmt++; + else if (*++fmt == '$') + bp[ix++] = *fmt++; + else { + fmt = exname(name, fmt); + cp = exlookup (name, macros); + while (cp && *cp) { + if (ix >= len) { + /* resize */ + len += INC; + bp = (char *) realloc(bp, + (unsigned)(len*sizeof(char))); + } + bp[ix++] = *cp++; + } + } + } + if (ix >= len) { + /* resize */ + len += INC; + bp = (char *) realloc(bp, (unsigned)(len*sizeof(char))); + } + bp[ix] = '\0'; + len = strlen(bp); + bp = (char *) realloc(bp, (unsigned) ((len+1)*sizeof(char))); + return bp; +} + +char *expand(buf, fmt, macros) +char *buf, *fmt; +Expand macros[]; +{ + register char *bp = buf, *cp; + char name[LINESIZE]; + + while(fmt && *fmt) { + if(*fmt != '$') + *bp++ = *fmt++; + else if(*++fmt == '$') + *bp++ = *fmt++; + else { + fmt = exname(name, fmt); + cp = exlookup(name, macros); + while(cp && *cp) + *bp++ = *cp++; + } + } + *bp = '\0'; + return buf; +} + +static char * +exname(buf, str) +register char *buf, *str; +{ + if(*str == '(') { + str++; + while(*str != ')' && *str != '\0') + *buf++ = *str++; + if(*str != '\0') + str++; + } + else + *buf++ = *str++; + *buf = '\0'; + return str; +} + +static char * +exlookup(name, list) +register char *name; +Expand list[]; +{ + register Expand *ep; + + for (ep = list; ep -> macro; ep++) { + if(lexequ(name, ep -> macro) == 0) + return (ep -> expansion); + } + return (""); +} diff --git a/Lib/util/flip_bits.c b/Lib/util/flip_bits.c new file mode 100644 index 0000000..62e786d --- /dev/null +++ b/Lib/util/flip_bits.c @@ -0,0 +1,43 @@ +/* flip_bits: reverse bits in char */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/flip_bits.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/flip_bits.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: flip_bits.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + +static unsigned char table[] = { +/* 0x00 */ 0x00, +/* 0x01 */ 0x08, +/* 0x02 */ 0x04, +/* 0x03 */ 0x0c, +/* 0x04 */ 0x02, +/* 0x05 */ 0x0a, +/* 0x06 */ 0x06, +/* 0x07 */ 0x0e, +/* 0x08 */ 0x01, +/* 0x09 */ 0x09, +/* 0x0a */ 0x05, +/* 0x0b */ 0x0d, +/* 0x0c */ 0x03, +/* 0x0d */ 0x0b, +/* 0x0e */ 0x07, +/* 0x0f */ 0x0f, + }; + +unsigned char flip_bits(ch) +unsigned char ch; +{ + unsigned char ret; + ret = table[(ch >> 4) & 0x0f]; + ret |= table[ch & 0x0f] << 4; + return ret; +} diff --git a/Lib/util/getfpath.c b/Lib/util/getfpath.c new file mode 100644 index 0000000..d0bec54 --- /dev/null +++ b/Lib/util/getfpath.c @@ -0,0 +1,47 @@ +/* getfpath: fix up pathnames */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/getfpath.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/getfpath.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: getfpath.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +/* + * convert a relative pathname into a full pathname - using base + * as the secret ingredient + */ + + +void getfpath (base, prog, buf) +char *base, *prog, *buf; +{ + if (*prog == '/' || strncmp (prog, "./", 2) == 0 || + strncmp (prog, "../", 3) == 0) + (void) strcpy (buf, prog); + else + (void) sprintf (buf, "%s/%s", base, prog); +} + +/* + * as above, but no buffer supplied, grab space off the heap + */ + +char *dupfpath (base, prog) +char *base, *prog; +{ + char tmpbuf[MAXPATHLENGTH]; + + getfpath (base, prog, tmpbuf); + return strdup (tmpbuf); +} diff --git a/Lib/util/hier_scanQ.c b/Lib/util/hier_scanQ.c new file mode 100644 index 0000000..3fe3b2f --- /dev/null +++ b/Lib/util/hier_scanQ.c @@ -0,0 +1,132 @@ +/* hier_scanQ.c: scan q which may stored in a hierarchy of directories */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/hier_scanQ.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/hier_scanQ.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: hier_scanQ.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include +#include +#include + +#define SIZE_INCR 1000 + +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +static void addtolist(); + +free_hier(arr, num) +char **arr; +int num; +{ + int i; + for (i = 0; i < num; i++) + free(arr[i]); + free((char *) arr); +} + +static int isNum(str) +char *str; +{ + int retval = 0; + + while (str != NULLCP && *str != '\0' + && (retval = isdigit(*str))) str++; + return retval; +} + +hier_scanQ(dname, base, pnum, parr, psize, nonMsg) +char *dname; +char *base; +int *pnum; +char ***parr; +int *psize; +IFP nonMsg; +{ + struct dirent *dp; + DIR *dirp; + char ndname[BUFSIZ]; + + if ((dirp = opendir(dname)) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, dname, + ("Can't open directory")); + return; + } + + while ((dp = readdir (dirp)) != NULL) { + if (strncmp (dp->d_name, "msg.", strlen("msg.")) == 0) + addtolist(dp->d_name, base, pnum, parr, psize); + else { + (void) sprintf (ndname, "%s/%s", + dname, dp -> d_name); + + if (isNum (dp->d_name)) { + char nbase[BUFSIZ]; + struct stat st; + + if (stat (ndname, &st) != NOTOK + && S_ISDIR(st.st_mode)) { + if (base) + (void) sprintf (nbase, + "%s/%s", + base, + dp -> d_name); + else + (void) sprintf (nbase, + dp -> d_name); + hier_scanQ(ndname, nbase, pnum, + parr, psize, nonMsg); + } else if (nonMsg != NULLIFP) + (*nonMsg) (ndname); + + } else if (nonMsg != NULLIFP && + lexequ(dp->d_name, ".") != 0 && + lexequ(dp->d_name, "..") != 0) + (*nonMsg) (ndname); + } + } + + (void) closedir (dirp); +} + +static void addtolist (name, base, pnum, parr, psize) +char *name; +char *base; +int *pnum; +char ***parr; +int *psize; +{ + char *np; + char fname[BUFSIZ]; + + if (base) + (void) sprintf (np = fname, "%s/%s", base, name); + else + np = name; + + if (*psize == *pnum) { + if (*psize == 0) { + *psize = SIZE_INCR; + *parr = (char **) smalloc ((int)sizeof (char *) * (*psize)); + } else { + *psize += SIZE_INCR; + *parr = (char **) realloc ((char *) (*parr), + (unsigned)sizeof (char *) * (*psize)); + if (*parr == NULLVP) + PP_OPER (NULLCP, + ("FATAL: Out of memory")); + } + } + (*parr)[(*pnum)++] = strdup (np); +} diff --git a/Lib/util/lock.c b/Lib/util/lock.c new file mode 100644 index 0000000..816169e --- /dev/null +++ b/Lib/util/lock.c @@ -0,0 +1,187 @@ +/* lock.c: file locking subroutines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/lock.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/lock.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: lock.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "sys.file.h" +#ifdef SUNOS4 +#include +#endif +#if defined(sun) || defined(SYS5) +#include +#endif +#include + + +static int lk_file (); +static int lk_unlck (); + +static struct { + char *name; + int mode; +} locks [FD_SETSIZE]; + +extern char *lockdir; +extern int lockstyle; +extern int lock_break_time; /* 30 minutes grace ? */ +extern time_t time (); + +FILE *flckopen (name, mode) +char *name; +char *mode; +{ + FILE *fp; + + if ((fp = fopen (name, mode)) == NULL) + return NULL; + + locks[fileno(fp)].mode = (*mode == 'r' ? O_RDONLY : O_WRONLY); + switch (lockstyle) { + case LOCK_FLOCK: +#ifdef LOCK_EX + if (flock (fileno (fp), LOCK_EX | LOCK_NB) == NOTOK) { + (void) fclose (fp); + return NULL; + } + return fp; +#else + break; +#endif + + case LOCK_FCNTL: +#ifdef F_RDLCK + { + struct flock l; + + l.l_len = 0; + l.l_start = 0; + l.l_whence = 0; + + if (*mode == 'r' && mode[1] != '+') + l.l_type = F_RDLCK; + else + l.l_type = F_WRLCK; + + if (fcntl (fileno(fp), F_SETLK, &l) < 0) { + (void) fclose (fp); + return NULL; + } + } + return fp; +#else + break; +#endif + case LOCK_LOCKF: +#ifdef F_TLOCK + if (lockf (fileno (fp), F_TLOCK, 0L) == NOTOK) { + (void) fclose (fp); + return NULL; + } + return fp; +#else + break; +#endif + default: + case LOCK_FILE: + if (lk_file (name, fileno (fp)) == NOTOK) { + (void) fclose (fp); + return NULL; + } + break; + } + PP_OPER (NULLCP, ("Specified styple of locking (%d) not supported", + lockstyle)); + return NULL; +} + +static int lk_file (name, n) +char *name; +int n; +{ + char locktmp[MAXPATHLENGTH]; + char lockname[MAXPATHLENGTH]; + struct stat st; + int fd; + time_t now; + + if (n < 0 || n >= FD_SETSIZE) + return NOTOK; + + if (fstat (n, &st) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, name, ("Can't fstat %d file", n)); + return NOTOK; + } + + (void) sprintf (locktmp, "%s/LCK%05.5o+%o.t", lockdir, + st.st_dev, st.st_ino); + (void) sprintf (lockname, "%s/LCK%05.5o+%o", + lockdir, st.st_dev, st.st_ino); + + if ((fd = open (locktmp, O_RDWR|O_CREAT, 0)) < 0) { + PP_SLOG (LLOG_EXCEPTIONS, locktmp, + ("Can't create lock temp file")); + return NOTOK; + } + (void) close (fd); + + if (stat (lockname, &st) != NOTOK) { + (void) time (&now); + if (st.st_mtime + lock_break_time < now) { + PP_NOTICE (("Forcing lock for %s", lockname)); + (void) unlink (lockname); + } + } + if (link (locktmp, lockname) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, lockname, + ("Can't lock by linking %s to ", locktmp)); + (void) unlink (locktmp); + return NOTOK; + } + (void) unlink (locktmp); + locks[fd].name = strdup (lockname); + return OK; +} + +int flckclose (fp) +FILE *fp; +{ + switch (lockstyle) { + case LOCK_FCNTL: + case LOCK_FLOCK: + if (locks[fileno(fp)].mode == O_WRONLY) + return check_close (fp); + else return fclose(fp); + + default: + case LOCK_FILE: + return lk_unlck (fp); + } +} + +static int lk_unlck (fp) +FILE *fp; +{ + int n = fileno (fp); + + if (n >= 0 && n < FD_SETSIZE && locks[n].name) { + (void) unlink (locks[n].name); + free (locks[n].name); + locks[n].name = NULLCP; + return check_close (fp); + } + (void) fclose (fp); + return NOTOK; +} diff --git a/Lib/util/lstr2oid.c b/Lib/util/lstr2oid.c new file mode 100644 index 0000000..a53b3dd --- /dev/null +++ b/Lib/util/lstr2oid.c @@ -0,0 +1,42 @@ +/* lstr2oid.c: labelled string -> OID */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/lstr2oid.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/lstr2oid.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: lstr2oid.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include + +OID lstr2oid (str) +char *str; +{ + char buf[BUFSIZ]; + char *ix; + int iy; + int copy = FALSE; + + for (ix = str, iy = 0; + NULLCP != ix && '\0' != *ix; + ix++) { + if ('(' == *ix) { + copy = TRUE; + if (iy != 0) + buf[iy++] = '.'; + } else if (')' == *ix) + copy = FALSE; + else if (TRUE == copy) + buf[iy++] = *ix; + } + buf[iy] = '\0'; + + return str2oid(buf); +} diff --git a/Lib/util/make b/Lib/util/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/util/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/util/multcat.c b/Lib/util/multcat.c new file mode 100644 index 0000000..7856942 --- /dev/null +++ b/Lib/util/multcat.c @@ -0,0 +1,44 @@ +/* multcat: concatenate strings together */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/multcat.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/multcat.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: multcat.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +/* VARARGS 1*/ +char * +multcat (va_alist) +va_dcl +{ + register va_list ap; + register char *oldstr, *ptr; + char *newstr; + unsigned newlen; + + va_start(ap); + for (newlen = 1; oldstr = va_arg(ap, char *);) + newlen += strlen (oldstr); + va_end(ap); + + ptr = newstr = smalloc ((int)newlen); + + va_start(ap); + for (; oldstr = va_arg(ap, char *); ptr--) + while(*ptr++ = *oldstr++); + va_end(ap); + + return (newstr); +} diff --git a/Lib/util/multcpy.c b/Lib/util/multcpy.c new file mode 100644 index 0000000..68a3e12 --- /dev/null +++ b/Lib/util/multcpy.c @@ -0,0 +1,37 @@ +/* multcpy: copy several strings */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/multcpy.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/multcpy.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: multcpy.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include + +/* VARARGS 2 */ +char * +multcpy (to, va_alist) +register char *to; +va_dcl +{ + register va_list ap; + register char *from; + + va_start(ap); + + while(from = va_arg(ap, char *)){ + while(*to++ = *from++); + to--; + } + va_end(ap); + return (to); /* return pointer to end of str */ +} diff --git a/Lib/util/oid2lstr.c b/Lib/util/oid2lstr.c new file mode 100644 index 0000000..787331f --- /dev/null +++ b/Lib/util/oid2lstr.c @@ -0,0 +1,83 @@ +/* oid2lstr.c: oid to labeled string */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/oid2lstr.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/oid2lstr.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: oid2lstr.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include + +char *oid2lstr(oid) +OID oid; +{ + static char buf[BUFSIZ]; + char tmp[BUFSIZ]; + char *oidstr, *num, *ix, *label; + int getLabel; + + num = oidstr = sprintoid(oid); + + if ('\0' == oidstr[0]) + return NULLCP; + + buf[0] = '\0'; + getLabel = TRUE; + + while (NULLCP != num) { + if ((ix = index(num, '.')) != NULLCP) + *ix = '\0'; + if (TRUE == getLabel) { + if (num == oidstr) { + /* first one put hack in */ + switch (atoi(num)) { + case 0: + (void) strcpy(tmp, "ccitt (0)"); + break; + case 1: + (void) strcpy(tmp, "iso (1)"); + break; + case 2: + (void) strcpy(tmp, "joint (2)"); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("First element of OID not ccitt, iso or joint")); + (void) sprintf(tmp, "(%d)", atoi(num)); + getLabel = FALSE; + } + } else { + OID toid = oid_cpy(str2oid(oidstr)); + label = oid2name (toid, OIDPART); + oid_free(toid); + if (index(label, '.') != NULLCP) { + getLabel = FALSE; + (void) sprintf (tmp, "(%d)", atoi(num)); + } else + (void) sprintf(tmp, "%s (%d)", + label, + atoi(num)); + } + } else + (void) sprintf (tmp, "(%d)", atoi(num)); + if (ix != NULLCP) { + *ix = '.'; + num = ix + 1; + } else + num = NULLCP; + if ('\0' != buf[0]) + (void) strcat(buf, " "); + (void) strcat(buf, tmp); + } + + return buf; +} + diff --git a/Lib/util/pe_fragment.c b/Lib/util/pe_fragment.c new file mode 100644 index 0000000..081cb64 --- /dev/null +++ b/Lib/util/pe_fragment.c @@ -0,0 +1,107 @@ +/* pe_fragment.c: break up big pe_strings into smaller ones */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/pe_fragment.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/pe_fragment.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: pe_fragment.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include + +static int pe_frag_aux (); + +int pe_fragment (pe, maxsize) +PE pe; +int maxsize; +{ + PE p; + + switch (pe -> pe_form) { + case PE_FORM_ICONS: + return OK; + + case PE_FORM_CONS: + switch (pe -> pe_id) { /* dont refragment yet... */ + case PE_PRIM_OCTS: + case PE_PRIM_BITS: + case PE_DEFN_IA5S: + return OK; + } + + for (p = pe -> pe_cons; p; p = p -> pe_next) + if (pe_fragment (p, maxsize) == NOTOK) + return NOTOK; + + return OK; + + case PE_FORM_PRIM: + return pe_frag_aux (pe, maxsize); + + } + return OK; +} + +static int pe_frag_aux (pe, maxsize) +PE pe; +int maxsize; +{ + char *cp; + PE last, p; + int size, n; + + if (pe -> pe_len == PE_LEN_INDF) + return OK; + if (pe -> pe_len < maxsize) + return OK; + + switch (pe -> pe_id) { + case PE_PRIM_OCTS: + case PE_DEFN_IA5S: + cp = (char *) pe -> pe_prim; + pe -> pe_form = PE_FORM_CONS; + last = NULLPE; + size = pe->pe_len; + pe -> pe_len = 0; + pe -> pe_prim = NULLPED; + while (size > 0) { + n = size > maxsize ? maxsize : size; + p = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, + PE_PRIM_OCTS); + if (pe == NULLPE) + return NOTOK; + if ((p -> pe_prim = PEDalloc (n)) == NULLPED) { + pe_free(p); + return NOTOK; + } + p -> pe_len = n; + PEDcpy (cp, p -> pe_prim, n); + if (last == NULLPE) { + if (seq_add (pe, p, -1) == NOTOK) + return NOTOK; + } + else { + if (seq_addon (pe, last, p) == NOTOK) + return NOTOK; + } + cp += n; + size -= n; + last = p; + } + break; + + default: + break; + } + return OK; +} + + diff --git a/Lib/util/prefix.c b/Lib/util/prefix.c new file mode 100644 index 0000000..060dd8a --- /dev/null +++ b/Lib/util/prefix.c @@ -0,0 +1,31 @@ +/* prefix: Determine if str1 is the prefix of str2 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/prefix.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/prefix.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: prefix.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +extern char chrcnv[]; + +int prefix(str1, str2) +register char *str1; +register char *str2; +{ + while(*str1) + if(chrcnv[*str1++] != chrcnv[*str2++]) + return (FALSE); + + return (TRUE); +} diff --git a/Lib/util/recrm.c b/Lib/util/recrm.c new file mode 100644 index 0000000..7ae2bc6 --- /dev/null +++ b/Lib/util/recrm.c @@ -0,0 +1,89 @@ +/* recrm: recursive remove */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/recrm.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/recrm.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: recrm.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include +#include + +static char currentdir[BUFSIZ]; + +int rmFiles(entry) +struct dirent *entry; +{ + struct stat statbuf; + char cbuf[BUFSIZ]; + + if (*entry->d_name == '.' && + (strcmp(entry->d_name,".") == 0) + || (strcmp(entry->d_name,"..") == 0)) + return 0; + (void) strcpy (cbuf, currentdir); + (void) strcat (cbuf, "/"); + (void) strcat (cbuf, entry -> d_name); + + if (stat(cbuf, &statbuf) != OK) { + PP_SLOG (LLOG_EXCEPTIONS, cbuf, ("Can't stat file")); + return 0; + } + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) + return 1; + else { + if (unlink(cbuf) == NOTOK) /* ignore rmdir will catch it */ + PP_SLOG(LLOG_EXCEPTIONS, cbuf, + ("can't remove file")); + else + PP_TRACE(("Removed '%s'", cbuf)); + return 0; + } +} + +/* recursive rmdir */ +recrm (dir) +char *dir; +{ + struct dirent **namelist, **ix; + int noOfSubdirs, i; + char buf[BUFSIZ]; + int retval = OK; + char *cdp; + + (void) strcpy (buf, dir); /* for our use */ + (void) strcpy (currentdir, dir); /* for rmFiles use */ + cdp = buf + strlen(buf); + + noOfSubdirs = _scandir(buf, &namelist, rmFiles, NULLIFP); + + for (i = 0, ix = namelist; i++ < noOfSubdirs && *ix; ix++) { + *cdp ++ = '/'; + (void) strcpy (cdp, (*ix) -> d_name); + if (recrm (buf) == NOTOK) { + retval = NOTOK; + break; + } + + if (rmdir (buf) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, buf, + ("Can't remove directory")); + retval = NOTOK; + break; + } + PP_TRACE(("Removed directory '%s'", buf)); + *-- cdp = 0; + } + + if (namelist) free((char *) namelist); + return retval; +} + diff --git a/Lib/util/rename_log.c b/Lib/util/rename_log.c new file mode 100644 index 0000000..3188fa8 --- /dev/null +++ b/Lib/util/rename_log.c @@ -0,0 +1,28 @@ +/* rename_log.c - renames the log file needed for channel initialisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/rename_log.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/rename_log.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: rename_log.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "head.h" + + +rename_log (newname) +char *newname; +{ + + ll_hdinit (pp_log_oper, newname); + ll_hdinit (pp_log_stat, newname); + ll_hdinit (pp_log_norm, newname); +} diff --git a/Lib/util/rp_valstr.c b/Lib/util/rp_valstr.c new file mode 100644 index 0000000..054ea2a --- /dev/null +++ b/Lib/util/rp_valstr.c @@ -0,0 +1,106 @@ +/* rp_valstr: convery values to strings */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/rp_valstr.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/rp_valstr.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: rp_valstr.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "head.h" + +char * +rp_valstr (val) /* return text string for reply value */ +int val; +{ + static char noval[] = "*** Illegal: 0000"; + /* (noval[0] == '*') => illegal */ + + switch (val){ + case RP_DONE: + return ("DONE"); + case RP_OK: + return ("OK"); + case RP_MOK: + return ("MOK"); + case RP_HOK: + return ("HOK"); + case RP_DOK: + return ("DOK"); + case RP_MAST: + return ("MAST"); + case RP_SLAV: + return ("SLAV"); + case RP_AOK: + return ("AOK"); + case RP_NET: + return ("NET"); + case RP_BHST: + return ("BHST"); + case RP_DHST: + return ("DHST"); + case RP_LIO: + return ("LIO"); + case RP_NIO: + return ("NIO"); + case RP_LOCK: + return ("LOCK"); + case RP_EOF: + return ("EOF"); + case RP_NS: + return ("NS"); + case RP_AGN: + return ("AGN"); + case RP_PARSE: + return ("PARSE"); + case RP_TIME: + return ("TIME"); + case RP_NOOP: + return ("NOOP"); + case RP_FIO: + return ("FIO"); + case RP_FCRT: + return ("FCRT"); + case RP_PROT: + return ("PROT"); + case RP_RPLY: + return ("RPLY"); + case RP_MECH: + return ("MECH"); + case RP_NO: + return ("NO"); + case RP_NDEL: + return ("NDEL"); + case RP_HUH: + return ("HUH"); + case RP_NCMD: + return ("NCMD"); + case RP_PARM: + return ("PARM"); + case RP_UCMD: + return ("UCMD"); + case RP_USER: + return ("USER"); + case RP_FOPN: + return ("FOPN"); + case RP_NAUTH: + return ("NAUTH"); + case RP_BAD: + return ("BAD"); + default: + break; + } + /* print illegal octal value */ + noval[15] = rp_gbbit (val) + '0'; + noval[16] = rp_gcbit (val) + '0'; + noval[17] = rp_gsbit (val) + '0'; + return (noval); +} diff --git a/Lib/util/siginit.c b/Lib/util/siginit.c new file mode 100644 index 0000000..dd39c25 --- /dev/null +++ b/Lib/util/siginit.c @@ -0,0 +1,80 @@ +/* signals: catch some disatorous signals */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/siginit.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/siginit.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: siginit.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +#ifndef sigmask +#define sigmask(m) (1<< ((m) - 1)) +#endif + +static SFD onsig (); + +void siginit () +{ + int mask; + + mask = sigblock (sigmask(SIGILL) | + sigmask(SIGFPE) | + sigmask(SIGBUS) | + sigmask(SIGSEGV) | + sigmask(SIGSYS) | + sigmask(SIGPIPE) ); + (void) signal (SIGILL, onsig); + (void) signal (SIGFPE, onsig); + (void) signal (SIGBUS, onsig); + (void) signal (SIGSEGV, onsig); + (void) signal (SIGSYS, onsig); + (void) signal (SIGPIPE, onsig); + (void) sigsetmask (mask); +} + +/* ARGSUSED */ +#ifdef SYS5 +static SFD onsig (sig) +int sig; +#else +static SFD onsig (sig, code, context) +int sig, code; +struct sigcontext *context; +#endif +{ +#ifdef BSD43 + extern char *sys_siglist[]; +#endif + + (void) signal (sig, SIG_DFL); /* to stop recursion */ + (void) signal (SIGIOT, SIG_DFL); /* for abort */ + (void) signal (SIGILL, SIG_DFL); /* for abort too */ +#ifdef SIGABRT + (void) signal (SIGABRT, SIG_DFL); +#endif + (void) sigsetmask (sigblock (0) & ~ (sigmask(SIGILL) | sigmask(SIGIOT) +#ifdef SIGABRT + | sigmask(SIGABRT) +#endif + )); +#ifndef BSD43 + PP_OPER (NULLCP, + ("Process dying on signal %d", sig)); +#else + PP_OPER (NULLCP, + ("Process dying on signal %d (%s)", sig, sys_siglist[sig])); +#endif + (void) abort (); + /* NOTREACHED */ +} diff --git a/Lib/util/str2arg.c b/Lib/util/str2arg.c new file mode 100644 index 0000000..7ddf4f2 --- /dev/null +++ b/Lib/util/str2arg.c @@ -0,0 +1,206 @@ +/* str2arg.c: convert a string into a list of args with + key = value processing */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/str2arg.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/str2arg.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: str2arg.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +/* convert string into argument list + * + * stash a pointer to each field into the passed array. + * any common seperators split the words. extra white-space + * between fields is ignored. + * + * if the separator is '=', then the current argument position in + * the array points to "=", the next the one is the key and the + * value follows it. This permits detecting variable assignment, + * in addition to positional arguments. + * i.e., key=value -> = key value + * + * specially-interpreted characters: + * space, tab, double-quote, backslash, comma, equal, slash, period, + * semi-colon, colon, carriage return, and line-feed (newline). + * preceding a special char with a backslash removes its + * interpretation. a backslash not followed by a special is used + * to preface an octal specification for one character + * + * a string begun with double-quote has only double-quote and + * backslash as special characters. + * + * a field which begins with a hash (#) is interpreted + * as marking the rest of the line as a comment and it is skipped, as + * are blank lines + */ + +extern int errno; + +int str2arg (srcptr, maxf, argv)/* convert srcptr to argument list */ + register char *srcptr; /* source data */ + int maxf; /* maximum number of permitted fields */ + char *argv[]; /* where to put the pointers */ +{ + char gotquote; /* currently parsing quoted string */ + char lastdlm; /* last delimeter character */ + register int ind; + register char *destptr; + + if (srcptr == 0) + { + errno = EINVAL; /* emulate system-call failure */ + return (NOTOK); + } + + for (lastdlm = (char) NOTOK, ind = 0, maxf -= 2; *srcptr != '\0'; ind++) + { + if (ind >= maxf) + { + errno = E2BIG; /* emulate system-call failure */ + return (NOTOK); + } + for (argv[ind] = destptr = srcptr; isspace (*srcptr); srcptr++) + ; /* skip leading white space */ +/* */ + + for (gotquote = FALSE; ; ) + { + switch (*srcptr) + { + default: /* just copy it */ + *destptr++ = *srcptr++; + break; + + case '\"': /* beginning or end of string */ + case '\'': + if (gotquote && gotquote == *srcptr) + gotquote = FALSE; + else if (gotquote) + *destptr ++ = *srcptr; + else + gotquote = *srcptr; + srcptr++; + break; + + case '\\': /* quote next character */ + srcptr++; /* just skip the back-slash */ + switch (*srcptr) + { /* convert octal values */ + case 'r': + *destptr++ = '\r'; + srcptr++; + break; + + case 'n': + *destptr++ = '\n'; + srcptr++; + break; + + case 'b': + *destptr++ = '\b'; + srcptr++; + break; + + case 'f': + *destptr++ = '\f'; + srcptr++; + break; + + default: + if (*srcptr >= '0' && *srcptr <= '7') + { + *destptr = '\0'; + do + *destptr = (*destptr << 3) | (*srcptr++ - '0'); + while (*srcptr >= '0' && *srcptr <= '7'); + destptr++; + break; + } /* otherwise DROP ON THROUGH */ + case '\\': + case '\"': + case ' ': + case ',': + case '\t': + case ';': + case '#': + case ':': + case '=': + case '/': + case '|': + *destptr++ = *srcptr++; + break; /* just copy it */ + } /* DROP ON THROUGH */ + break; + + case '=': /* make '=' prefix to pair */ + if (gotquote) + { + *destptr++ = *srcptr++; + break; + } + + ind++; /* put value ahead of '=' */ + + argv[ind] = argv[ind - 1]; + lastdlm = '='; + argv[ind - 1] = "="; + *destptr = '\0'; + srcptr++; + goto nextarg; + + case ' ': + case '\t': + case '\n': + case '\r': + case ',': + case ';': + case '#': + case ':': + case '/': + case '|': + if (gotquote) + { /* don't interpret the char */ + *destptr++ = *srcptr++; + break; + } + + if (isspace (lastdlm)) + { + if (isspace (*srcptr)) + { /* shouldn't be possible */ + errno = EINVAL; + return (NOTOK); + } + else + if (*srcptr != '#') + ind--; /* "xxx , yyy" is only 2 fields */ + } + lastdlm = *srcptr; + srcptr++; + case '\0': + *destptr = '\0'; + goto nextarg; + } + + lastdlm = (char) NOTOK; /* disable when field started */ + } + + nextarg: + if (argv[ind][0] == '\0' && lastdlm == '#') + break; /* rest of line is comment */ + } + + argv[ind] = (char *) 0; + return (ind); +} diff --git a/Lib/util/sys5_regex.c b/Lib/util/sys5_regex.c new file mode 100644 index 0000000..f51c3c3 --- /dev/null +++ b/Lib/util/sys5_regex.c @@ -0,0 +1,75 @@ +#include + +#ifdef SYS5 + +/* sys5_regex.c: system 5 Regex emulation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/sys5_regex.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/sys5_regex.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: sys5_regex.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + +/* + * Emulation of UCB regular expressions routines using + * the ATT variety. Note that the regex syntax is not + * identical (ATT has extra features) so it may be necessary + * to preprocess the string before passing to regcmp(). + * + * I am not sure if my mapping of the return from regex() is + * adequate. It may also be necessary to count '(...)$n' parts + * of the regular expression to be able to provide return value + * storage for regex(). + * + * You probably need to lib agains libPW for these routines but + * it may be necessary to include an explicit "-lc" before the + * "-lPW" so as not to pick up other (unwanted) PWB routines. + */ + +static char * complied_regex; + +char * re_comp(s) +char *s; +{ + char * res; + extern char * regcmp(); + + if (s == (char *)0 || *s == '\0') + return (char *)0; + + res = regcmp(s, 0); + if (res == (char *)0) + return "invalid regular expression"; + + if (complied_regex != (char *)0) + free(complied_regex); + + complied_regex = res; + return (char *)0; +} + +re_exec(s) +char *s; +{ + extern char * regex(); + + if (complied_regex == (char *)0) + return -1; + + if (regex(complied_regex, s) == (char *)0) + return 0; + else + return 1; +} +#else + +sys5_regex_stub () {} + +#endif /* SYS5 */ diff --git a/Lib/util/timeout.c b/Lib/util/timeout.c new file mode 100644 index 0000000..8ff34b0 --- /dev/null +++ b/Lib/util/timeout.c @@ -0,0 +1,54 @@ +/* timeout.c: provide a timeout function */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/timeout.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/timeout.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: timeout.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include +#include "util.h" + + + +/* __________________________________________________________________________ + + +provide a timeout function for jobs that could potentially hang +Only one entry is given - timeout(value) +timeout(value) will be longjumped back to + +____________________________________________________________________________*/ + + + + +jmp_buf _timeobuf; +static SFP oldalrm; + +/* ARGSUSED */ +SFD _tcatch(sig) +int sig; +{ + longjmp(_timeobuf,1); +} + + +void _timeout(val) +unsigned val; +{ + if(val) + oldalrm = signal (SIGALRM, _tcatch); + (void) alarm(val); + if (!val) + (void) signal (SIGALRM, oldalrm); +} diff --git a/Lib/util/timer.c b/Lib/util/timer.c new file mode 100644 index 0000000..88248e6 --- /dev/null +++ b/Lib/util/timer.c @@ -0,0 +1,68 @@ +/* timer.c: utilities to provide timing information */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/timer.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/timer.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: timer.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +#define NBBY 8 /* no. bits / byte */ + +static void tvsub (); + +void timer_start (tv) +struct timeval *tv; +{ +#ifdef UNICORN + (void) gettimeofday (tv); +#else + (void) gettimeofday (tv, (struct timezone *)0); +#endif +} + +void timer_end (tv, cc, string) +struct timeval *tv; +int cc; +char *string; +{ + long ms; + float bs; + struct timeval stoptime, td; +#ifdef UNICORN /* funny gettimeofday */ + (void) gettimeofday (&stoptime); +#else + (void) gettimeofday (&stoptime, (struct timezone *)0); +#endif + + tvsub (&td, &stoptime, tv); + ms = (td.tv_sec * 1000) + (td.tv_usec / 1000); + bs = (((float) cc * NBBY * 1000) / (float) (ms ? ms : 1)) / NBBY; + + PP_NOTICE (("%s: %d bytes in %d.%02d seconds (%.2f Kbytes/s)", + string, cc, td.tv_sec, td.tv_usec / 10000, bs / 1024)); +} + +static void tvsub (tdiff, t1, t0) +register struct timeval *tdiff, + *t1, + *t0; +{ + tdiff -> tv_sec = t1 -> tv_sec - t0 -> tv_sec; + tdiff -> tv_usec = t1 -> tv_usec - t0 -> tv_usec; + if (tdiff -> tv_usec < 0) + tdiff -> tv_sec--, tdiff -> tv_usec += 1000000; +} + + diff --git a/Lib/util/tryfork.c b/Lib/util/tryfork.c new file mode 100644 index 0000000..b985be2 --- /dev/null +++ b/Lib/util/tryfork.c @@ -0,0 +1,28 @@ +/* tryfork: attempt to fork a child - makes several attempts */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/tryfork.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/tryfork.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: tryfork.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +int tryfork() +{ + int i, pid; + + for(i = 0; i < MAXFORK; sleep(1), i++) + if((pid = fork()) != -1) + break; + return pid; +} diff --git a/Lib/util/utctime.c b/Lib/util/utctime.c new file mode 100644 index 0000000..8e9753c --- /dev/null +++ b/Lib/util/utctime.c @@ -0,0 +1,90 @@ +/* utctime: utctime functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/utctime.c,v 6.0 1991/12/18 20:25:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/util/RCS/utctime.c,v 6.0 1991/12/18 20:25:18 jpo Rel $ + * + * $Log: utctime.c,v $ + * Revision 6.0 1991/12/18 20:25:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +UTC time_t2utc (); +time_t utc2time_t (); +UTC utcdup (); +time_t time (); + +UTC time_t2utc(t) +time_t t; +{ + struct tm *tm; + struct UTCtime uts; + + tm = gmtime (&t); + tm2ut (tm, &uts); + return utcdup(&uts); +} + + +UTC utclocalise(utc) +UTC utc; +{ + time_t ti; + struct tm *tm; + struct UTCtime uts; + + ti = utc2time_t(utc); + tm = localtime(&ti); + tm2ut (tm, &uts); +#ifdef sun + if (tm -> tm_gmtoff != 0) { + uts.ut_flags |= UT_ZONE; + uts.ut_zone = tm -> tm_gmtoff / 60; + } +#endif + return utcdup(&uts); +} + +UTC utcdup (utc) +UTC utc; +{ + UTC ut; + + ut = (UTC) smalloc (sizeof *ut); + *ut = *utc; + return ut; +} + +time_t utc2time_t(utc) +UTC utc; +{ + struct tm *tm; + if (utc == NULLUTC) + return (time_t) 0; + if (utc -> ut_mon <= 0) utc -> ut_mon = 1; /* hack around isode bug */ + tm = ut2tm (utc); + return gtime (tm); +} + +UTC utcnow () +{ + time_t now; + + (void) time (&now); + return time_t2utc (now); +} + +int utcequ (ut1, ut2) +UTC ut1, ut2; +{ + return bcmp ((char *)ut1, (char *)ut2, sizeof *ut1); +} diff --git a/Lib/version.major b/Lib/version.major new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/Lib/version.major @@ -0,0 +1 @@ +6 diff --git a/Lib/version.minor b/Lib/version.minor new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Lib/version.minor @@ -0,0 +1 @@ +0 diff --git a/Lib/version.sh b/Lib/version.sh new file mode 100755 index 0000000..8372550 --- /dev/null +++ b/Lib/version.sh @@ -0,0 +1,48 @@ +: run this script through /bin/sh + +: this hacks past a bug in make... +exec 3<&- 4<&- 5<&- 6<&- 7<&- + +OFS="$IFS" IFS=: + +if [ "x$1" = x ]; then echo 'usage: version.sh module' 1>&2; exit 1; fi + +for A in rprompt hostname uname who +do + for D in $PATH + do + if [ ! -f $D/$A ]; then + continue + fi + case $A in + rprompt) LOCAL=`$A %h` + ;; + hostname) LOCAL=`$A` + ;; + uname) LOCAL=`$A -n` + ;; + who) LOCAL=`$A am i | sed -e 's%^\(.*\)!.*$%\1%'` + ;; + esac + break + done + if [ "x$LOCAL" != x ]; then + break + fi +done + +IFS= + +if [ ! -r version.major ]; then echo 0 > version.major; fi +if [ ! -r version.minor ]; then echo 1 > version.minor; fi +if [ ! -r version.local ]; then echo 0 > version.local; fi +echo `cat version.major` `cat version.minor` `cat version.local` $1 $2 > version +rm -f version.c version.local + +awk ' { major = $1; minor = $2; local = $3 + 1; sfw = $4; + if (NF >= 5) note = $5; else note = ""; } +END { printf "char *%sversion = \"%s%s %d.%d #%d ", sfw, sfw, note, major, minor, local + printf "%d\n", local > "version.local"; }' < version +echo '('$LOCAL') of '`date`'";' + +rm -f version diff --git a/Lib/x400/Makefile b/Lib/x400/Makefile new file mode 100644 index 0000000..7075ff7 --- /dev/null +++ b/Lib/x400/Makefile @@ -0,0 +1,341 @@ +# PP X400 1988 asn1 stuff +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/Makefile,v 6.0 1991/12/18 20:25:37 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:25:37 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + +SRCS = enctypes2mem.c Toks_tables.c MTA_tables.c MTA-ops.c IOB_tables.c \ + Auth_tables.c Ext_tables.c Trans_tables.c\ + RTS84_tables.c fixorig.c rasn.c + +OBJS = enctypes2mem.o Toks_tables.o MTA_tables.o MTA-ops.o IOB_tables.o \ + Auth_tables.o Ext_tables.o Trans_tables.o\ + RTS84_tables.o fixorig.o rasn.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +PYFLAGS = -P +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(LIBCCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) +SHADOW = x400-made + +LINTLIBS = ../addr/llib-laddr.ln \ + ../charset/llib-lcs.ln \ + ../format/llib-lfmt.ln \ + ../io/llib-lio.ln \ + ../or/llib-lor.ln \ + ../parse/llib-lparse.ln \ + ../pp/llib-lpp.ln \ + ../qmgr/llib-lqmgr.ln \ + ../table/llib-ltable.ln \ + ../tai/llib-ltai.ln \ + ../util/llib-lutil.ln + +############################################################ +# +# Building Rules +# +############################################################ + +default: ${SHADOW} + + +${SHADOW}: $(OBJS) + $(AR) r$(ARFLAGS) ../libpp.a $? + touch $@ + +lintlib: llib-lx400.ln +llib-lx400.ln: $(SRCS) + $(LINT) $(LLFLAGS) -Cx400 $(SRCS) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) $(LINTISODE) + +############################################################ +# +# token modules +# +############################################################ + +Toks_tables.o: Auth-types.h + +Toks_tables.c Toks-types.h: tokens.py + $(PEPSY) $(POFLAGS) -A -h -f tokens.py + -cmp -s Toks-types.h $(HEADERS)/Toks-types.h || \ + cp Toks-types.h $(HEADERS)/Toks-types.h + -if [ -f Toks_defs.h ]; then \ + cmp -s Toks_defs.h $(HEADERS)/Toks_defs.h || \ + cp Toks_defs.h $(HEADERS)/Toks_defs.h; \ + fi + -if [ -f Toks_pre_defs.h ]; then \ + cmp -s Toks_pre_defs.h $(HEADERS)/Toks_pre_defs.h || \ + cp Toks_pre_defs.h $(HEADERS)/Toks_pre_defs.h; \ + fi + +############################################################ +# +# Auth modules +# +############################################################ + +Auth_tables.o: Auth-types.h + +Auth_tables.c Auth-types.h: authen.py + $(PEPSY) $(POFLAGS) -A -h -f authen.py + -cmp -s Auth-types.h $(HEADERS)/Auth-types.h || \ + cp Auth-types.h $(HEADERS)/Auth-types.h + -if [ -f Auth_defs.h ]; then \ + cmp -s Auth_defs.h $(HEADERS)/Auth_defs.h || \ + cp Auth_defs.h $(HEADERS)/Auth_defs.h; \ + cmp -s Auth_pre_defs.h $(HEADERS)/Auth_pre_defs.h || \ + cp Auth_pre_defs.h $(HEADERS)/Auth_pre_defs.h; \ + fi + +############################################################ +# +# MTA modules +# +############################################################ + +MTA_tables.o: MTA-types.h + +MTA-asn.py:mta.ry + $(ROSY) $(RYFLAGS) -pepsy -o $@ mta.ry + -cmp -s MTA-ops.h $(HEADERS)/MTA-ops.h ||\ + cp MTA-ops.h $(HEADERS)/MTA-ops.h + +MTA-types.h MTA_tables.c: MTA-asn.py + $(PEPSY) $(POFLAGS) -A -h -f MTA-asn.py + -cmp -s MTA-types.h $(HEADERS)/MTA-types.h || \ + cp MTA-types.h $(HEADERS)/MTA-types.h + -if [ -f MTA_defs.h ]; then \ + cmp -s MTA_defs.h $(HEADERS)/MTA_defs.h || \ + cp MTA_defs.h $(HEADERS)/MTA_defs.h; \ + cmp -s MTA_pre_defs.h $(HEADERS)/MTA_pre_defs.h || \ + cp MTA_pre_defs.h $(HEADERS)/MTA_pre_defs.h; \ + fi + +############################################################ +# +# Extension stuff +# +############################################################ + +Ext_tables.o: Ext-types.h + +Ext-types.h Ext_tables.c: extent.py + $(PEPSY) $(POFLAGS) -A -h -f extent.py + -cmp -s Ext-types.h $(HEADERS)/Ext-types.h || \ + cp Ext-types.h $(HEADERS)/Ext-types.h + -if [ -f Ext_defs.h ]; then \ + cmp -s Ext_defs.h $(HEADERS)/Ext_defs.h || \ + cp Ext_defs.h $(HEADERS)/Ext_defs.h; \ + cmp -s Ext_pre_defs.h $(HEADERS)/Ext_pre_defs.h || \ + cp Ext_pre_defs.h $(HEADERS)/Ext_pre_defs.h; \ + fi + +############################################################ +# +# Trans stuff +# +############################################################ + +Trans_tables.o: Trans-types.h + +Trans-types.h Trans_tables.c: transfer.py + $(PEPSY) $(POFLAGS) -A -h -f transfer.py + -cmp -s Trans-types.h $(HEADERS)/Trans-types.h ||\ + cp Trans-types.h $(HEADERS)/Trans-types.h + -if [ -f Trans_defs.h ]; then\ + cmp -s Trans_defs.h $(HEADERS)/Trans_defs.h ||\ + cp Trans_defs.h $(HEADERS)/Trans_defs.h; \ + cmp -s Trans_pre_defs.h $(HEADERS)/Trans_pre_defs.h ||\ + cp Trans_pre_defs.h $(HEADERS)/Trans_pre_defs.h; \ + fi + +############################################################ +# +# Information Object stuff +# +############################################################ + +IOB_tables.o: IOB-types.h + +IOB-types.h IOB_tables.c: iob.py + $(PEPSY) $(POFLAGS) -A -h -f iob.py + -cmp -s IOB-types.h $(HEADERS)/IOB-types.h ||\ + cp IOB-types.h $(HEADERS)/IOB-types.h + -if [ -f IOB_defs.h ]; then \ + cmp -s IOB_defs.h $(HEADERS)/IOB_defs.h ||\ + cp IOB_defs.h $(HEADERS)/IOB_defs.h; \ + cmp -s IOB_pre_defs.h $(HEADERS)/IOB_pre_defs.h ||\ + cp IOB_pre_defs.h $(HEADERS)/IOB_pre_defs.h; \ + fi + +############################################################ +# +# RTS 84 stuff +# +############################################################ + +RTS84_tables.o: RTS84-types.h + +RTS84-types.h RTS84_tables.c: Rts_posy.py + $(PEPSY) $(POFLAGS) -A -h -f Rts_posy.py + -cmp -s RTS84-types.h $(HEADERS)/RTS84-types.h ||\ + cp RTS84-types.h $(HEADERS)/RTS84-types.h + -if [ -f RTS84_defs.h ]; then \ + cmp -s RTS84_defs.h $(HEADERS)/RTS84_defs.h ||\ + cp RTS84_defs.h $(HEADERS)/RTS84_defs.h; \ + cmp -s RTS84_pre_defs.h $(HEADERS)/RTS84_pre_defs.h ||\ + cp RTS84_pre_defs.h $(HEADERS)/RTS84_pre_defs.h; \ + fi + +############################################################ +# +# Other stuff +# +############################################################ + +install:; + +clean: tidy + rm -f *.h ${OBJS} llib-lx400.ln \ + Toks* Auth* MTA* Ext* \ + Trans* IOB* RTS84* \ + $(HEADERS)/Toks-types.h $(HEADERS)/Toks_defs.h \ + $(HEADERS)/Toks_pre_defs.h \ + $(HEADERS)/Auth-types.h $(HEADERS)/Auth_defs.h \ + $(HEADERS)/Auth_pre_defs.h \ + $(HEADERS)/MTA-ops.h $(HEADERS)/MTA-types.h \ + $(HEADERS)/MTA_defs.h $(HEADERS)/MTA_pre_defs.h \ + $(HEADERS)/Ext-types.h $(HEADERS)/Ext_defs.h \ + $(HEADERS)/Ext_pre_defs.h \ + $(HEADERS)/Trans-types.h $(HEADERS)/Trans_defs.h \ + $(HEADERS)/Trans_pre_defs.h \ + $(HEADERS)/IOB-types.h $(HEADERS)/IOB_defs.h \ + $(HEADERS)/IOB_pre_defs.h \ + $(HEADERS)/RTS84-types.h $(HEADERS)/RTS84_defs.h \ + $(HEADERS)/RTS84_pre_defs.h +tidy: + rm -f core a.out Makefile.old $(SHADOW) + + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +enctypes2mem.o: enctypes2mem.c +enctypes2mem.o: ../../h/util.h +enctypes2mem.o: ../../h/config.h +enctypes2mem.o: ../../h/ll_log.h +enctypes2mem.o: ../../h/tb_bpt84.h +enctypes2mem.o: ../../h/list_bpt.h +enctypes2mem.o: ../../h/tb_p1.h +Toks_tables.o: Toks_tables.c +Toks_tables.o: Toks-types.h +Toks_tables.o: Auth-types.h +MTA_tables.o: MTA_tables.c +MTA_tables.o: MTA-types.h +MTA_tables.o: Toks-types.h +MTA_tables.o: Auth-types.h +MTA-ops.o: MTA-ops.c +MTA-ops.o: MTA-types.h +MTA-ops.o: Toks-types.h +MTA-ops.o: Auth-types.h +MTA-ops.o: MTA-ops.h +IOB_tables.o: IOB_tables.c +IOB_tables.o: IOB-types.h +IOB_tables.o: MTA-types.h +IOB_tables.o: Toks-types.h +IOB_tables.o: Auth-types.h +Auth_tables.o: Auth_tables.c +Auth_tables.o: Auth-types.h +Ext_tables.o: Ext_tables.c +Ext_tables.o: Ext-types.h +Ext_tables.o: MTA-types.h +Ext_tables.o: Toks-types.h +Ext_tables.o: Auth-types.h +Ext_tables.o: Toks-types.h +Ext_tables.o: Auth-types.h +Trans_tables.o: Trans_tables.c +Trans_tables.o: Trans-types.h +Trans_tables.o: MTA-types.h +Trans_tables.o: Toks-types.h +Trans_tables.o: Auth-types.h +RTS84_tables.o: RTS84_tables.c +RTS84_tables.o: RTS84-types.h +fixorig.o: fixorig.c +fixorig.o: ../../h/util.h +fixorig.o: ../../h/config.h +fixorig.o: ../../h/ll_log.h +fixorig.o: ../../h/adr.h +fixorig.o: ../../h/list_rchan.h +fixorig.o: ../../h/chan.h +fixorig.o: ../../h/table.h +fixorig.o: ../../h/list_bpt.h +fixorig.o: ../../h/auth.h +fixorig.o: ../../h/list_bpt.h +fixorig.o: ../../h/extension.h +fixorig.o: ../../h/mta.h +fixorig.o: ../../h/adr.h +fixorig.o: ../../h/list_bpt.h +fixorig.o: ../../h/aparse.h +fixorig.o: ../../h/ap.h +fixorig.o: ../../h/util.h +fixorig.o: ../../h/or.h +fixorig.o: ../../h/chan.h +fixorig.o: ../../h/auth.h +fixorig.o: ../../h/list_rchan.h +fixorig.o: ../../h/or.h +rasn.o: rasn.c +rasn.o: ../../h/util.h +rasn.o: ../../h/config.h +rasn.o: ../../h/ll_log.h +rasn.o: ../../h/q.h +rasn.o: ../../h/adr.h +rasn.o: ../../h/list_rchan.h +rasn.o: ../../h/chan.h +rasn.o: ../../h/table.h +rasn.o: ../../h/list_bpt.h +rasn.o: ../../h/auth.h +rasn.o: ../../h/list_bpt.h +rasn.o: ../../h/extension.h +rasn.o: ../../h/mta.h +rasn.o: ../../h/adr.h +rasn.o: ../../h/list_bpt.h +rasn.o: ../../h/aparse.h +rasn.o: ../../h/ap.h +rasn.o: ../../h/util.h +rasn.o: ../../h/or.h +rasn.o: ../../h/chan.h +rasn.o: ../../h/auth.h +rasn.o: ../../h/list_rchan.h +rasn.o: ../../h/mta.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Lib/x400/Rts_posy.py b/Lib/x400/Rts_posy.py new file mode 100644 index 0000000..e253398 --- /dev/null +++ b/Lib/x400/Rts_posy.py @@ -0,0 +1,30 @@ +-- Rts_posy.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/Rts_posy.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: Rts_posy.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + + +RTS84 DEFINITIONS ::= + +BEGIN + +Request ::= + CHOICE { + NULL, + + [1] IMPLICIT SET { + mTAName[0] + IMPLICIT IA5String, + password[1] + ANY + } + } + +END diff --git a/Lib/x400/authen.py b/Lib/x400/authen.py new file mode 100644 index 0000000..3f47e55 --- /dev/null +++ b/Lib/x400/authen.py @@ -0,0 +1,199 @@ +-- authen.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/authen.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: authen.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + +-- Authentication Framework for LOCATOR project. +-- Based on Geneva X.509 Authentication Framework +-- Written by M.Roe, University College London. + +-- Version 1 April 1988 +-- Version 2 August 1988 (for ISODE-4.0) +-- Version 3 November 1988 (Copenhagen IS) +-- Version 4 June 1989 (Minor change to revocation list) + + + +Auth +-- {iso identified-organization(3) locator(999) modules(0) authentication(1)} +DEFINITIONS ::= + +BEGIN +-- IMPORTS +-- Change +-- Name +-- FROM IF +-- { +-- joint-iso-ccitt +-- ds(5) +-- modules(1) +-- informationFramework(1) +-- }; + +-- Declare forward references to other modules as ANY + +Name ::= + ANY + +External ::= + ANY + +-- Use this type to represent the ENCRYPTED macro. +-- Should be BIT STRING, but use OCTET STRING for the moment. + +Encrypted ::= + BIT STRING + +-- Use this type to represent the SIGNED macro. + +SignedType ::= + SEQUENCE { + tobesigned External, + algorithm AlgorithmIdentifier, + signature Encrypted} + +-- Use this type to represent the SIGNATURE macro. + +Signature ::= + SEQUENCE { + algorithm AlgorithmIdentifier, + signature Encrypted} + +-- Use this type to represent the PROTECTED macro. + +Protected ::= + Signature + +-- These types are created by the SIGNED macro. + +CertificateList ::= + SignedType + +Certificate ::= + SignedType + +HotList ::= + SignedType + +-- This is signed to make CertificateList + +ListBody ::= + SEQUENCE { + signature AlgorithmIdentifier, + issuer Name, + lastUpdate UTCTime, + revokedCertificates HotList OPTIONAL} + +-- This is signed to make Certificate + +CertificateBody ::= + SEQUENCE { + version [0] Version DEFAULT 0, + serialNumber SerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo} + +-- This is signed to revoke a certificate + +RevokedCertficate ::= + SEQUENCE { + signature AlgorithmIdentifier, + issuer Name, + serialNumber SerialNumber, + revocationDate UTCTime} + +Version ::= + INTEGER + +SerialNumber ::= + INTEGER + +Validity ::= + SEQUENCE { + notBefore UTCTime, + notAfter UTCTime} + +SubjectPublicKeyInfo ::= + SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey EncryptionKey} + +EncryptionKey ::= + BIT STRING + +AlgorithmIdentifier ::= + SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters INTEGER} + +-- These are the possible parameters + +KeySize ::= + INTEGER + +BlockSize ::= + INTEGER + +KeyAndBlockSize ::= + INTEGER + + +-- Attribute Syntaxes + +-- CertificateSyntax ::= ATTRIBUTE-SYNTAX +-- Certificate +-- MULTI-VALUED +-- MATCHES FOR EQUALITY +-- +-- CertificateListSyntax ::= ATTRIBUTE-SYNTAX +-- CertificateList +-- SINGLE-VALUED +-- MATCHES FOR EQUALITY +-- +-- PasswordSyntax ::= ATTRIBUTE-SYNTAX +-- Password +-- SINGLE-VALUED +-- MATCHES FOR EQUALITY +-- +-- UserCertificate ::= ATTRIBUTE +-- WITH ATTRIBUTE-SYNTAX CertificateSyntax +-- +-- CACertificate ::= ATTRIBUTE +-- WITH ATTRIBUTE-SYNTAX CertificateSyntax +-- +-- CertificateRevocationList ::= ATTRIBUTE +-- WITH ATTRIBUTE-SYNTAX CertificateListSyntax +-- +-- AuthorityRevocationList ::= ATTRIBUTE +-- WITH ATTRIBUTE-SYNTAX CertificateListSyntax +-- +-- UserPassword ::= ATTRIBUTE +-- WITh ATTRIBUTE-SYNTAX PasswordSyntax +-- +-- userPassword UserPassword ::= +-- {attributeType 35} +-- +-- userCertificate UserCertificate ::= +-- {attributeType 36} +-- +-- caCertificate CACertificate ::= +-- {attributeType 37} +-- +-- authorityRevocationList AuthorityRevocationList ::= +-- {attributeType 38} +-- +-- certificateRevocationList CertificateRevocationList ::= +-- {attributeType 39} +-- + +END diff --git a/Lib/x400/enctypes2mem.c b/Lib/x400/enctypes2mem.c new file mode 100644 index 0000000..65cf3b9 --- /dev/null +++ b/Lib/x400/enctypes2mem.c @@ -0,0 +1,151 @@ +/* enctypes2mem.c - Stores X.400 encoded types into PP internal text form */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/x400/RCS/enctypes2mem.c,v 6.0 1991/12/18 20:25:37 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/x400/RCS/enctypes2mem.c,v 6.0 1991/12/18 20:25:37 jpo Rel $ + * + * $Log: enctypes2mem.c,v $ + * Revision 6.0 1991/12/18 20:25:37 jpo + * Release 6.0 + * + */ + + +#include "util.h" +#include "tb_bpt84.h" +#include "list_bpt.h" +#include "tb_p1.h" +#include + + +extern CMD_TABLE bptbl_body_parts84 [/* body part types */]; +static void undefined2mem(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +void enctypes2mem (field, undef, ptr) +int field; +char *undef; +LIST_BPT **ptr; +{ + LIST_BPT *new, + *base = NULLIST_BPT; + char *value; + int i; + + + PP_TRACE (("x40084/enctypes2mem (%d)", field)); + + if (field == 0 || field < 0) { + value = rcmd_srch (BPT_IA5, bptbl_body_parts84); + *ptr = list_bpt_new (value); + return; + } + + + /* This is a temp measure because of erroneous encoding from bull */ + if (field > 1023) + field = 1; + + + for (i = EI_TOTAL - 1; i >= 0; i--) + if (field & (1 << i)) { + switch (i) { + case 0: + undefined2mem (undef, &base); + continue; + case 1: + value = rcmd_srch (BPT_TLX, + bptbl_body_parts84); + break; + case 2: + value = rcmd_srch (BPT_IA5, + bptbl_body_parts84); + break; + case 3: + value = rcmd_srch (BPT_G3FAX, + bptbl_body_parts84); + break; + case 4: + value = rcmd_srch (BPT_TIF0, + bptbl_body_parts84); + break; + case 5: + value = rcmd_srch (BPT_TTX, + bptbl_body_parts84); + break; + case 6: + value = rcmd_srch (BPT_VIDEOTEX, + bptbl_body_parts84); + break; + case 7: + value = rcmd_srch (BPT_VOICE, + bptbl_body_parts84); + break; + case 8: + value = rcmd_srch (BPT_SFD, + bptbl_body_parts84); + break; + case 9: + value = rcmd_srch (BPT_TIF1, + bptbl_body_parts84); + break; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("x40084/enctyp2mem (i=%d) err", i)); + continue; + + } /* -- end of switch -- */ + + new = list_bpt_new (value); + list_bpt_add (&base, new); + + } /* -- end of if -- */ + + *ptr = base; + return; +} + + + + +static void undefined2mem (undef, base) +char *undef; +LIST_BPT **base; +{ + LIST_BPT *new; + char *value; + char *argv[100]; + char buf [BUFSIZ]; + int n, argc; + + + PP_TRACE (("undefined2mem (%s)", + undef ? undef : "undefined")); + + + /* -- if info_undefined not specified then set to "undefined" -- */ + if (!isstr (undef)) { + value = rcmd_srch (BPT_UNDEFINED, bptbl_body_parts84); + new = list_bpt_new (value); + list_bpt_add (base, new); + return; + } + + + /* -- otherwise set to info_undefined values -- */ + (void) sprintf (buf, "%s", undef); + argc = str2arg (buf, 100, argv); + for (n = 0; n < argc; n++) { + new = list_bpt_new (argv[n]); + list_bpt_add (base, new); + } +} diff --git a/Lib/x400/extent.py b/Lib/x400/extent.py new file mode 100644 index 0000000..bb41672 --- /dev/null +++ b/Lib/x400/extent.py @@ -0,0 +1,329 @@ +-- extent.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/extent.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: extent.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + + +Ext DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +IMPORTS + ActualRecipientName, + NonDeliveryReasonCode, + NonDeliveryDiagnosticCode, + ORAddress, + ORAddressAndOrDirectoryName, + ORAddressAndOptionalDirectoryName, + MessageDeliveryTime, + TypeOfMTSUser, + OriginallyIntendedRecipientName, + RecipientCertificate, + GlobalDomainIdentifier, + RoutingAction, + ArrivalTime, + DeferredTime, + OtherActions, + MTAName + FROM MTA + ProofOfDelivery, + Certificates, + SecurityLabel, + Token + FROM Toks + AlgorithmIdentifier, + Signature + FROM Auth; + +RecipientReassignmentProhibited ::= ENUMERATED { + recipient-reassignment-allowed (0), + recipient-reassignment-prohibited (1) } + +OriginatorRequestedAlternateRecipient ::= ORAddressAndOrDirectoryName + +DLExpansionProhibited ::= ENUMERATED { + dl-expansion-allowed (0), + dl-expansion-prohibited (1) } + +ConversionWithLossProhibited ::= ENUMERATED { + conversion-with-loss-allowed (0), + conversion-with-loss-prohibited (1) } + +LatestDeliveryTime ::= Time + +RequestedDeliveryMethod ::= SEQUENCE OF INTEGER { -- each different in order of preference, most preferred first + any-delivery-method (0), + mhs-delivery (1), + physical-delivery (2), + telex-delivery (3), + teletex-delivery (4), + g3-facsimile-delivery (5), + g4-facsimile-delivery (6), + ia5-terminal-delivery (7), + videotex-delivery (8), + telephone-delivery (9) } (0..ub-integer-options) + +PhysicalForwardingProhibited ::= ENUMERATED { + physical-forwarding-allowed (0), + physical-forwarding-prohibited (1) } + +PhysicalForwardingAddressRequest ::= ENUMERATED { + physical-forwarding-address-not-requested (0), + physical-forwarding-address-requested (1) } + +PhysicalDeliveryModes ::= BIT STRING { + ordinary-mail (0), + special-delivery (1), + express-mail (2), + counter-collection (3), + counter-collection-with-telephone-advice (4), + counter-collection-with-telex-advice (5), + counter-collection-with-teletex-advice (6), + bureau-fax-delivery (7) + -- bits 0 to 6 are mutually exclusive + -- bit 7 can be set with any of bits 0 to 6 -- } (SIZE (0..ub-bit-options)) + +RegisteredMailType ::= INTEGER { + non-registered-mail (0), + registered-mail (1), + registered-mail-to-addressee-in-person (2) } (0..ub-integer-options) + +RecipientNumberForAdvice ::= TeletexString (SIZE (1..ub-recipient-number-for-advice-length)) + +PhysicalRenditionAttributes ::= OBJECT IDENTIFIER + +OriginatorReturnAddress ::= ORAddress + +PhysicalDeliveryReportRequest ::= INTEGER { + return-of-undeliverable-mail-by-PDS (0), + return-of-notification-by-PDS (1), + return-of-notification-by-MHS (2), + return-of-notification-by-MHS-and-PDS (3) } (0..ub-integer-options) + +OriginatorCertificate ::= Certificates + +MessageToken ::= Token + +ContentConfidentialityAlgorithmIdentifier ::= AlgorithmIdentifier + +ContentIntegrityCheck ::= Signature +-- SIGNATURE SEQUENCE { +-- algorithm-identifier ContentIntegrityAlgorithmIdentifier, +-- content Content } + +ContentIntegrityAlgorithmIdentifier ::= AlgorithmIdentifier + + +MessageOriginAuthenticationCheck ::= Signature +-- SIGNATURE SEQUENCE { +-- algorithm-identifier MessageOriginAuthenticationAlgorithmIdentifier, +-- content Content, +-- content-identifier ContentIdentifier OPTIONAL, +-- message-security-label MessageSecurityLabel OPTIONAL } + +MessageOriginAuthenticationAlgorithmIdentifier ::= AlgorithmIdentifier + +MessageSecurityLabel ::= SecurityLabel + +ProofOfSubmissionRequest ::= ENUMERATED { + proof-of-submission-not-requested (0), + proof-of-submission-requested (1) } + +SequenceNumber ::= INTEGER + +ProofOfDeliveryRequest ::= ENUMERATED { + proof-of-delivery-not-requested (0), + proof-of-delivery-requested (1) } + +ContentCorrelator ::= ANY -- maximum ub-content-correlator-length octets including all encoding + +ProbeOriginAuthenticationCheck ::= Signature +-- SIGNATURE SEQUENCE { +-- algorithm-identifier ProbeOriginAuthenticationAlgorithmIdentifier, +-- content-identifier ContentIdentifier OPTIONAL, +-- message-security-label MessageSecurityLabel OPTIONAL } + +ProbeOriginAuthenticationAlgorithmIdentifier ::= AlgorithmIdentifier + +RedirectionHistory ::= SEQUENCE SIZE (1..ub-redirections) OF Redirection + +Redirection ::= SEQUENCE { + intended-recipient-name IntendedRecipientName, + redirection-reason RedirectionReason } + +IntendedRecipientName ::= SEQUENCE { + address ORAddressAndOptionalDirectoryName, + redirection-time Time } + +RedirectionReason ::= ENUMERATED { + recipient-assigned-alternate-recipient (0), + originator-requested-alternate-recipient (1), + recipient-MD-assigned-alternate-recipient (2) } + +DLExpansionHistory ::= SEQUENCE SIZE (1..ub-dl-expansions) OF DLExpansion + +DLExpansion ::= SEQUENCE { + address ORAddressAndOptionalDirectoryName, + dl-expansion-time Time } + +PhysicalForwardingAddress ::= ORAddressAndOptionalDirectoryName + + +OriginatorAndDLExpansionHistory ::= SEQUENCE SIZE (0..ub-dl-expansions) OF OriginatorAndDLExpansion + +OriginatorAndDLExpansion ::= SEQUENCE { + originator-or-dl-name ORAddressAndOptionalDirectoryName, + origination-or-expansion-time Time } + +ReportingDLName ::= ORAddressAndOptionalDirectoryName + +ReportingMTACertificate ::= Certificates + +ReportOriginAuthenticationCheck ::= Signature +-- SIGNATURE SEQUENCE { +-- algorithm-identifier ReportOriginAuthenticationAlgorithmIdentifier, +-- content-identifier ContentIdentifier OPTIONAL, +-- message-security-label MessageSecurityLabel OPTIONAL, +-- per-recipient SEQUENCE SIZE (1..ub-recipients) OF PerRecipientReportFields } + +ReportOriginAuthenticationAlgorithmIdentifier ::= AlgorithmIdentifier + +PerRecipientReportFields ::= SEQUENCE { + actual-recipient-name ActualRecipientName, + originally-intended-recipient-name OriginallyIntendedRecipientName OPTIONAL, + report CHOICE { + delivery [0] PerRecipientDeliveryReportFields, + non-delivery [1] PerRecipientNonDeliveryReportFields } } + +PerRecipientDeliveryReportFields ::= SEQUENCE { + message-delivery-time MessageDeliveryTime, + type-of-MTS-user TypeOfMTSUser, + recipient-certificate [0] RecipientCertificate OPTIONAL, + proof-of-delivery [1] ProofOfDelivery OPTIONAL } + +PerRecipientNonDeliveryReportFields ::= SEQUENCE { + non-delivery-reason-code NonDeliveryReasonCode, + non-delivery-diagnostic-code NonDeliveryDiagnosticCode OPTIONAL } + +OriginatingMTACertificate ::= Certificates + +ProofOfSubmission ::= Signature +-- SIGNATURE SEQUENCE { +-- algorithm-identifier ProofOfSubmissionAlgorithmIdentifier, +-- message-submission-envelope MessageSubmissionEnvelope, +-- message-submission-identifier MessageSubmissionIdentifier, +-- message-submission-time MessageSubmissionTime } + +ProofOfSubmissionAlgorithmIdentifier ::= AlgorithmIdentifier + +InternalTraceInformation ::= SEQUENCE OF InternalTraceInformationElement + +InternalTraceInformationElement ::= SEQUENCE { + global-domain-identifier GlobalDomainIdentifier, + mta-name MTAName, + mta-supplied-information MTASuppliedInformation } + +MTASuppliedInformation ::= SET { + arrival-time [0] ArrivalTime, + routing-action [2] RoutingAction, + attempted CHOICE { + mta MTAName, + domain GlobalDomainIdentifier } OPTIONAL, + deferred-time [1] DeferredTime OPTIONAL, + other-actions[3] BIT STRING DEFAULT {} } +-- other-actions[3] OtherActions DEFAULT {} } + + +-- Extension Attributes + +CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) + +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) + +TeletexOrganizationName ::= TeletexString (SIZE (1..ub-organization-name-length)) + +TeletexPersonalName ::= SET { + surname [0] TeletexString (SIZE (1..ub-surname-length)), + given-name [1] TeletexString (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] TeletexString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] TeletexString (SIZE (1..ub-generation-qualifier-length)) OPTIONAL } + +TeletexOrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF + TeletexOrganizationalUnitName + +TeletexOrganizationalUnitName ::= TeletexString (SIZE (1..ub-organizational-unit-name-length)) + +TeletexDomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) OF + TeletexDomainDefinedAttribute + +TeletexDomainDefinedAttribute ::= SEQUENCE { + type TeletexString (SIZE (1..ub-domain-defined-attribute-type-length)), + value TeletexString (SIZE (1..ub-domain-defined-attribute-value-length)) } + +PDSName ::= PrintableString (SIZE (1..ub-pds-name-length)) + +PhysicalDeliveryCountryName ::= CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length)) } + +PostalCode ::= CHOICE { + numeric-code NumericString (SIZE (1..ub-postal-code-length)), + printable-code PrintableString (SIZE (1..ub-postal-code-length)) } + +PhysicalDeliveryOfficeName ::= PDSParameter + +PhysicalDeliveryOfficeNumber ::= PDSParameter + +ExtensionORAddressComponents ::= PDSParameter + +PhysicalDeliveryPersonalName ::= PDSParameter + +PhysicalDeliveryOrganizationName ::= PDSParameter + +ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter + +UnformattedPostalAddress ::= SET { + printable-address SEQUENCE SIZE (1..ub-physical-address-lines) OF + PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString (SIZE (1..ub-unformatted-address-length)) OPTIONAL } + +StreetAddress ::= PDSParameter + +PostOfficeBoxAddress ::= PDSParameter + +PosteRestanteAddress ::= PDSParameter + +UniquePostalName ::= PDSParameter + +LocalPostalAttributes ::= PDSParameter + +PDSParameter ::= SET { + printable-string PrintableString (SIZE(1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString (SIZE(1..ub-pds-parameter-length)) OPTIONAL } + +ExtendedNetworkAddress ::= CHOICE { + e163-4-address SEQUENCE { + number [0] NumericString (SIZE (1..ub-e163-4-number-length)), + sub-address [1] NumericString (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL } + , psap-address PresentationAddress } +-- quick hack +PresentationAddress ::= ANY + +TerminalType ::= INTEGER { + telex (3), + teletex (4), + g3-facsimile (5), + g4-facsimile (6), + ia5-terminal (7), + videotex (8) } (0..ub-integer-options) + +Time ::= UTCTime + +END diff --git a/Lib/x400/fixorig.c b/Lib/x400/fixorig.c new file mode 100644 index 0000000..3b40ace --- /dev/null +++ b/Lib/x400/fixorig.c @@ -0,0 +1,67 @@ +/* fixorig.c: routine to lie about originator address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/x400/RCS/fixorig.c,v 6.0 1991/12/18 20:25:37 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/x400/RCS/fixorig.c,v 6.0 1991/12/18 20:25:37 jpo Rel $ + * + * $Log: fixorig.c,v $ + * Revision 6.0 1991/12/18 20:25:37 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "adr.h" +#include "or.h" + +x400_fixorig (orig, rewrite) +ADDR *orig; +char *rewrite; +{ + OR_ptr or, or1, or2; + OR_ptr o1, o2, o3; + char *p; + char buf[BUFSIZ]; + + if ((p = index (rewrite, '-')) == NULL || + *(p+1) != '>') { + PP_LOG (LLOG_EXCEPTIONS, ("rewrite rule \"%s\" missing ->", + rewrite)); + return; + } + + *p = '\0'; + if ((or = or_std2or(orig -> ad_r400adr)) == NULLOR) + return; + + if ((or1 = or_std2or (rewrite)) == NULLOR || + (or2 = or_std2or (p + 2)) == NULLOR) { + *p = '-'; + PP_LOG (LLOG_EXCEPTIONS, ("Error in or str '%s'", rewrite)); + return; + } + *p = '-'; + + for (o1 = or, o2 = or1, o3 = or2; o2 && o1 && o3; + o1 = o1 -> or_next, o2 = o2 ->or_next, o3 = o3 -> or_next) { + if (or_cmp (o1, o2)) { + if (o1 -> or_type == o3 -> or_type) { + free (o1 -> or_value); + o1 -> or_value = strdup (o3 -> or_value); + } + } + } + if (o2 == NULLOR && o3 == NULLOR) { /* we matched! */ + or_or2std (or, buf, 0); + if (buf[0] != '\0') { + free (orig -> ad_r400adr); + orig -> ad_r400adr = strdup (buf); + } + } + or_free (or); + or_free (or1); + or_free (or2); +} diff --git a/Lib/x400/iob.py b/Lib/x400/iob.py new file mode 100644 index 0000000..2a3cc9b --- /dev/null +++ b/Lib/x400/iob.py @@ -0,0 +1,573 @@ +-- iob.py - MHS P22 definitions +-- starting p602 in blue book x400(88) + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/iob.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: iob.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- + +IOB +-- { +-- joint-iso-ccitt +-- mhs-motis(6) +-- ipms(1) +-- modules(0) +-- information-objects(2) +-- } +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN +IMPORTS + ub-auto-forward-comment, ub-free-form-name, + ub-ipm-identifier-suffix, ub-local-imp-identifier, + ub-subject-field, ub-telephone-number + FROM UB + { + joint-iso-ccitt + mhs-motis(6) + ipms(1) + modules(0) + upper-bounds(10) + } + + EncodedInformationTypes, G3FacsimileNonBasicParameters, + MessageDeliveryTime, ORAddress, +-- ORName but not right yet + StandardAttributes, DomainDefinedAttributes, ExtensionAttributes, + OtherMessageDeliveryFields, SupplementaryInformation, + TeletexNonBasicParameters + FROM MTA + { + joint-iso-ccitt + mhs-motis(6) + mts(3) + modules(0) + mts-abstract-service(1) + }; +-- Change +-- Name +-- FROM IF +-- { +-- joint-iso-ccitt +-- ds(5) +-- modules(1) +-- informationFramework(1) +-- }; + +Time ::= UTCTime + +-- Information object + +InformationObject ::= CHOICE { + ipm [0] IPM, + ipn [1] IPN + } +-- IPM + +IPM ::= SEQUENCE { + heading Heading, + body Body + } + +-- Heading + +Heading ::= SET { + this-IPM ThisIPMField, + originator [0] OriginatorField OPTIONAL, + authorizing-users [1] AuthorizingUsersField OPTIONAL, + primary-recipients [2] PrimaryRecipientsField DEFAULT {}, + copy-recipients [3] CopyRecipientsField OPTIONAL, + blind-copy-recipients [4] BlindCopyRecipientsField OPTIONAL, + replied-to-IPM [5] RepliedToIPMField OPTIONAL, + obsoleted-IPMs [6] ObsoletedIPMsField DEFAULT {}, + related-IPMs [7] RelatedIPMsField DEFAULT {}, + subject [8] EXPLICIT SubjectField OPTIONAL, + expiry-time [9] ExpiryTimeField OPTIONAL, + reply-time [10] ReplyTimeField OPTIONAL, + reply-recipients [11] ReplyRecipientsField OPTIONAL, + importance [12] ImportanceField DEFAULT normal, + sensitivity [13] SensitivityField OPTIONAL, + auto-forwarded [14] AutoForwardedField DEFAULT FALSE, + extensions [15] ExtensionsField DEFAULT {} + } + +-- Heading components types + +IPMIdentifierSequence ::= SEQUENCE OF IPMIdentifier + +IPMIdentifier ::= [APPLICATION 11] SET { + user ORName OPTIONAL, + user-relative-identifier LocalIPMIdentifier + } + +LocalIPMIdentifier ::= PrintableString + (SIZE (0..ub-local-ipm-identifier)) + +RecipientSequence ::= SEQUENCE OF RecipientSpecifier + +RecipientSpecifier ::= SET { + recipient [0] ORDescriptor, + notification-requests [1] NotificationRequests DEFAULT {}, + reply-requested [2] BOOLEAN DEFAULT FALSE + } + +NotificationRequests ::= BIT STRING { + rn(0), + nrn(1), + ipm-return(2) + } + +ORDescriptorSequence ::= SEQUENCE OF ORDescriptor + +ORDescriptor ::= SET { + formal-name ORName OPTIONAL, + free-form-name [0] FreeFormName OPTIONAL, + telephone-number [1] TelephoneNumber OPTIONAL + } + +FreeFormName ::= TeletexString (SIZE (0..ub-free-form-name)) + +TelephoneNumber ::= PrintableString (SIZE (0..ub-telephone-number)) + +-- This IPM heading field + +ThisIPMField ::= IPMIdentifier + +-- Originating heading field + +OriginatorField ::= ORDescriptor + +--Authorizing Users heading field + +--AuthorizingUsersField ::= SEQUENCE OF AuthorizingUsersSubfield + +--AuthorizingUsersSubfield ::= ORDescriptor + +-- To simplify coding + +AuthorizingUsersField ::= ORDescriptorSequence + +-- Primary Recipients heading field + +--PrimaryRecipientsField ::= SEQUENCE OF PrimaryRecipientsSubfield + +--PrimaryRecipientsSubfield ::= RecipientSpecifier + +-- To simplify coding + +PrimaryRecipientsField ::= RecipientSequence + +-- Copy Recipients heading field + +--CopyRecipientsField ::= SEQUENCE OF CopyRecipientsSubfield + +--CopyRecipientsSubfield ::= RecipientSpecifier + +-- To simplify coding + +CopyRecipientsField ::= RecipientSequence + +-- Blind Copy Recipients heading field + +--BlindCopyRecipientsField ::= SEQUENCE OF BlindCopyRecipientsSubfield + +--BlindCopyRecipientsSubfield ::= RecipientSpecifier + +BlindCopyRecipientsField ::= RecipientSequence + +-- Replied-to IPM heading field + +RepliedToIPMField ::= IPMIdentifier + +-- Obsoleted IPMs heading field + +--ObsoletedIPMsField ::= SEQUENCE OF ObsoletedIPMsSubfield + +--ObsoletedIPMsSubfield ::= IPMIdentifier + +-- To simplify coding + +ObsoletedIPMsField ::= IPMIdentifierSequence + +-- Related IPMs heading field + +--RelatedIPMsField ::= SEQUENCE OF RelatedIPMsSubfield + +--RelatedIPMsSubfield ::= IPMIdentifier + +-- To simplify coding + +RelatedIPMsField ::= IPMIdentifierSequence + +-- Subject heading field + +SubjectField ::= TeletexString (SIZE (0..ub-subject-field)) + +-- Expiry Time heading field + +ExpiryTimeField ::= Time + +-- Reply Time heading field + +ReplyTimeField ::= Time + +-- Reply Recipients heading field + +--ReplyRecipientsField ::= SEQUENCE OF ReplyRecipientsSubfield + +--ReplyRecipientsSubfield ::= ORDescriptor + +-- To simplify coding + +ReplyRecipientsField ::= ORDescriptorSequence + +-- Importance heading field + +ImportanceField ::= ENUMERATED { + low (0), + normal (1), + high (2) + } + +-- Sensitivity heading field + +SensitivityField ::= ENUMERATED { + personal (1), + private (2), + company-confidential (3) + } + +-- Auto-forwarded heading field + +AutoForwardedField ::= BOOLEAN + +-- Extensions heading field + +ExtensionsField ::= SET OF HeadingExtension + +HeadingExtension ::= SEQUENCE { + type OBJECT IDENTIFIER, + value ANY +} + +-- Incomplete Copy + +IncompleteCopy ::= NULL + +Languages ::= SET OF Language + +Language ::= PrintableString (SIZE (2..2)) + +RFC822FieldList ::= SEQUENCE OF RFC822Field + +RFC822Field ::= IA5String + +-- Body + +Body ::= + SEQUENCE OF BodyPart + +BodyPart ::= + + CHOICE { + ia5-text [0] IA5TextBodyPart, + + voice [2] VoiceBodyPart, + + g3-facsimile [3] G3FacsimileBodyPart, + + g4-class1 [4] G4Class1BodyPart, + + teletex [5] TeletexBodyPart, + + videotex [6] VideotexBodyPart, + + encrypted [8] EncryptedBodyPart, + + message [9] MessageBodyPart, + + mixed-mode [11] MixedModeBodyPart, + + bilaterally-defined [14] BilaterallyDefinedBodyPart, + + nationally-defined [7] NationallyDefinedBodyPart, + + externally-defined [15] ExternallyDefinedBodyPart, + + -- not in x400 88 ? + + tlx [1] TLXBodyPart, + + sfd [10] SFDBodyPart, + + odif [12] ODIFBodyPart, + + iso6937Text [13] ISO6937TextBodyPart + } + + +-- body part types + +IA5TextBodyPart ::= SEQUENCE { + parameters IA5TextParameters, + data IA5TextData + } + +IA5TextParameters ::= SET { + repertoire [0] Repertoire DEFAULT ia5 + } + +IA5TextData ::= IA5String + +Repertoire ::= ENUMERATED { + ita2 (2), + ia5 (5) + } + +TLXBodyPart ::= ANY + +-- Voice body part + +VoiceBodyPart ::= SEQUENCE { + parameters VoiceParameters, + data VoiceData + } + +VoiceParameters ::= SET {} -- for further study + +VoiceData ::= BIT STRING -- for further study + +-- G3 Facsimile body part + +G3FacsimileBodyPart ::= SEQUENCE { + parameters G3FacsimileParameters, + data G3FacsimileData + } + +G3FacsimileParameters ::= SET { + number-of-pages [0] INTEGER OPTIONAL, + non-basic-parameters [1] G3FacsimileNonBasicParameters OPTIONAL + } + +G3FacsimileData ::= SEQUENCE OF BIT STRING + +-- G4 class 1 and mixed-mode body parts + +--G4Class1BodyPart ::= SEQUENCE OF ProtocolElement + +G4Class1BodyPart ::= ANY + +-- MixedModeBodyPart ::= SEQUENCE OF ProtocolElement + +MixedModeBodyPart ::= ANY + +-- Teletex body part + +TeletexBodyPart ::= SEQUENCE { + parameters TeletexParameters, + data TeletexData + } + +TeletexParameters ::= SET { + number-of-pages [0] INTEGER OPTIONAL, + telex-compatible [1] BOOLEAN DEFAULT FALSE, + non-basic-parameters [2] TeletexNonBasicParameters OPTIONAL + } + +TeletexData ::= SEQUENCE OF TeletexString + +-- Videotex body part + +VideotexBodyPart ::= SEQUENCE { + parameters VideotexParameters, + data VideotexData + } + +VideotexParameters ::= SET { + syntax [0] VideotexSyntax OPTIONAL + } +VideotexSyntax ::= INTEGER { + ids (0), + data-syntax1 (1), + data-syntax2 (2), + data-syntax3 (3)} + +VideotexData ::= SEQUENCE OF VideotexString + +-- Encrypted body part + +EncryptedBodyPart ::= SEQUENCE { + parameters EncryptedParameters, + data EncryptedData + } + +EncryptedParameters ::= SET {}-- for further study + +EncryptedData ::= BIT STRING -- for further study + +-- Message body part + +MessageBodyPart ::= SEQUENCE { + parameters MessageParameters, + data MessageData + } + +MessageParameters ::= SET { + delivery-time [0] MessageDeliveryTime OPTIONAL, + delivery-envelope [1] OtherMessageDeliveryFields OPTIONAL + } + +MessageData ::= IPM + +SFDBodyPart ::= ANY + +ODIFBodyPart ::= + -- from appendix A minutes of the PODA Munich meeting July 6th 1988. + OCTET STRING + + +-- motis-86-6937 (extra body part) +ISO6937TextBodyPart ::= SEQUENCE { + parameters ISO6937Parameters, + data ISO6937Data} + +ISO6937Parameters ::= SET { + repertoire [0] ISO6937Repertoire DEFAULT part1and2} + +ISO6937Repertoire ::= ENUMERATED { + -- + -- values are assigned by the ISO registration + -- authority. Other values are for further study, + -- and shall be relayed. + -- + part1and2 (0), + teletexSubRepertoire (3)} + +ISO6937Data ::= SEQUENCE OF ISO6937Line + -- sequence may contain zero elements + +ISO6937Line ::= [0] IMPLICIT OCTET STRING + -- additional protocol element to those defined by CCITT + + +BilaterallyDefinedBodyPart ::= OCTET STRING + +NationallyDefinedBodyPart ::= ANY + +-- Externally defined body part + +--ExternallyDefinedBodyPart ::= SEQUENCE { +-- parameters [0] ExternallyDefinedParameters OPTIONAL +-- data ExternallyDefinedData +-- } + +--ExternallyDefinedParameters ::= EXTERNAL + +--ExternallyDefinedData ::= EXTERNAL + +ExternallyDefinedBodyPart ::= ANY + +-- IPN + +IPN ::= SET { + -- common-fields -- COMPONENTS OF CommonFields, + + choice [0] EXPLICIT CHOICE { + non-receipt-fields [0] NonReceiptFields, + receipt-fields [1] ReceiptFields + } + } +RN ::= IPN -- with receipt-fields chosen + +NRN ::= IPN -- with non-receipt-fields chosen + +CommonFields ::= SET { + subject-ipm SubjectIPMField, + ipn-originator [1] IPNOriginatorField OPTIONAL, + ipn-preferred-recipient [2] IPNPreferredRecipientField OPTIONAL, + conversion-eits ConversionEITsField OPTIONAL + } + +NonReceiptFields ::= SET { + non-receipt-reason [0] NonReceiptReasonField, + discard-reason [1] DiscardReasonField OPTIONAL, + auto-forward-comment [2] AutoForwardCommentField OPTIONAL, + returned-ipm [3] ReturnedIPMField OPTIONAL + } + +ReceiptFields ::= SET { + receipt-time [0] ReceiptTimeField, + acknowledgment-mode [1] AcknowledgmentModeField DEFAULT manual, + suppl-receipt-info [2] SupplReceiptInfoField DEFAULT "" + } + +-- Common fields + +SubjectIPMField ::= IPMIdentifier + +IPNOriginatorField ::= ORDescriptor + +IPNPreferredRecipientField ::= ORDescriptor + +ConversionEITsField ::= EncodedInformationTypes + +-- Non-receipt fields + +NonReceiptReasonField ::= ENUMERATED { + ipm-discarded (0), + ipm-auto-forward (1) + } + +DiscardReasonField ::= ENUMERATED { + ipm-expired (0), + ipm-obsoleted (1), + user-subscription-terminated (2) + } + +AutoForwardCommentField ::= AutoForwardComment + +AutoForwardComment ::= PrintableString + (SIZE (0..ub-auto-forward-comment)) + +ReturnedIPMField ::= IPM + +-- Receipt fields + +ReceiptTimeField ::= Time + +AcknowledgmentModeField ::= ENUMERATED { + manual (0), + automatic (1) + } + +-- SupplReceiptInfoField ::= SupplementaryInformation + +SupplReceiptInfoField ::= PrintableString + (SIZE (1..ub-supplementary-info-length)) + +-- Message store realization + +ForwardedInfo ::= SET { + auto-forwarded-comment [0] + AutoForwardComment OPTIONAL, + cover-note [1] + IA5TextBodyPart OPTIONAL, + this-ipm-prefix [2] + PrintableString (SIZE(1..ub-ipm-identifier-suffix)) + OPTIONAL + } + +-- Have to have as mta.py not right +ORName ::= [APPLICATION 0] SEQUENCE { + standard-attributes StandardAttributes, + domain-defined DomainDefinedAttributes OPTIONAL, + extension-attributes ExtensionAttributes OPTIONAL, + directory-name [0] ANY OPTIONAL } +-- directory-name [0] EXPLICIT ANY OPTIONAL } +-- Change +-- directory-name [0] EXPLICIT Name OPTIONAL } + +END -- of IPMSInformationObjects diff --git a/Lib/x400/make b/Lib/x400/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Lib/x400/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Lib/x400/mta.ry b/Lib/x400/mta.ry new file mode 100644 index 0000000..2b85c4d --- /dev/null +++ b/Lib/x400/mta.ry @@ -0,0 +1,1056 @@ +-- mta.ry - MTA definitions + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/mta.ry,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: mta.ry,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + + + +MTA -- { joint-iso-ccitt mhs-motis(6) mts(3) modules(0) mta-abstract-service(2) } + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +IMPORTS Token, ProofOfDelivery, Certificates, + SecurityContext, SecurityLabel + FROM Toks; + +ExtensionType ::= + CHOICE { + global INTEGER, + local OBJECT IDENTIFIER} + +Criticality ::= + BIT STRING { + for-submission (0), + for-transfer (1), + for-delivery (2) } (SIZE (0..ub-bit-options)) + +ExtensionField ::= + SEQUENCE { + type [0] EXPLICIT ExtensionType, + criticality [1] Criticality OPTIONAL, + value [2] EXPLICIT ANY OPTIONAL} + +Extensions ::= + SET OF ExtensionField + +-- Extension Attributes + +ExtensionAttribute ::= + SEQUENCE { + type [0] INTEGER, + value [1] ANY} + +ExtensionAttributes ::= + SET OF ExtensionAttribute + +-- MTS-bind and MTS-unbind + +Password ::= + CHOICE { + ia5string IA5String, + octetstring OCTET STRING + } + +Credentials ::= + CHOICE { + simple Password, + strong StrongCredentials} + +StrongCredentials ::= + SET { + bind-token [0] Token OPTIONAL, + certificate [1] Certificates OPTIONAL} + + +MTSBindArgument ::= + SET { + initiator-name ObjectName, + messages-waiting [1] EXPLICIT MessagesWaiting OPTIONAL, + initiator-credentials [2] EXPLICIT InitiatorCredentials, + security-context [3] SecurityContext OPTIONAL} + + --The EXPLICIT is necessary due to funny + --encoding of IMPLICIT tags in asn1 and + --the interaction with types that are + --CHOICE's. + +MTSBindResult ::= + SET { + responder-name ObjectName, + messages-waiting [1] EXPLICIT MessagesWaiting OPTIONAL, + responder-credentials [2] EXPLICIT ResponderCredentials} --as above + +MTSBindError ::= + INTEGER { + busy (0), + authentication-error (2), + unacceptable-dialogue-mode (3), + unacceptable-security-context (4) } + + + +-- Association Control Parameters + + +ObjectName ::= CHOICE { + mTS-user ORAddressAndOptionalDirectoryName, + mTA [0] MTAName} + +MessagesWaiting ::= SET { + urgent [0] DeliveryQueue, + normal [1] DeliveryQueue, + non-urgent [2] DeliveryQueue } + +DeliveryQueue ::= SET { + messages [0] INTEGER (0..ub-queue-size), + octets [1] INTEGER DEFAULT 0 } + +InitiatorCredentials ::= CHOICE { + simple Password, + strong [0] StrongCredentials } + +ResponderCredentials ::= CHOICE { + simple Password, + strong[0] StrongCredentials } + +Context ::= OBJECT IDENTIFIER + + +-- Submission Port + + +messageSubmission OPERATION + ARGUMENT SEQUENCE { + envelope MessageSubmissionEnvelope, + content Content } + RESULT SET { + message-submission-identifier MessageSubmissionIdentifier, + message-submission-time [0] MessageSubmissionTime, + content-identifier ContentIdentifier OPTIONAL, + extensions [1] Extensions DEFAULT {}} + ERRORS { + submissionControlViolated, + elementOfServiceNotSubscribed, + originatorInvalid, + recipientImproperlySpecified, + inconsistentRequest, + securityError, + unsupportedCriticalFunction, + remoteBindError } + ::= 3 + +probeSubmission OPERATION + ARGUMENT + envelope ProbeSubmissionEnvelope + RESULT SET { + probe-submission-identifier ProbeSubmissionIdentifier, + probe-submission-time [0] ProbeSubmissionTime, + content-identifier ContentIdentifier OPTIONAL } + ERRORS { + submissionControlViolated, + elementOfServiceNotSubscribed, + originatorInvalid, + recipientImproperlySpecified, + inconsistentRequest, + securityError, + unsupportedCriticalFunction, + remoteBindError } + ::= 4 + +cancelDeferredDelivery OPERATION + ARGUMENT + message-submission-identifier MessageSubmissionIdentifier + RESULT NULL + ERRORS { + deferredDeliveryCancellationRejected, + messageSubmissionIdentifierInvalid, + remoteBindError } + ::= 7 + +submissionControl OPERATION + ARGUMENT + controls SubmissionControls + RESULT + waiting Waiting + ERRORS { + securityError} + ::= 2 + +submissionControlViolated ERROR + ::= 1 + +elementOfServiceNotSubscribed ERROR + ::= 4 + +deferredDeliveryCancellationRejected ERROR + ::= 8 + +originatorInvalid ERROR + ::= 2 + +recipientImproperlySpecified ERROR + PARAMETER + improperly-specified-recipients SEQUENCE SIZE (1..ub-recipients) OF + ORAddressAndOptionalDirectoryName + ::= 3 + +messageSubmissionIdentifierInvalid ERROR + ::= 7 + +inconsistentRequest ERROR + ::= 11 + +securityError ERROR + PARAMETER + security-problem SecurityProblem + ::= 12 + +SecurityProblem ::= INTEGER (0..ub-security-problems) + +unsupportedCriticalFunction ERROR + ::= 13 + + +-- Delivery Operations + +messageDelivery OPERATION + ARGUMENT SEQUENCE { + envelope MessageDeliveryEnvelope, + content Content } + RESULT SET { + recipient-certificate [0] RecipientCertificate OPTIONAL, + proof-of-delivery [1] ProofOfDelivery OPTIONAL} + ERRORS { + deliveryControlViolated, + securityError, + unsupportedCriticalFunction} + ::= 5 + +reportDelivery OPERATION + ARGUMENT SET { + envelope ReportDeliveryEnvelope, + returned-content [0] Content OPTIONAL } + RESULT NULL + ERRORS { + deliveryControlViolated, + securityError, + unsupportedCriticalFunction} + ::= 6 + +deliveryControl OPERATION + ARGUMENT + controls DeliveryControls + RESULT + waiting Waiting + ERRORS { + controlViolatesRegistration, + securityError } + ::= 2 + + + +-- Delivery Errors + +deliveryControlViolated ERROR + ::= 1 + +controlViolatesRegistration ERROR + ::= 14 + +remoteBindError ERROR + ::= 15 + + + + +-- Submission Port Parameters + +MessageSubmissionIdentifier ::= MTSIdentifier + +MessageSubmissionTime ::= Time + +ProbeSubmissionIdentifier ::= MTSIdentifier + +ProbeSubmissionTime ::= Time + +SubmissionControls ::= Controls + +Waiting ::= SET { + waiting-operations [0] Operations DEFAULT { }, + waiting-messages [1] WaitingMessages DEFAULT { }, + waiting-content-types [2] SET SIZE (0..ub-content-types) OF ContentType DEFAULT { }, + waiting-encoded-information-types EncodedInformationTypes OPTIONAL } + +Operations ::= BIT STRING { + probe-submission-or-report-delivery (0), + message-submission-or-message-delivery (1) } (SIZE (0..ub-bit-options)) + -- holding 'one', not-holding 'zero' + +WaitingMessages ::= BIT STRING { + long-content (0), + low-priority (1), + other-security-labels (2) } (SIZE (0..ub-bit-options)) + +-- Delivery Port + +DeliveryControls ::= Controls + +Controls ::= SET { + restrict [0] BOOLEAN DEFAULT TRUE, + -- update 'TRUE', remove 'FALSE' + permissible-operations [1] Operations OPTIONAL, + permissible-maximum-content-length [2] ContentLength OPTIONAL, + permissible-lowest-priority Priority OPTIONAL, + permissible-content-types [4] SET SIZE (1..ub-content-types) OF ContentType OPTIONAL, + permissible-encoded-information-types EncodedInformationTypes OPTIONAL, + permissible-security-context [5] SecurityContext OPTIONAL } + +-- Note[:| -] The Tags [0], [1] and [2] are altered for the Register operation only. + +RecipientCertificate ::= Certificates + +-- Administration Port + +RegisterArgument ::= + SET { + user-name UserName OPTIONAL, + user-address [0] UserAddress OPTIONAL, + deliverable-encoded-information-types EncodedInformationTypes OPTIONAL, + deliverable-maximum-content-length [1] EXPLICIT ContentLength OPTIONAL, + default-delivery-controls [2] EXPLICIT DefaultDeliveryControls OPTIONAL, + deliverable-content-types [3] SET SIZE (1..ub-content-types) OF ContentType OPTIONAL, + labels-and-redirections [4] SET SIZE (1..ub-labels-and-redirections) OF + LabelAndRedirection OPTIONAL } + +ChangeCredentialsArgument ::= + SET { + old-credentials [0] Credentials, + new-credentials [1] Credentials -- same CHOICE as for old-credentials -- } + + +-- Administration Port Parameters + +UserName ::= ORAddressAndOptionalDirectoryName + +UserAddress ::= CHOICE { + x121 [0] SEQUENCE { + x121-address NumericString (SIZE (1..ub-x121-address-length)) OPTIONAL, + tsap-id PrintableString (SIZE (1..ub-tsap-id-length)) OPTIONAL } + +-- , presentation [1] PSAPAddress -- } + +-- PSAPAddress ::= PresentationAddress + +DefaultDeliveryControls ::= Controls + +LabelAndRedirection ::= SET { + user-security-label [0] SecurityLabel OPTIONAL, + recipient-assigned-alternate-recipient [1] RecipientAssignedAlternateRecipient OPTIONAL } + +RecipientAssignedAlternateRecipient ::= ORAddressAndOptionalDirectoryName + +-- Message Submission Envelope + +MessageSubmissionEnvelope ::= SET { + originator-name OriginatorName, + original-eits OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + priority Priority DEFAULT normal, + per-message-indicators PerMessageIndicators DEFAULT {}, + deferred-delivery-time [0] DeferredDeliveryTime OPTIONAL, + extensions [2] Extensions DEFAULT {}, + per-recipient-fields [1] SEQUENCE SIZE (1..ub-recipients) OF + PerRecipientMessageSubmissionFields OPTIONAL } + +PerMessageSubmissionExtensions ::= Extensions + +PerRecipientMessageSubmissionFields ::= SET { + recipient-name RecipientName, + originator-report-request [0] OriginatorReportRequest, + explicit-conversion [1] ExplicitConversion OPTIONAL, + extensions [2] PerRecipientMessageSubmissionExtensions DEFAULT { } } + +PerRecipientMessageSubmissionExtensions ::= Extensions + +-- Probe Submission Envelope + +ProbeSubmissionEnvelope ::= SET { + originator-name OriginatorName, + original-eits OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + content-length [0] ContentLength DEFAULT 0, + per-message-indicators PerMessageIndicators DEFAULT {}, + extensions [2] Extensions DEFAULT {}, + per-recipient-fields [3] SEQUENCE SIZE (1..ub-recipients) OF + PerRecipientProbeSubmissionFields } + +PerRecipientProbeSubmissionFields ::= SET { + recipient-name RecipientName, + originator-report-request [0] OriginatorReportRequest, + explicit-conversion [1] ExplicitConversion OPTIONAL, + extensions [2] Extensions DEFAULT { } } + + +-- Message Delivery Envelope + +MessageDeliveryEnvelope ::= SEQUENCE { + identifier MessageDeliveryIdentifier, + time MessageDeliveryTime, + fields OtherMessageDeliveryFields } + +OtherMessageDeliveryFields ::= SET { + content-type DeliveredContentType, + originator-name OriginatorName, + original-encoded-information-types [1] OriginalEncodedInformationTypes OPTIONAL, + priority Priority DEFAULT normal, + delivery-flags [2] DeliveryFlags OPTIONAL, + other-recipient-names [3] OtherRecipientNames OPTIONAL, + this-recipient-name [4] ThisRecipientName, + originally-intended-recipient-name [5] OriginallyIntendedRecipientName OPTIONAL, + converted-encoded-information-types [6] ConvertedEncodedInformationTypes OPTIONAL, + message-submission-time [7] MessageSubmissionTime, + content-identifier [8] ContentIdentifier OPTIONAL, + extensions [9] Extensions DEFAULT { } } + +-- Report Delivery Envelope + +ReportDeliveryEnvelope ::= SET { + subject-submission-identifier SubjectSubmissionIdentifier, + content-identifier ContentIdentifier OPTIONAL, + content-type ContentType OPTIONAL, + original-eits OriginalEncodedInformationTypes OPTIONAL, + extensions [1] Extensions DEFAULT {}, + per-recipient-fields SEQUENCE SIZE (1..ub-recipients) OF PerRecipientReportDeliveryFields } + +PerReportDeliveryFields ::= SET { + subject-submission-identifier SubjectSubmissionIdentifier, + content-identifier ContentIdentifier OPTIONAL, + content-type ContentType OPTIONAL, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + extensions [1] Extensions DEFAULT { } } + +PerRecipientReportDeliveryFields ::= SET { + actual-recipient-name [0] ActualRecipientName, + report [1] Report, + converted-encoded-information-types ConvertedEncodedInformationTypes OPTIONAL, + originally-intended-recipient-name [2] OriginallyIntendedRecipientName OPTIONAL, + supplementary-information [3] SupplementaryInformation OPTIONAL, + extensions [4] Extensions DEFAULT { } } + +Report ::= CHOICE { + delivery [0] DeliveryReport, + non-delivery [1] NonDeliveryReport } + +DeliveryReport ::= SET { + message-delivery-time [0] MessageDeliveryTime, + type-of-MTS-user [1] TypeOfMTSUser DEFAULT public } + +NonDeliveryReport ::= SET { + non-delivery-reason-code [0] NonDeliveryReasonCode, + non-delivery-diagnostic-code [1] NonDeliveryDiagnosticCode OPTIONAL } + +-- Envelope Fields + +OriginatorName ::= ORAddressAndOrDirectoryName + +OriginalEncodedInformationTypes ::= EncodedInformationTypes + +-- Should really be a CHOICE +ContentType ::= CHOICE { + built-in BuiltInContentType, + external ExternalContentType } + +BuiltInContentType ::= [APPLICATION 6] INTEGER { + unidentified (0), + external (1), -- identified by the object-identifier of the EXTERNAL content + interpersonal-messaging-1984 (2), + interpersonal-messaging-1988 (22) } (0..ub-built-in-content-type) + +ExternalContentType ::= OBJECT IDENTIFIER + +DeliveredContentType ::= CHOICE { + built-in [0] BuiltInContentType, + external ExternalContentType +} + +ContentIdentifier ::= [APPLICATION 10] PrintableString (SIZE (1..ub-content-id-length)) + +PerMessageIndicators ::= [APPLICATION 8] BIT STRING { + disclosure-of-recipients (0), -- disclosure-of-recipients-allowed 'one', + -- disclosure-of-recipient-prohibited 'zero'; + -- ignored for Probe-submission + implicit-conversion-prohibited (1), -- implicit-conversion-prohibited 'one', + -- implicit-conversion-allowed 'zero' + alternate-recipient-allowed (2), -- alternate-recipient-allowed 'one', + -- alternate-recipient-prohibited 'zero' + content-return-request (3) -- content-return-requested 'one', + -- content-return-not-requested 'zero'; + -- ignored for Probe-submission -- } + (SIZE (0..ub-bit-options)) + +RecipientName ::= ORAddressAndOrDirectoryName + +OriginatorReportRequest ::= BIT STRING { + report (3), + non-delivery-report (4) + -- at most one bit shall be 'one': + -- report bit 'one' requests a 'report'; + -- non-delivery-report bit 'one' requests a 'non-delivery-report'; + -- both bits 'zero' requests 'no-report' -- } (SIZE (0..ub-bit-options)) + +ExplicitConversion ::= INTEGER { + ia5-text-to-teletex (0), + teletex-to-telex (1), + telex-to-ia5-text (2), + telex-to-teletex (3), + telex-to-g4-class-1 (4), + telex-to-videotex (5), + ia5-text-to-telex (6), + telex-to-g3-facsimile (7), + ia5-text-to-g3-facsimile (8), + ia5-text-to-g4-class-1 (9), + ia5-text-to-videotex (10), + teletex-to-ia5-text (11), + teletex-to-g3-facsimile (12), + teletex-to-g4-class-1 (13), + teletex-to-videotex (14), + videotex-to-telex (15), + videotex-to-ia5-text (16), + videotex-to-teletex (17) } (0..ub-integer-options) + +DeferredDeliveryTime ::= Time + +Priority ::= [APPLICATION 7] ENUMERATED { + normal (0), + non-urgent (1), + urgent (2) } + +ContentLength ::= INTEGER (0..ub-content-length) + +MessageDeliveryIdentifier ::= MTSIdentifier + +MessageDeliveryTime ::= Time + +DeliveryFlags ::= BIT STRING { + implicit-conversion-prohibited (1) -- implicit-conversion-prohibited 'one', + -- implicit-conversion-allowed 'zero' -- } + (SIZE (0..ub-bit-options)) + +OtherRecipientNames ::= SEQUENCE SIZE (1..ub-recipients) OF OtherRecipientName + +OtherRecipientName ::= ORAddressAndOrDirectoryName + +ThisRecipientName ::= ORAddressAndOrDirectoryName + +OriginallyIntendedRecipientName ::= ORAddressAndOrDirectoryName + +ConvertedEncodedInformationTypes ::= EncodedInformationTypes + +SubjectSubmissionIdentifier ::= MTSIdentifier + +TypeOfMTSUser ::= INTEGER { + public (0), + private (1), + ms (2), + dl (3), + pdau (4), + physical-recipient (5), + other (6) } (0..ub-mts-user-types) + +NonDeliveryReasonCode ::= INTEGER { + transfer-failure (0), + unable-to-transfer (1), + conversion-not-performed (2), + physical-rendition-not-performed (3), + physical-delivery-not-performed (4), + restricted-delivery (5), + directory-operation-unsuccessful (6) } (0..ub-reason-codes) + +NonDeliveryDiagnosticCode ::= INTEGER { + unrecognised-OR-name (0), + ambiguous-OR-name (1), + mts-congestion (2), + loop-detected (3), + recipient-unavailable (4), + maximum-time-expired (5), + encoded-information-types-unsupported (6), + content-too-long (7), + conversion-impractical (8), + implicit-conversion-prohibited (9), + implicit-conversion-not-subscribed (10), + invalid-arguments (11), + content-syntax-error (12), + size-constraint-violation (13), + protocol-violation (14), + content-type-not-supported (15), + too-many-recipients (16), + no-bilateral-agreement (17), + unsupported-critical-function (18), + conversion-with-loss-prohibited (19), + line-too-long (20), + page-split (21), + pictorial-symbol-loss (22), + punctuation-symbol-loss (23), + alphabetic-character-loss (24), + multiple-information-loss (25), + recipient-reassignment-prohibited (26), + redirection-loop-detected (27), + dL-expansion-prohibited (28), + no-DL-submit-permission (29), + dl-expansion-failure (30), + physical-rendition-attributes-not-supported (31), + undeliverable-mail-physical-delivery-address-incorrect (32), + undeliverable-mail-physical-delivery-office-incorrect-or-invalid (33), + undeliverable-mail-physical-delivery-address-incomplete (34), + undeliverable-mail-recipient-unknown (35), + undeliverable-mail-recipient-deceased (36), + undeliverable-mail-organization-expired (37), + undeliverable-mail-recipient-refused-to-accept (38), + undeliverable-mail-recipient-did-not-claim (39), + undeliverable-mail-recipient-changed-address-permanently (40), + undeliverable-mail-recipient-changed-address-temporarily (41), + undeliverable-mail-recipient-changed-temporary-address (42), + undeliverable-mail-new-address-unknown (43), + undeliverable-mail-recipient-did-not-want-forwarding (44), + undeliverable-mail-originator-prohibited-forwarding (45), + secure-messaging-error (46), + unable-to-downgrade (47) } (0..ub-diagnostic-codes) + +SupplementaryInformation ::= PrintableString (SIZE (1..ub-supplementary-info-length)) + + +-- Common Parameter Types + +Content ::= OCTET STRING -- when the content-type has the integer value external, the value of the + -- content octet string is the ASN.1 encoding of the external-content; + -- an external-content is a data type EXTERNAL + +MTSIdentifier ::= [APPLICATION 4] SEQUENCE { + global-domain-identifier GlobalDomainIdentifier, + local-identifier LocalIdentifier } + +LocalIdentifier ::= IA5String (SIZE (1..ub-local-id-length)) + +GlobalDomainIdentifier ::= [APPLICATION 3] SEQUENCE { + country-name CountryName, + administration-domain-name AdministrationDomainName, + private-domain-identifier PrivateDomainIdentifier OPTIONAL } + +PrivateDomainIdentifier ::= CHOICE { + numeric NumericString (SIZE (1..ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) } + +MTAName ::= IA5String (SIZE (1..ub-mta-name-length)) + +Time ::= UTCTime + +-- OR Names + +ORAddressAndOrDirectoryName ::= ORName + +ORAddressAndOptionalDirectoryName ::= ORName + +ORName ::= [APPLICATION 0] SEQUENCE { + standard-attributes StandardAttributes, + domain-defined DomainDefinedAttributes OPTIONAL, + extension-attributes ExtensionAttributes OPTIONAL, + directory-name [0] Name OPTIONAL } + +ORAddress ::= SEQUENCE { + standard-attributes StandardAttributes, + domain-defined-attributes DomainDefinedAttributes OPTIONAL, + -- see also teletex-domain-defined-attributes + extension-attributes ExtensionAttributes OPTIONAL } + +-- Note[:| -] the OR-address is semantically absent from the OR-name if the standard-attribute sequence is +-- empty and the domain-defined-attributes and extension-attributes are both omitted. + + +-- Standard Attributes + +StandardAttributes ::= SEQUENCE { + country-name CountryName OPTIONAL, + administration-domain-name AdministrationDomainName OPTIONAL, + network-address [0] NetworkAddress OPTIONAL, + -- see also extended-network-address + terminal-identifier [1] TerminalIdentifier OPTIONAL, + private-domain-name [2] EXPLICIT PrivateDomainName OPTIONAL, + organization-name [3] OrganizationName OPTIONAL, + -- see also teletex-organization-name + numeric-user-identifier [4] NumericUserIdentifier OPTIONAL, + personal-name [5] PersonalName OPTIONAL, + organizational-unit-names [6] OrganizationalUnitNames OPTIONAL + -- see also teletex-organizational-unit-names -- } + +CountryName ::= [APPLICATION 1] EXPLICIT CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length)) +} + +AdministrationDomainName ::= [APPLICATION 2] EXPLICIT CHOICE { + numeric NumericString (SIZE (0..ub-domain-name-length)), + printable PrintableString (SIZE (0..ub-domain-name-length)) +} + +NetworkAddress ::= X121Address + +X121Address ::= NumericString (SIZE (1..ub-x121-address-length)) + +TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length)) + +PrivateDomainName ::= CHOICE { + numeric NumericString (SIZE (1..ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) +} + +OrganizationName ::= PrintableString (SIZE (1..ub-organization-name-length)) + +NumericUserIdentifier ::= NumericString (SIZE (1..ub-numeric-user-id-length)) + +PersonalName ::= SET { + surname [0] PrintableString (SIZE (1..ub-surname-length)), + given-name [1] PrintableString (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] PrintableString (SIZE (1..ub-generation-qualifier-length)) OPTIONAL } + +OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF OrganizationUnitName + +OrganizationUnitName ::= PrintableString (SIZE (1..ub-organizational-unit-name-length)) + + +-- Domain-defined Attributes + +DomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) OF DomainDefinedAttribute + +DomainDefinedAttribute ::= SEQUENCE { + type PrintableString (SIZE (1..ub-domain-defined-attribute-type-length)), + value PrintableString (SIZE (1..ub-domain-defined-attribute-value-length)) } + + +-- Encoded Information Types + +EncodedInformationTypes ::= [APPLICATION 5] SET { + built-in-encoded-information-types [0] BuiltInEncodedInformationTypes, +-- non-basic-parameters COMPONENTS OF NonBasicParameters, + external-encoded-information-types [4] ExternalEncodedInformationTypes OPTIONAL } + + +-- Built-in Encoded Information Types + +BuiltInEncodedInformationTypes ::= BIT STRING { + undefined (0), + telex (1), + ia5-text (2), + g3-facsimile (3), + g4-class-1 (4), + teletex (5), + videotex (6), + voice (7), + sfd (8), + mixed-mode (9) } (SIZE (0..ub-built-in-encoded-information-types)) + +-- Non-basic Parameters + +NonBasicParameters ::= SET { + g3-facsimile [1] G3FacsimileNonBasicParameters DEFAULT { }, + teletex [2] TeletexNonBasicParameters DEFAULT { }, + g4-class-1-and-mixed-mode [3] G4Class1AndMixedModeNonBasicParameters OPTIONAL } + +G3FacsimileNonBasicParameters ::= BIT STRING { + two-dimensional (8), + fine-resolution (9), + unlimited-length (20), + b4-length (21), + a3-width (22), + b4-width (23), + uncompressed (30) } -- as defined in [|CCITT] Recommendation T.30 + +TeletexNonBasicParameters ::= SET { + graphic-character-sets [0] TeletexString OPTIONAL, + control-character-sets [1] TeletexString OPTIONAL, + page-formats [2] OCTET STRING OPTIONAL, + miscellaneous-terminal-capabilities [3] TeletexString OPTIONAL, + private-use [4] OCTET STRING OPTIONAL -- maximum ub-teletex-private-use-length octets -- } + -- as defined in [|CCITT] Recommendation T.62 + +G4Class1AndMixedModeNonBasicParameters ::= PresentationCapabilities + +PresentationCapabilities ::= ANY -- as defined in [|CCITT] Recommendations T.400, T.503 and T.501 + + +-- External Encoded Information Types + +ExternalEncodedInformationTypes ::= SET SIZE (1..ub-encoded-information-types) OF + ExternalEncodedInformationType + +ExternalEncodedInformationType ::= OBJECT IDENTIFIER + +-- END OF MTS + +MTABindArgument ::= + CHOICE { + no-auth NULL, -- if no authentication is required + auth [1] SET { -- if authentication is required + initiator-name [0] MTAName, + initiator-credentials[1] EXPLICIT InitiatorCredentials, + security-context [2] SecurityContext OPTIONAL } } + +MTABindResult ::= + CHOICE { + no-auth NULL, -- if no authentication is required + auth[1] SET { -- if authentication is required + responder-name [0] MTAName, + responder-credentials[1] EXPLICIT ResponderCredentials + } + } + +MTABindError ::= + INTEGER { + busy (0), + authentication-error (2), + unacceptable-dialogue-mode (3), + unacceptable-security-context (4) } (0..ub-integer-options) + + +-- Transfer Port + +MessageTransferArgument ::= + SEQUENCE { + envelope MessageTransferEnvelope, + content Content } + + +ReportTransferArgument ::= + SEQUENCE { + envelope ReportTransferEnvelope, + content ReportTransferContent } + + +-- Message Transfer Envelope + +MessageTransferEnvelope ::= SET { + message-identifier MessageIdentifier, + originator-name OriginatorName, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + priority Priority DEFAULT normal, + per-message-indicators PerMessageIndicators DEFAULT { }, + deferred-delivery-time [0] DeferredDeliveryTime OPTIONAL, + per-domain-bilateral-information [1] SEQUENCE OF PerDomainBilateralInformation OPTIONAL, + trace-information TraceInformation, + extensions [3] Extensions DEFAULT { } , + per-recipient-fields [2] SEQUENCE SIZE (1..ub-recipients) OF + PerRecipientMessageTransferFields } + +PerMessageTransferFields ::= SET { + message-identifier MessageIdentifier, + originator-name OriginatorName, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + priority Priority DEFAULT normal, + per-message-indicators PerMessageIndicators DEFAULT { }, + deferred-delivery-time [0] DeferredDeliveryTime OPTIONAL, + per-domain-bilateral-information [1] SEQUENCE OF PerDomainBilateralInformation OPTIONAL, + trace-information TraceInformation, + extensions [3] Extensions DEFAULT { } } + +PerRecipientMessageTransferFields ::= SET { + recipient-name RecipientName, + originally-specified-recipient-number [0] OriginallySpecifiedRecipientNumber, + per-recipient-indicators [1] PerRecipientIndicators, + explicit-conversion [2] ExplicitConversion OPTIONAL, + extensions [3] Extensions DEFAULT { } } + +-- Probe Transfer Envelope + +ProbeTransferEnvelope ::= SET { + probe-identifier ProbeIdentifier, + originator-name OriginatorName, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + content-length [0] ContentLength OPTIONAL, + per-message-indicators PerMessageIndicators DEFAULT { }, + per-domain-bilateral-information [1] SEQUENCE SIZE (1..ub-transfer) OF + PerDomainBilateralInformation OPTIONAL, + trace-information TraceInformation, + extensions [3] Extensions DEFAULT { }, + per-recipient-fields [2] SEQUENCE SIZE (1..ub-recipients) OF PerRecipientProbeTransferFields } + +PerProbeTransferFields ::= SET { + probe-identifier ProbeIdentifier, + originator-name OriginatorName, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType, + content-identifier ContentIdentifier OPTIONAL, + content-length [0] ContentLength OPTIONAL, + per-message-indicators PerMessageIndicators DEFAULT { }, + per-domain-bilateral-information [1] SEQUENCE SIZE (1..ub-transfer) OF + PerDomainBilateralInformation OPTIONAL, + trace-information TraceInformation, + extensions [3] Extensions DEFAULT { } } + +PerRecipientProbeTransferFields ::= SET { + recipient-name RecipientName, + originally-specified-recipient-number [0] OriginallySpecifiedRecipientNumber, + per-recipient-indicators [1] PerRecipientIndicators, + explicit-conversion [2] ExplicitConversion OPTIONAL, + extensions [3] Extensions DEFAULT { } } + + +-- Report Transfer Envelope + +ReportTransferEnvelope ::= SET { + report-identifier ReportIdentifier, + report-destination-name ReportDestinationName, + trace-information TraceInformation, + extensions [1] Extensions DEFAULT { } } + +-- Report Transfer Content + +ReportTransferContent ::= SET { + subject-identifier SubjectIdentifier, + subject-intermediate-trace-information SubjectIntermediateTraceInformation OPTIONAL, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType OPTIONAL, + content-identifier ContentIdentifier OPTIONAL, + returned-content [1] Content OPTIONAL, + additional-information [2] AdditionalInformation OPTIONAL, + extensions [3] Extensions DEFAULT { }, + per-recipient-fields [0] SEQUENCE SIZE (1..ub-recipients) OF + PerRecipientReportTransferFields } + +PerReportTransferFields ::= SET { + subject-identifier SubjectIdentifier, + subject-intermediate-trace-information SubjectIntermediateTraceInformation OPTIONAL, + original-encoded-information-types OriginalEncodedInformationTypes OPTIONAL, + content-type ContentType OPTIONAL, + content-identifier ContentIdentifier OPTIONAL, + returned-content [1] Content OPTIONAL, + additional-information [2] AdditionalInformation OPTIONAL, + extensions [3] Extensions DEFAULT { } } + +PerRecipientReportTransferFields ::= SET { + actual-recipient-name [0] ActualRecipientName, + originally-specified-recipient-number [1] OriginallySpecifiedRecipientNumber, + per-recipient-indicators [2] PerRecipientIndicators, + last-trace-information [3] LastTraceInformation, + originally-intended-recipient-name [4] OriginallyIntendedRecipientName OPTIONAL, + supplementary-information [5] SupplementaryInformation OPTIONAL, + extensions [6] Extensions DEFAULT { } } + + +-- Envelope & Report Content Fields + +MessageIdentifier ::= MTSIdentifier + +PerDomainBilateralInformation ::= SEQUENCE { + country-name CountryName, + domain-information DomainInformation, + bilateral-information BilateralInformation} + +DomainInformation ::= + CHOICE { + administration-domain-name AdministrationDomainName, + private-domain-name AdministrationAndPrivateDomainName} + +AdministrationAndPrivateDomainName ::= + SEQUENCE { + administration-domain-name [0] AdministrationDomainName, + private-domain-identifier [1] PrivateDomainIdentifier OPTIONAL} + +BilateralInformation ::= ANY -- maximum ub-bilateral-info octets including all encoding + +OriginallySpecifiedRecipientNumber ::= INTEGER (SIZE (1..ub-recipients)) + +PerRecipientIndicators ::= BIT STRING { + responsibility (0), + -- responsible 'one', not-responsible 'zero' + originating-MTA-report (1), + originating-MTA-non-delivery-report (2), + -- either originating-MTA-report, or originating-MTA-non-delivery-report, or both, shall be 'one': + -- originating-MTA-report bit 'one' requests a 'report'; + -- originating-MTA-non-delivery-report bit 'one' requests a 'non-delivery-report'; + -- both bits 'one' requests an 'audited-report'; + -- bits 0 - 2 'don't care' for Report Transfer Content + originator-report (3), + originator-non-delivery-report (4), + -- at most one bit shall be 'one': + -- originator-report bit 'one' requests a 'report'; + -- originator-non-delivery-report bit 'one' requests a 'non-delivery-report'; + -- both bits 'zero' requests 'no-report' + reserved-5 (5), + reserved-6 (6), + reserved-7 (7) + -- reserved- bits 5 - 7 shall be 'zero' -- } (SIZE (8..ub-bit-options)) + +ProbeIdentifier ::= MTSIdentifier + +ReportIdentifier ::= MTSIdentifier + +ReportDestinationName ::= ORAddressAndOptionalDirectoryName + +SubjectIdentifier ::= MessageOrProbeIdentifier + +MessageOrProbeIdentifier ::= MTSIdentifier + +SubjectIntermediateTraceInformation ::= TraceInformation + +AdditionalInformation ::= ANY -- maximum ub-additional-info octets including all encoding + +ActualRecipientName ::= ORAddressAndOptionalDirectoryName + +LastTraceInformation ::= SET { + arrival-time [0] ArrivalTime, + converted-encoded-information-types ConvertedEncodedInformationTypes OPTIONAL, + report [1] EXPLICIT Report } + + +-- Common Parameter Types + +TraceInformation ::= [APPLICATION 9] SEQUENCE SIZE (1..ub-transfers) OF TraceInformationElement + +TraceInformationElement ::= SEQUENCE { + global-domain-identifier GlobalDomainIdentifier, + domain-supplied-information DomainSuppliedInformation } + +DomainSuppliedInformation ::= SET { + arrival-time [0] ArrivalTime, + routing-action [2] RoutingAction, + attempted-domain GlobalDomainIdentifier OPTIONAL, + deferred-time [1] DeferredTime OPTIONAL, + converted-encoded-information-types ConvertedEncodedInformationTypes OPTIONAL, + other-actions [3] OtherActions DEFAULT { } } + +AdditionalActions ::= SET { + deferred-time [1] DeferredTime OPTIONAL, + converted-encoded-information-types ConvertedEncodedInformationTypes OPTIONAL, + other-actions [3] OtherActions DEFAULT { } } + +RoutingAction ::= ENUMERATED { + relayed (0), + rerouted (1) } + +DeferredTime ::= Time + +ArrivalTime ::= Time + +OtherActions ::= BIT STRING { + redirected (0), + dl-operation (1) } (SIZE (0..ub-bit-options)) + +Name ::= ANY -- for now... +END diff --git a/Lib/x400/rasn.c b/Lib/x400/rasn.c new file mode 100644 index 0000000..834bb86 --- /dev/null +++ b/Lib/x400/rasn.c @@ -0,0 +1,484 @@ +/* rasn.c: incremental ASN1 reader */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/x400/RCS/rasn.c,v 6.0 1991/12/18 20:25:37 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Lib/x400/RCS/rasn.c,v 6.0 1991/12/18 20:25:37 jpo Rel $ + * + * $Log: rasn.c,v $ + * Revision 6.0 1991/12/18 20:25:37 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include +#include + +extern PE ps2pe_aux (); + +static struct qbuf *qbase; +static void add2qb (); +static int check_external (); +static int check_pserr (), qbproc (); +static int attempt_parse (), read_octet_hdr (), read_octet (); +static int proc_body (), proc_hdr (), proc_hdr_aux (); + +IFP asn_procfnx = proc_hdr; +static IFP hdrfnx, bodyfnx; +static int ext_type; +#define PENDING (-2) +static int bad = 0, oct_length; + +void asn_init (hf, bf, ext) +IFP hf, bf; +int ext; +{ + if (qbase) + qb_free (qbase); + qbase = NULL; + oct_length = bad = 0; + hdrfnx = hf; + bodyfnx = bf; + asn_procfnx = proc_hdr; + ext_type = ext; +} + + +static int proc_hdr (qp) +struct qbuf *qp; +{ + char *pestr; + int result; + int len; + + add2qb (&qbase, qp); + + pestr = qb2str (qbase); + len = qbase -> qb_len; + result = attempt_parse (pestr, &len); + free (pestr); + switch (result) { + case PENDING: + return OK; + case DONE: + case NOTOK: + return result; + case OK: + break; + } + + PP_TRACE (("Header read, %d bytes", len)); + if ((result = qbproc (qbase, &len, NULLIFP)) != OK) + return result; + asn_procfnx = proc_body; + return proc_body ((struct qbuf *)NULL); +} + +static int ext_length = 0; + +static int attempt_parse (str, len) +char *str; +int *len; +{ + PS ps; + PE pe; + int type; + char *ptr; + int len_left; + int retval = OK; + + if ((ps = ps_alloc (str_open)) == NULLPS) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't allocate PS")); + return NOTOK; + } + if (str_setup (ps, str, *len, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't bind str to PS")); + ps_free (ps); + return NOTOK; + } + + ext_length = 0; + if (ext_type) { + switch (ext_length = check_external (ps)) { + case PENDING: + ps_free (ps); + return PENDING; + case NOTOK: + ps_free (ps); + if (hdrfnx && (*hdrfnx) (NULLPE, NOTOK)) + return NOTOK; + bad = 1; + *len = 0; + return OK; + default: + break; + } + } + + ptr = ps -> ps_ptr; /* save where we had got to */ + len_left = *len - (ptr - str); + + if ((pe = ps2pe_aux (ps, 1, 0)) == NULLPE) { + ps_free (ps); + return check_pserr (ps); + } + + if (ps -> ps_cnt <= 0) { + ps_free (ps); + return PENDING; + } + switch (PE_ID(pe -> pe_class, pe -> pe_id)) { + case PE_ID (PE_CLASS_CONT, 0): + type = MT_UMPDU; + if (pe -> pe_len == PE_LEN_INDF) + ext_length += 2; + break; + case PE_ID (PE_CLASS_CONT, 1): + type = MT_DMPDU; + (void) str_setup (ps, ptr, len_left, 1); + break; + case PE_ID (PE_CLASS_CONT, 2): + type = MT_PMPDU; + (void) str_setup (ps, ptr, len_left, 1); + break; + default: + pe_free (pe); + ps_free (ps); + if (hdrfnx && (*hdrfnx) (NULLPE, NOTOK) != OK) + return NOTOK; + bad = 1; + *len = 0; + return OK; + } + pe_free (pe); + + if ((pe = ps2pe(ps)) == NULLPE) + return check_pserr (ps); + + if (hdrfnx && (*hdrfnx) (pe, type) != OK) + retval = NOTOK; + else + retval = type == MT_UMPDU ? OK : DONE; + + *len -= ps -> ps_cnt; + ps_free (ps); + pe_free (pe); + return retval; +} + +/* ARGSUSED */ +static int proc_done (qb) +struct qbuf *qb; +{ + PP_TRACE(("proc_done()")); + return DONE; +} + +static int proc_body (qp) +struct qbuf *qp; +{ + int i; + static int count, used; + + if (qp) + add2qb (&qbase, qp); + if (bad) { + i = qbase -> qb_len; + return qbproc (qbase, &i, bodyfnx); + } + + if (qbase -> qb_len && count > 0) + if ((i = qbproc (qbase, &count, bodyfnx)) != OK) + return i; + + for (;qbase -> qb_len > 0;) { + char *pestr = qb2str (qbase); + used = 0; + i = read_octet_hdr (pestr, qbase -> qb_len, + &count, &used); + free (pestr); + + switch (i) { + case DONE: + (void) qbproc (qbase, &used, NULLIFP); + if (qbase -> qb_len - ext_length > 0) { + PP_LOG(LLOG_EXCEPTIONS, + ("Trailing garbage (%d bytes) on end of PDU", + qbase -> qb_len - used)); + } + asn_procfnx = proc_done; + return DONE; + case NOTOK: + return NOTOK; + case PENDING: + return OK; + case OK: + (void) qbproc (qbase, &used, NULLIFP); + if ((i = qbproc (qbase, &count, bodyfnx)) != OK) + return i; + if (qbase -> qb_len <= 0) + return OK; + break; + } + } + return OK; +} + + +static int check_external (ps) +PS ps; +{ + PE pe; + int extra = 0; + char *psptr = ps -> ps_ptr; + + /* EXTERNAL Wrapper */ + if ((pe = ps2pe_aux (ps, 1, 0)) == NULLPE) + return check_pserr (ps); + + if (PE_ID (pe -> pe_class, pe -> pe_id) != + PE_ID (PE_CLASS_UNIV, PE_CONS_EXTN)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Missing EXTERNAL wrapper; found %s/%d", + pe_classlist[pe -> pe_class], pe -> pe_id)); + pe_free (pe); + return NOTOK; + } + if (pe -> pe_len == PE_LEN_INDF) + extra += 2; + pe_free (pe); + + if ((pe = ps2pe (ps)) == NULLPE) + return check_pserr (ps); + + if (PE_ID (pe -> pe_class, pe -> pe_id) != + PE_ID (PE_CLASS_UNIV, PE_PRIM_INT)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Missing External ID, found %s/%d", + pe_classlist[pe -> pe_class], pe -> pe_id)); + pe_free (pe); + return NOTOK; + } + pe_free (pe); + + /* ANY Context 0 wrapper */ + if ((pe = ps2pe_aux (ps, 1, 0)) == NULLPE) + return check_pserr (ps); + + if (PE_ID (pe -> pe_class, pe -> pe_id) != + PE_ID (PE_CLASS_CONT, 0)) { + PP_LOG (LLOG_EXCEPTIONS, + ("Not an EXTERNAL ANY type; found %s/%d", + pe_classlist[pe -> pe_class], pe -> pe_id)); + pe_free (pe); + return NOTOK; + } + if (pe -> pe_len == PE_LEN_INDF) + extra += 2; + pe_free (pe); + PP_TRACE (("%d bytes read, %d extra at end...", + ps -> ps_ptr - psptr, extra)); + /* OK EXTERNAL checks out. */ + return extra; +} + +static int qbproc (q, len, fnx) +struct qbuf *q; +int *len; +IFP fnx; +{ + struct qbuf *qp; + int i; + + if (q == NULL || q -> qb_len <= 0) + return OK; + if (q -> qb_len != q ->qb_forw -> qb_len && + qb_pullup (q) == NOTOK) + adios (NULLCP, "qb_pullup failed"); + + for (qp = NULL; *len > 0; ) { + if (qp == NULL && + (qp = q -> qb_forw) == q) + break; + i = min(qp -> qb_len, *len); + if (fnx) { + int result; + result = (*fnx) (qp -> qb_data, i); + if (result != OK) + return result; + } + *len -= i; + qp -> qb_data += i; + qp -> qb_len -= i; + q -> qb_len -= i; + if (qp -> qb_len <= 0) { + remque (qp); + free ((char *)qp); + qp = NULL; + } + } + return OK; +} + +static void add2qb (qpp, qp) +struct qbuf **qpp, *qp; +{ + struct qbuf *q; + + if (*qpp == NULL) { + *qpp = (struct qbuf *) smalloc (sizeof *qp); + bzero ((char *)*qpp, sizeof **qpp); + (*qpp) -> qb_forw = (*qpp) -> qb_back = *qpp; + } + for (q = qp -> qb_forw; q != qp; q = qp -> qb_forw) { + remque (q); + insque (q, (*qpp) -> qb_back); + (*qpp) -> qb_len += q -> qb_len; + qp -> qb_len -= q -> qb_len; + } +} + +static int read_octet_hdr (str, len, countp, usedp) +char *str; +int len; +int *countp; +int *usedp; +{ + static PS ps; + + *usedp = 0; + if (len < 1) + return OK; + if (ps == NULLPS) + if ((ps = ps_alloc (str_open)) == NULLPS) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't setup PS")); + return NOTOK; + } + if (str_setup (ps, str, len, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't attach string to PS")); + return NOTOK; + } + + return read_octet (ps, countp, usedp); +} + +#define MAXSTACK 100 +static int stackidx = -1; +static struct stack { +#define STACK_EOC 1 +#define STACK_LEN 2 + int type; + int len; +} mystack[MAXSTACK]; + +static int read_octet (ps, countp, usedp) +PS ps; +int *countp; +int *usedp; +{ + PE pe; + char *psptr; + + PP_TRACE (("read_octet() stackidx = %d u=%d c=%d ol=%d", stackidx, + *usedp, *countp, oct_length)); + if (stackidx >= 0 && mystack[stackidx].type == STACK_LEN && + mystack[stackidx].len <= oct_length) { + stackidx --; + PP_TRACE (("read_octet length done, poping stack")); + if (stackidx < 0) + return DONE; + else + return read_octet (ps, countp, usedp); + } + + psptr = ps -> ps_ptr; + if ((pe = ps2pe_aux (ps, 1, 0)) == NULLPE) + return check_pserr (ps); + + if (pe -> pe_class == PE_CLASS_UNIV && + pe -> pe_id == PE_UNIV_EOC) { + pe_free (pe); + PP_TRACE (("stackidx %d, type=%d", stackidx, + mystack[stackidx].type)); + if (stackidx < 0 || mystack[stackidx].type != STACK_EOC) { + PP_LOG (LLOG_EXCEPTIONS, ("Unexpected EOC string")); + return NOTOK; + } + PP_TRACE (("read_octet EOC found, poping stack")); + *usedp += ps -> ps_ptr - psptr; + oct_length += ps -> ps_ptr - psptr; + stackidx --; + if (stackidx == -1) { + PP_TRACE (("read_octet used %d", *usedp)); + return DONE; + } + else + return read_octet (ps, countp, usedp); + } + + if (pe -> pe_class != PE_CLASS_UNIV || + pe -> pe_id != PE_PRIM_OCTS) { + PP_LOG (LLOG_EXCEPTIONS, + ("Not an OCTET STRING expecting %s/%d got %s/%d", + pe_classlist[PE_CLASS_UNIV], PE_PRIM_OCTS, + pe_classlist[pe -> pe_class], pe -> pe_id)); + return NOTOK; + } + if (pe -> pe_form != PE_FORM_PRIM) { + *usedp += ps -> ps_ptr - psptr; + oct_length += ps -> ps_ptr - psptr; + if (stackidx >= MAXSTACK - 1) { + PP_LOG (LLOG_EXCEPTIONS, ("Internal stack overflow")); + return NOTOK; + } + stackidx ++; + if (pe -> pe_len == PE_LEN_INDF) { + PP_TRACE (("read_octet cons INDF found, pushing...")); + mystack[stackidx].type = STACK_EOC; + } + else { + PP_TRACE (("read_octet cons len %d found pushing", + pe -> pe_len)); + mystack[stackidx].type = STACK_LEN; + mystack[stackidx].len = oct_length + pe -> pe_len; + } + return read_octet (ps, countp, usedp); + } + stackidx ++; + mystack[stackidx].type = STACK_LEN; + mystack[stackidx].len = oct_length + pe -> pe_len; + *countp = pe -> pe_len; + oct_length += pe -> pe_len; + *usedp += ps -> ps_ptr - psptr; + PP_TRACE (("read_octet used %d count %d ol=%d", *usedp, *countp, + oct_length)); + pe_free (pe); + return OK; +} + +static int check_pserr (ps) +PS ps; +{ + int retval = PENDING; + + switch (ps -> ps_errno) { + case PS_ERR_EOF: + case PS_ERR_EOFLEN: + case PS_ERR_EOFID: + case PS_ERR_NONE: + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error: %s", + ps_error (ps -> ps_errno))); + retval = NOTOK; + break; + } + return retval; +} diff --git a/Lib/x400/tokens.py b/Lib/x400/tokens.py new file mode 100644 index 0000000..1a6838b --- /dev/null +++ b/Lib/x400/tokens.py @@ -0,0 +1,132 @@ +-- tokens.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/tokens.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: tokens.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + +-- Security related definitions from X.400 +-- Version 1 December 1988 +-- Author: M.Roe, University College London + + +Toks +-- {iso identified-organisation(3) locator(99) modules(0) tokens(2)} +DEFINITIONS IMPLICIT TAGS ::= +BEGIN + +IMPORTS + Encrypted, SignedType, Signature, Protected, AlgorithmIdentifier, + Certificate, EncryptionKey + FROM Auth; + + +-- Security Label + +SecurityContext ::= SET SIZE (1..ub-security-labels) OF SecurityLabel + +SecurityLabel ::= SET { + security-policy-identifier SecurityPolicyIdentifier OPTIONAL, + security-classification SecurityClassification OPTIONAL, + privacy-mark PrivacyMark OPTIONAL, + security-categories SecurityCategories OPTIONAL } + +SecurityPolicyIdentifier ::= OBJECT IDENTIFIER + +SecurityClassification ::= INTEGER { + unmarked (0), + unclassified (1), + restricted (2), + confidential (3), + secret (4), + top-secret (5) } (0..ub-integer-options) + +PrivacyMark ::= PrintableString (SIZE (1..ub-privacy-mark-length)) + +SecurityCategories ::= SET SIZE (1..ub-security-categories) OF SecurityCategory + +SecurityCategory ::= SEQUENCE { + type [0] OBJECT IDENTIFIER, + value [1] ANY} + +-- Proof of Delivery + +ProofOfDelivery ::= + SET { + certificates [0] Certificates OPTIONAL, + signature [1] Signature OPTIONAL} + +ProofOfDeliveryBody ::= + SEQUENCE { + algorithm AlgorithmIdentifier, + time UTCTime, + recipient ANY, + content OCTET STRING} + +-- We don't handle certification paths at the moment +Certificates ::= + SEQUENCE { + certificate Certificate} + +-- Tokens + +Token ::= + SEQUENCE { + type OBJECT IDENTIFIER, + token [1] ANY} + +TokenData ::= + SEQUENCE { + type [0] INTEGER, + value [1] ANY} + +AsymmetricToken ::= SignedType + +AsymmetricTokenBody ::= + SEQUENCE { + signature-algorithm-identifier AlgorithmIdentifier, + time Nonce, + signed-data [0] TokenData OPTIONAL, + encryption-algorithm-identifier [1] AlgorithmIdentifier OPTIONAL, + encrypted-data [2] Encrypted OPTIONAL} + +SymmetricToken ::= + SEQUENCE { + algorithm AlgorithmIdentifier, + encrypted-data Encrypted} + +SymmetricTokenBody ::= + SEQUENCE { + time Nonce, + data TokenData} + +Nonce ::= + CHOICE { + time Time, + random RandomNumber} + +RandomNumber ::= + BIT STRING + +MessageTokenSignedData ::= + SEQUENCE { + content-confidentiality-algorithm [0] AlgorithmIdentifier OPTIONAL, + content-integrity-check [1] Signature OPTIONAL, + message-sequence-number [4] INTEGER DEFAULT 0} + +MessageTokenEncryptedData ::= + SEQUENCE { + content-confidentiality-key [0] EncryptionKey OPTIONAL, + content-integrity-check [1] Signature OPTIONAL, + content-integrity-key [3] EncryptionKey OPTIONAL, + message-sequence-number [4] INTEGER DEFAULT 0} + +Time ::= UTCTime + +END + diff --git a/Lib/x400/transfer.py b/Lib/x400/transfer.py new file mode 100644 index 0000000..51c905d --- /dev/null +++ b/Lib/x400/transfer.py @@ -0,0 +1,56 @@ +-- transfer.py: + + +-- @(#) $Header: /xtel/pp/pp-beta/Lib/x400/RCS/transfer.py,v 6.0 1991/12/18 20:25:37 jpo Rel $ +-- +-- $Log: transfer.py,v $ +-- Revision 6.0 1991/12/18 20:25:37 jpo +-- Release 6.0 +-- +-- +-- + + +Trans +-- {iso identified-organisation(3) locator(999) modules(0) transfer(8)} +DEFINITIONS IMPLICIT TAGS ::= +BEGIN + +IMPORTS + MessageTransferEnvelope, Content, + ReportTransferEnvelope, ReportTransferContent, + ProbeTransferEnvelope +-- Extras + , + MTABindArgument, MTABindResult, MTABindError +-- End Extras + FROM MTA; + +MtsAPDU ::= + CHOICE { + message [0] MessageAPDU, + report [1] ReportAPDU, + probe [2] ProbeTransferEnvelope} + +MessageAPDU ::= + SEQUENCE { + envelope MessageTransferEnvelope, + content Content} + +ReportAPDU ::= + SEQUENCE { + envelope ReportTransferEnvelope, + content ReportTransferContent} + +ProbeAPDU ::= + ProbeTransferEnvelope + +--- additions for 1988 BIND macro + +Bind1988Argument ::= [16] EXPLICIT MTABindArgument + +Bind1988Result ::= [17] EXPLICIT MTABindResult + +Bind1988Error ::= [18] EXPLICIT MTABindError + +END diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e43f75f --- /dev/null +++ b/Makefile @@ -0,0 +1,76 @@ +# Master makefile for the whole PP +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/RCS/Makefile,v 6.0 1991/12/18 20:02:50 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:02:50 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = Lib Src Chans Format Tools Uip examples +ALLDIRS = $(SUBDIRS) man doc +DIRS = $(PPDIR) \ + $(TXTDIR) $(PRIDIR) $(SPLDIR) $(MANDIR) $(USRBINDIR) \ + $(BINDIR) $(CMDDIR) $(TBLDIR) \ + $(LOGDIR) $(QUEDIR) \ + $(CHANDIR) $(FORMDIR) $(MACDIR) $(TOOLDIR) \ + $(MANDIR) $(MANDIR)/man1 $(MANDIR)/man3 \ + $(MANDIR)/man8 + + +############################################################ +# +# Building Rules +# +############################################################ + +default: + for i in $(SUBDIRS); \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +install clean tidy all lint define depend: + for i in $(ALLDIRS); \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +dirs: + @for i in $(DIRS); \ + do if [ ! -d $$i ]; \ + then set -x; mkdir $$i; \ + $(CHOWN) $(PPUSER) $$i; \ + case "$$i" in $(LOGDIR)) $(CHMOD) a=rwx $@;; esac; \ + fi; \ + done + +# $(DIRS) junk: +# @-base=`expr $@ : '\(.*\)/[^/]*'`; \ +# test -r $$base || echo " ++++ you must create $$base" +# mkdir $@ +# $(CHOWN) $(PPUSER) $@ +# case "$@" in $(LOGDIR)) $(CHMOD) a=rwx $@;; esac + +distribution: README CHANGES clean + cd doc;make clean + +README: man/man8/pp-gen.8 + nroff -man $? > $@ + +CHANGES: pp-changes.ms + nroff -ms $? > $@ + +image: distribution # with CARE + case `pwd` in */pp-beta) exit 1;; esac + rm -f Make.defs* h/config.h + rm -f Lib/version.local Lib/ppversion.c + rm -f CHECK-OUT + rm -rf test_suite + diff --git a/README b/README new file mode 100644 index 0000000..b94efaa --- /dev/null +++ b/README @@ -0,0 +1,330 @@ + + + +PP-GEN(8) MAINTENANCE COMMANDS PP-GEN(8) + + + +NAME + pp-gen - generating the PP message system + + You should read over this entire document first, before typ- + ing any commands. + +READ THIS + This documentation describes how to configure, generate, and + install the PP message system. It is intended only as a + quick guide. The full details are in the PP documentation + set - _P_P _M_a_n_u_a_l$ _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n. This can be + found in the doc/manual/volume1 directory + +SYNOPSIS + make + +DESCRIPTION + This is a description of how one can bring up the PP message + system. It is assumed that you have super-user privileges + in order to (re-)install the software. Super-user + privileges are not required to configure or generate this + software. + + PP is normally installed with most programs and directories + owned by a single user. Conventionally this username is "pp" + and is not a normal user id but this is not required. You + should normally do most of the compilation and configuration + as this user. + + The distribution tape contains the hierarchy for the pp-6.0/ + directory. Bring the sources on-line by changing to a + directory for local sources and running tar as the pp user- + name you have chosen, e.g.: + + % cd /usr/src/local/ + % tar xf _t_a_r_f_i_l_e + % cd pp-6.0/ + +CONFIGURATION + First, go to the config/ directory: + + % cd config + + Select the Makefile and include-file skeletons which most + closely match your system. The current choices are: + + sun Fairly standard sun configuration + vax Fairly standard vax configuration + s5r4 System Five, release 4 + hpux Hewlet Packard + + _m_o_r_e _s_a_m_p_l_e_s _w_e_l_c_o_m_e + + + +Sun Release 4.1 Last change: 25 Nov 1989 1 + + + + + + +PP-GEN(8) MAINTENANCE COMMANDS PP-GEN(8) + + + + The makefile skeleton has the extension .make, and the + include-file skeleton has the extension .h. + + MAKEFILE + Copy the makefile skeleton of your choice to pickle.make, + where "pickle" is the name of your system. Now edit this + file to set the _m_a_k_e variables. There are many of these, + please refer to _T_h_e _P_P _M_a_n_u_a_l: _V_o_l_u_m_e _1 - _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d + _O_p_e_r_a_t_i_o_n. However, some of the more obvious variables are + documented in ./OPTIONS.make. + + Link pickle.make to Make.defs in the base directory. + + % ln pickle.make ../Make.defs + + + INCLUDE-FILE + Copy the include-file skeleton of your choice to pickle.h, + where "pickle" is the name of your system. Now add any + additional definitions you may need. Consult the file + ./OPTIONS.h for a list. + + Now, link pickle.h to ../h/config.h. + + % ln pickle.h ../h/config.h + +GENERATION + It is assumed that you have ISODE 7.0 installed on the + machine in question, including the X.500 libraries -ldsap + -lisode. If you wish to build the grey book channels for + JANET mail, you should first build and install the unix- + niftp package. + + Go to the pp-6.0/ directory and generate the basic system: + + % cd .. + % ./make + + + This will cause a complete generation of the system. If all + goes well, proceed with the installation. If not, complain, + as there "should be no problems" at this step. It may be + worth saving the output of the make stage in a file in case + things do go wrong. + +INSTALLATION + You will need to be the super-user to install the software. + There are two kinds of activities: once-only activities that + you perform the first time the software is installed; and + each-time activities that you perform every time the + software is installed. + + + + +Sun Release 4.1 Last change: 25 Nov 1989 2 + + + + + + +PP-GEN(8) MAINTENANCE COMMANDS PP-GEN(8) + + + + The first once-only activity is to create the necessary + basic directories to install the commands. This is done by + issuing the command as super-user: + + # su + # ./make dirs + + Note that the pp user id needs to have been allocated at + this point. + + The second once-only activity is to make sure that PP will + run when when the machine goes multi-user. On Berkeley UNIX + systems, add something along these lines to the + /etc/rc.local file: + + if [ -f /usr/lib/pp/pp.start ]; then + /usr/lib/pp/pp.start & (echo -n ' pp') > /dev/console + fi + + There are some examples of this start-up script in the con- + fig directory. + + NOTE + If you wish to use smtp then it may be appropriate to start + the smtp server for /_e_t_c/_i_n_e_t_d by adding a suitable line to + /etc/inetd.conf. See Volume 1 for more details, but the + basic format is something like: + + smtp stream tcp nowait pp /usr/lib/pp/cmds/chans/smtpd + smtpd /usr/lib/pp/cmds/chans/smtpsrvr smtp + + + To allow processes to contact the qmgr you must add a line + to your isoentities file, + + pickle "pp qmgr" 1.17.6.2.1 #1001/Internet=pickle+18000 + + You will need to replace "pickle" by your local host, and + you may need to change the isomacro "Internet" to something + else if you have a local ethernet or similar. + + Alternatively you may add a suitable entry to the directory + if this is being used as a nameserver. Some samples are + given below the examples directory. + + Then to install the following each-time activity is: + + % su + Password: + # ./make install + + + + + +Sun Release 4.1 Last change: 25 Nov 1989 3 + + + + + + +PP-GEN(8) MAINTENANCE COMMANDS PP-GEN(8) + + + + If you plan to run the MTAconsole program (and you should!) + you will need to install the application defaults file. This + is in the MTAconsole directory and it should be installed as + MTAconsole in the app-defaults directory in your X hierar- + chy. For instance: + + # cd Src/MTAconsole + # cp MTAconsole.ad /usr/lib/X11/app-defaults/MTAconsole + + The same is true of the user utility xalert. This has a + similar set of application defaults that should be + installed. + + That's about it. This will install everything. To clean-up + the source tree as well, then use: + + % make clean + + at this point. (However, unless you are very tight for space + save this step until you are sure things are working.) + + If this is the first time you have used PP it is worth pick- + ing one of the example configurations in the examples/ + directory. Choose a sample that is close to your require- + ments as a starting point. The available samples are + + LOCALSMTP Very simple local smtp only + JANET A simple JANET configuration + INTERNET A simple Internet site + + Change to one of these directories, and read the README + there. This will tell you to do various things, depending on + what configuration you have chosen. Remember, this is only + an example and will not deal with all your needs. + + After all is set up, and at regular intervals, you should + check all is ok by running _c_k_c_o_n_f_i_g (found in the tools + directory) which will check things are installed correctly. + + Finally, if you are interested in discussing PP with others + running the software, drop a note to the Janet mailbox + "pp-people-request@cs.ucl.ac.uk", and ask to be added to the + "pp-people@cs.ucl.ac.uk" list. + +TAILORING + Tailoring is an essential part of running PP. This is some- + what complex to achieve the correct setup and so is + described in Volume 1 of the PP manual. It is important that + this is followed carefully. + +GENERATING DOCUMENTATION + The directory doc/ contains the documentation set for this + + + +Sun Release 4.1 Last change: 25 Nov 1989 4 + + + + + + +PP-GEN(8) MAINTENANCE COMMANDS PP-GEN(8) + + + + release. Consult the file doc/READ-ME for a description of + each document. The directory doc/ps/ contains PostScript + versions of each document. These can be used to generate + standard documentation on PostScript printers, but users who + want to preview the documentation should generate the .dvi + files from the SLiTeX and LaTeX sources. + + If you received this distribution from the network, then the + directory doc/ps/ does not contain any PostScript files. + There should be a separate compressed _t_a_r file, containing + only PostScript files, available on the machine where you + retrieved this distribution. + +REPORTING PROBLEMS + Comments concerning this release should be directed to the + authors. Consult the preface in the _U_s_e_r'_s _M_a_n_u_a_l for a + current postal address. Alternately, if you have access to + the Janet network, comments may be sent to the mailbox + "pp-support@cs.ucl.ac.uk". Do not send bug reports to the + pp-people discussion group. + +SEE ALSO + ckconfig(8), dbmbuild(8) + _T_h_e _P_P _M_a_n_u_a_l: _V_o_l_u_m_e _1 - _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Sun Release 4.1 Last change: 25 Nov 1989 5 + + + diff --git a/Src/LINEconsole/Makefile b/Src/LINEconsole/Makefile new file mode 100644 index 0000000..435b660 --- /dev/null +++ b/Src/LINEconsole/Makefile @@ -0,0 +1,204 @@ +# Makefile for MTA console - line based +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/Makefile,v 6.0 1991/12/18 20:26:30 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:26:30 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = assoc.c drive.c io.c \ + channels.c mtas.c msgs.c \ + heuristics.c status.c misc.c badness.c +OBJS = assoc.o drive.o io.o \ + channels.o mtas.o msgs.o \ + heuristics.o status.o misc.o badness.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +MAKE = ./make + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xconsole + +############################################################ +# +# Console +# +############################################################ + +console: xconsole + +xconsole: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-dir inst-LINEconsole + +inst-LINEconsole: $(CMDDIR)/LINEconsole +$(CMDDIR)/LINEconsole: xconsole + -$(BACKUP) $@ zxconsole + rm -f $@ + $(INSTALL) xconsole $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "LINEconsole installed normally"; echo "" + +inst-dir: $(CMDDIR) + + +lint: l-console + +l-console: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old $(PROGS) zxconsole + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +assoc.o: assoc.c +assoc.o: console.h +assoc.o: ../../h/head.h +assoc.o: ../../h/util.h +assoc.o: ../../h/config.h +assoc.o: ../../h/ll_log.h +assoc.o: ../../h/retcode.h +assoc.o: ../../h/sys.file.h +assoc.o: ../../h/qmgr.h +assoc.o: ../../h/Qmgr-types.h +assoc.o: ../../h/Qmgr-ops.h +drive.o: drive.c +drive.o: console.h +drive.o: ../../h/head.h +drive.o: ../../h/util.h +drive.o: ../../h/config.h +drive.o: ../../h/ll_log.h +drive.o: ../../h/retcode.h +drive.o: ../../h/sys.file.h +drive.o: ../../h/qmgr.h +drive.o: ../../h/Qmgr-types.h +drive.o: ../../h/Qmgr-ops.h +io.o: io.c +io.o: console.h +io.o: ../../h/head.h +io.o: ../../h/util.h +io.o: ../../h/config.h +io.o: ../../h/ll_log.h +io.o: ../../h/retcode.h +io.o: ../../h/sys.file.h +io.o: ../../h/qmgr.h +io.o: ../../h/Qmgr-types.h +io.o: ../../h/Qmgr-ops.h +channels.o: channels.c +channels.o: console.h +channels.o: ../../h/head.h +channels.o: ../../h/util.h +channels.o: ../../h/config.h +channels.o: ../../h/ll_log.h +channels.o: ../../h/retcode.h +channels.o: ../../h/sys.file.h +channels.o: ../../h/qmgr.h +channels.o: ../../h/Qmgr-types.h +channels.o: ../../h/Qmgr-ops.h +mtas.o: mtas.c +mtas.o: console.h +mtas.o: ../../h/head.h +mtas.o: ../../h/util.h +mtas.o: ../../h/config.h +mtas.o: ../../h/ll_log.h +mtas.o: ../../h/retcode.h +mtas.o: ../../h/sys.file.h +mtas.o: ../../h/qmgr.h +mtas.o: ../../h/Qmgr-types.h +mtas.o: ../../h/Qmgr-ops.h +msgs.o: msgs.c +msgs.o: console.h +msgs.o: ../../h/head.h +msgs.o: ../../h/util.h +msgs.o: ../../h/config.h +msgs.o: ../../h/ll_log.h +msgs.o: ../../h/retcode.h +msgs.o: ../../h/sys.file.h +msgs.o: ../../h/qmgr.h +msgs.o: ../../h/Qmgr-types.h +msgs.o: ../../h/Qmgr-ops.h +heuristics.o: heuristics.c +heuristics.o: console.h +heuristics.o: ../../h/head.h +heuristics.o: ../../h/util.h +heuristics.o: ../../h/config.h +heuristics.o: ../../h/ll_log.h +heuristics.o: ../../h/retcode.h +heuristics.o: ../../h/sys.file.h +heuristics.o: ../../h/qmgr.h +heuristics.o: ../../h/Qmgr-types.h +heuristics.o: ../../h/Qmgr-ops.h +status.o: status.c +status.o: console.h +status.o: ../../h/head.h +status.o: ../../h/util.h +status.o: ../../h/config.h +status.o: ../../h/ll_log.h +status.o: ../../h/retcode.h +status.o: ../../h/sys.file.h +status.o: ../../h/qmgr.h +status.o: ../../h/Qmgr-types.h +status.o: ../../h/Qmgr-ops.h +misc.o: misc.c +misc.o: console.h +misc.o: ../../h/head.h +misc.o: ../../h/util.h +misc.o: ../../h/config.h +misc.o: ../../h/ll_log.h +misc.o: ../../h/retcode.h +misc.o: ../../h/sys.file.h +misc.o: ../../h/qmgr.h +misc.o: ../../h/Qmgr-types.h +misc.o: ../../h/Qmgr-ops.h +badness.o: badness.c +badness.o: console.h +badness.o: ../../h/head.h +badness.o: ../../h/util.h +badness.o: ../../h/config.h +badness.o: ../../h/ll_log.h +badness.o: ../../h/retcode.h +badness.o: ../../h/sys.file.h +badness.o: ../../h/qmgr.h +badness.o: ../../h/Qmgr-types.h +badness.o: ../../h/Qmgr-ops.h +badness.o: tai_defs.inc + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/LINEconsole/assoc.c b/Src/LINEconsole/assoc.c new file mode 100644 index 0000000..404d42e --- /dev/null +++ b/Src/LINEconsole/assoc.c @@ -0,0 +1,634 @@ +/* assoc.c: routines to manage association with qmgr */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/assoc.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/assoc.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: assoc.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +extern char *host, *actual_host, *cmd_argv[]; +extern int assocD, cmd_argc; +extern Command comm; + +int connected = FALSE; +extern int authorised; + + +static IFP stopfnx = NULLIFP; +static jmp_buf toplevel; + +static char *service = "pp qmgr"; +static struct client_dispatch *channelread_op, + *channelcontrol_op, + *mtaread_op, + *mtacontrol_op, + *readchannelmtamessage_op, + *msgcontrol_op, + *quecontrol_op, + *qmgrStatus_op, + *quit_op; +static void acs_advise(), ros_advise(); +void advise(); +int remoteStop(); +PE passwdpeps[1], *passwdpep = passwdpeps; +/* CLIENT OPERATIONS */ +extern int do_channelread(); +extern int do_channelcontrol(); +extern int do_mtaread(); +extern int do_mtacontrol(); +extern int do_readchannelmtamessage(); +extern int do_msgcontrol(); +extern int do_quecontrol(); +int do_quit(); + +/* CLIENT RESULTS */ +extern int channelread_result(); +extern int channelcontrol_result(); +extern int mtaread_result(); +extern int mtacontrol_result(); +extern int readchannelmtamessage_result(); +extern int msgcontrol_result(); +extern int quecontrol_result(); +extern int qmgrStatus_result(); +/* CLIENT ERRORS */ +static int general_error(); + +#define channelread_error general_error +#define channelcontrol_error general_error +#define mtaread_error general_error +#define mtacontrol_error general_error +#define readchannelmtamessage_error general_error +#define msgcontrol_error general_error +#define quecontrol_error general_error +#define qmgrStatus_error general_error + +/* CLIENT STRUCTURE */ + +struct client_dispatch client_dispatches[] = { +{ + "channelread", operation_Qmgr_channelread, +#ifdef PEPSY_VERSION + do_channelread, &_ZUNIV_mod, _ZUTCTimeUNIV, +#else + do_channelread, free_UNIV_UTCTime, +#endif + channelread_result, channelread_error, + "read information on channels" +}, +{ + "channelcontrol", operation_Qmgr_channelcontrol, +#ifdef PEPSY_VERSION + do_channelcontrol, &_ZQmgr_mod, _ZChannelControlQmgr, +#else + do_channelcontrol, free_Qmgr_ChannelControl, +#endif + channelcontrol_result, channelcontrol_error, + "control channel" +}, +{ + "mtaread", operation_Qmgr_mtaread, +#ifdef PEPSY_VERSION + do_mtaread, &_ZQmgr_mod, _ZMtaReadQmgr, +#else + do_mtaread, free_Qmgr_MtaRead, +#endif + mtaread_result, mtaread_error, + "read information on mtas" +}, +{ + "mtacontrol", operation_Qmgr_mtacontrol, +#ifdef PEPSY_VERSION + do_mtacontrol, &_ZQmgr_mod, _ZMtaControlQmgr, +#else + do_mtacontrol, free_Qmgr_MtaControl, +#endif + mtacontrol_result, mtacontrol_error, + "control mta" +}, +{ + "readchannelmtamessage", operation_Qmgr_readChannelMtaMessage, +#ifdef PEPSY_VERSION + do_readchannelmtamessage, &_ZQmgr_mod, _ZMsgReadQmgr, +#else + do_readchannelmtamessage, free_Qmgr_MsgRead, +#endif + readchannelmtamessage_result, readchannelmtamessage_error, + "read a set of messages" +}, +{ + "msgcontrol", operation_Qmgr_msgcontrol, +#ifdef PEPSY_VERSION + do_msgcontrol, &_ZQmgr_mod, _ZMsgControlQmgr, +#else + do_msgcontrol, free_Qmgr_MsgControl, +#endif + msgcontrol_result, msgcontrol_error, + "control msg" +}, +{ + "quecontrol", operation_Qmgr_qmgrControl, +#ifdef PEPSY_VERSION + do_quecontrol, &_ZQmgr_mod, _ZQMGRControlQmgr, +#else + do_quecontrol, free_Qmgr_QMGRControl, +#endif + quecontrol_result, quecontrol_error, + "control qmgr" +}, +{ + "qmgrStatus", operation_Qmgr_qmgrStatus, NULLIFP, +#ifdef PEPSY_VERSION + &_ZQmgr_mod, _ZQmgrStatusQmgr, +#else + free_Qmgr_QmgrStatus, +#endif + qmgrStatus_result, qmgrStatus_error, + "control qmgr" +}, +{ + "quit", 0, do_quit, +#ifdef PEPSY_VERSION + NULL, 0, NULLIFP, NULLIFP, +#else + NULLIFP, NULLIFP, NULLIFP, +#endif + "terminate the association and exit" +}, +{ + NULL +} +}; + +init_assoc() +{ + struct client_dispatch *ix; + + for (ix = client_dispatches; ix->ds_name; ix++){ + if (strcmp(ix -> ds_name, "channelread") == 0) + channelread_op = ix; + else if (strcmp(ix->ds_name, "channelcontrol") == 0) + channelcontrol_op = ix; + else if (strcmp(ix->ds_name, "quit") == 0) + quit_op = ix; + else if (strcmp(ix->ds_name, "mtaread") == 0) + mtaread_op = ix; + else if (strcmp(ix->ds_name, "mtacontrol") == 0) + mtacontrol_op = ix; + else if (strcmp(ix->ds_name, "readchannelmtamessage") == 0) + readchannelmtamessage_op = ix; + else if (strcmp(ix->ds_name, "msgcontrol") == 0) + msgcontrol_op = ix; + else if (strcmp(ix->ds_name, "quecontrol") == 0) + quecontrol_op = ix; + else if (strcmp(ix->ds_name, "qmgrStatus") == 0) + qmgrStatus_op = ix; + } + stopfnx = remoteStop; +} + +ConnectProc () +{ + char *args; + args = strdup(host); + do_connect(&args); + free(args); +} + +do_connect(args) +char **args; +{ + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + AEI aei; + OID ctx, + tmppci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (host) free(host); + host = strdup(*args); + if (actual_host) free(actual_host); + actual_host = strdup(host); + if ((aei = _str2aei (host, service, QMGR_CTX_OID, + 0, dap_user, dap_passwd)) == NULLAEI) { + advise (NULLCP, "%s: unknown entity", + host); + return NOTOK; + } + if ((pa = aei2addr (aei)) == NULLPA) { + advise (NULLCP, "%s", "address translation failed"); + return NOTOK; + } + + if ((ctx = oid_cpy (QMGR_AC)) == NULLOID) { + advise (NULLCP, "%s", "out of memory"); + return NOTOK; + } + + if ((tmppci = oid_cpy (QMGR_PCI)) == NULLOID) { + advise (NULLCP, "%s", "out of memory"); + return NOTOK; + } + pc -> pc_nctx = 1; + pc -> pc_ctx[0].pc_id = 1; + pc -> pc_ctx[0].pc_asn = tmppci; + pc -> pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (PLocalHostName ())) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + + fprintf(stdout, "Please wait while attempt to connect to %s...", host); + fflush(stdout); + + if (AcAssocRequest (ctx, NULLAEI, aei, NULLPA, + pa, pc, NULLOID, 0, ROS_MYREQUIRE, + SERIAL_NONE, 0, sf, passwdpep, *passwdpep ? 1 : 0, + NULLQOS, acc, aci) == NOTOK) { + acs_advise (aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; + } + if (acc -> acc_result != ACS_ACCEPT) { + advise (NULLCP, "Association rejected: [%s]", + AcErrString (acc->acc_result)); + return NOTOK; + } + + assocD = acc->acc_sd; + + set_authmode(acc); + + ACCFREE (acc); + + if (RoSetService (assocD, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + return NOTOK; + } + fprintf(stdout, "connected\n"); + fflush(stdout); + connected = TRUE; + TaiInit(); + return OK; +} + +DisconnectProc() +{ + my_invoke(disconnect, &host); +} + +QuitProc() +{ + if (connected == TRUE) + DisconnectProc(); +} + +static void resetForDisconnect() +{ + connected = FALSE; + clear_msg_level(); + clear_mta_level(); + clear_channel_level(); +} + +extern time_t currentTime; + +static int invoke (ad, ops, ds, args) +int ad; +struct RyOperation ops[]; +register struct client_dispatch *ds; +char **args; +{ + int result; + caddr_t in; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + in = NULL; + time(¤tTime); + + if (ds -> ds_argument && (*ds -> ds_argument) (ad, ds, args, &in) == NOTOK) + return 0; + + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + return (*stopfnx) (ad, (struct AcSAPfinish *) 0); + break; + case DONE: + (void) AcUAbortRequest (ad, NULLPEP, 0, &acis); + (void) RyLose (ad, roi); + return NOTOK; + } + + if (connected != TRUE) + return NOTOK; + + switch (result = RyStub (ad, ops, ds -> ds_operation, RyGenID (ad), + NULLIP, in, ds -> ds_result, + ds -> ds_error, ROS_SYNC, roi)) { + case NOTOK: /* failure */ + if (ROS_FATAL(rop->rop_reason)) { + ros_advise (rop, "STUB"); + fprintf(stderr, + "Disconnected from '%s'\n", host); + comm = Disconnect; + resetForDisconnect(); + } + break; + + case OK: /* got a result/error response */ + break; + + case DONE: /* got RO-END? */ + advise (NULLCP, "%s", "got RO-END.INDICATION"); + connected = FALSE; + /* NOTREACHED */ + + default: + advise (NULLCP, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + } + +#ifdef PEPSY_VERSION + if (ds -> ds_fr_mod && in) + fre_obj (in, ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod); +#else + if (ds -> ds_free && in) + (*ds -> ds_free)(in); +#endif + return OK; +} + +Operations currentop; + +my_invoke(op, args) +Operations op; +char **args; +{ + caddr_t in; + currentop = op; + switch (op) { + case chanread: + invoke(assocD, table_Qmgr_Operations, + channelread_op,(char **) NULL); + break; + case chanstop: + case chanstart: + case chanclear: + case chancacheadd: + invoke(assocD, table_Qmgr_Operations, + channelcontrol_op, args); + break; + case mtaread: + invoke(assocD, table_Qmgr_Operations, + mtaread_op, args); + break; + case mtastop: + case mtastart: + case mtaclear: + case mtacacheadd: + invoke(assocD, table_Qmgr_Operations, + mtacontrol_op, args); + break; + case readchannelmtamessage: + invoke(assocD, table_Qmgr_Operations, + readchannelmtamessage_op, args); + break; + case msgstop: + case msgstart: + case msgclear: + case msgcacheadd: + invoke(assocD, table_Qmgr_Operations, + msgcontrol_op, args); + break; + case quit: + invoke(assocD, table_Qmgr_Operations, + quit_op, (char **) NULL); + break; + case connect: + return do_connect(args); + case disconnect: + if (connected == TRUE) + do_quit(assocD, quit_op, args, &in); + break; + case quecontrol: + invoke(assocD, table_Qmgr_Operations, + quecontrol_op, args); + break; + case qmgrStatus: + invoke(assocD, table_Qmgr_Operations, + qmgrStatus_op, args); + return 0; + default: + break; + } + return 0; +} + +/* ARGSUSED */ +int do_quit (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args, + **arg; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (ad >= 0) { +#ifdef CONNECTING_1 + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) +#else + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, acr, aci) == NOTOK) +#endif + acs_advise (aca, "A-RELEASE.REQUEST"); + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (ad, NULLPEP, 0, aci); + advise (NULLCP, "Release rejected by peer: %d", acr -> acr_reason); + } + ad = -1; + } + + resetForDisconnect(); +} + +/* */ +/* error routine */ + +/* ARGSUSED */ +static general_error (ad, id, err, parameter, roi) +int ad, + id, + err; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + + if (err == RY_REJECT) { + advise (NULLCP, "%s", RoErrString ((int) parameter)); + return OK; + } + + if ((rye = finderrbyerr (table_Qmgr_Errors, err)) != + (struct RyError *) NULL) + advise (NULLCP, "Error: %s", rye -> rye_name); + else + advise (NULLCP, "Error: %d", err); + + return OK; +} + +/* */ +/* advising routines */ + +static void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", + AcErrString (aca -> aca_reason)); + + advise (NULLCP, "%s: %s (source %d)", event, buffer, + aca -> aca_source); +} + + +static void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", + RoErrString (rop -> rop_reason)); + + advise (NULLCP, "%s: %s", event, buffer); +} + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + char buffer[BUFSIZ]; + + va_start (ap); + asprintf (buffer, ap); + fprintf(stdout, "%s\n",buffer); + va_end (ap); +} +#else +/* VARARGS2 */ + +void advise(what, fmt) +char *what, + *fmt; +{ + advise(what,fmt); +} +#endif + +/* */ + +/* ARGSUSED */ +int remoteStop(fd, dummy) +int fd; +struct AcSAPfinish *dummy; +{ + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + + connected = FALSE; + + /* isode release */ + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + + comm = Disconnect; + return NOTOK; +} + +struct type_Qmgr_BindArgument *ba; + +fillin_passwdpep(user, passwd, auth) +char *user, + *passwd; +int auth; +{ + + if (*passwdpep != NULL) { + pe_free(*passwdpep); + free_Qmgr_BindArgument(ba); + *passwdpep = NULL; + } + + ba = (struct type_Qmgr_BindArgument *) smalloc (sizeof *ba); + + if (auth != TRUE) { + /* no authentication */ + ba -> offset = type_Qmgr_BindArgument_noAuthentication; + } else { + ba -> offset = type_Qmgr_BindArgument_weakAuthentication; + ba -> un.weakAuthentication = + (struct type_Qmgr_WeakAuthentication *) + smalloc(sizeof(struct type_Qmgr_WeakAuthentication)); + ba -> un.weakAuthentication->username = str2qb(user, strlen(user), 1); + if (passwd != NULLCP && *passwd != '\0') + ba -> un.weakAuthentication->passwd = str2qb(passwd, strlen(passwd), 1); + else + ba -> un.weakAuthentication->passwd = NULL; + } + + if (encode_Qmgr_BindArgument(passwdpep, 1, NULLCP, 0, ba) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("failed to encode BindArgument [%s]", PY_pepy)); + *passwdpep = NULLPE; + free_Qmgr_BindArgument(ba); + exit(1); + } + (*passwdpep)->pe_context = 3; +} diff --git a/Src/LINEconsole/badness.c b/Src/LINEconsole/badness.c new file mode 100644 index 0000000..8db04bf --- /dev/null +++ b/Src/LINEconsole/badness.c @@ -0,0 +1,738 @@ +/* badness.c: routines calculating and using "badness" */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: badness.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +#define DEFAULT_TOTAL_NUMBER 10000.0 +#define DEFAULT_TOTAL_VOLUME 1000000.0 +static struct tailor *tailors = NULL; +extern double atof(); +extern char tailorfile[]; +extern int max_vert_lines; +extern time_t currentTime; +double ub_total_number = DEFAULT_TOTAL_NUMBER, + ub_total_volume = DEFAULT_TOTAL_VOLUME; + +/* */ + +static double parse_ub(ub) +char *ub; +{ + double pre; + char c; + + switch (sscanf(ub, "%lf%c", &pre, &c)) { + case 1: + return pre; + case 2: + switch (c) { + case 'h': + pre *= 60.0; + break; + case 'd': + pre *= 24.0 * 60.0; + break; + case 'k': + pre *= 1000.0; + break; + case 'M': + pre *= 1000000.0; + break; + default: + break; + } + break; + default: + return 0.0; + } + return pre; +} + +static void add_total_ubs(entry) +char *entry; +{ + char *ix, *str, *margv[20]; + int i, margc; + char *buf = strdup(entry); + + if ((ix = index(buf, ':')) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect console tailor file entry '%s'",buf)); + free(buf); + return; + } + ix++; + (void) compress(ix, ix); + margc = sstr2arg(ix, 20, margv, ","); + i = 0; + while (i < margc) { + if ((ix = index(margv[i], '<')) != NULL) { + *ix = '\0'; + str = margv[i]; + ix++; + while(*ix != '\0' && isspace(*ix)) ix++; + while(*str != '\0' && isspace(*str)) str++; + if (*ix == '\0' || *str == '\0') + return; + if (strncmp(str, "num", 3) == 0) + ub_total_number = parse_ub(ix); + else if (strncmp(str, "vol", 3) == 0) + ub_total_volume = parse_ub(ix); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown console tailor variable '%s'", + str)); + } + i++; + } + free(buf); +} + +static struct tailor *tailor_new(entry) +char *entry; +{ + struct tailor *ret; + char *ix, *str, *margv[20]; + int i, margc; + char *buf = strdup(entry); + ret = (struct tailor *) calloc(1, sizeof(*ret)); + + if ((ix = index(buf, ':')) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect console tailor file entry '%s'",buf)); + free((char *) ret); + free(buf); + return NULL; + } + *ix = '\0'; + ret->key = strdup(buf); + ix++; + (void) compress(ix, ix); + margc = sstr2arg(ix, 20, margv, ","); + + i = 0; + while (i < margc) { + if ((ix = index(margv[i], '<')) != NULL) { + *ix = '\0'; + str = margv[i]; + ix++; + while (*ix != '\0' && isspace(*ix)) ix++; + while (*str != '\0' && isspace(*str)) str++; + if (*ix == '\0' || *str == '\0') + return NULL; + + if (strncmp(str, "num", 3) == 0) + ret->ub_number = parse_ub(ix); + else if (strncmp(str, "vol", 3) == 0) + ret->ub_volume = parse_ub(ix); + else if (strncmp(str, "age", 3) == 0) + ret->ub_age = parse_ub(ix); + else if (strncmp(str, "las", 3) == 0) + ret->ub_last = parse_ub(ix); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown console tailor variable '%s'", + str)); + } + i++; + } + free(buf); + return ret; +} + +static void tailor_add(plist, new) +struct tailor **plist, *new; +{ + new->next = *plist; + *plist = new; +} + +void tailor_free(list) +struct tailor *list; +{ + if (list->key) free(list->key); + if (list->next) tailor_free(list->next); + free((char *) list); +} + +/* */ + +struct tailor *find_tailor(name, list) +char *name; +struct tailor *list; +{ + while (list != NULL + && strcmp(list->key, name) != 0) + list = list->next; + return list; +} + +/* */ +#include "tai_defs.inc" +extern char *myname; + +static void tailor_add_one_default(plist, type, hardwired) +struct tailor **plist; +char *type, + *hardwired; +{ + if (find_tailor(type, *plist) == NULL) + tailor_add(plist,tailor_new(hardwired)); +} + +static void tailor_add_defaults(plist) +struct tailor **plist; +{ + /* mts defaults */ + tailor_add_one_default(plist, "mtsin-chan", default_mtsin_chan); + tailor_add_one_default(plist, "mtsout-chan", default_mtsout_chan); + tailor_add_one_default(plist, "mtsboth-chan", default_mtsboth_chan); + tailor_add_one_default(plist, "mtsin-mta", default_mtsin_mta); + tailor_add_one_default(plist, "mtsout-mta", default_mtsout_mta); + tailor_add_one_default(plist, "mtsboth-mta", default_mtsboth_mta); + tailor_add_one_default(plist, "mtsin-msg", default_mtsin_msg); + tailor_add_one_default(plist, "mtsout-msg", default_mtsout_msg); + tailor_add_one_default(plist, "mtsboth-msg", default_mtsboth_msg); + + /* mta defaults */ + tailor_add_one_default(plist, "mtain-chan", default_mtain_chan); + tailor_add_one_default(plist, "mtaout-chan", default_mtaout_chan); + tailor_add_one_default(plist, "mtaboth-chan", default_mtaboth_chan); + tailor_add_one_default(plist, "mtain-mta", default_mtain_mta); + tailor_add_one_default(plist, "mtaout-mta", default_mtaout_mta); + tailor_add_one_default(plist, "mtaboth-mta", default_mtaboth_mta); + tailor_add_one_default(plist, "mtain-msg", default_mtain_msg); + tailor_add_one_default(plist, "mtaout-msg", default_mtaout_msg); + tailor_add_one_default(plist, "mtaboth-msg", default_mtaboth_msg); + + /* internal defaults */ + tailor_add_one_default(plist, "internal-chan", default_internal_chan); + tailor_add_one_default(plist, "internal-mta", default_internal_mta); + tailor_add_one_default(plist, "internal-msg", default_internal_msg); + + /* passive defaults */ + tailor_add_one_default(plist, "passive-chan", default_passive_chan); + tailor_add_one_default(plist, "passive-mta", default_passive_mta); + tailor_add_one_default(plist, "passive-msg", default_passive_msg); +} + + +/* */ + +TaiInit() +{ + FILE *fp = NULL; + char buf[BUFSIZ]; + + if (tailors) { + tailor_free(tailors); + tailors = NULL; + } + /* read in console tailor file */ + if (tailorfile[0] != '\0') { + if ((fp = fopen(tailorfile, "r")) == NULL + && tailorfile[0] != '/') { + char *home; + /* try relative to home directory */ + if ((home = getenv("HOME")) != NULLCP) { + (void) sprintf(buf, "%s/%s", + home, tailorfile); + fp = fopen(buf, "r"); + } + } + + if (fp != NULL) { + while (fgets(buf, BUFSIZ, fp) != NULLCP) { + (void) compress(buf, buf); + if (buf[0] == '\n' || buf[0] == '\0' + || buf[0] == '#') + continue; + if (strncmp(buf,"totals", strlen("totals")) == 0) + add_total_ubs(buf); + else + tailor_add(&tailors, tailor_new(buf)); + } + fclose(fp); + } + } + tailor_add_defaults(&tailors); +} + +/* */ + +add_tailor_to_chan(chan) +struct chan_struct *chan; +{ + char buf[BUFSIZ]; + + sprintf(buf, "%s-chan", chan->channelname); + + if ((chan->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-chan", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + chan->tai = find_tailor(buf, tailors); + } +} + +add_tailor_to_mta(chan, mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + char buf[BUFSIZ]; + + sprintf(buf, "%s-mta", chan->channelname); + + if ((mta->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-mta", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + mta->tai = find_tailor(buf, tailors); + } +} + +add_tailor_to_msg(chan, msg) +struct chan_struct *chan; +struct msg_struct *msg; +{ + char buf[BUFSIZ]; + + if (chan == NULL) + return; + + sprintf(buf, "%s-msg", chan->channelname); + + if ((msg->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-msg", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + msg->tai = find_tailor(buf, tailors); + } +} + +/* */ + +int volBadness(vol) +int vol; +{ + int retval = 0; + if (ub_total_volume != 0.0) + retval = (int) (vol*100/ub_total_volume); + if (vol != 0 && retval == 0) + retval = 1; + return retval; +} + +int numBadness(num) +int num; +{ + int retval = 0; + if (ub_total_number != 0.0) + retval = (int) (num*100/ub_total_number); + if (num != 0 && retval == 0) + return 1; + return retval; +} + +int chanBadness(chan) +struct chan_struct *chan; +{ + double average_db = 0.0, + age, + last; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = chan->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for channel '%s'", chan->channelname)); + return 0; + } + + if (chan->inbound <= 0 + && chan->numberMessages == 0 + && chan->numberReports == 0) + return 0; + + if (tai->ub_number != 0.0) { + if ((chan->numberMessages + chan->numberReports) >= tai->ub_number) + return max_bad_channel; + average_db += ((chan->numberMessages+chan->numberReports) * 100)/ tai->ub_number; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (chan->volumeMessages >= tai->ub_volume) + return max_bad_channel; + average_db += (chan->volumeMessages * 100)/tai->ub_volume; + noFactors++; + } + + if (tai->ub_age != 0.0) { + if (chan->oldestMessage != 0 && + (chan->numberMessages != 0 || chan->numberReports != 0)) + age = (currentTime-chan->oldestMessage) / 60.0; + else + age = 0.0; + if (age >= tai->ub_age) + return max_bad_channel; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_last != 0.0) { + if (chan->status->lastSuccess != 0) + last = (currentTime - chan->status->lastSuccess)/60.0; + else + last = 0.0; + if (last >= tai->ub_last) + return max_bad_channel; + if (last >= tai->ub_last/2) { + average_db += (last * 100)/tai->ub_last; + noFactors++; + } + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_channel / (noFactors * 100)); + + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ + +int mtaBadness(mta) +struct mta_struct *mta; +{ + double average_db = 0.0, + age, + last; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = mta->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for mta '%s'", mta->mta)); + return 0; + } + + if (mta->numberMessages == 0 && mta->numberReports == 0) + return 0; + + if (tai->ub_number != 0.0) { + if (mta->numberMessages+mta->numberReports >= tai->ub_number) + return max_bad_mta; + average_db += ((mta->numberMessages+mta->numberReports) * 100)/ tai->ub_number; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (mta->volumeMessages >= tai->ub_volume) + return max_bad_mta; + average_db += (mta->volumeMessages * 100)/tai->ub_volume; + noFactors++; + } + + if (tai->ub_age != 0.0) { + if (mta->oldestMessage != 0 + && (mta->numberMessages != 0 || mta->numberReports != 0)) + age = (currentTime-mta->oldestMessage) / 60.0; + else + age = 0; + if (age >= tai->ub_age) + return max_bad_mta; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_last != 0.0) { + if (mta->status->lastSuccess != 0) + last = (currentTime - mta->status->lastSuccess)/60.0; + else + last = 0; + if (last >= tai->ub_last) + return max_bad_mta; + if (last >= tai->ub_last/2) { + average_db += (last * 100)/tai->ub_last; + noFactors++; + } + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_mta / (noFactors * 100)); + + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ + +int msgBadness(msg) +struct msg_struct *msg; +{ + double average_db = 0.0, + age; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = msg->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for msg '%s'", msg->msginfo->queueid)); + return 0; + } + + if (msg->msginfo->expiryTime != 0 + && (currentTime - msg->msginfo->expiryTime) >= 0) + /* expired so max_bad_msg ?? */ + return max_bad_msg; + + if (tai->ub_age != 0.0) { + age = (currentTime-msg->msginfo->age) / 60.0; + if (age >= tai->ub_age) + return max_bad_msg; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (msg->msginfo->size > tai->ub_volume) + return max_bad_msg; + average_db += (msg->msginfo->size * 100) / tai->ub_volume; + noFactors++; + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_msg / (noFactors * 100)); + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ + +/* ordering routines */ + +static int channel_compare(one, two) +struct chan_struct **one, + **two; +/* return -1 if one worse state then two */ +{ + int onebad, + twobad; + onebad = chanBadness((*one)); + twobad = chanBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_channels(list, num) +struct chan_struct **list; +int num; +/* order display_list */ +{ + qsort((char *) &(list[0]),num, + sizeof(list[0]),(IFP)channel_compare); +} + + +static int mta_compare (one, two) +struct mta_struct **one, + **two; +/* returns -1 if ione in worse state than two */ +{ + int onebad, + twobad; + onebad = mtaBadness((*one)); + twobad = mtaBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_mtas(plist,num) +struct mta_struct ***plist; +int num; +{ + struct mta_struct **temp = *plist; + qsort((char *)&(temp[0]),num,sizeof(temp[0]),(IFP)mta_compare); +} + +extern int number_msgs; +extern struct msg_struct **global_msg_list; + +static int msg_compare (one, two) +struct msg_struct **one, + **two; +/* returns -1 if ione in worse state than two */ +{ + int onebad, + twobad; + onebad = msgBadness((*one)); + twobad = msgBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_msgs() +{ + qsort((char *) &(global_msg_list[0]),number_msgs, + sizeof(global_msg_list[0]),(IFP)msg_compare); +} + diff --git a/Src/LINEconsole/channels.c b/Src/LINEconsole/channels.c new file mode 100644 index 0000000..09291c2 --- /dev/null +++ b/Src/LINEconsole/channels.c @@ -0,0 +1,965 @@ +/* channels.c: channel routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/channels.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/channels.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: channels.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +struct chan_struct **globallist = NULL, **chan_matches = NULL, + *currentchan = NULL; +int num_channels = 0, chan_num_matches = 0; +char *chan_match = NULL; + +struct chan_struct *find_channel(); + +extern char *time_t2RFC(), *vol2str(), *cmd_argv[], + *time_t2str(), *mystrtotime(), *lowerfy(); +extern int cmd_argc; +extern Level lev; +extern time_t boottime; +static void create_channel_list(), update_channel_list(); +static struct chan_struct *create_channel(); +static void display_channel_list(); +static void free_channel_list(); + +extern int total_number_reports, total_number_messages, total_volume, compat; +extern int connected; +extern struct procStatus *create_status(); +extern int info_shown; + +int channel_all = FALSE; + +#define CHAN_READ_INTERVAL 60 + +/* ARGSUSED */ +int do_channelread (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_UNIV_UTCTime **arg; +{ + char *str; + UTC utc; + + utc = (UTC) malloc (sizeof(struct UTCtime)); + utc->ut_flags = UT_SEC; + + utc->ut_sec = CHAN_READ_INTERVAL; + + str = utct2str(utc); + *arg = str2qb (str, strlen(str), 1); + return OK; +} + +/* ARGSUSED */ +int channelread_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_ChannelReadResult *result; +struct RoSAPindication *roi; +{ + if (compat) { + total_number_reports = 0; + total_number_messages = 0; + total_volume = 0; + } + if (globallist) + update_channel_list(result->channels); + else + create_channel_list(result->channels); + order_channels(globallist, num_channels); + return OK; +} + +channel_list() +{ + if (connected == TRUE) { + if (cmd_argc > 1 && lexequ(cmd_argv[1], "all") == 0) + channel_all = TRUE; + else + channel_all = FALSE; + my_invoke(chanread, (char **) NULL); + if (globallist) + display_channel_list(globallist, num_channels); + } + +} + +channel_do_refresh () +{ + if (connected == TRUE) { + my_invoke(chanread, (char **) NULL); + if (lev == channel) { + if (chan_num_matches > 0 && info_shown == TRUE) + channel_info_regex(); + else + display_channel_list(globallist, num_channels); + } + } +} + +/* */ + +extern FILE *out; + +static void display_channel_info(chan) +struct chan_struct *chan; +{ + char *str, + *info_str; + int info_strlen = BUFSIZ; + info_str = calloc(1, (unsigned) info_strlen); + + sprintf(info_str, ssformat, tab, + chan->channelname, + chan->channeldescrip); + if (chan->status->cachedUntil != 0) { + str = time_t2RFC(chan->status->cachedUntil); + sprintf(info_str, plus_ssformat, info_str, tab, + "delayed until", + str); + free(str); + } + if (chan->oldestMessage != 0 && + (chan->numberMessages != 0 || chan->numberReports != 0)) { + str = time_t2str(time((time_t *)0) - chan->oldestMessage); + sprintf(info_str, plus_ssformat, info_str, tab, + "oldest message", + str); + free(str); + } + if (chan->numberMessages != 0) + sprintf(info_str, plus_sdformat, info_str, tab, + "number of messages", + chan->numberMessages); + if (chan->numberReports != 0) + sprintf(info_str, plus_sdformat, info_str, tab, + "number of DRs", + chan->numberReports); + + if (chan->volumeMessages != 0) { + str = vol2str(chan->volumeMessages); + sprintf(info_str, plus_ssformat, info_str, tab, + "volume of messages", + str); + free(str); + } + if (chan->numberActiveProcesses != 0) + sprintf(info_str, plus_sdformat, info_str, tab, + "number of active processes", + chan->numberActiveProcesses); + sprintf(info_str, plus_ssformat, info_str, tab, + "status", + (chan->status->enabled == TRUE) ? "enabled" : "disabled"); + if (chan->status->lastAttempt != 0) { + str = time_t2RFC(chan->status->lastAttempt); + sprintf(info_str, plus_ssformat, info_str, tab, + "last attempt", + str); + free(str); + } + if (chan->status->lastSuccess != 0) { + str = time_t2RFC(chan->status->lastSuccess); + sprintf(info_str, plus_ssformat, info_str, tab, + "last success", + str); + free(str); + } + + switch (chan->priority) { + case int_Qmgr_Priority_low: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "low"); + break; + case int_Qmgr_Priority_normal: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "normal"); + break; + case int_Qmgr_Priority_high: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "high"); + break; + default: + break; + } + if (chan->maxprocs == 0) + sprintf(info_str, plus_ssformat, info_str, tab, + "maximum processes", + "unlimited"); + else + sprintf(info_str, plus_sdformat, info_str, tab, + "maximum processes", + chan->maxprocs); + + fprintf(out, "%s\n", info_str); + free(info_str); +} + +static void display_channel(chan) +struct chan_struct *chan; +{ + /* one line per channel */ + char str[BUFSIZ]; + + sprintf(str,"%s",chan->channelname); + if (chan -> numberActiveProcesses >= 1) + sprintf(str, "%s (ACTIVE %d process%s)", + str, chan->numberActiveProcesses, + (chan->numberActiveProcesses > 1) ? "s" : ""); + sprintf(str,"%s: %d", + str,chan->numberMessages); + if (chan->numberReports != 0) + sprintf(str,"%s + %d", str, chan->numberReports); + if (chan->given_num_mtas != 0) + sprintf(str,"%s/%d",str, chan->given_num_mtas); + if (chan->status->enabled != TRUE) + sprintf(str, "%s (DISABLED)", str); + + fprintf(out, "%s\n", str); +} + +channel_info() +{ + if (chan_num_matches > 0) { + openpager(); + display_channel_info(chan_matches[0]); + closepager(); + } +} + +channel_info_regex() +{ + int i; + if (chan_num_matches > 0) { + openpager(); + if (chan_num_matches > 1) + fprintf(out, "%s: %d matches\n\n", + chan_match, chan_num_matches); + for (i = 0; i < chan_num_matches; i++) { + display_channel_info(chan_matches[i]); + fprintf(out, "\n"); + } + closepager(); + } +} + +static void display_channel_list(list, num) +struct chan_struct **list; +int num; +{ + int i; + int badnessPast = FALSE; + + openpager(); + + for (i = 0; i < num; i++) { + if (badnessPast == FALSE + && chanBadness(list[i]) == 0) { + if (channel_all == FALSE) + i = num; + else if (badnessPast == FALSE) { + fprintf(out, "==================================== Channels below have zero badness\n"); + badnessPast = TRUE; + display_channel(list[i]); + } + } else + display_channel(list[i]); + } + closepager(); +} + +/* */ + +static void create_channel_list(list) +struct type_Qmgr_PrioritisedChannelList *list; +/* calloc and fillin in globallist */ +{ + struct type_Qmgr_PrioritisedChannelList *ix = list; + int i, + num = 0; + + while (ix != NULL) { + num++; + + ix = ix->next; + } + + num_channels = num; + globallist = (struct chan_struct **) calloc((unsigned) num, + sizeof(struct chan_struct *)); + chan_matches = (struct chan_struct **) calloc((unsigned) num, + sizeof(struct chan_struct *)); + ix = list; + i = 0; + while ((ix != NULL) + && (i < num)) { + globallist[i] = create_channel(ix); + i++; + ix = ix->next; + } + +} + +static void update_channel(old, new) +struct chan_struct *old; +struct type_Qmgr_PrioritisedChannelList *new; +{ + struct type_Qmgr_ChannelInfo *info; + + info = new->PrioritisedChannel->channel; + /* name and description don't change */ + old->oldestMessage = convert_time(info->oldestMessage); + old->numberMessages = info->numberMessages; + old->numberReports = info->numberReports; + old->volumeMessages = info->volumeMessages; + old->given_num_mtas = info->numberMtas; + if (compat) { + total_volume += old->volumeMessages; + total_number_reports += old->numberReports; + total_number_messages += old->numberMessages; + } + old->numberActiveProcesses = info->numberActiveProcesses; + update_status(old->status,info->status); + old->priority = new->PrioritisedChannel->priority->parm; + old->maxprocs = info->maxprocs; +} + +static void update_channel_list(new) +struct type_Qmgr_PrioritisedChannelList *new; +{ + struct type_Qmgr_PrioritisedChannelList *ix = new; + char *name = NULL; + struct chan_struct *chan; + + while (ix != NULL) { + if (name != NULL) free(name); + name = qb2str(ix->PrioritisedChannel->channel->channel); + + chan = find_channel(name); + if (chan == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: can not find channel %s",name)); + abort(); + } + update_channel(chan,ix); + ix = ix->next; + } +} + +static struct chan_struct *create_channel(chan) +struct type_Qmgr_PrioritisedChannelList *chan; +{ + struct chan_struct *temp; + struct type_Qmgr_ChannelInfo *info; + + temp = (struct chan_struct *) calloc(1, sizeof(*temp)); + info = chan->PrioritisedChannel->channel; + + temp->channelname = qb2str(info->channel); + temp->channeldescrip = qb2str(info->channelDescription); + + temp->oldestMessage = convert_time(info->oldestMessage); + temp->numberMessages = info->numberMessages; + temp->numberReports = info->numberReports; + temp->volumeMessages = info->volumeMessages; + temp->given_num_mtas = info->numberMtas; + if (compat) { + total_volume += temp->volumeMessages; + total_number_reports += temp->numberReports; + total_number_messages += temp->numberMessages; + } + temp->numberActiveProcesses = info->numberActiveProcesses; + temp->status = create_status(info->status); + if (temp->status->lastSuccess == 0) + temp->status->lastSuccess = boottime; + temp->priority = chan->PrioritisedChannel->priority->parm; + temp->inbound = bit_test(info->direction, bit_Qmgr_direction_inbound); + temp->outbound = bit_test(info->direction, bit_Qmgr_direction_outbound); + temp->chantype = info->chantype; + temp->maxprocs = info->maxprocs; + add_tailor_to_chan(temp); + return temp; +} + +clear_channel_level() +{ + if (globallist) + free_channel_list(globallist, num_channels); + globallist = NULL; + if (chan_matches) free(chan_matches); + chan_matches = NULL; + num_channels = 0; +} + +static void free_channel_list(list, num) +struct chan_struct **list; +int num; +{ + int i =0; + if (list == NULL) + return; + while (i < num) { + free(list[i]->channelname); + free(list[i]->channeldescrip); + free ((char *)list[i]->status); + i++; + } + free((char *) list); +} + +/* */ +struct chan_struct *find_channel(name) +char *name; +{ + int i = 0; + while ((i < num_channels) && + (lexequ(globallist[i]->channelname, name) != 0)) + i++; + + if (i >= num_channels) + return NULL; + else + return globallist[i]; +} + +extern char *re_comp(); +extern int re_exec(); + +int find_channel_regex(name) +char *name; +{ + int i = 0; + char *diag; + + if ((diag = re_comp(name)) != 0) { + fprintf(stderr, + "re_comp error for '%s' [%s]\n", name, diag); + return 0; + } + + for (i = 0, chan_num_matches = 0; i < num_channels; i++) + if (re_exec(lowerfy(globallist[i]->channelname)) == 1) + chan_matches[chan_num_matches++] = globallist[i]; + + return chan_num_matches; +} + + +channel_set_current_regex() +{ + int cont = TRUE, doquit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (chan_match == NULLCP) ? "" : chan_match); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + } + (void) compress(buf, buf); + + if (emptyStr(buf) && (chan_match == NULLCP)) + fprintf(stdout, "no match set\n"); + else { + if (!emptyStr(buf)) { + if (lexequ(buf, "q") != 0) { + if (chan_match) free(chan_match); + chan_match = strdup(buf); + } else + doquit = TRUE; + } + cont = FALSE; + } + } + if (doquit == TRUE) + return NOTOK; + if (find_channel_regex(chan_match) == 0) { + fprintf(stdout, "unable to find match for '%s'\n", + chan_match); + return NOTOK; + } + return OK; +} + +channel_set_current() +{ + int cont = TRUE, i, doquit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (chan_match == NULLCP) ? "" : chan_match); + fflush(stdout); + + + if (gets(buf) == NULL) + exit (OK); + } + compress(buf, buf); + if (emptyStr(buf) && (chan_match == NULLCP)) + fprintf(stdout, "no match set\n"); + else if (!emptyStr(buf) && lexequ(buf, "q") == 0) { + doquit = TRUE; + cont = FALSE; + } else { + char *expr = (emptyStr(buf)) ? chan_match : buf; + int num = find_channel_regex(expr); + switch (num) { + case 0: + fprintf(stdout, "unable to find match for '%s'\n", expr); + break; + case 1: + cont = FALSE; + if (expr != chan_match) { + if (chan_match) free(chan_match); + chan_match = strdup(expr); + } + currentchan = chan_matches[0]; + break; + default: + fprintf(stdout, "'%s' matches %d possible channels (", + expr, num); + for (i = 0; i < num; i++) + fprintf(stdout, "%s%s", + chan_matches[i]->channelname, + (i == num - 1) ? "" : ","); + fprintf(stdout, ")\n\tneed unique channel\n"); + break; + } + } + } + if (doquit == TRUE) + return NOTOK; + return OK; +} + +int is_loc_chan(chan) +struct chan_struct *chan; +{ + if (chan->chantype == int_Qmgr_chantype_mts + && chan->outbound > 0) + return TRUE; + else + return FALSE; +} + +/* */ + +channel_next() +{ + if (globallist) { + int i = 0; + if (chan_num_matches > 0) { + while ((i < num_channels) && + chan_matches[0] != globallist[i]) + i++; + if (i >= num_channels - 1) + i = 0; + else + i++; + } + if (chan_match) free(chan_match); + chan_match = strdup(globallist[i]->channelname); + find_channel_regex(chan_match); + } +} + +channel_previous() +{ + if (globallist) { + int i = num_channels -1; + if (chan_num_matches > 0) { + while ((i >= 0) && + chan_matches[0] != globallist[i]) + i--; + if (i <= 0) + i = num_channels - 1; + else + i--; + } + if (chan_match) free(chan_match); + chan_match = strdup(globallist[i]->channelname); + find_channel_regex(chan_match); + } +} + +/* */ + +channel_control(op, chan, mytime) +Operations op; +char *chan, *mytime; +{ + char *args[3]; + args[0] = chan; + args[1] = (char *) op; + args[2] = mytime; + my_invoke(op, args); +} + +channel_enable_regex() +{ + int cont, i = 0; + char buf[BUFSIZ]; + + if (chan_num_matches > 0) { + + if (chan_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + chan_match, chan_num_matches); + + for (i = 0; i < chan_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (chan_num_matches == 1) { + fprintf(stdout, "enabling '%s'.\n", + chan_matches[i]->channelname); + buf[0] = 'y'; + } else { + fprintf(stdout, "enable '%s' (y/n/q) ?", + chan_matches[i]->channelname); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch (buf[0]) { + case 'y': + case 'Y': + channel_control(chanstart, + chan_matches[i]->channelname, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = chan_num_matches; + default: + break; + } + } + } + + } +} + +channel_disable_regex() +{ + int cont, i; + char buf[BUFSIZ]; + + if (chan_num_matches > 0) { + + if (chan_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + chan_match, chan_num_matches); + + for (i = 0; i < chan_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (chan_num_matches == 1) { + fprintf(stdout, "disabling '%s'.\n", + chan_matches[i]->channelname); + buf[0] = 'y'; + } else { + fprintf(stdout, "disable '%s' (y/n/q) ?", + chan_matches[i]->channelname); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch (buf[0]) { + case 'y': + case 'Y': + channel_control(chanstop, + chan_matches[i]->channelname, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = chan_num_matches; + default: + break; + } + } + } + + } +} + +channel_clear_regex() +{ + int cont, i; + char buf[BUFSIZ]; + + if (chan_num_matches > 0) { + + if (chan_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + chan_match, chan_num_matches); + + for (i = 0; i < chan_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (chan_num_matches == 1) { + fprintf(stdout, "clearing '%s'.\n", + chan_matches[i]->channelname); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear '%s' (y/n/q) ?", + chan_matches[i]->channelname); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch (buf[0]) { + case 'y': + case 'Y': + channel_control(chanclear, + chan_matches[i]->channelname, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = chan_num_matches; + default: + break; + } + } + } + + } +} + +channel_force(chan) +struct chan_struct *chan; +{ + + if (chan->status->enabled != TRUE) + channel_control(chanstart, chan->channelname, NULLCP); + if (chan->status->cachedUntil != 0) + channel_control(chanclear, chan->channelname, NULLCP); +} + +channel_below_clear_regex() +{ + int cont, i; + char buf[BUFSIZ]; + + if (chan_num_matches > 0) { + if (chan_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + chan_match, chan_num_matches); + for (i = 0; i < chan_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (chan_num_matches == 1) { + fprintf(stdout, "clearing entities below '%s'.\n", + chan_matches[i]->channelname); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear entities below '%s' (y/n/q) ?", + chan_matches[i]->channelname); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch (buf[0]) { + case 'y': + case 'Y': + currentchan = chan_matches[i]; + my_invoke(mtaread, + &(chan_matches[i]->channelname)); + mta_downforce_list(chan_matches[i]); + channel_force(chan_matches[i]); + currentchan = NULL; + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = chan_num_matches; + default: + break; + } + } + } + } +} + +channel_delay_regex() +{ + int cont, i, dcont; + char buf[BUFSIZ]; + char delay[BUFSIZ]; + + delay[0] = '\0'; + + if (chan_num_matches > 0) { + + if (chan_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + chan_match, chan_num_matches); + + for (i = 0; i < chan_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (chan_num_matches == 1) { + fprintf(stdout, "delaying '%s'.\n", + chan_matches[i]->channelname); + buf[0] = 'y'; + } else { + fprintf(stdout, "delay '%s' (y/n/q) ?", + chan_matches[i]->channelname); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch (buf[0]) { + case 'y': + case 'Y': + dcont = TRUE; + while (dcont == TRUE) { + fprintf(stdout, "Delay (in s m h d and/or w) [%s] = ", + (delay[0] != '\0') ? delay : ""); + fflush(stdout); + + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + + if (emptyStr(buf)) { + if (delay[0] != '\0') + /* happy with the one we got */ + dcont = FALSE; + else + fprintf(stdout, "no delay given\n"); + } else { + dcont = FALSE; + strcpy(delay, buf); + } + } + + channel_control(chancacheadd, + chan_matches[i]->channelname, + delay); + case 'n': + case 'N': + cont = FALSE; + break; + case 'Q': + case 'q': + cont = FALSE; + i = chan_num_matches; + default: + break; + } + } + } + + } +} + +/* ARGSUSED */ +int do_channelcontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_ChannelControl **arg; +/* args[0] = channel */ +/* args[1] = stop,start,clear,cacheadd */ +/* args[2] = time */ +{ + char *timestr; + *arg = (struct type_Qmgr_ChannelControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + switch ((Operations) args[1]) { + case chanstart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case chanstop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case chanclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case chancacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[2]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for channels", + args[1])); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +int channelcontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_PrioritisedChannelList *result; +struct RoSAPindication *roi; +{ + if (compat) { + total_number_reports = 0; + total_number_messages = 0; + total_volume = 0; + } + if (globallist) + update_channel_list(result); + else + create_channel_list(result); + return OK; + +} diff --git a/Src/LINEconsole/console.h b/Src/LINEconsole/console.h new file mode 100644 index 0000000..75fa5f6 --- /dev/null +++ b/Src/LINEconsole/console.h @@ -0,0 +1,177 @@ +/* console.h: include files and typedefs for lineconsole */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/console.h,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: console.h,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + * + */ +#ifndef _H_MTACONSOLE_CONSOLE +#define _H_MTACONSOLE_CONSOLE + +#include "head.h" +#include "sys.file.h" +#include "qmgr.h" +#include +#include + +typedef enum { + Unknown, Ambiguous, + Quit, Connect, Disconnect, Heuristics, Quecontrol, + Up, Down, Status, Set, Current, Refresh, + List, Enable, Disable, Delay, Clear, Info, + BelowClear, AboveClear, Next, Previous, +} Command; + +typedef enum { + unknown, + quit, connect, disconnect, quecontrol, qmgrStatus, + chanread, chanstop, chanstart, + chancacheadd, chandownforce, chanclear, chaninfo, + channext, chanprev, + mtaread, mtastop, mtastart, + mtacacheadd, mtaforce, mtadownforce, mtaclear, mtainfo, + mtanext, mtaprev, + readchannelmtamessage, msgstop, msgstart, + msgcacheadd, msgforce, msgclear, msginfo, + msgnext, msgprev, + mtacontrol +} Operations; + +typedef enum { + top, + channel, + mta, + msg +} Level; + + +typedef struct client_dispatch { + char *ds_name; + int ds_operation; + IFP ds_argument; +#ifdef PEPSY_VERSION + modtyp *ds_fr_mod; + int ds_fr_index; +#else + IFP ds_free; +#endif + IFP ds_result; + IFP ds_error; + char *ds_help; +} Client_dispatch; + +typedef struct procStatus { + char enabled; /* boolean TRUE or FALSE */ + time_t lastAttempt, + cachedUntil, + lastSuccess; +} ProcStatus; + +typedef struct tailor { + char *key; + double ub_number, + ub_volume, + ub_age, + ub_last; + struct tailor *next; +} TailorInfo; + +/* 4 factors (num, vol, age, last) == max 400 % */ +#define max_bad_channel 400 + +/* 4 factors (num, vol, age, last) == max 400 % */ +#define max_bad_mta 400 + +/* 2 factors (vol, age) == max 200 % */ +#define max_bad_msg 200 + +typedef struct permsginfo { + char *queueid; + char *originator; + char *contenttype; + char *eit; + int priority; + int size; + time_t expiryTime; + time_t deferredTime; + time_t age; + int errorCount; + char *inChannel; + char *uaContentId; +} Permsginfo; + + + +typedef struct recip { + int id; + char *recipient; + char *mta; + char *actChan; + char *chansOutstanding; + struct procStatus *status; + char *info; + struct recip *next; +} Recip; + + + +typedef struct msg_struct { + struct permsginfo *msginfo; + struct recip *reciplist; + struct tailor *tai; +} Msg_struct; + + + +typedef struct mta_struct { + char *mta; + time_t oldestMessage; + int numberMessages, + numberReports, + volumeMessages; + struct procStatus *status; + int priority; + char active; + char *info; + struct tailor *tai; +} Mta_struct; + + + +typedef struct chan_struct { + char *channelname, + *channeldescrip; + time_t oldestMessage; + int numberMessages, + numberReports, + volumeMessages, + numberActiveProcesses; + struct procStatus *status; + int priority; + struct mta_struct **mtalist; + int num_mtas; + int given_num_mtas; + int display_num; + int inbound; + int outbound; + int chantype; + int maxprocs; + struct tailor *tai; +} Chan_struct; + +extern void openpager(), closepager(), update_status(); +extern char *command2str(), *lowerfy(); +extern Command get_command(); + +#define ssformat "%-*s %s" +#define sdformat "%-*s %s" +#define plus_ssformat "%s\n%-*s %s" +#define plus_sdformat "%s\n%-*s %d" + +#define tab 30 + +#endif diff --git a/Src/LINEconsole/drive.c b/Src/LINEconsole/drive.c new file mode 100644 index 0000000..16a9f4f --- /dev/null +++ b/Src/LINEconsole/drive.c @@ -0,0 +1,478 @@ +/* drive.c: main routine for line based console */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/drive.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/drive.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: drive.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ +#include "console.h" + +extern Command get_command(); +extern int connected, info_shown; +extern char *host; + +int total_volume, total_number_messages, total_number_reports; +int assocD = -1; +time_t currentTime; +Command comm = Unknown; + +main(argc, argv) +int argc; +char **argv; +{ + init(argc, argv); + top_level_menu(); + QuitProc(); +} + +#define ARG_QUEUE 1 +#define ARG_USER 2 +#define ARG_AUTHORISED 3 + +int bypassHostQuestions = FALSE; +extern char *username; +extern int authorised; + +static CMD_TABLE tb_args [] = { /* all possible cmdline args */ + "-queue", ARG_QUEUE, + "-queu", ARG_QUEUE, + "-que", ARG_QUEUE, + "-qu", ARG_QUEUE, + "-q", ARG_QUEUE, + + "-user", ARG_USER, + "-use", ARG_USER, + "-us", ARG_USER, + "-u", ARG_USER, + + "-authorised", ARG_AUTHORISED, + "-authorise", ARG_AUTHORISED, + "-authoris", ARG_AUTHORISED, + "-authori", ARG_AUTHORISED, + "-author", ARG_AUTHORISED, + "-autho", ARG_AUTHORISED, + "-auth", ARG_AUTHORISED, + "-aut", ARG_AUTHORISED, + "-au", ARG_AUTHORISED, + "-a", ARG_AUTHORISED, + + 0, -1 + }; + +init(argc, argv) +int argc; +char **argv; +{ + int i; + isodetailor(argv[0], 1); + init_host(); + init_pager(); + for (i = 1; i < argc; i++) { + switch(cmd_srch(argv[i], tb_args)) { + case ARG_QUEUE: + if (++i >= argc) + fprintf(stderr, + "No hostname given with flag '%s'\n", + argv[i-1]); + else { + if (host) free(host); + host = strdup(argv[i]); + comm = Connect; + bypassHostQuestions = TRUE; + } + break; + case ARG_USER: + if (++i >= argc) + fprintf(stderr, + "No username given with flag '%s'\n", + argv[i-1]); + else { + if (username) free(username); + username = strdup(argv[i]); + } + break; + + case ARG_AUTHORISED: + authorised = TRUE; + break; + + default: + fprintf(stderr, + "Unknown flag '%s'\n", + argv[i]); + } + } + init_assoc(); +} + +extern char prompt[], *level2str(); +extern int compat; +Level lev = top; + +top_level_menu() +{ + reset_prompt_regex(); + if (comm == Unknown) + comm = get_command(top); + while (comm != Quit) { + switch (comm) { + case Connect: + set_host(); + ConnectProc(); + if (connected == TRUE) { + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + channel_level_menu(); + lev = top; + reset_prompt_regex(); + } + break; + case Disconnect: + DisconnectProc(); + comm = Unknown; + break; + case Heuristics: + heuristics_menu(); + break; + case Status: + print_status(); + break; + case Set: + variables(); + break; + default: + fprintf(stderr, + "Unknown command '%s' in top level menu\n", + command2str(comm)); + break; + } + if (comm != Quit + && comm != Disconnect) + comm = get_command(top); + + } +} + +channel_level_menu() +{ + + int cont = TRUE; + lev = channel; + reset_prompt_regex(); + comm = List; /* get_command(channel);*/ + info_shown = FALSE; + + while (cont == TRUE) { + switch (comm) { + case Disconnect: + case Quit: + cont = FALSE; + break; + case Heuristics: + heuristics_menu(); + break; + case Status: + print_status(); + break; + case Set: + variables(); + break; + case Refresh: + channel_do_refresh(); + break; + case Quecontrol: + Qcontrol(); + break; + case Current: + if (channel_set_current() == OK) + reset_prompt_regex(); + break; + case Down: + if (channel_set_current() == OK) { + mta_level_menu(); + lev = channel; + reset_prompt_regex(); + } + break; + case Next: + channel_next(); + reset_prompt_regex(); + channel_info_regex(); + break; + case Previous: + channel_previous(); + reset_prompt_regex(); + channel_info_regex(); + break; + case Info: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_info_regex(); + } + break; + case List: + channel_list(); + break; + case Enable: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_enable_regex(); + } + break; + case Disable: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_disable_regex(); + } + break; + case Delay: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_delay_regex(); + } + break; + case Clear: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_clear_regex(); + } + break; + case BelowClear: + if (channel_set_current_regex() == OK) { + reset_prompt_regex(); + channel_below_clear_regex(); + } + break; + default: + fprintf(stderr, + "Unknown command '%s' in channel level menu\n", + command2str(comm)); + break; + } + if (cont == TRUE) { + if (comm != Quit + && comm != Disconnect) + comm = get_command(channel); + else + cont = FALSE; + } + } + clear_channel_level(); +} + +mta_level_menu() +{ + + int cont = TRUE; + lev = mta; + reset_prompt_regex(); + comm = List; /* get_command(mta);*/ + info_shown = FALSE; + + while (cont == TRUE) { + switch (comm) { + case Disconnect: + case Quit: + case Up: + cont = FALSE; + break; + case Heuristics: + heuristics_menu(); + break; + case Status: + print_status(); + break; + case Set: + variables(); + break; + case Current: + if (mta_set_current() == OK) + reset_prompt_regex(); + break; + case Refresh: + mta_do_refresh(); + break; + case Down: + if (mta_set_current() == OK) { + msg_level_menu(); + lev = mta; + reset_prompt_regex(); + } + break; + case Next: + mta_next(); + reset_prompt_regex(); + mta_info_regex(); + break; + case Previous: + mta_previous(); + reset_prompt_regex(); + mta_info_regex(); + break; + case Info: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_info_regex(); + } + break; + case List: + mta_list(); + break; + case Enable: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_enable_regex(); + } + break; + case Disable: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_disable_regex(); + } + break; + case Delay: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_delay_regex(); + } + break; + case Clear: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_clear_regex(); + } + break; + case BelowClear: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_clear_below_regex(); + } + break; + case AboveClear: + if (mta_set_current_regex() == OK) { + reset_prompt_regex(); + mta_clear_above_regex(); + } + break; + default: + fprintf(stderr, + "Unknown command '%s' in mta level menu\n", + command2str(comm)); + break; + } + if (cont == TRUE) { + if (comm != Quit + && comm != Disconnect) + comm = get_command(mta); + else + cont = FALSE; + } + } + clear_mta_level(); +} + +msg_level_menu() +{ + + int cont = TRUE; + lev = msg; + reset_prompt_regex(); + comm = List; /* get_command(msg); */ + info_shown = FALSE; + + while (cont == TRUE) { + switch (comm) { + case Disconnect: + case Quit: + case Up: + cont = FALSE; + break; + case Next: + msg_next(); + reset_prompt_regex(); + msg_info_regex(); + break; + case Previous: + msg_previous(); + reset_prompt_regex(); + msg_info_regex(); + break; + case Heuristics: + heuristics_menu(); + break; + case Status: + print_status(); + break; + case Set: + variables(); + break; + case Refresh: + msg_do_refresh(); + break; + case Current: + if (msg_set_current() == OK) + reset_prompt_regex(); + break; + case Info: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_info_regex(); + } + break; + case List: + msg_list(); + break; + case Enable: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_enable_regex(); + } + break; + case Disable: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_disable_regex(); + } + break; + case Delay: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_delay_regex(); + } + break; + case Clear: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_clear_regex(); + } + break; + case AboveClear: + if (msg_set_current_regex() == OK) { + reset_prompt_regex(); + msg_clear_above_regex(); + } + break; + default: + fprintf(stderr, + "Unknown command '%s' in msg level menu\n", + command2str(comm)); + break; + } + if (cont == TRUE) { + if (comm != Quit + && comm != Disconnect) + comm = get_command(msg); + else + cont = FALSE; + } + } + clear_msg_level(); +} + diff --git a/Src/LINEconsole/heuristics.c b/Src/LINEconsole/heuristics.c new file mode 100644 index 0000000..51aecec --- /dev/null +++ b/Src/LINEconsole/heuristics.c @@ -0,0 +1,20 @@ +/* heuristics_menu.c: routines to alter display heuristics */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/heuristics.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/heuristics.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: heuristics.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +heuristics_menu() +{ +} diff --git a/Src/LINEconsole/io.c b/Src/LINEconsole/io.c new file mode 100644 index 0000000..673c189 --- /dev/null +++ b/Src/LINEconsole/io.c @@ -0,0 +1,544 @@ +/* io.c: i/o routines for linebased console */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/io.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/io.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: io.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ +#include "console.h" +#include + +/* */ +/* paging routines */ + +char *cmd_argv[100]; +int cmd_argc; + +char *pager; +FILE *out; +extern FILE *popen (); +SFP oldpipe; +int pipeopen, pageron, fileopen; + +init_pager() +{ + if ((pager = getenv("PAGER")) == NULL) + pager = strdup("more"); + else + pager = strdup(pager); + pageron = TRUE; +} + +/* ARGSUSED */ +static void piped(sig) +int sig; +{ + pipeopen = 0; +} + +void openpager() +{ + FILE *fp; + fileopen = FALSE; + if (cmd_argc > 1) { + int i; + for (i = 1; i < cmd_argc; i++) { + if (lexequ(cmd_argv[i], ">") == 0 + || lexequ(cmd_argv[i], ">>") == 0) { + int append = (lexequ(cmd_argv[i], ">") == 0) ? FALSE : TRUE; + i++; + if (i >= cmd_argc) + fprintf(stderr, + "redirect argument (%s) given but no destination specified\n", + cmd_argv[i-1]); + else if ((fp = fopen(cmd_argv[i], + (append == TRUE) ? "a" : "w")) == NULL) + fprintf(stderr, + "unable to open redirect destination '%s' for %s\n", + cmd_argv[i], + (append == TRUE) ? "appending" : "writing"); + else { + fileopen = TRUE; + out = fp; + i = cmd_argc; + } + } + } + } + + if (fileopen == TRUE) + return; + + if (pageron == TRUE) { + oldpipe = signal(SIGPIPE, piped); + if (isatty(1) == 0 + || pager == NULLCP) + out = stdout; + else if ((out = popen(pager,"w")) == NULL) { + fprintf(stderr, "unable to start pager '%s': %s\n", + pager, sys_errname (errno)); + out = stdout; + } + pipeopen = 1; + } else + out = stdout; +} + +void closepager() +{ + if (out != stdout) { + if (fileopen == TRUE) + fclose(out); + else + pclose(out); + out = stdout; + } + pipeopen = 0; + if (pageron == TRUE) + signal(SIGPIPE, oldpipe); +} + +/* */ +/* routine to read in commands */ +static CMD_TABLE tb_commands [] = { /* all possible commands */ + "aboveclear", (int) AboveClear, + "aboveclea", (int) AboveClear, + "abovecle", (int) AboveClear, + "abovecl", (int) AboveClear, + "abovec", (int) AboveClear, + "above", (int) AboveClear, + "abov", (int) AboveClear, + "abo", (int) AboveClear, + "ab", (int) AboveClear, + "a", (int) AboveClear, + + "belowclear", (int) BelowClear, + "belowclea", (int) BelowClear, + "belowcle", (int) BelowClear, + "belowcl", (int) BelowClear, + "belowc", (int) BelowClear, + "below", (int) BelowClear, + "belo", (int) BelowClear, + "bel", (int) BelowClear, + "be", (int) BelowClear, + "b", (int) BelowClear, + + + "clear", (int) Clear, + "clea", (int) Clear, + "cle", (int) Clear, + "cl", (int) Clear, + + "connect", (int) Connect, + "connec", (int) Connect, + "conne", (int) Connect, + "conn", (int) Connect, + "con", (int) Connect, + "co", (int) Connect, + + "current", (int) Current, + "curren", (int) Current, + "curre", (int) Current, + "curr", (int) Current, + "cur", (int) Current, + "cu", (int) Current, + + "c", (int) Ambiguous, + + "delay", (int) Delay, + "dela", (int) Delay, + "del", (int) Delay, + "de", (int) Delay, + + "disable", (int) Disable, + "disabl", (int) Disable, + "disab", (int) Disable, + "disa", (int) Disable, + + "disconnect", (int) Disconnect, + "disconnec", (int) Disconnect, + "disconne", (int) Disconnect, + "disconn", (int) Disconnect, + "discon", (int) Disconnect, + "disco", (int) Disconnect, + "disc", (int) Disconnect, + + "dis", (int) Ambiguous, + + "down", (int) Down, + "dow", (int) Down, + "do", (int) Down, + + "d", (int) Ambiguous, + + "enable", (int) Enable, + "enabl", (int) Enable, + "enab", (int) Enable, + "ena", (int) Enable, + "en", (int) Enable, + "e", (int) Enable, + + "heuristics", (int) Heuristics, + "heuristic", (int) Heuristics, + "heuristi", (int) Heuristics, + "heurist", (int) Heuristics, + "heuris", (int) Heuristics, + "heuri", (int) Heuristics, + "heur", (int) Heuristics, + "heu", (int) Heuristics, + "he", (int) Heuristics, + "h", (int) Heuristics, + + "informatio", (int) Info, + "informati", (int) Info, + "informat", (int) Info, + "informa", (int) Info, + "inform", (int) Info, + "infor", (int) Info, + "info", (int) Info, + "inf", (int) Info, + "in", (int) Info, + "i", (int) Info, + + + "list", (int) List, + "lis", (int) List, + "li", (int) List, + "l", (int) List, + + "next", (int) Next, + "nex", (int) Next, + "ne", (int) Next, + "n", (int) Next, + + "previous", (int) Previous, + "previou", (int) Previous, + "previo", (int) Previous, + "previ", (int) Previous, + "prev", (int) Previous, + "pre", (int) Previous, + "pr", (int) Previous, + "p", (int) Previous, + + "quecontrol", (int) Quecontrol, + "quecontro", (int) Quecontrol, + "quecontr", (int) Quecontrol, + "quecont", (int) Quecontrol, + "quecon", (int) Quecontrol, + "queco", (int) Quecontrol, + "quec", (int) Quecontrol, + "que", (int) Quecontrol, + + + "quit", (int) Quit, + "qui", (int) Quit, + + "qu", (int) Ambiguous, + "q", (int) Ambiguous, + + "refresh", (int) Refresh, + "refres", (int) Refresh, + "refre", (int) Refresh, + "refr", (int) Refresh, + "ref", (int) Refresh, + "re", (int) Refresh, + "r", (int) Refresh, + + "status", (int) Status, + "statu", (int) Status, + "stat", (int) Status, + "sta", (int) Status, + "st", (int) Status, + + "set", (int) Set, + "se", (int) Set, + + "s", (int) Ambiguous, + + "up", (int) Up, + "u", (int) Up, + + "unknown", (int) Unknown, + 0, -1 + }; + +Command str2command(); +char *level2str(); +void command_options(); +extern int connected; +extern int authorised; +extern char *host; +extern Command comm; +extern Level lev; +extern struct chan_struct *currentchan; +extern struct mta_struct *currentmta; +char prompt[BUFSIZ]; + +extern char *chan_match, *mta_match, *msg_match; + +reset_prompt_regex() +{ + switch(lev) { + case top: + sprintf(prompt, "%s", level2str(lev)); + break; + case channel: + sprintf(prompt, "%s", + (chan_match) ? chan_match : level2str(lev)); + break; + case mta: + sprintf(prompt, "%s.%s", + (currentchan) ? currentchan->channelname : level2str(channel), + (mta_match) ? mta_match : level2str(lev)); + break; + case msg: + sprintf(prompt, "%s.%s.%s", + (currentchan) ? currentchan->channelname : level2str(channel), + (currentmta) ? currentmta->mta : level2str(mta), + (msg_match) ? msg_match : level2str(lev)); + break; + } +} + +int info_shown; + +static void set_info(com) +Command com; +{ + switch(com) { + case Info: + case Next: + case Previous: + info_shown = TRUE; + case Refresh: + case Heuristics: + case Status: + break; + default: + info_shown = FALSE; + break; + } +} + +Command get_command(lev) +Level lev; +{ + Command ret = Unknown; + int cont = TRUE; + static char buf[BUFSIZ]; + cmd_argc = 0; + while (cont == TRUE) { + fprintf(stdout, "%s> ", prompt); + fflush (stdout); + + if (gets(buf) == NULL) + exit(OK); + (void) compress(buf, buf); + + cmd_argc = sstr2arg(buf, 100, cmd_argv, " \t"); + + if (cmd_argc == 0) { + /* use same command as before */ + ret = comm; + cont = FALSE; + } else if ((ret = str2command(cmd_argv[0])) == Unknown) { + fprintf(stdout, + "Unknown command '%s'\n", cmd_argv[0]); + command_options(lev); + } else if (ret == Ambiguous) { + fprintf(stdout, + "Ambiguous command '%s'\n", cmd_argv[0]); + command_options(lev); + ret = Unknown; + } else if (check_command(ret, lev) == NOTOK) { + fprintf(stdout, + "Command '%s' unavailable at '%s' level\n", + command2str(ret), level2str(lev)); + command_options(lev); + } else if (ret == Connect && connected == TRUE) + fprintf(stdout, + "Already connected (to %s)\n", host); + else if (ret == Disconnect && connected == FALSE) + fprintf(stdout, + "Already unconnected\n"); + else + cont = FALSE; + } + set_info(ret); + return ret; +} + +/* */ +/* command recognition routines */ + +Command str2command(str) +char *str; +{ + Command ret; + + if ((ret = (Command) cmd_srch(str, tb_commands)) == -1) + ret = Unknown; + return ret; +} + +char *command2str(com) +Command com; +{ + return rcmd_srch(com, tb_commands); +} + +int check_command(com, lev) +Command com; +Level lev; +{ + switch(lev) { + case top: + switch(com) { + case Connect: + case Disconnect: + case Heuristics: + case Quit: + case Status: + case Set: + return OK; + default: + return NOTOK; + } + case channel: + switch(com) { + case Disconnect: + case Down: + case Heuristics: + case Quit: + case List: + case Current: + case Info: + case Next: + case Previous: + case Refresh: + case Status: + case Set: + return OK; + case Enable: + case Disable: + case Delay: + case Clear: + case BelowClear: + case Quecontrol: + if (authorised == TRUE) + return OK; + default: + return NOTOK; + } + case mta: + switch(com) { + case Disconnect: + case Down: + case Up: + case Heuristics: + case Quit: + case List: + case Current: + case Info: + case Next: + case Previous: + case Refresh: + case Status: + case Set: + return OK; + case Enable: + case Disable: + case Delay: + case Clear: + case BelowClear: + case AboveClear: + case Quecontrol: + if (authorised == TRUE) + return OK; + default: + return NOTOK; + } + case msg: + switch(com) { + case Disconnect: + case Up: + case Heuristics: + case Quit: + case List: + case Current: + case Info: + case Next: + case Previous: + case Refresh: + case Status: + case Set: + return OK; + case Enable: + case Disable: + case Delay: + case Clear: + case AboveClear: + case Quecontrol: + if (authorised == TRUE) + return OK; + default: + return NOTOK; + } + default: + return NOTOK; + } +} + +void command_options(lev) +Level lev; +{ + fprintf(stdout, + "Commands available are:"); + switch(lev) { + case top: + fprintf(stdout, + "connect, disconnect, quit, status, set\n\tand heuristics\n"); + break; + case channel: + fprintf(stdout, + "disconnect, quit, current, status, set, refresh\n\tdown, next, previous, list, info%sand heuristics\n", + (authorised == TRUE) ? ",\n\tenable, disable, delay, clear\n\tbelowclear, quecontrol " : " "); + break; + case mta: + fprintf(stdout, + "disconnect, quit, current, status, set, refresh\n\tdown, up, next, previous, list, info%sand heuristics\n", + (authorised == TRUE) ? ",\n\tenable, disable, delay, clear\n\tbelowclear, aboveclear, quecontrol " : " "); + break; + case msg: + fprintf(stdout, + "disconnect, quit, current, status, set, refresh\n\tup, next, previous, list, info%sand heuristics\n", + (authorised == TRUE) ? ",\n\tenable, disable, delay, clear\n\taboveclear, quecontrol " : " "); + break; + } +} + +/* */ +/* level manipulation routines */ + +char *level2str(lev) +Level lev; +{ + switch(lev) { + case top: + return "top"; + case channel: + return "channel"; + case mta: + return "mta"; + case msg: + return "msg"; + } + return ""; +} diff --git a/Src/LINEconsole/make b/Src/LINEconsole/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/LINEconsole/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/LINEconsole/misc.c b/Src/LINEconsole/misc.c new file mode 100644 index 0000000..1f701cf --- /dev/null +++ b/Src/LINEconsole/misc.c @@ -0,0 +1,746 @@ +/* misc.c: misc routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/misc.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/misc.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: misc.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ +#include "console.h" +#include +#include + +char *host = NULLCP, tailorfile[MAXPATHLENGTH]; +char *actual_host = NULLCP; +char *username = NULLCP; +int authorised = FALSE; +extern char *cmd_argv[]; +extern int cmd_argc, bypassHostQuestions, connected; + +init_host() +{ + char buf[BUFSIZ]; + int uid; + struct passwd *pwd; + uid = getuid(); + pwd = getpwuid(uid); + username = strdup(pwd->pw_name); + strcpy(tailorfile, ".MTAconsole"); + gethostname(buf, BUFSIZ); + host = strdup(buf); + +} + +set_host() +{ + int cont = TRUE; + char buf[BUFSIZ]; + char *password = NULLCP; + + if (bypassHostQuestions == TRUE) { + bypassHostQuestions = FALSE; + cont = FALSE; + } else if (cmd_argc > 1) { + if (host) free(host); + host = strdup(cmd_argv[1]); + cont = FALSE; + } + + while (cont == TRUE) { + fprintf(stdout, "host (%s) = ", + (host == NULLCP) ? "" : host); + fflush(stdout); + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (host == NULL) + fprintf(stdout, "no host set\n"); + else + /* happy with the one we've got */ + cont = FALSE; + } else { + if (host) free(host); + host = strdup(buf); + cont = FALSE; + } + } + + if (authorised == TRUE) { + if (password) free(password); + password = strdup(getpassword("password = ")); + } + fillin_passwdpep(username, password, authorised); + if (password) free(password); +} + +extern char *Qversion, *Qinformation; + +set_authmode (acc) +struct AcSAPconnect *acc; +{ + struct type_Qmgr_BindResult *br; + + br = NULL; + authorised = FALSE; + if (Qversion != NULLCP) { + free(Qversion); + Qversion = NULLCP; + } + if (Qinformation != NULLCP) { + free (Qinformation); + Qinformation = NULLCP; + } + + if (acc->acc_ninfo >= 1) { + if (decode_Qmgr_BindResult (acc->acc_info[0], 1, + NULLVP, NULLIP, &br) == NOTOK) + PP_LOG(LLOG_EXCEPTIONS, ("failed to parse connect data [%s]", + PY_pepy)); + else { + switch (br->result) { + case int_Qmgr_result_acceptedFullAccess: + authorised = TRUE; + break; + case int_Qmgr_result_acceptedLimitedAccess: + default: + authorised = FALSE; + break; + } + if (br -> information != NULL) + Qinformation = qb2str (br -> information); + + if (br -> version != NULL) + Qversion = qb2str (br -> version); + + free_Qmgr_BindResult(br); + } + } +} + +/* */ + +int uk_order = 0; + +char * +reverse_adr(adr) +char *adr; +{ + extern char *rindex(); + + char *ret = malloc(strlen(adr) + 1), savech; + char *ix = adr, *iy = ret, *dom_end, *cix, *last, *dot; + int cont; + while (*ix != '\0') { + switch (*ix) { + case '@': + case '%': + /* start of domain so reverse */ + *iy++ = *ix++; + dom_end = ix; + cont = TRUE; + while (*dom_end != '\0' + && cont == TRUE) { + switch(*dom_end) { + case ',': + case ':': + cont = FALSE; + break; + default: + dom_end++; + break; + } + } + /* domain stretches from ix -> dom_end */ + + last = dom_end; + while (last != ix) { + savech = *last; + *last = '\0'; + if ((dot = rindex(ix, '.')) == NULLCP) { + dot = ix; + cix = dot; + } else + cix = dot + 1; + *last = savech; + do + { + *iy++ = *cix++; + } while (cix != last); + + if (dot != ix) { + *iy++ = '.'; + last = dot; + } else + last = ix; + } + ix = dom_end; + break; + + default: + *iy++ = *ix++; + break; + } + } + *iy = '\0'; + return ret; +} + +char * +reverse_mta(mta) +char *mta; +{ + extern char *index(); + char *adr, *ret, *ix; + char buf[BUFSIZ]; + (void) sprintf(buf, "foo@%s", mta); + ret = reverse_adr(buf); + ix = index (ret, '@'); + adr = strdup(++ix); + free(ret); + return adr; +} + +resize_info_str(pold, poldlen, inc) +char **pold; +int *poldlen, + inc; +{ + if ((int)strlen(*pold) + inc >= *poldlen) { + *poldlen += BUFSIZ; + *pold = realloc(*pold, (unsigned) *poldlen); + } +} + +char *time_t2RFC(in) +time_t in; +{ + char buf[BUFSIZ]; + struct tm *tm; + struct UTCtime uts; +#ifdef SVR4 + extern long timezone; +#else + struct timeval dummy; + struct timezone time_zone; +#endif + + tm = localtime (&in); + tm2ut (tm, &uts); + uts.ut_flags |= UT_ZONE; +#ifdef SVR4 + uts.ut_zone = timezone / 60; +#else + gettimeofday(&dummy, &time_zone); + uts.ut_zone = time_zone.tz_minuteswest; +#endif + UTC2rfc(&uts, buf); + return strdup(buf); +} + +/* convert number to volume */ + +char *vol2str(vol) +int vol; +{ + char buf[BUFSIZ]; + + if (vol < 1024) + sprintf(buf, "%d bytes", vol); + else if (vol < 1048576) + sprintf(buf, "%d Kbytes", (vol/1024)); + else + sprintf(buf, "%d Mbytes", (vol/1048576)); + return strdup(buf); +} + +char *time_t2str(in) +time_t in; +{ + char buf[BUFSIZ]; + time_t result; + buf[0] = '\0'; + + if (in < 0) + return strdup("still in the womb"); + + if ((result = in / (60 * 60 * 24)) != 0) { + sprintf(buf, "%d day%s", + result, + (result == 1) ? "" : "s"); + in = in % (60 * 60 * 24); + } + + if ((result = in / (60 * 60)) != 0) { + sprintf(buf, + (buf[0] == '\0') ? "%s%d hr%s" : "%s %d hr%s", + buf, + result, + (result == 1) ? "" : "s"); + in = in % (60 * 60); + } + if ((result = in / 60) != 0) { + sprintf(buf, + (buf[0] == '\0') ? "%s%d min%s" : "%s %d min%s", + buf, + result, + (result == 1) ? "" : "s"); + in = in % 60; + } + + if (buf[0] == '\0' && in != 0) + sprintf(buf, "%d sec%s", + in, + (in == 1) ? "" : "s"); + if (buf[0] == '\0') + sprintf(buf, "just born"); + return strdup(buf); +} + +#define MaxCharPerInt 16 + +/* convert integer to string */ +char *itoa(i) +int i; +{ + char buf[MaxCharPerInt]; + + sprintf(buf,"%d",i); + + return strdup(buf); + +} + +num2unit(num, buf) +int num; +char *buf; +{ + if (num > 1000000) + (void) sprintf(buf, "%.2f M", + (double) num / 1000000.0); + else if (num > 1000) + (void) sprintf(buf, "%.2f k", + (double) num / 1000.0); + else + (void) sprintf(buf, "%d", num); +} + +time_t parsetime(s) +char *s; +{ + int n; + if (s == NULLCP || *s == NULL) return 0; + while(*s != NULL && isspace(*s)) s++; + n = 0; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + s++; + } + while (*s != NULL && isspace(*s)) s++; + if (*s != NULL && isalpha(*s)) { + switch (*s) { + case 's': + case 'S': + break; + case 'm': + case 'M': + n *= 60; + break; + case 'h': + case 'H': + n *= 3600; + break; + case 'd': + case 'D': + n *= 86400; + break; + case 'w': + case 'W': + n *= 604800; + break; + default: + break; + } + return n + parsetime(s+1); + } + else return n + parsetime(s); +} + +char *mystrtotime(str) +char *str; +{ + UTC utc; + time_t newsecs; + time_t current; + char *retval; + + newsecs = parsetime(str); + time(¤t); + + current += newsecs; + + utc = time_t2utc(current); + + retval = utct2str(utc); + free((char *) utc); + return strdup(retval); +} + +char *lowerfy (s) +char *s; +{ + static char buf[BUFSIZ]; + char *cp; + + for (cp = buf; *s; s++) + if (isascii (*s) && isupper (*s)) + *cp++ = tolower (*s); + else + *cp ++ = *s; + *cp = NULL; + return buf; +} + +emptyStr(buf) +char *buf; +{ + return (isspace(buf[0]) || buf[0] == '\0'); +} + +/* */ + +/* ARGSUSED */ +int do_quecontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +int args; +struct type_Qmgr_QMGROp **arg; +{ + *arg = (struct type_Qmgr_QMGROp *) malloc(sizeof(**arg)); + (*arg)->parm = args; + return OK; +} + +/* ARGSUSED */ +int quecontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_Pseudo__qmgrControl *result; +struct RoSAPindication *roi; +{ + return OK; +} + +static CMD_TABLE tb_controls [] = { /* quecontrol options */ + "abort", int_Qmgr_QMGROp_abort, + "abor", int_Qmgr_QMGROp_abort, + "abo", int_Qmgr_QMGROp_abort, + "ab", int_Qmgr_QMGROp_abort, + "a", int_Qmgr_QMGROp_abort, + + "decreasemaxchans", int_Qmgr_QMGROp_decreasemaxchans, + "decreasemaxchan", int_Qmgr_QMGROp_decreasemaxchans, + "decreasemaxcha", int_Qmgr_QMGROp_decreasemaxchans, + "decreasemaxch", int_Qmgr_QMGROp_decreasemaxchans, + "decreasemaxc", int_Qmgr_QMGROp_decreasemaxchans, + "decreasemax", int_Qmgr_QMGROp_decreasemaxchans, + "decreasema", int_Qmgr_QMGROp_decreasemaxchans, + "decreasem", int_Qmgr_QMGROp_decreasemaxchans, + "decrease", int_Qmgr_QMGROp_decreasemaxchans, + "decreas", int_Qmgr_QMGROp_decreasemaxchans, + "decrea", int_Qmgr_QMGROp_decreasemaxchans, + "decre", int_Qmgr_QMGROp_decreasemaxchans, + "decr", int_Qmgr_QMGROp_decreasemaxchans, + "dec", int_Qmgr_QMGROp_decreasemaxchans, + "de", int_Qmgr_QMGROp_decreasemaxchans, + + "disableAll", int_Qmgr_QMGROp_disableAll, + "disableAl", int_Qmgr_QMGROp_disableAll, + "disableA", int_Qmgr_QMGROp_disableAll, + + "disableSubmission", int_Qmgr_QMGROp_disableSubmission, + "disableSubmissio", int_Qmgr_QMGROp_disableSubmission, + "disableSubmissi", int_Qmgr_QMGROp_disableSubmission, + "disableSubmiss", int_Qmgr_QMGROp_disableSubmission, + "disableSubmis", int_Qmgr_QMGROp_disableSubmission, + "disableSubmi", int_Qmgr_QMGROp_disableSubmission, + "disableSubm", int_Qmgr_QMGROp_disableSubmission, + "disableSub", int_Qmgr_QMGROp_disableSubmission, + "disableSu", int_Qmgr_QMGROp_disableSubmission, + "disableS", int_Qmgr_QMGROp_disableSubmission, + + "enableAll", int_Qmgr_QMGROp_enableAll, + "enableAl", int_Qmgr_QMGROp_enableAll, + "enableA", int_Qmgr_QMGROp_enableAll, + + "enableSubmission", int_Qmgr_QMGROp_enableSubmission, + "enableSubmissio", int_Qmgr_QMGROp_enableSubmission, + "enableSubmissi", int_Qmgr_QMGROp_enableSubmission, + "enableSubmiss", int_Qmgr_QMGROp_enableSubmission, + "enableSubmis", int_Qmgr_QMGROp_enableSubmission, + "enableSubmi", int_Qmgr_QMGROp_enableSubmission, + "enableSubm", int_Qmgr_QMGROp_enableSubmission, + "enableSub", int_Qmgr_QMGROp_enableSubmission, + "enableSu", int_Qmgr_QMGROp_enableSubmission, + "enableS", int_Qmgr_QMGROp_enableSubmission, + + "increasemaxchans", int_Qmgr_QMGROp_increasemaxchans, + "increasemaxchan", int_Qmgr_QMGROp_increasemaxchans, + "increasemaxcha", int_Qmgr_QMGROp_increasemaxchans, + "increasemaxch", int_Qmgr_QMGROp_increasemaxchans, + "increasemaxc", int_Qmgr_QMGROp_increasemaxchans, + "increasemax", int_Qmgr_QMGROp_increasemaxchans, + "increasema", int_Qmgr_QMGROp_increasemaxchans, + "increasem", int_Qmgr_QMGROp_increasemaxchans, + "increase", int_Qmgr_QMGROp_increasemaxchans, + "increas", int_Qmgr_QMGROp_increasemaxchans, + "increa", int_Qmgr_QMGROp_increasemaxchans, + "incre", int_Qmgr_QMGROp_increasemaxchans, + "incr", int_Qmgr_QMGROp_increasemaxchans, + "inc", int_Qmgr_QMGROp_increasemaxchans, + "in", int_Qmgr_QMGROp_increasemaxchans, + "i", int_Qmgr_QMGROp_increasemaxchans, + + "rereadQueue", int_Qmgr_QMGROp_rereadQueue, + "rereadQueu", int_Qmgr_QMGROp_rereadQueue, + "rereadQue", int_Qmgr_QMGROp_rereadQueue, + "rereadQu", int_Qmgr_QMGROp_rereadQueue, + "rereadQ", int_Qmgr_QMGROp_rereadQueue, + "reread", int_Qmgr_QMGROp_rereadQueue, + "rerea", int_Qmgr_QMGROp_rereadQueue, + "rere", int_Qmgr_QMGROp_rereadQueue, + "rer", int_Qmgr_QMGROp_rereadQueue, + + + "restart", int_Qmgr_QMGROp_restart, + "restar", int_Qmgr_QMGROp_restart, + "resta", int_Qmgr_QMGROp_restart, + "rest", int_Qmgr_QMGROp_restart, + "res", int_Qmgr_QMGROp_restart, + + "terminate", int_Qmgr_QMGROp_gracefulTerminate, + "terminat", int_Qmgr_QMGROp_gracefulTerminate, + "termina", int_Qmgr_QMGROp_gracefulTerminate, + "termin", int_Qmgr_QMGROp_gracefulTerminate, + "termi", int_Qmgr_QMGROp_gracefulTerminate, + "term", int_Qmgr_QMGROp_gracefulTerminate, + "ter", int_Qmgr_QMGROp_gracefulTerminate, + "te", int_Qmgr_QMGROp_gracefulTerminate, + "t", int_Qmgr_QMGROp_gracefulTerminate, + + 0, -1 + }; + + +static int str2control(str) +char *str; +{ + Command ret; + char *ix = str, savech, *start; + + while (*ix != '\0' && isspace(*ix)) ix++; + start = ix; + while (*ix != '\0' && !isspace(*ix)) ix++; + savech = *ix; + *ix = '\0'; + + ret = (Command) cmd_srch(start, tb_controls); + *ix = savech; + return ret; +} + +static int control_options() +{ + fprintf(stdout, + "Qmgr Controls available are:"); + fprintf(stdout, + "abort, terminate, restart, rereadQueue,\n\tdisableSubmission, enableSubmission, disableAll, enableAll, increasemaxchans, and decreasemaxchans\n"); +} + +static int get_control(pcontrol) +int *pcontrol; +{ + int cont = TRUE, first = TRUE; + int ret = NOTOK, control; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "quecontrol (q=quit)> "); + fflush (stdout); + + if (gets(buf) == NULL) + exit(OK); + } + compress(buf, buf); + + if (buf[0] == 'q') { + /* use same command as before */ + cont = FALSE; + } else if ((control = str2control(buf)) < 0) { + fprintf(stdout, + "Unknown control '%s'\n", buf); + control_options(); + } else { + *pcontrol = control; + cont = FALSE; + ret = OK; + } + } + + return ret; +} + +Qcontrol() +{ + int control; + + if (get_control(&control) == OK) + my_invoke(quecontrol, (char **) control); +} + +extern char *pager; +extern int pageron; + +#define PAGER 1 +#define TAILORFILE 2 +#define AUTHORISED 3 +#define USER 4 + +static CMD_TABLE tb_variables [] = { /* line console variables */ + "pager", PAGER, + "tailorfile", TAILORFILE, + "authorised", AUTHORISED, + "user", USER, + 0, -1 + }; + +print_variables() +{ + if (pager) { + fprintf(stdout, + "pager='%s' (%s)\n", + pager, + (pageron == TRUE) ? "on" : "off"); + } else + fprintf(stdout, + "no pager set\n"); + if (tailorfile[0] != '\0') + fprintf(stdout, + "tailorfile='%s'\n", + tailorfile); + else + fprintf(stdout, + "no tailorfile set\n"); + + fprintf(stdout, + "authorised=%s\n", + (authorised == TRUE) ? "yes" : "no"); + fprintf(stdout, + "user='%s'\n", + username); +} + +str2variable(str) +char *str; +{ + return cmd_srch(str, tb_variables); +} + +variables() +{ + if (cmd_argc > 1) { + int i; + char *ix; + for (i = 1; i < cmd_argc; i++) { + if ((ix = index(cmd_argv[i], '=')) == NULLCP) + fprintf(stderr, + "unable to parse '%s' as variable=value\n", + cmd_argv[i]); + else { + *ix = '\0'; + switch (str2variable(cmd_argv[i])) { + case PAGER: + *ix++ = '='; + if (*ix == '\0' + || lexequ(ix, "-") == 0) { + if (pager) free(pager); + pager = NULLCP; + } else if (lexequ(ix, "on") == 0) + pageron = TRUE; + else if (lexequ(ix, "off") == 0) + pageron = FALSE; + else { + if (pager) free(pager); + pager = strdup(ix); + } + break; + + case TAILORFILE: + if (connected == TRUE) + fprintf(stderr, + "cannot change tailorfile while connected\n"); + else { + *ix++ = '='; + strcpy(tailorfile, ix); + } + break; + + case USER: + if (connected == TRUE) + fprintf(stderr, + "cannot change username while connected\n"); + else { + *ix++ = '='; + if (username) free(username); + username = strdup(ix); + } + break; + + case AUTHORISED: + *ix++ = '='; + switch(*ix) { + case 'y': + case 'Y': + if (connected == TRUE) + fprintf(stderr, + "cannot turn authorised while connected\n"); + else + authorised = TRUE; + break; + case 'n': + case 'N': + authorised = FALSE; + break; + default: + fprintf(stdout, + "Don't recognise boolean value '%s'\n", + ix); + } + break; + + default: + fprintf(stderr, + "unknown variable '%s' ", + cmd_argv[i]); + *ix = '='; + fprintf(stderr, + "in '%s'\n", + cmd_argv[i]); + break; + } + } + } + } + print_variables(); +} diff --git a/Src/LINEconsole/msgs.c b/Src/LINEconsole/msgs.c new file mode 100644 index 0000000..3937f40 --- /dev/null +++ b/Src/LINEconsole/msgs.c @@ -0,0 +1,1339 @@ +/* msgs.c: msgs routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/msgs.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/msgs.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: msgs.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +static struct msg_struct **create_msg_list(); +static void display_msg_list(); + +extern struct procStatus *create_status(); +extern char *time_t2RFC(), *vol2str(), *time_t2str(), *cmd_argv[], + *mystrtotime(), *itoa(); +extern Level lev; +extern int info_shown, cmd_argc; + +struct msg_struct **msg_matches = NULL; +int msg_num_matches = 0; +char *msg_match = NULLCP; + +struct msg_struct **global_msg_list = NULL, + *find_msg(); +int number_msgs = 0; + +#define MSG_READ_INTERVAL 60 /* in secs */ + +/* ARGSUSED */ +int do_readchannelmtamessage (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +/* args[0] = chan args[1] = mta or name in case of local chan */ +struct type_Qmgr_MsgRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MsgRead *) malloc(sizeof(**arg)); + bzero ((char *) *arg, sizeof(**arg)); + /* fillin time */ + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MSG_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + if (args[0] != NULLCP) + (*arg)->channel = str2qb(args[0], strlen(args[0]), 1); + if (args[1] != NULLCP) + (*arg)->mta = str2qb(args[1], strlen(args[1]), 1); + +} + +/* ARGSUSED */ +int readchannelmtamessage_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_MsgList *result; +struct RoSAPindication *roi; +{ + free_msg_list(); + global_msg_list = create_msg_list(result->msgs); + order_msgs(); + return OK; +} + +extern struct chan_struct *currentchan; +extern struct mta_struct *currentmta; +extern int connected; + +msg_list() +{ + if (connected == TRUE + && currentchan != NULL + && currentmta != NULL) { + char *args[2]; + args[0] = currentchan->channelname; + args[1] = currentmta->mta; + my_invoke(readchannelmtamessage, args); + if (global_msg_list) + display_msg_list(global_msg_list, number_msgs); + } +} + +msg_do_refresh () +{ + char *args[2]; + if (!connected) + return; + if (currentchan && currentmta) { + mta_do_refresh(); + args[0] = currentchan->channelname; + args[1] = currentmta->mta; + my_invoke(readchannelmtamessage, args); + if (msg_match) + find_msg_regex(msg_match); + reset_prompt_regex(); + + if (lev == msg) { + if (msg_num_matches > 0 && info_shown == TRUE) + msg_info_regex(); + else if (global_msg_list) + display_msg_list(global_msg_list, + number_msgs); + } + } +} + +/* */ +extern int uk_order; +extern char *reverse_adr(); +extern FILE *out; + +static void display_msg(msg) +struct msg_struct *msg; +{ + char str[BUFSIZ]; + char *ch1, *ch2; + + if (msg->reciplist == NULL + || msg->reciplist->next == NULL) + /* delivery report */ + sprintf(str,"dr (%s) to %s", + msg->msginfo->queueid, + msg->msginfo->originator); + else { + struct recip *ix = msg->reciplist; + int found = 0; + + while (ix != NULL && found == 0) { + if (ix->actChan != NULL + && currentchan != NULL + && strcmp(ix->actChan, + currentchan->channelname) == 0) { + /* channel matches */ + if (is_loc_chan(currentchan) == TRUE) { + if (ix->recipient && currentmta + && strcmp(ix->recipient, currentmta->mta) == 0) + found = 1; + } else if (ix->mta != NULL + && currentmta != NULL + && strcmp(ix->mta, + currentmta->mta) == 0) + /* mta matches */ + found = 1; + } + if (found == 0) + ix = ix->next; + } + if (ix != NULL && ix->id == 0) { + /* delivery report ? */ + ch1 = (uk_order) ? reverse_adr(ix -> recipient) + : ix -> recipient; + sprintf(str, "dr (%s) to %s", + msg->msginfo->queueid, + ch1); + if (uk_order && ch1 != ix -> recipient) free(ch1); + } else { + if (ix == NULL) ix = msg->reciplist->next; + + ch1 = (uk_order) ? reverse_adr(ix -> recipient) : ix -> recipient; + ch2 = (uk_order) ? reverse_adr(msg->msginfo->originator) : msg->msginfo->originator; + + sprintf(str, "%s to %s from %s", + msg->msginfo->queueid, + ch1, ch2); + if (uk_order) { + if (ch1 != ix -> recipient) free(ch1); + if (ch2 != msg->msginfo->originator) free(ch2); + } + } + } + + fprintf(out, "%s\n", str); +} + +display_msg_info(msg) +struct msg_struct *msg; +{ + struct recip *ix; + char *str, *ch, + *info_str, + temp[BUFSIZ]; + int info_strlen = BUFSIZ; + info_str = calloc(1, BUFSIZ); + + sprintf(temp, "%s", msg->msginfo->queueid); + resize_info_str(&info_str, &info_strlen, strlen(temp)+1); + sprintf(info_str, "%s\n", temp); + + ch = (uk_order) ? reverse_adr(msg->msginfo->originator) + : msg->msginfo->originator; + sprintf(temp, ssformat, tab, "originator ", ch); + if (uk_order && ch != msg->msginfo->originator) free(ch); + resize_info_str(&info_str, &info_strlen, strlen(temp+1)); + sprintf(info_str, "%s%s\n", info_str, temp); + + if (msg->msginfo->size != 0) { + char size[BUFSIZ]; + + if (msg->msginfo->size > 1000000) + (void) sprintf(size, "%.2f M", + (double) (msg->msginfo->size)/1000000.0); + else if (msg->msginfo->size > 1000) + (void) sprintf(size, "%.2f k", + (double) (msg->msginfo->size)/1000.0); + else + (void) sprintf(size, "%d bytes", + msg -> msginfo -> size); + sprintf(temp, ssformat, tab, + "size", size); + resize_info_str(&info_str, &info_strlen, strlen(temp)+1); + sprintf(info_str, "%s%s\n", info_str, temp); + } + if (msg->msginfo->uaContentId != NULLCP) { + sprintf(temp, ssformat, tab, + "ua content id", + msg->msginfo->uaContentId); + resize_info_str(&info_str, &info_strlen, strlen(temp)+1); + sprintf(info_str, "%s%s\n", info_str, temp); + } + + if (msg->msginfo->inChannel != NULLCP) { + sprintf(temp, ssformat, tab, + "inbound channel", + msg->msginfo->inChannel); + resize_info_str(&info_str, &info_strlen, strlen(temp)+1); + sprintf(info_str, "%s%s\n", info_str, temp); + } + + ix = msg->reciplist; + if (ix != NULL) ix = ix->next; + while (ix != NULL) { + sprintf(info_str, "%s\n", info_str); + ch = (uk_order) ? reverse_adr(ix -> recipient) + : ix -> recipient; + sprintf(temp, ssformat, tab, + "to", + ch); + if (uk_order && ch != ix -> recipient) free(ch); + + sprintf(temp, "%s(id %d)", temp, ix->id); + + if (ix->info != NULLCP) + sprintf(temp, plus_ssformat, temp, tab, + "error info", + ix -> info); + + if (ix->chansOutstanding == NULL) + sprintf(temp, plus_ssformat, temp, tab, + "", + "awaiting DRs"); + else + sprintf(temp, plus_ssformat, temp, tab, + "remaining channels", + ix->chansOutstanding); + if (ix->status->cachedUntil != 0) { + str = time_t2RFC(ix->status->cachedUntil); + sprintf(temp, plus_ssformat, temp, tab, + "delayed until", + str); + free(str); + } + sprintf(temp, plus_ssformat, temp, tab, + "status", + (ix->status->enabled == TRUE) ? "enabled" : "disabled"); + + if (ix->status->lastAttempt != 0) { + str = time_t2RFC(ix->status->lastAttempt); + sprintf(temp, plus_ssformat, temp, tab, + "last attempt", + str); + free(str); + } + + if (ix->status->lastSuccess != 0) { + str = time_t2RFC(ix->status->lastSuccess); + sprintf(temp, plus_ssformat, temp, tab, + "last success", + str); + free(str); + } + resize_info_str(&info_str, &info_strlen, strlen(temp)+1); + sprintf(info_str, "%s%s\n", info_str, temp); + ix = ix->next; + } + sprintf(info_str, "%s\n", info_str); + + temp[0] = '\0'; + if (msg->msginfo->contenttype != NULLCP) + sprintf(temp, plus_ssformat, temp, tab, + "content type", + msg->msginfo->contenttype); + + if (msg->msginfo->eit != NULL) + sprintf(temp, plus_ssformat, temp, tab, + "eits", + msg->msginfo->eit); + str = time_t2str(time((time_t *) 0) - msg->msginfo->age); + sprintf(temp, plus_ssformat, temp, tab, + "Age", + str); + free(str); + if (msg->msginfo->expiryTime != 0) { + str = time_t2RFC(msg->msginfo->expiryTime); + sprintf(temp, plus_ssformat, temp, tab, + "Expiry time", + str); + free(str); + } + if (msg->msginfo->deferredTime != 0) { + str = time_t2RFC(msg->msginfo->deferredTime); + sprintf(temp, plus_ssformat, temp, tab, + "Deferred until", + str); + free(str); + } + switch (msg->msginfo->priority) { + case int_Qmgr_Priority_low: + sprintf(temp, plus_ssformat, temp, tab, + "priority", + "low"); + break; + case int_Qmgr_Priority_normal: + sprintf(temp, plus_ssformat, temp, tab, + "priority", + "normal"); + break; + case int_Qmgr_Priority_high: + sprintf(temp, plus_ssformat, temp, tab, + "priority", + "high"); + break; + default: + break; + } + if (msg->msginfo->errorCount != 0) + sprintf(temp, plus_sdformat, temp, tab, + "number of errors", + msg->msginfo->errorCount); + resize_info_str(&info_str, &info_strlen, strlen(temp)); + sprintf(info_str, "%s%s", info_str, temp); + + fprintf(out, "%s", info_str); + free(info_str); +} + + +msg_info_regex() +{ + int i; + if (msg_num_matches > 0) { + openpager(); + if (msg_num_matches > 1) + fprintf(out, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + display_msg_info(msg_matches[i]); + fprintf(out, "\n"); + } + closepager(); + } +} + +static void display_msg_list(list, num) +struct msg_struct **list; +int num; +{ + int i; + openpager(); + + for (i = 0;i < num; i++) + display_msg(list[i]); + closepager(); +} + +msg_force_list(list, num) +struct msg_struct **list; +int num; +{ + int i; + for (i = 0;i < num; i++) + msg_force(list[i]); +} + +/* */ +static char *create_eits(eit) +struct type_Qmgr_EncodedInformationTypes *eit; +{ + struct type_Qmgr_EncodedInformationTypes *ix; + char *str, + buf[BUFSIZ]; + int first; + if (eit == NULL) + return NULL; + ix =eit; + first = TRUE; + + while (ix != NULL) { + str = qb2str(ix->PrintableString); + if (first == TRUE) { + sprintf(buf,"%s",str); + first = FALSE; + } else + sprintf(buf,"%s, %s",buf, str); + free(str); + ix = ix->next; + } + return strdup(buf); +} + +static struct permsginfo *create_msginfo(info) +struct type_Qmgr_PerMessageInfo *info; +{ + struct permsginfo *temp; + + temp = (struct permsginfo *) calloc(1,sizeof(*temp)); + + temp->queueid = qb2str(info->queueid); + temp -> originator = qb2str(info->originator); + if (info->contenttype != NULL) + temp->contenttype = qb2str(info->contenttype); + else + temp->contenttype = NULL; + temp->eit = create_eits(info->eit); + temp->age = convert_time(info->age); + temp->size = info->size; + temp->priority = info->priority->parm; + if (info->expiryTime == NULL) + temp->expiryTime = 0; + else + temp->expiryTime = convert_time(info->expiryTime); + if (info->deferredTime == NULL) + temp->deferredTime = 0; + else + temp->deferredTime = convert_time(info->deferredTime); + if (info->optionals & opt_Qmgr_PerMessageInfo_errorCount) + temp->errorCount = info->errorCount; + if (info->inChannel != NULL) + temp->inChannel = qb2str(info->inChannel); + else + temp->inChannel = NULLCP; + if (info->uaContentId != NULL) + temp -> uaContentId = qb2str(info->uaContentId); + else + temp -> uaContentId = NULLCP; + return temp; +} + +static char *create_chans(list, done, pfirst) +struct type_Qmgr_ChannelList *list; +int done; +char **pfirst; +{ + int count; + char buf[BUFSIZ], + *str; + + struct type_Qmgr_ChannelList *ix; + count = 0; + ix = list; + while (count < done && ix != NULL) { + ix = ix->next; + count++; + } + if (ix == NULL) + /* all done waiting for delivery notifcation */ + return NULL; + + str = qb2str(ix->Channel); + sprintf(buf,"%s",str); + free(str); + *pfirst = qb2str(ix->Channel); + ix = ix->next; + + while (ix != NULL) { + str = qb2str(ix->Channel); + sprintf(buf, "%s, %s",buf,str); + free(str); + ix = ix->next; + } + return strdup(buf); +} + +static struct recip *create_recip(recip) +struct type_Qmgr_RecipientInfo *recip; +{ + struct recip *temp; + + temp = (struct recip *) calloc(1,sizeof(*temp)); + + temp->id = recip->id->parm; + + temp -> recipient = qb2str(recip->user); + temp->mta = qb2str(recip->mta); + temp->chansOutstanding = create_chans(recip->channelList, + recip->channelsDone, + &temp->actChan); + temp->status = create_status(recip->procStatus); + if (recip -> info != NULL) + temp -> info = qb2str (recip -> info); + return temp; +} + + +static struct recip *create_reciplist(list) +struct type_Qmgr_RecipientList *list; +{ + struct recip *head = NULL, + *tail = NULL, + *temp; + + while (list != NULL) { + if (list->RecipientInfo->id != 0) { + temp = create_recip(list->RecipientInfo); + if (head == NULL) + tail = head = temp; + else { + tail->next = temp; + tail = temp; + } + } + list = list->next; + } + return head; +} + +static struct msg_struct *create_msg(msg) +struct type_Qmgr_MsgStruct *msg; +{ + struct msg_struct *temp; + + temp = (struct msg_struct *) calloc(1, sizeof(*temp)); + temp->msginfo = create_msginfo(msg->messageinfo); + temp->reciplist = create_reciplist(msg->recipientlist); + add_tailor_to_msg(currentchan, temp); + return temp; +} + +static struct msg_struct **create_msg_list(list) +struct type_Qmgr_MsgStructList *list; +{ + struct type_Qmgr_MsgStructList *ix = list; + struct msg_struct **msglist; + int i; + number_msgs = 0; + while (ix != NULL) { + number_msgs++; + ix = ix->next; + } + + msglist = (struct msg_struct **) calloc((unsigned) number_msgs, + sizeof(struct msg_struct *)); + + ix = list; + i = 0; + while ((ix != NULL) + & (i < number_msgs)) { + msglist[i] = create_msg(ix->MsgStruct); + i++; + ix = ix->next; + } + return msglist; +} + +clear_msg_level() +{ + free_msg_list(); + if (msg_matches) { + free(msg_matches); + msg_matches = NULL; + } + msg_num_matches = 0; +} + +free_msg_list() +{ + int i = 0; + if (global_msg_list == NULL || number_msgs == 0) + return; + + while (i < number_msgs) { + free_permsginfo(global_msg_list[i]->msginfo); + free_reciplist(global_msg_list[i]->reciplist); + i++; + } + free((char *) global_msg_list); + global_msg_list = NULL; + number_msgs = 0; +} + +free_permsginfo(info) +struct permsginfo *info; +{ + free(info->queueid); + free(info->originator); + if (info->eit != NULL) free(info->eit); + if (info->inChannel != NULL) free(info->inChannel); + if (info->uaContentId != NULLCP) free(info->uaContentId); + free((char *) info); +} + +free_reciplist(list) +struct recip *list; +{ + struct recip *ix = list, + *temp; + + while (ix != NULL) { + if (ix->recipient) free(ix->recipient); + if (ix->mta != NULL) free(ix->mta); + if (ix->actChan != NULL) free(ix->actChan); + if (ix->chansOutstanding != NULL) free(ix->chansOutstanding); + if (ix -> info != NULL) free(ix->info); + free((char *) ix->status); + temp = ix; + ix = ix->next; + free((char *) temp); + } +} + +/* */ + +struct recip *find_recip(msg, id) +struct msg_struct *msg; +int id; +{ + struct recip *ix; + if (msg == NULL) + return NULL; + ix = msg->reciplist; + + while (ix != NULL + && ix -> id != id) + ix = ix->next; + return ix; +} + +struct msg_struct *find_msg(qid) +char *qid; +{ + int i = 0; + + while ((i < number_msgs) && + (strcmp(global_msg_list[i]->msginfo->queueid,qid) != 0)) + i++; + + if (i >= number_msgs) + return NULL; + else + return global_msg_list[i]; +} + +extern char *re_comp(); +extern int re_exec(); + +int find_msg_regex(name) +char *name; +{ + int i = 0; + char *diag; + + if ((diag = re_comp(name)) != 0) { + fprintf(stderr, + "re_comp error for '%s' [%s]\n", name, diag); + return 0; + } + + if (msg_matches) { + free(msg_matches); + msg_matches = NULL; + } + + msg_matches = (struct msg_struct **) calloc(number_msgs, + sizeof(struct msg_struct *)); + + for (i = 0, msg_num_matches = 0; i < number_msgs; i++) + if (re_exec(lowerfy(global_msg_list[i]->msginfo->queueid)) == 1) + msg_matches[msg_num_matches++] = global_msg_list[i]; + + return msg_num_matches; +} + +msg_set_current_regex() +{ + int cont = TRUE, quit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (msg_match == NULLCP) ? "" : msg_match); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + } + compress(buf, buf); + + if (emptyStr(buf) && msg_match == NULLCP) + fprintf(stdout, "no match set\n"); + else { + if (!emptyStr(buf)) { + if (lexequ(buf, "q") != 0) { + if (msg_match) free(msg_match); + msg_match = strdup(buf); + } else + quit = TRUE; + } + cont = FALSE; + } + } + if (quit == TRUE) + return NOTOK; + if (find_msg_regex(msg_match) == 0) { + fprintf(stdout, "unable to find match for '%s'\n", + msg_match); + return NOTOK; + } + return OK; +} + +msg_set_current() +{ + int cont = TRUE, i, quit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (msg_match == NULL) ? "" : msg_match); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + } + compress(buf, buf); + + if (emptyStr(buf) && msg_match == NULLCP) + fprintf(stdout, "no match set\n"); + else if (!emptyStr(buf) && lexequ(buf, "q") == 0) { + quit = TRUE; + cont = FALSE; + } else { + char *exp = (emptyStr(buf)) ? msg_match : buf; + int num = find_msg_regex(exp); + switch (num) { + case 0: + fprintf(stdout, "unable to find match for '%s'\n", exp); + break; + case 1: + cont = FALSE; + if (exp != msg_match) { + if (msg_match) free(msg_match); + msg_match = strdup(exp); + } + break; + default: + fprintf(stdout, "'%s' matches %d possible msgs (", + exp, num); + for (i = 0; i < num; i++) + fprintf(stdout, "%s%s", + msg_matches[i]->msginfo->queueid, + (i == num -1) ? "" : ","); + fprintf(stdout, ")\n\tneed unqiue msg\n"); + break; + } + } + } + if (quit == TRUE) + return NOTOK; + return OK; +} + +/* */ + +msg_next() +{ + if (global_msg_list) { + int i = 0; + + if (msg_num_matches > 0) { + while (i < number_msgs && + msg_matches[0] != global_msg_list[i]) + i++; + if (i >= number_msgs - 1) + i = 0; + else + i++; + } + if (msg_match) free(msg_match); + msg_match = strdup(global_msg_list[i]->msginfo->queueid); + find_msg_regex(msg_match); + } +} + +msg_previous() +{ + if (global_msg_list) { + int i = number_msgs - 1; + + if (msg_num_matches > 0) { + while (i <= 0 && + msg_matches[0] != global_msg_list[i]) + i--; + if (i <= 0) + i = number_msgs - 1; + else + i--; + } + if (msg_match) free(msg_match); + msg_match = strdup(global_msg_list[i]->msginfo->queueid); + find_msg_regex(msg_match); + } +} + +/* */ + + +msg_control(op, msg, usrs, mytime) +Operations op; +char *msg, *usrs, *mytime; +{ + + /* arg1 = QID arg2 = time arg3 = control arg4.. = userlist */ + char *usrlist[100], **args; + int numberUsrs, i = 0, ix; + + numberUsrs = sstr2arg(usrs, 100, usrlist, ","); + + args = (char **) calloc((unsigned)(4+numberUsrs), sizeof(char *)); + args[0] = msg; + args[1] = mytime; + args[2] = (char *) op; + ix = 3; + while(i < numberUsrs && ix < (3+numberUsrs)) + args[ix++] = usrlist[i++]; + my_invoke(op, args); + free((char *) args); +} + +msg_enable_regex() +{ + int cont, i = 0, ucont; + char buf[BUFSIZ], users[BUFSIZ]; + users[0] = '\0'; + + if (msg_num_matches > 0) { + if (msg_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (msg_num_matches == 1) { + fprintf(stdout, "enabling '%s'.\n", + msg_matches[i]->msginfo->queueid); + buf[0] = 'y'; + } else { + fprintf(stdout, "enable '%s' (y/n/q) ?", + msg_matches[i]->msginfo->queueid); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + ucont = TRUE; + while (ucont == TRUE) { + fprintf(stdout, "User list (,) (*=all) = "); + fflush(stdout); + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (users[0] != '\0') + ucont = FALSE; + else + fprintf(stdout, "no user list given\n"); + } else { + ucont = FALSE; + strcpy(users, buf); + } + } + msg_control(msgstart, + msg_matches[i]->msginfo->queueid, + users, NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = msg_num_matches; + default: + break; + } + } + } + } +} + +msg_disable_regex() +{ + int cont, i = 0, ucont; + char buf[BUFSIZ], users[BUFSIZ]; + users[0] = '\0'; + + if (msg_num_matches > 0) { + if (msg_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (msg_num_matches == 1) { + fprintf(stdout, "disabling '%s'.\n", + msg_matches[i]->msginfo->queueid); + buf[0] = 'y'; + } else { + fprintf(stdout, "disable '%s' (y/n/q) ?", + msg_matches[i]->msginfo->queueid); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + ucont = TRUE; + while (ucont == TRUE) { + fprintf(stdout, "User list (,) (*=all) = "); + fflush(stdout); + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (users[0] != '\0') + ucont = FALSE; + else + fprintf(stdout, "no user list given\n"); + } else { + ucont = FALSE; + strcpy(users, buf); + } + } + msg_control(msgstop, + msg_matches[i]->msginfo->queueid, + users, NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = msg_num_matches; + default: + break; + } + } + } + } +} + + +msg_clear_regex() +{ + int cont, i = 0, ucont; + char buf[BUFSIZ], users[BUFSIZ]; + users[0] = '\0'; + + if (msg_num_matches > 0) { + if (msg_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (msg_num_matches == 1) { + fprintf(stdout, "clearing '%s'.\n", + msg_matches[i]->msginfo->queueid); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear '%s' (y/n/q) ?", + msg_matches[i]->msginfo->queueid); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + ucont = TRUE; + while (ucont == TRUE) { + fprintf(stdout, "User list (,) (*=all) = "); + fflush(stdout); + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (users[0] != '\0') + ucont = FALSE; + else + fprintf(stdout, "no user list given\n"); + } else { + ucont = FALSE; + strcpy(users, buf); + } + } + msg_control(msgclear, + msg_matches[i]->msginfo->queueid, + users, NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = msg_num_matches; + default: + break; + } + } + } + } +} + +msg_clear_above_regex() +{ + int cont, i = 0, above = FALSE; + char buf[BUFSIZ]; + + if (msg_num_matches > 0) { + if (msg_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (msg_num_matches == 1) { + fprintf(stdout, "clearing entities above '%s'.\n", + msg_matches[i]->msginfo->queueid); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear entities above '%s' (y/n/q) ?", + msg_matches[i]->msginfo->queueid); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + msg_force(msg_matches[i]); + above = TRUE; + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = msg_num_matches; + default: + break; + } + } + } + if (above == TRUE) + mta_clear_above_regex(); + } +} + +msg_force (msg) +struct msg_struct *msg; +{ + char **args = NULL; + + int numberUsrs = 0, force; + int ix; + struct recip *temp; + if (msg == NULL + || msg->msginfo == NULL) return; + + for (temp = msg->reciplist, numberUsrs = 0; + temp != NULL; temp = temp -> next, numberUsrs++) + continue; + + args = (char **) calloc((unsigned)(4+numberUsrs), sizeof(char *)); + args[0] = msg->msginfo->queueid; + args[1] = NULL; + + ix = 3; + force = FALSE; + for (temp = msg->reciplist; temp != NULL; temp = temp -> next) + if (temp->status + && temp->status->enabled != TRUE) { + args[ix++] = itoa(temp->id); + force = TRUE; + } + if (force == TRUE) { + args[ix] = NULLCP; + args[2] = (char *) msgstart; + my_invoke(msgstart, args); + } + + ix = 3; + force = FALSE; + + for (temp = msg->reciplist; temp != NULL; temp = temp -> next) + if (temp->status + && temp->status->cachedUntil != 0) { + args[ix++] = itoa(temp->id); + force = TRUE; + } + if (force == TRUE) { + args[ix] = NULLCP; + args[2] = (char *) msgclear; + my_invoke(msgstart, args); + } + for (ix = 3; args[ix] != NULLCP && ix < 4+numberUsrs; ix++) + free (args[ix]); + free((char *) args); +} + +msg_delay_regex() +{ + int cont, i = 0, ucont, dcont; + char buf[BUFSIZ], users[BUFSIZ], delay[BUFSIZ]; + users[0] = '\0'; + delay[0] = '\0'; + + if (msg_num_matches > 0) { + if (msg_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + msg_match, msg_num_matches); + for (i = 0; i < msg_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (msg_num_matches == 1) { + fprintf(stdout, "delaying '%s'.\n", + msg_matches[i]->msginfo->queueid); + buf[0] = 'y'; + } else { + fprintf(stdout, "delay '%s' (y/n/q) ?", + msg_matches[i]->msginfo->queueid); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + ucont = TRUE; + while (ucont == TRUE) { + fprintf(stdout, "User list (,) (*=all) = "); + fflush(stdout); + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (users[0] != '\0') + ucont = FALSE; + else + fprintf(stdout, "no user list given\n"); + } else { + ucont = FALSE; + strcpy(users, buf); + } + } + dcont = TRUE; + while (dcont == TRUE) { + fprintf(stdout, "Delay (in s m h d and/or w) = "); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + compress(buf, buf); + if (emptyStr(buf)) { + if (delay[0] != '\0') + dcont = FALSE; + else + fprintf(stdout, "no user list given\n"); + } else { + dcont = FALSE; + strcpy(delay, buf); + } + } + msg_control(msgcacheadd, + msg_matches[i]->msginfo->queueid, + users, delay); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = msg_num_matches; + default: + break; + } + } + } + } +} + +struct type_Qmgr_UserList *create_userlist(qid, argv) +char *qid, + **argv; +{ + struct type_Qmgr_UserList *temp, + *head = NULL, + *tail = NULL; + int i = 0; + struct msg_struct *msg; + struct recip *ix; + + if (strcmp(argv[i], "*") == 0) { + if ((msg = find_msg(qid)) == NULL) + return NULL; + ix = msg -> reciplist; + while (ix != NULL) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) + malloc(sizeof(struct type_Qmgr_RecipientId)); + temp->RecipientId->parm = ix -> id; + ix = ix -> next; + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = tail->next; + } + } + } else { + while (argv[i] != NULL) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) + malloc(sizeof(struct type_Qmgr_RecipientId)); + temp->RecipientId->parm = atoi(argv[i++]); + + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = tail->next; + } + } + } + return head; +} + +/* ARGSUSED */ +int do_msgcontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_MsgControl **arg; +/* args[0] = qid */ +/* args[1] = time */ +/* args[2] = stop, start, clear cacheadd*/ +/* args[3..] = NULL terminated list of users */ +{ + char *timestr; + *arg = (struct type_Qmgr_MsgControl *) malloc(sizeof(**arg)); + + (*arg)->qid = str2qb(args[0], + strlen(args[0]), + 1); + + (*arg)->users = create_userlist(args[0], &(args[3])); + + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + switch ((Operations) args[2]) { + case msgstart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case msgstop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case msgclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case msgcacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[1]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for msgs", + args[1])); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +msgcontrol_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +struct type_Qmgr_Pseudo__newmessage *result; +struct RoSAPindication *roi; +{ + return OK; +} diff --git a/Src/LINEconsole/mtas.c b/Src/LINEconsole/mtas.c new file mode 100644 index 0000000..8d9a672 --- /dev/null +++ b/Src/LINEconsole/mtas.c @@ -0,0 +1,1089 @@ +/* mtas.c: mta routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/mtas.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/mtas.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: mtas.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +char *mta_match = NULLCP; +int mta_num_matches = 0; +struct mta_struct **mta_matches = NULL; + +extern int connected; +extern struct procStatus *create_status(); +extern struct chan_struct *currentchan, *find_channel(); +extern char *time_t2RFC(), *vol2str(), *time_t2str(), *cmd_argv[], + *itoa(), *mystrtotime(); +extern int total_number_reports, total_number_messages, total_volume, compat, + cmd_argc; + +#define MTA_READ_INTERVAL 60 /* in secs */ + +extern struct msg_struct **global_msg_list; +extern int number_msgs; + +static void display_mta_list(); +static void update_mta_list(); +static struct mta_struct **create_mta_list(); +static struct mta_struct *create_mta(); + +extern Level lev; +extern int info_shown; + +struct mta_struct *currentmta = NULL, *find_mta(); + +/* ARGSUSED */ +int do_mtaread (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; /* args[0] is channel name */ +struct type_Qmgr_MtaRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MtaRead *) malloc(sizeof(**arg)); + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MTA_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); +} + + +/* ARGSUSED */ +int mtaread_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_PrioritisedMtaList *result; +struct RoSAPindication *roi; +{ + + struct chan_struct *chan = currentchan; + + + free_mta_list(&(chan->mtalist), &(chan->num_mtas)); + chan->mtalist = NULL; + chan->num_mtas = 0; + if (result != NULL) + update_mta_list(result, chan); + else + update_channel_from_mtas(chan, 0, 0, 0, 0); + order_mtas(&(chan->mtalist),chan->num_mtas); + return OK; +} + +mta_list() +{ + if (connected == TRUE && currentchan != NULL) { + my_invoke(mtaread, &(currentchan->channelname)); + display_mta_list(currentchan); + } +} + +mta_do_refresh () +{ + if (connected == TRUE) { + channel_do_refresh(); + if (currentchan != NULL) { + my_invoke(mtaread, &(currentchan->channelname)); + if (mta_match) + find_mta_regex(currentchan, mta_match); + reset_prompt_regex(); + + if (lev == mta) { + if (mta_num_matches > 0 && info_shown == TRUE) + mta_info_regex(); + else + display_mta_list(currentchan); + } + } + } +} + +/* */ + +clear_mta_level() +{ + if (currentchan) { + free_mta_list(&(currentchan->mtalist), &(currentchan->num_mtas)); + currentchan->mtalist = NULL; + currentchan->num_mtas = 0; + } + currentmta = NULL; +} + +free_mta_list(plist, pnum) +struct mta_struct ***plist; +int *pnum; +{ + int i = 0; + + while(i < (*pnum)){ + if ((*plist) [i] != NULL) { + free((*plist)[i]->mta); + if ((*plist)[i]->info != NULLCP) + free((*plist)[i] -> info); + free((char *) (*plist)[i]->status); + } + i++; + } + if (*plist != NULL) + free((char *) (*plist)); + *plist = NULL; + *pnum = 0; +} + +static void update_mta_list(new, chan) +struct type_Qmgr_PrioritisedMtaList *new; +struct chan_struct *chan; +{ + int numberMsgs = 0, + numberDrs = 0, + numberMtas = 0, + volume = 0; + chan->mtalist = create_mta_list(new,&numberMtas, + &numberDrs,&numberMsgs,&volume, + chan); + update_channel_from_mtas(chan, numberMsgs, numberDrs, numberMtas, volume); +} + +static struct mta_struct **create_mta_list(list, pnum, pdr, pmsgnum, pvolume, chan) +struct type_Qmgr_PrioritisedMtaList *list; +int *pnum, + *pdr, + *pmsgnum, + *pvolume; +struct chan_struct *chan; +{ + struct type_Qmgr_PrioritisedMtaList *ix = list; + struct mta_struct **mtalist; + int i; + while (ix != NULL) { + (*pnum)++; + + ix = ix->next; + } + + mtalist = (struct mta_struct **) calloc( (unsigned)(*pnum), + sizeof(struct mta_struct *)); + + ix = list; + i = 0; + *pmsgnum = 0; + *pdr = 0; + + while ((ix != NULL) + && ( i < (*pnum))) { + mtalist[i] = create_mta(ix->PrioritisedMta, chan); + *pmsgnum += mtalist[i]->numberMessages; + *pdr += mtalist[i]->numberReports; + *pvolume += mtalist[i]->volumeMessages; + i++; + ix = ix->next; + } + return mtalist; +} + +static struct mta_struct *create_mta(themta, chan) +struct type_Qmgr_PrioritisedMta *themta; +struct chan_struct *chan; +{ + struct mta_struct *temp; + struct type_Qmgr_MtaInfo *info = themta->mta; + + temp = (struct mta_struct *) malloc(sizeof(*temp)); + + temp->mta = qb2str(info->mta); + temp->oldestMessage = convert_time(info->oldestMessage); + temp->numberMessages = info->numberMessage; + temp->numberReports = info->numberDRs; + temp->volumeMessages = info->volumeMessages; + temp->status = create_status(info->status); + temp->priority = themta->priority->parm; + temp->active = info->active; + if (info -> info != NULL) + temp -> info = qb2str(info -> info); + else + temp -> info = NULLCP; + add_tailor_to_mta(chan, temp); + return temp; +} + +update_mta(old, info) +struct mta_struct *old; +struct type_Qmgr_MtaInfo *info; +{ + /* name doesn't change */ + old->oldestMessage = convert_time(info->oldestMessage); + old->numberMessages = info->numberMessage; + old->numberReports = info->numberDRs; + old->volumeMessages = info->volumeMessages; + old->active = info->active; + if (old -> info) + free (old -> info); + if (info -> info != NULL) + old -> info = qb2str(info -> info); + else + old -> info = NULLCP; + update_status(old->status,info->status); +} + +update_channel_from_mtas(chan, nmsgs, ndrs, nmtas, volume) +struct chan_struct *chan; +int nmsgs, + ndrs, + nmtas, + volume; +{ + int changed = FALSE; + + if (chan -> numberMessages != nmsgs) { + if (compat) + total_number_messages + += nmsgs - chan -> numberMessages; + chan -> numberMessages = nmsgs; + changed = TRUE; + } + + if (chan -> numberReports != ndrs) { + if (compat) + total_number_reports += ndrs - chan -> numberReports; + chan -> numberReports = ndrs; + changed = TRUE; + } + + if (chan -> num_mtas != nmtas) { + chan -> num_mtas = nmtas; + changed = TRUE; + } + if (chan -> volumeMessages != volume) { + if (compat) + total_volume += volume - chan -> volumeMessages; + chan -> volumeMessages = volume; + changed = TRUE; + } + + if (chan->given_num_mtas != chan -> num_mtas) { + chan -> given_num_mtas = chan->num_mtas; + changed = TRUE; + } +} + + +/* */ +extern int uk_order; +extern char *reverse_mta(); +extern FILE *out; + +static void display_mta(mta) +struct mta_struct *mta; +{ + char str[BUFSIZ]; + char *ch; + + ch = (uk_order)? reverse_mta(mta->mta) : mta->mta; + sprintf(str, "%s %s: %d",ch, + (mta -> active) ? "(ACTIVE)" : "", + mta->numberMessages); + if (uk_order && ch != mta->mta) free(ch); + if (mta->numberReports != 0) + sprintf(str, "%s + %d", str, mta->numberReports); + if (mta->status->enabled != TRUE) + sprintf(str, "%s (DISABLED)", str); + fprintf(out, "%s\n", str); +} + +display_mta_info(chan,mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + char *str, + *info_str, + *ch; + int info_strlen = BUFSIZ; + char tmpbuf[BUFSIZ]; + info_str = calloc(1, (unsigned) info_strlen); + + ch = (uk_order) ? reverse_mta(mta->mta) : mta->mta; + + sprintf(tmpbuf, "on channel '%s'", chan->channelname); + sprintf(info_str, ssformat, tab, + ch, tmpbuf); + + if (uk_order && ch != mta->mta) + free(ch); + + if (mta->status->cachedUntil != 0) { + str = time_t2RFC(mta->status->cachedUntil); + sprintf(info_str, plus_ssformat, info_str, tab, + "delayed until", + str); + free(str); + } + if (mta->info != NULLCP) + sprintf (info_str, plus_ssformat, info_str, tab, + "error info", + mta -> info); + + str = time_t2str(time((time_t *) 0) - mta->oldestMessage); + sprintf(info_str, plus_ssformat, info_str, tab, + "oldest message", + str); + free(str); + + str = itoa(mta->numberMessages); + sprintf(info_str, plus_ssformat, info_str, tab, + "number of messages", + str); + free(str); + + if (mta->numberReports != 0) { + str = itoa(mta->numberReports); + sprintf(info_str, plus_ssformat, info_str, tab, + "number of drs", + str); + free(str); + } + + str = vol2str(mta->volumeMessages); + sprintf(info_str, plus_ssformat, info_str, tab, + "volume of messages", + str); + free(str); + + if (mta -> active) + sprintf(info_str, plus_ssformat, info_str, tab, + "active", + "processes running"); + + sprintf(info_str, plus_ssformat, info_str, tab, + "status", + (mta->status->enabled == TRUE) ? "enabled" : "disabled"); + if (mta->status->lastAttempt != 0) { + str = time_t2RFC(mta->status->lastAttempt); + sprintf(info_str, plus_ssformat, info_str, tab, + "last attempt", + str); + free(str); + } + if (mta->status->lastSuccess != 0) { + str = time_t2RFC(mta->status->lastSuccess); + sprintf(info_str, plus_ssformat, info_str, tab, + "last success", + str); + free(str); + } + + switch (mta->priority) { + case int_Qmgr_Priority_low: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "low"); + break; + case int_Qmgr_Priority_normal: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "normal"); + break; + case int_Qmgr_Priority_high: + sprintf(info_str, plus_ssformat, info_str, tab, + "priority", + "high"); + break; + default: + break; + } + + fprintf(out, "%s", info_str); + free(info_str); +} + +mta_info_regex() +{ + int i; + if (currentchan && mta_num_matches > 0) { + openpager(); + if (mta_num_matches > 1) + fprintf(out, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + display_mta_info(currentchan, mta_matches[i]); + fprintf(out, "\n"); + } + closepager(); + } +} + +static void display_mta_list(chan) +struct chan_struct *chan; +{ + int i; + + openpager(); + + for (i = 0; i < chan->num_mtas; i++) + display_mta(chan->mtalist[i]); + closepager(); +} + +/* */ + +struct mta_struct *find_mta(chan, name) +struct chan_struct *chan; +char *name; +{ + int i = 0; + while ((i < chan->num_mtas) && + (strcmp(chan->mtalist[i]->mta, name) != 0)) + i++; + if (i >= chan->num_mtas) + return NULL; + else + return chan->mtalist[i]; +} + +extern char *re_comp(); +extern int re_exec(); + +int find_mta_regex(chan, name) +struct chan_struct *chan; +char *name; +{ + int i = 0; + char *diag; + + if ((diag = re_comp(name)) != 0) { + fprintf(stderr, + "re_comp error for '%s' [%s]\n", name, diag); + return 0; + } + + if (mta_matches) { + free(mta_matches); + mta_matches = NULL; + } + mta_matches = (struct mta_struct **) calloc(chan->num_mtas, + sizeof(struct mta_struct *)); + + for (i = 0, mta_num_matches = 0; i < chan->num_mtas; i++) + if (re_exec(lowerfy(chan->mtalist[i]->mta)) == 1) + mta_matches[mta_num_matches++] = chan->mtalist[i]; + + return mta_num_matches; +} + +mta_set_current_regex() +{ + int cont = TRUE, quit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (mta_match == NULLCP) ? "" : mta_match); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + } + compress(buf, buf); + + if (emptyStr(buf) && mta_match == NULLCP) + fprintf(stdout, "no match set\n"); + else { + if (!emptyStr(buf)) { + if (lexequ(buf, "q") != 0) { + if (mta_match) free(mta_match); + mta_match = strdup(buf); + } else + quit = TRUE; + } + cont = FALSE; + } + } + if (quit == TRUE) + return NOTOK; + if (find_mta_regex(currentchan, mta_match) == 0) { + fprintf(stdout, "unable to find match for '%s'\n", + mta_match); + return NOTOK; + } + return OK; +} + +mta_set_current() +{ + int cont = TRUE, i, quit = FALSE, first = TRUE; + char buf[BUFSIZ]; + + if (currentchan == NULL) + channel_set_current(); + + while (cont == TRUE) { + if (cmd_argc > 1 && first == TRUE) { + strcpy(buf, cmd_argv[1]); + first = FALSE; + } else { + fprintf(stdout, "match expression (%s) (q=quit) = ", + (mta_match == NULL) ? "" : mta_match); + fflush(stdout); + + if (gets(buf) == NULL) + exit (OK); + } + compress(buf, buf); + + if (emptyStr(buf) && mta_match == NULLCP) + fprintf(stdout, "no match set\n"); + else if (!emptyStr(buf) && lexequ(buf, "q") == 0) { + quit = TRUE; + cont = FALSE; + } else { + char *exp = (emptyStr(buf)) ? mta_match : buf; + int num = find_mta_regex(currentchan, exp); + switch (num) { + case 0: + fprintf(stdout, "unable to find match for '%s'\n", exp); + break; + case 1: + cont = FALSE; + if (exp != mta_match) { + if (mta_match) free(mta_match); + mta_match = strdup(exp); + } + currentmta = mta_matches[0]; + break; + default: + fprintf(stdout, "'%s' matches %d possible mtas (", + exp, num); + for (i = 0; i < num; i++) + fprintf(stdout, "%s%s", + mta_matches[i]->mta, + (i == num -1) ? "" : ","); + fprintf(stdout, ")\n\tneed unqiue mta\n"); + break; + } + } + } + if (quit == TRUE) + return NOTOK; + return OK; +} + + +/* */ + +mta_next () +{ + if (currentchan && currentchan -> num_mtas > 0) { + int i = 0; + if (mta_num_matches > 0) { + while (i < currentchan -> num_mtas && + currentchan->mtalist[i] != mta_matches[0]) + i++; + if (i >= currentchan -> num_mtas - 1) + i = 0; + else + i++; + } + if (mta_match) free(mta_match); + mta_match = strdup(currentchan->mtalist[i]->mta); + find_mta_regex(currentchan, mta_match); + } +} + +mta_previous () +{ + if (currentchan && currentchan -> num_mtas > 0) { + int i = currentchan -> num_mtas - 1; + if (mta_num_matches > 0) { + while (i >= 0 && + currentchan->mtalist[i] != mta_matches[0]) + i--; + if (i <= 0) + i = currentchan -> num_mtas - 1; + else + i--; + } + if (mta_match) free(mta_match); + mta_match = strdup(currentchan -> mtalist[i]-> mta); + find_mta_regex(currentchan, mta_match); + } +} + +/* */ + + +mta_control(op, chan, mta, mytime) +Operations op; +char *chan, *mta, *mytime; +{ + char *args[4]; + args[0] = chan; + args[1] = mta; + args[2] = (char *) op; + args[3] = mytime; + my_invoke(op, args); +} + +mta_enable_regex() +{ + int cont, i = 0; + char buf[BUFSIZ]; + + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "enabling '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "enable '%s' (y/n/q) ?", + mta_matches[i]->mta); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + mta_control(mtastart, + currentchan->channelname, + mta_matches[i]->mta, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + } +} + +mta_disable_regex() +{ + int cont, i = 0; + char buf[BUFSIZ]; + + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "disabling '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "disable '%s' (y/n/q) ?", + mta_matches[i]->mta); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + mta_control(mtastop, + currentchan->channelname, + mta_matches[i]->mta, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + } +} + +mta_clear_regex() +{ + int cont, i = 0; + char buf[BUFSIZ]; + + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "clearing '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear '%s' (y/n/q) ?", + mta_matches[i]->mta); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + mta_control(mtaclear, + currentchan->channelname, + mta_matches[i]->mta, + NULLCP); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + } +} + +mta_force (chan, mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + if (mta->status->enabled != TRUE) + mta_control(mtastart, chan->channelname, + mta->mta, NULLCP); + if (mta->status->cachedUntil != 0) + mta_control(mtaclear, chan->channelname, + mta->mta, NULLCP); + +} + +mta_clear_below_regex() +{ + int cont, i = 0; + char buf[BUFSIZ]; + + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "clearing entities below '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear entities below '%s' (y/n/q) ?", + mta_matches[i]->mta); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + mta_downforce(currentchan, + mta_matches[i]); + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + } +} + +mta_clear_above_regex() +{ + int cont, i = 0, above = FALSE; + char buf[BUFSIZ]; + + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "clearing entities above '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "clear entities above '%s' (y/n/q) ?", + mta_matches[i]->mta); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + mta_force(currentchan, + mta_matches[i]); + above = TRUE; + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + if (above == TRUE) + channel_force(currentchan); + + } +} + +mta_downforce_list (chan) +struct chan_struct *chan; +{ + int i; + for (i = 0; i < chan->num_mtas; i++) + mta_downforce(chan, chan->mtalist[i]); +} + +mta_downforce (chan, mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + struct msg_struct **oldlist; + int oldnum; + char *args[2]; + + args[0] = chan -> channelname; + args[1] = mta->mta; + oldlist = global_msg_list; + oldnum = number_msgs; + global_msg_list = NULL; + number_msgs = 0; + currentmta = mta; + my_invoke(readchannelmtamessage, args); + msg_force_list(global_msg_list); + currentmta = NULL; + free_msg_list(); + global_msg_list = oldlist; + number_msgs = oldnum; + + mta_force(chan, mta); +} + +mta_delay_regex() +{ + int dcont, cont, i = 0; + char buf[BUFSIZ], delay[BUFSIZ]; + delay[0] = '\0'; + if (currentchan && mta_num_matches > 0) { + if (mta_num_matches > 1) + fprintf(stdout, "%s: %d matches\n\n", + mta_match, mta_num_matches); + for (i = 0; i < mta_num_matches; i++) { + cont = TRUE; + while (cont == TRUE) { + if (mta_num_matches == 1) { + fprintf(stdout, "delaying '%s'.\n", + mta_matches[i]->mta); + buf[0] = 'y'; + } else { + fprintf(stdout, "delay '%s' (y/n/q) ?", + mta_matches[i]->mta); + fflush(stdout); + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + } + switch(buf[0]) { + case 'y': + case 'Y': + dcont = TRUE; + while (dcont == TRUE) { + fprintf(stdout, "Delay (in s m h d and/or w) [%s] = "); + fflush(stdout); + + if (gets(buf) == NULL) + exit(OK); + compress(buf, buf); + + if (emptyStr(buf)) { + if (delay[0] != '\0') + /* happy with the one we got */ + dcont = FALSE; + else + fprintf(stdout, "no delay given\n"); + } else { + dcont = FALSE; + strcpy(delay, buf); + } + } + mta_control(mtacacheadd, + currentchan->channelname, + mta_matches[i]->mta, + delay); + + case 'n': + case 'N': + cont = FALSE; + break; + case 'q': + case 'Q': + cont = FALSE; + i = mta_num_matches; + default: + break; + } + } + } + } +} + +/* ARGSUSED */ +int do_mtacontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_MtaControl **arg; +/* args[0] = channel */ +/* args[1] = mta */ +/* args[2] = stop,start,clear,cacheadd */ +/* args[3] = time */ +{ + char *timestr; + *arg = (struct type_Qmgr_MtaControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + (*arg)->mta = str2qb(args[1], + strlen(args[1]), + 1); + + switch ((Operations) args[2]) { + case mtastart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case mtastop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case mtaclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case mtacacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[3]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for mtas", + args[2])); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +int mtacontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_MtaInfo *result; +struct RoSAPindication *roi; +{ + char *chan_name, + *name; + struct chan_struct *chan; + struct mta_struct *mta; + + chan_name = qb2str(result->channel); + chan = find_channel(chan_name); + + if (chan == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: mtacontrol_result can't find channel %s",chan_name)); + return NOTOK; + } + + name = qb2str(result->mta); + mta = find_mta(chan, name); + + if (mta == NULL) { +#ifdef not_ipm_yet + if (forceDown == TRUE) { + free(chan_name); + free(name); + return OK; + } +#endif + PP_LOG(LLOG_EXCEPTIONS, + ("console:can not find mta %s on channel %s", + name, chan_name)); + abort(); + } else { + update_mta(mta,result); + } + order_mtas(&(chan->mtalist),chan->num_mtas); + free(chan_name); + free(name); + return OK; +} diff --git a/Src/LINEconsole/status.c b/Src/LINEconsole/status.c new file mode 100644 index 0000000..cb2189e --- /dev/null +++ b/Src/LINEconsole/status.c @@ -0,0 +1,151 @@ +/* status.c: status routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/status.c,v 6.0 1991/12/18 20:26:30 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/status.c,v 6.0 1991/12/18 20:26:30 jpo Rel $ + * + * $Log: status.c,v $ + * Revision 6.0 1991/12/18 20:26:30 jpo + * Release 6.0 + * + */ + +#include "console.h" + +time_t convert_time(qb) +struct type_UNIV_UTCTime *qb; +{ + char *str; + time_t temp; + if (qb == NULL) + return 0; + str = qb2str(qb); + temp = utc2time_t(str2utct(str, strlen(str))); + free(str); + return temp; +} + +struct procStatus *create_status(status) +struct type_Qmgr_ProcStatus *status; +{ + struct procStatus *temp; + + temp = (struct procStatus *) malloc(sizeof(*temp)); + + temp->enabled = status->enabled; + temp->lastAttempt = convert_time(status->lastAttempt); + temp->cachedUntil = convert_time(status->cachedUntil); + temp->lastSuccess = convert_time(status->lastSuccess); + return temp; +} + +void update_status(old, new) +struct procStatus *old; +struct type_Qmgr_ProcStatus *new; +{ + time_t tmp; + old->enabled = new->enabled; + + old->lastAttempt = convert_time(new->lastAttempt); + + old->cachedUntil = convert_time(new->cachedUntil); + + if ((tmp = convert_time(new->lastSuccess)) != 0) + old->lastSuccess = tmp; +} + +/* */ + +extern FILE *out; +extern int connected; +extern int total_volume, total_number_messages, total_number_reports; +extern char *time_t2RFC(); + +time_t boottime = 0; +int messagesIn = 0, messagesOut = 0, addrIn = 0, addrOut = 0, + maxChans = 0, currChans = 0; +double opsPerSec = 0.0, runnableChans = 0.0, + msgsInPerSec = 0.0, msgsOutPerSec = 0.0; +int compat = FALSE; +extern int authorised; +char *Qversion = NULLCP, *Qinformation = NULLCP; +extern char *actual_host; + +print_status() +{ + char buf[BUFSIZ]; + openpager(); + + if (connected == FALSE) + fprintf(out, "Unconnected\n"); + else { + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + /* connected */ + fprintf(out, "Connected to %s%s\n", (Qinformation) ? Qinformation : actual_host, + (authorised == TRUE) ? " with full access" : ""); + + if (Qversion) + fprintf(out, "running %s\n", Qversion); + if (total_volume != 0 + && (total_number_messages != 0 + || total_number_reports != 0)) { + num2unit(total_volume, buf); + fprintf(out, "Total Volume = %s\n", buf); + + fprintf(out,"%d msg%s + %d report%s\n", + total_number_messages, + (total_number_messages == 1) ? "" : "s", + total_number_reports, + (total_number_reports == 1) ? "" : "s"); + } + if (!compat) { +#define NUMBUF 15 + char adIn[NUMBUF], mgIn[NUMBUF], adOut[NUMBUF], mgOut[NUMBUF], *str; + str = time_t2RFC(boottime); + num2unit(addrIn, adIn); + num2unit(messagesIn, mgIn); + num2unit(addrOut, adOut); + num2unit(messagesOut, mgOut); + fprintf(out, "running since %s\nInbound %s Message%s to %s Recipient%s\nOutbound %s Message%s to %s Recipient%s\n", + str, mgIn, (messagesIn != 1) ? "s" : "", + adIn, (addrIn != 1) ? "s" : "", + mgOut, (messagesOut != 1) ? "s" : "", + adOut, (addrOut != 1) ? "s" : ""); + free(str); + } else + fprintf(out, "Running in 5.0 compatability mode\n"); + } + closepager(); +} + +/* ARGSUSED */ +int qmgrStatus_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_QmgrStatus *result; +struct RoSAPindication *roi; +{ + if (result) { + if (result->boottime) + boottime = convert_time(result->boottime); + messagesIn = result->messagesIn; + messagesOut = result->messagesOut; + addrIn = result->addrIn; + addrOut = result->addrOut; + opsPerSec = (double) result->opsPerSec; + runnableChans = (double) result->runnableChans; + msgsInPerSec = (double) result->msgsInPerSec; + msgsOutPerSec = (double) result->msgsOutPerSec; + maxChans = result->maxChans; + currChans = result->currChans; + total_volume = result->totalVolume; + total_number_messages = result->totalMsgs; + total_number_reports = result->totalDrs; + } + return OK; +} diff --git a/Src/LINEconsole/tai_defs.inc b/Src/LINEconsole/tai_defs.inc new file mode 100644 index 0000000..d5440c2 --- /dev/null +++ b/Src/LINEconsole/tai_defs.inc @@ -0,0 +1,31 @@ +#define default_mtsin_chan "mtsin-chan:last<2h" +#define default_mtsin_mta "mtsin-mta:last<2h" +#define default_mtsin_msg "mtsin-msg:last<2h" + +#define default_mtsout_chan "mtsout-chan:age<2h,num<500,vol<1M,last<2h" +#define default_mtsout_mta "mtsout-mta:age<2h,num<500,vol<1M,last<2h" +#define default_mtsout_msg "mtsout-msg:age<2h,vol<1M" + +#define default_mtsboth_chan "mtsboth-chan:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_mta "mtsboth-mta:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_msg "mtsboth-msg:age<2h,vol<1M" + +#define default_mtain_chan "mtain-chan:last<2h" +#define default_mtain_mta "mtain-mta:last<2h" +#define default_mtain_msg "mtain-msg:last<2h" + +#define default_mtaout_chan "mtaout-chan:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaout_mta "mtaout-mta:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaout_msg "mtaout-msg:age<48h,vol<10M" + +#define default_mtaboth_chan "mtaboth-chan:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaboth_mta "mtaboth-mta:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaboth_msg "mtaboth-msg:age<48h,vol<10M" + +#define default_internal_chan "internal-chan:age<20,vol<1M,num<10,last<20" +#define default_internal_mta "internal-mta:age<20,vol<1M,num<10,last<20" +#define default_internal_msg "internal-msg:age<20,vol<1M" + +#define default_passive_chan "passive-chan:age<20,vol<1M,num<10,last<20" +#define default_passive_mta "passive-mta:age<20,vol<1M,num<10,last<20" +#define default_passive_msg "passive-msg:age<20,vol<1M" diff --git a/Src/MTAconsole/.MTAconsole b/Src/MTAconsole/.MTAconsole new file mode 100644 index 0000000..cfb84b4 --- /dev/null +++ b/Src/MTAconsole/.MTAconsole @@ -0,0 +1,8 @@ +# comment +totals:num<10k,vol<1M +822-local-chan:age<1h +822-local-mta:num<10 +internal-chan:age<20,vol<1M,num<100,last<10 + + + diff --git a/Src/MTAconsole/.MTAconsole~ b/Src/MTAconsole/.MTAconsole~ new file mode 100644 index 0000000..de783b1 --- /dev/null +++ b/Src/MTAconsole/.MTAconsole~ @@ -0,0 +1,7 @@ +totals:num<10k,vol<1M +822-local-chan:age<1h +822-local-mta:num<10 +internal-chan:age<20,vol<1M,num<100,last<10 + + + diff --git a/Src/MTAconsole/Makefile b/Src/MTAconsole/Makefile new file mode 100644 index 0000000..43fe095 --- /dev/null +++ b/Src/MTAconsole/Makefile @@ -0,0 +1,226 @@ +# Makefile for MTA console - x version +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/Makefile,v 6.0 1991/12/18 20:26:48 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:26:48 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = assoc.c auto.c badness.c bops.c create.c data.c \ + display.c drive.c misc.c ops.c parse.c popup.c workops.c +# WidgetWrap.c +OBJS = assoc.o auto.o badness.o bops.o create.o data.o \ + display.o drive.o misc.o ops.o parse.o popup.o workops.o +# WidgetWrap.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LM = #/crg/users/jpo/tmp/malloc_debug/libmalloc.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -u $(INCLUDE) #-DXAW_BC +LINTLIBS = $(LINTISODE) ../../Lib/llib-lpp.ln $(LINTX) + +PROGS = xconsole + +############################################################ +# +# Building Rules +# +############################################################ + +default: default-$(X11) + +default-true: $(PROGS) + +default-false default-:; @echo "X11 not defined so not builing the MTAconsole" + +############################################################ +# +# Console +# +############################################################ + +console: xconsole +display.o: back.bit +badness.o: tai_defs.inc + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +xconsole: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LM)\ + $(LIBPP) $(LIBSYS) \ + $(LIBX) $(LM) + +############################################################ +# +# Misc stuff +# +############################################################ + +install: install-$(X11) + +install- install-false:; @echo "X11 not defined so not installing MTAconsole" + +install-true: inst-dir inst-MTAconsole; + +inst-MTAconsole: $(CMDDIR)/MTAconsole $(APPDEFAULTS)/Mtaconsole + +$(CMDDIR)/MTAconsole: xconsole + -$(BACKUP) $@ zxconsole + rm -f $@ + $(INSTALL) xconsole $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "MTAconsole installed normally"; echo "" + +$(APPDEFAULTS)/Mtaconsole: Mtaconsole.ad + -$(BACKUP) $@ zMtaconsole.ad + rm -rf $@ + $(INSTALL) Mtaconsole.ad $@ + -$(CHMOD) 444 $@ + -$(CHOWN) $(ROOTUSER) $@ + -@ls -ls $@ + -@echo "MTAconsole application defaults installed normally"; echo "" + +inst-dir: $(CMDDIR) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old $(PROGS) zxconsole + + +lint: l-console + +l-console: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +assoc.o: assoc.c +assoc.o: ../../h/util.h +assoc.o: ../../h/config.h +assoc.o: ../../h/ll_log.h +assoc.o: console.h +assoc.o: ../../h/util.h +assoc.o: ../../h/Qmgr-types.h +assoc.o: ../../h/Qmgr-ops.h +assoc.o: ../../h/qmgr.h +assoc.o: ../../h/Qmgr-types.h +assoc.o: ../../h/Qmgr-ops.h +auto.o: auto.c +auto.o: console.h +auto.o: ../../h/util.h +auto.o: ../../h/config.h +auto.o: ../../h/ll_log.h +auto.o: ../../h/Qmgr-types.h +badness.o: badness.c +badness.o: console.h +badness.o: ../../h/util.h +badness.o: ../../h/config.h +badness.o: ../../h/ll_log.h +badness.o: ../../h/Qmgr-types.h +badness.o: tai_defs.inc +bops.o: bops.c +bops.o: console.h +bops.o: ../../h/util.h +bops.o: ../../h/config.h +bops.o: ../../h/ll_log.h +bops.o: ../../h/Qmgr-types.h +create.o: create.c +create.o: console.h +create.o: ../../h/util.h +create.o: ../../h/config.h +create.o: ../../h/ll_log.h +create.o: ../../h/Qmgr-types.h +data.o: data.c +data.o: console.h +data.o: ../../h/util.h +data.o: ../../h/config.h +data.o: ../../h/ll_log.h +data.o: ../../h/Qmgr-types.h +data.o: ../../h/Qmgr-types.h +display.o: display.c +display.o: console.h +display.o: ../../h/util.h +display.o: ../../h/config.h +display.o: ../../h/ll_log.h +display.o: ../../h/Qmgr-types.h +drive.o: drive.c +drive.o: console.h +drive.o: ../../h/util.h +drive.o: ../../h/config.h +drive.o: ../../h/ll_log.h +drive.o: ../../h/Qmgr-types.h +misc.o: misc.c +misc.o: console.h +misc.o: ../../h/util.h +misc.o: ../../h/config.h +misc.o: ../../h/ll_log.h +misc.o: ../../h/Qmgr-types.h +misc.o: back.bit +ops.o: ops.c +ops.o: console.h +ops.o: ../../h/util.h +ops.o: ../../h/config.h +ops.o: ../../h/ll_log.h +ops.o: ../../h/Qmgr-types.h +ops.o: ../../h/Qmgr-types.h +parse.o: parse.c +parse.o: console.h +parse.o: ../../h/util.h +parse.o: ../../h/config.h +parse.o: ../../h/ll_log.h +parse.o: ../../h/Qmgr-types.h +popup.o: popup.c +popup.o: console.h +popup.o: ../../h/util.h +popup.o: ../../h/config.h +popup.o: ../../h/ll_log.h +popup.o: ../../h/Qmgr-types.h +workops.o: workops.c +workops.o: console.h +workops.o: ../../h/util.h +workops.o: ../../h/config.h +workops.o: ../../h/ll_log.h +workops.o: ../../h/Qmgr-types.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/MTAconsole/Mtaconsole.ad b/Src/MTAconsole/Mtaconsole.ad new file mode 100644 index 0000000..9d26a7a --- /dev/null +++ b/Src/MTAconsole/Mtaconsole.ad @@ -0,0 +1,670 @@ +Mtaconsole.normalfont: -adobe-new century schoolbook-medium-r-normal--14-* +Mtaconsole.activefont: -adobe-new century schoolbook-bold-r-normal--14-* +Mtaconsole.disabledfont: -adobe-new century schoolbook-medium-i-normal--14-* + +Mtaconsole.mtsboth_chan: last<2h,age<2h,vol<1M,num<100 + + +!configuration details + +!general +Mtaconsole*top: ChainTop +Mtaconsole*bottom: ChainTop +Mtaconsole*left: ChainLeft +Mtaconsole*right: ChainLeft +Mtaconsole*Form.borderWidth: 0 +Mtaconsole*Viewport.borderWidth: 0 +Mtaconsole*Box.borderWidth: 0 +Mtaconsole*Command.shapeStyle: oval +Mtaconsole*List.pasteBuffer: True + +#ifdef COLOR +Mtaconsole*StripChart.foreground: red +#endif + +Mtaconsole*StripChart*jumpScroll: 1 +Mtaconsole*StripChart*height: 75 +Mtaconsole*StripChart*width: 100 +Mtaconsole*runChansStripChart.minScale: 3 + +!specfic + +Mtaconsole*mainvpane.right: ChainRight +Mtaconsole*mainvpane.bottom: ChainBottom + +!command widgets + +Mtaconsole*generalCommands.showGrip: False +Mtaconsole*generalCommands.skipAdjust: True + +Mtaconsole*refreshCommand.resizable: True +Mtaconsole*refreshCommand.accelerators: #override\n\ +MetaR: set() notify() unset()\n + +Mtaconsole*quitCommand.fromHoriz: refreshCommand +Mtaconsole*quitCommand.accelerators: #override\n\ +MetaQ: set() notify() unset()\n + +Mtaconsole*connectCommand.resizable: True +Mtaconsole*connectCommand.fromHoriz: quitCommand +Mtaconsole*connectCommand.accelerators: #override\n\ +MetaD: set() notify() unset()\n\ +MetaC: set() notify() unset()\n + +Mtaconsole*modeCommand.resizable: True +Mtaconsole*modeCommand.fromHoriz: connectCommand +Mtaconsole*modeCommand.accelerators: #override\n\ +MetaM: set() notify() unset()\n + +Mtaconsole*configCommand.fromHoriz: modeCommand +Mtaconsole*configCommand.accelerators: #override\n\ +MetaF: set() notify() unset()\n + +Mtaconsole*qcontrolCommand.fromHoriz: configCommand + +!status form + +Mtaconsole*statusForm.showGrip: False +Mtaconsole*statusForm.skipAdjust: True + +Mtaconsole*statusMainPane.orientation: vertical +Mtaconsole*statusMainPane.bottom: ChainBottom + +Mtaconsole*statusMainPane*showGrip: False +Mtaconsole*statusMainPane*skipAdjust: True + +Mtaconsole*statusPane.borderWidth: 0 +Mtaconsole*statusPane.orientation: horizontal + +Mtaconsole*runChans.label: runable chans +Mtaconsole*runChans.borderWidth: 0 + +Mtaconsole*runChansStripChart.fromVert: runChans + +Mtaconsole*.label: qmgr ops/sec +Mtaconsole*qOps.borderWidth: 0 + +Mtaconsole*qOpsStripChart.fromVert: qOps + +!status pane 2 + +Mtaconsole*statusPane2.borderWidth: 0 +Mtaconsole*statusPane2.orientation: horizontal +!Mtaconsole*statusPane2.fromVert: statusPane + +Mtaconsole*msgInPs.label: msg in/sec +Mtaconsole*msgInPs.borderWidth: 0 + +Mtaconsole*msgInPsStripChart.fromVert: msgInPs + +Mtaconsole*msgOutPs.label: msg out/sec +Mtaconsole*msgOutPs.borderWidth: 0 + +Mtaconsole*msgOutPsStripChart.fromVert: msgOutPs + +Mtaconsole*statusFormEnd.fromHoriz: statusMainPane +Mtaconsole*statusFormEnd.borderWidth: 0 +Mtaconsole*statusFormEnd.right: ChainRight +Mtaconsole*statusFormEnd.bottom: ChainBottom + +Mtaconsole*totalVolume.resizable: True + +Mtaconsole*totalNumber.resizable: True +Mtaconsole*totalNumber.fromVert: totalVolume + +Mtaconsole*timeLabel.resizable: True +Mtaconsole*timeLabel.borderWidth: 0 +Mtaconsole*timeLabel.fromVert: totalNumber +Mtaconsole*timeLabel.mappedWhenManaged: False + +Mtaconsole*headerLabel.resizable: True +Mtaconsole*headerLabel.borderWidth: 0 +Mtaconsole*headerLabel.fromVert: timeLabel + +Mtaconsole*errorLabel.resizable: True +Mtaconsole*errorLabel.borderWidth: 0 +Mtaconsole*errorLabel.fromVert: headerLabel +Mtaconsole*errorLabel.mappedWhenManaged: False + +Mtaconsole*statLabel.resizable: True +Mtaconsole*statLabel.borderWidth: 0 +Mtaconsole*statLabel.fromVert: errorLabel +Mtaconsole*statLabel.mappedWhenManaged: False + +!channel widgets + +Mtaconsole*channelForm.showGrip: False +Mtaconsole*channelForm.skipAdjust: True + +Mtaconsole*channelHeader.borderWidth: 0 +Mtaconsole*channelHeader.label: Channel commands + +Mtaconsole*channelCommands.width: 600 +Mtaconsole*channelCommands.vSpace: 0 +Mtaconsole*channelCommands.fromHoriz: channelHeader + +Mtaconsole*channelNext.label: ++ + +Mtaconsole*channelPrev.label: -- + +Mtaconsole*channelClear.label: clear delay + +Mtaconsole*channelCacheadd.label: add delay + +Mtaconsole*channelDownforce.label: downward force attempt + +Mtaconsole*channelLabel.borderWidth: 0 +Mtaconsole*channelLabel.resizable: True +Mtaconsole*channelLabel.fromVert: channelCommands + +Mtaconsole*channelForm2.defaultDistance: 0 + +Mtaconsole*channelViewport.width: 600 +Mtaconsole*channelViewport.height: 120 +Mtaconsole*channelViewport.hSpace: 0 +Mtaconsole*channelViewport.allowVert: True +Mtaconsole*channelViewport.right: ChainRight +Mtaconsole*channelViewport.bottom: ChainBottom + +Mtaconsole*channels.width: 600 +Mtaconsole*channels*Label.translations: #override\n\ +: curChan() readChan()\n\ +: excl_curChan()\n\ +: readChan()\n + +Mtaconsole*channelAllViewport.width: 600 +Mtaconsole*channelAllViewport.height: 120 +Mtaconsole*channelAllViewport.hSpace: 0 +Mtaconsole*channelAllViewport.allowVert: True +Mtaconsole*channelAllViewport.right: ChainRight +Mtaconsole*channelAllViewport.bottom: ChainBottom +Mtaconsole*channelAllViewport.mappedWhenManaged: False + +!Mtaconsole*channelAll.mappedWhenManaged: False + +Mtaconsole*channelAllList.resizable: True +Mtaconsole*channelAllList.forceColumns: True +Mtaconsole*channelAllList.borderWidth: 0 +Mtaconsole*channelAllList.right: ChainRight +Mtaconsole*channelAllList.bottom: ChainBottom + +Mtaconsole*switchForm.defaultDistance: 0 + +!control widgets + +Mtaconsole*controlForm.defaultDistance: 0 +Mtaconsole*controlForm.right: ChainRight +Mtaconsole*controlForm.bottom: ChainBottom + +Mtaconsole*controlVpane.resizable: True +Mtaconsole*controlVpane.borderWidth: 0 +Mtaconsole*controlVpane.bottom: ChainBottom +Mtaconsole*controlVpane.right: ChainRight + +!mta widgets + +Mtaconsole*mtaForm.vSpace: 0 +Mtaconsole*mtaForm.hSpace: 0 +Mtaconsole*mtaForm.showGrip: False +Mtaconsole*mtaForm.skipAdjust: True + +Mtaconsole*mtaDivider.borderWidth: 0 +Mtaconsole*mtaDivider.label: Mta commands + +Mtaconsole*mtaCommands.width: 600 +Mtaconsole*mtaCommands.vSpace: 0 +Mtaconsole*mtaCommands.fromHoriz: mtaDivider + +Mtaconsole*mtaNext.label: ++ + +Mtaconsole*mtaPrev.label: -- + +Mtaconsole*mtaClear.label: clear delay + +Mtaconsole*mtaCacheadd.label: add delay + +Mtaconsole*mtaForce.label: force attempt + +Mtaconsole*mtaDownforce.label: downward force attempt + +Mtaconsole*mtaLabel.borderWidth: 0 +Mtaconsole*mtaLabel.resizable: True +Mtaconsole*mtaLabel.fromVert: mtaCommands + +Mtaconsole*mtaForm2.defaultDistance: 0 + +Mtaconsole*mtaViewport.width: 600 +Mtaconsole*mtaViewport.height: 120 +Mtaconsole*mtaViewport.hSpace: 0 +Mtaconsole*mtaViewport.allowVert: True +!commented out to stop flickering +!Mtaconsole*mtaViewport.allowHoriz: True +Mtaconsole*mtaViewport.right: ChainRight +Mtaconsole*mtaViewport.bottom: ChainBottom + +Mtaconsole*mtas.width: 1 +Mtaconsole*mtas.height: 1 +Mtaconsole*mtas*Label.translations: #override\n\ +: curMta() readMta()\n\ +: excl_curMta()\n\ +: readMta()\n + +Mtaconsole*mtaAllViewport.width: 600 +Mtaconsole*mtaAllViewport.height: 120 +Mtaconsole*mtaAllViewport.hSpace: 0 +Mtaconsole*mtaAllViewport.allowVert: True +Mtaconsole*mtaAllViewport.right: ChainRight +Mtaconsole*mtaAllViewport.bottom: ChainBottom +Mtaconsole*mtaAllViewport.mappedWhenManaged: False + +!Mtaconsole*mtaAll.mappedWhenManaged: False + +Mtaconsole*mtaAllList.resizable: True +Mtaconsole*mtaAllList.forceColumns: True +Mtaconsole*mtaAllList.borderWidth: 0 +Mtaconsole*mtaAllList.right: ChainRight +Mtaconsole*mtaAllList.bottom: ChainBottom + +!msg widgets + +Mtaconsole*msgForm.showGrip: False +Mtaconsole*msgForm.skipAdjust: True + +Mtaconsole*msgDivider.borderWidth: 0 +Mtaconsole*msgDivider.label: Msg commands + +Mtaconsole*msgCommands.width: 600 +Mtaconsole*msgCommands.vSpace: 0 +Mtaconsole*msgCommands.fromHoriz: msgDivider + +Mtaconsole*msgNext.label: ++ + +Mtaconsole*msgPrev.label: -- + +Mtaconsole*msgShowall.label: show all +Mtaconsole*msgShowall.mappedWhenManaged: False +Mtaconsole*msgClear.label: clear delay + +Mtaconsole*msgCacheadd.label: add delay + +Mtaconsole*msgForce.label: force attempt + +Mtaconsole*msgLabel.borderWidth: 0 +Mtaconsole*msgLabel.resizable: True +Mtaconsole*msgLabel.fromVert: msgCommands + +Mtaconsole*msgForm2.defaultDistance: 0 + +Mtaconsole*msgViewport.width: 600 +Mtaconsole*msgViewport.height: 120 +Mtaconsole*msgViewport.hSpace: 0 +Mtaconsole*msgViewport.allowHoriz: True +Mtaconsole*msgViewport.allowVert: True +Mtaconsole*msgViewport.bottom: ChainBottom +Mtaconsole*msgViewport.right: ChainRight + +Mtaconsole*msgs.width: 1 +Mtaconsole*msgs.height: 1 +Mtaconsole*msgs*Label.translations: #override\n\ +: curMsg() readMsg()\n\ +: excl_curMsg()\n\ +: readMsg()\n + +Mtaconsole*msgAllViewport.width: 600 +Mtaconsole*msgAllViewport.height: 120 +Mtaconsole*msgAllViewport.hSpace: 0 +Mtaconsole*msgAllViewport.allowVert: True +Mtaconsole*msgAllViewport.allowHoriz: True +Mtaconsole*msgAllViewport.right: ChainRight +Mtaconsole*msgAllViewport.bottom: ChainBottom +Mtaconsole*msgAllViewport.mappedWhenManaged: False + +!Mtaconsole*msgAll.mappedWhenManaged: False + +Mtaconsole*msgAllList.resizable: True +Mtaconsole*msgAllList.forceColumns: True +Mtaconsole*msgAllList.borderWidth: 0 +Mtaconsole*msgAllList.right: ChainRight +Mtaconsole*msgAllList.bottom: ChainBottom + +!monitor widgets + +Mtaconsole*monitorViewport.allowVert: True +Mtaconsole*monitorViewport.allowHoriz: True +Mtaconsole*monitorViewport.right: ChainRight +Mtaconsole*monitorViewport.bottom: ChainBottom + +Mtaconsole*monitorForm.defaultDistance: 0 + +Mtaconsole*monitorForm.Form.Label.translations: #override\n\ +: chanModeRead()\n\ +: chanMode()\n\ +: chanRefresh()\n + +Mtaconsole*monitorForm.Form.Form.Label.translations: #override\n\ +: mtaModeRead()\n\ +: mtaMode()\n\ +: mtaRefresh()\n + +Mtaconsole*MonitorMTAForm.horizDistance: 20 +!popup widgets + +!qcontrol popup + +Mtaconsole*qcontrol.translations: #override\n\ +: mymenupopdown()\n\ +: mymenupopdown()\n + +Mtaconsole*increaseMaxChannels.label: ++maximum channels +Mtaconsole*decreaseMaxChannels.label: --maximum channels + +Mtaconsole*enableSubmission.label: enable submission + +Mtaconsole*disableSubmission.label: disable submission + +Mtaconsole*enableAll.label: enable all + +Mtaconsole*disableAll.label: disable all + +Mtaconsole*rereadQ.label: reread Q + +Mtaconsole*restartQmgr.label: restart Qmgr + +Mtaconsole*gracefulStop.label: graceful stop + +Mtaconsole*emergencyStop.label: emergency stop + +!yesno popup + +Mtaconsole*yesnoOK.label: ok +Mtaconsole*yesnoOK.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*yesnoNotok.label: notok +Mtaconsole*yesnoNotok.fromHoriz: yesnoOK +Mtaconsole*yesnoNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +!one popup + +Mtaconsole*oneOk.label: ok +Mtaconsole*oneOk.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*oneNotok.label: notok +Mtaconsole*oneNotok.fromHoriz: oneOk +Mtaconsole*oneNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +Mtaconsole*oneForm*Label.borderWidth: 0 +Mtaconsole*oneForm*Label.resizable: True + +Mtaconsole*oneLabelOne.fromVert: oneOk + +Mtaconsole*oneTextOne.fromVert: oneOk +Mtaconsole*oneTextOne.fromHoriz: oneLabelOne +Mtaconsole*oneTextOne.resizable: True +Mtaconsole*oneTextOne*editType: edit + +!two popup + +Mtaconsole*twoOk.label: ok +Mtaconsole*twoOk.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*twoNotok.label: notok +Mtaconsole*twoNotok.fromHoriz: twoOk +Mtaconsole*twoNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +Mtaconsole*twoForm*Label.borderWidth: 0 +Mtaconsole*twoForm*Label.resizable: True + +Mtaconsole*twoForm*Text*editType: edit +Mtaconsole*twoForm*Text.resizable: True +Mtaconsole*twoForm*Text*translations: #override\n\ +Up: previousField()\n\ +Down: nextField()\n\ +Tab: nextField()\n\ +: thisField() select-start()\n + +Mtaconsole*twoLabelOne.fromVert: twoOk + +Mtaconsole*twoTextOne.fromVert: twoOk +Mtaconsole*twoTextOne.fromHoriz: twoLabelOne + +Mtaconsole*twoLabelTwo.fromVert: twoLabelOne + +Mtaconsole*twoTextTwo.fromVert: twoTextOne +Mtaconsole*twoTextTwo.fromHoriz: twoLabelOne + +!three popup + +Mtaconsole*threeForm*Label.borderWidth: 0 +Mtaconsole*threeForm*Label.resizable: True + +Mtaconsole*threeForm*Text*editType: edit +Mtaconsole*threeForm*Text*resizable: True +Mtaconsole*threeForm*Text*translations: #override\n\ +Up: previousField()\n\ +Down: nextField()\n\ +Tab: nextField()\n\ +: thisField() select-start()\n + +Mtaconsole*threeOk.label: ok +Mtaconsole*threeOk.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*threeNotok.label: notok +Mtaconsole*threeNotok.fromHoriz: threeOk +Mtaconsole*threeNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +Mtaconsole*threeLabelOne.fromVert: threeOk + +Mtaconsole*threeTextOne.fromVert: threeOk +Mtaconsole*threeTextOne.fromHoriz: threeLabelOne + +Mtaconsole*threeLabelTwo.fromVert: threeLabelOne + +Mtaconsole*threeTextTwo.fromVert: threeTextOne +Mtaconsole*threeTextTwo.fromHoriz: threeLabelTwo + +Mtaconsole*threeLabelThree.fromVert: threeLabelTwo + +Mtaconsole*threeTextThree.fromVert: threeTextTwo +Mtaconsole*threeTextThree.fromHoriz: threeLabelThree + +!config popup + +Mtaconsole*configForm*Label.borderWidth: 0 +Mtaconsole*configForm*Label.resizable: True + +Mtaconsole*configForm*Command.resizable: True + +Mtaconsole*configForm*Text*editType: edit +Mtaconsole*configForm*Text.resizable: True +Mtaconsole*configForm*Text*translations: #override\n\ +Up: previousField()\n\ +Down: nextField()\n\ +Tab: nextField()\n\ +: thisField() select-start()\n + +Mtaconsole*configOk.label: ok +Mtaconsole*configOk.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*configNotok.label: notok +Mtaconsole*configNotok.fromHoriz: configOk +Mtaconsole*configNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +Mtaconsole*versionLabel.label: This console is running +Mtaconsole*versionLabel.fromVert: configOk + +Mtaconsole*configVersion.fromVert: configOk +Mtaconsole*configVersion.fromHoriz: versionLabel + +Mtaconsole*qmgrVersionLabel.label: The qmgr is running +Mtaconsole*qmgrVersionLabel.fromVert: configVersion + +Mtaconsole*qmgrVersion.fromVert: configVersion +Mtaconsole*qmgrVersion.fromHoriz: qmgrVersionLabel +Mtaconsole*qmgrVersion.label: ??? + +Mtaconsole*autoRefreshLabel.label: Auto-Refresh +Mtaconsole*autoRefreshLabel.fromVert: qmgrVersionLabel + +Mtaconsole*autoRefreshToggle.fromVert: qmgrVersionLabel +Mtaconsole*autoRefreshToggle.fromHoriz: autoRefreshLabel + +Mtaconsole*refreshIntervalLabel.fromHoriz: autoRefreshToggle +Mtaconsole*refreshIntervalLabel.fromVert: qmgrVersionLabel +Mtaconsole*refreshIntervalLabel.label: Interval + +Mtaconsole*refreshIntervalText.fromVert: qmgrVersionLabel +Mtaconsole*refreshIntervalText.fromHoriz: refreshIntervalLabel + +Mtaconsole*inactiveLabel.fromVert: refreshIntervalText +Mtaconsole*inactiveLabel.label: Inactive timeout + +Mtaconsole*inactiveText.fromVert: refreshIntervalText +Mtaconsole*inactiveText.fromHoriz: inactiveLabel + +Mtaconsole*autoReconnectLabel.label: Auto-Reconnect +Mtaconsole*autoReconnectLabel.fromVert: inactiveText + +Mtaconsole*autoReconnectToggle.fromVert: inactiveText +Mtaconsole*autoReconnectToggle.fromHoriz: autoReconnectLabel + +Mtaconsole*arStartLabel.label: Interval +Mtaconsole*arStartLabel.fromVert: inactiveText +Mtaconsole*arStartLabel.fromHoriz: autoReconnectToggle + +Mtaconsole*arStartText.fromVert: inactiveText +Mtaconsole*arStartText.fromHoriz: arStartLabel + +Mtaconsole*backOffLabel.label: Back off +Mtaconsole*backOffLabel.fromVert: arStartText + +Mtaconsole*backOffToggle.fromVert: arStartText +Mtaconsole*backOffToggle.fromHoriz: backOffLabel + +Mtaconsole*boIncLabel.fromVert: arStartText +Mtaconsole*boIncLabel.fromHoriz: backOffToggle +Mtaconsole*boIncLabel.label: back off increment + +Mtaconsole*boIncText.fromVert: arStartText +Mtaconsole*boIncText.fromHoriz: boIncLabel + +Mtaconsole*maxRCIntLabel.fromVert: boIncText +Mtaconsole*maxRCIntLabel.label: Maximum reconnect interval + +Mtaconsole*maxRCIntText.fromVert: boIncText +Mtaconsole*maxRCIntText.fromHoriz: maxRCIntLabel + +Mtaconsole*confPopupLabel.fromVert: maxRCIntText +Mtaconsole*confPopupLabel.label: Confirmation popups + +Mtaconsole*confPopupToggle.fromVert: maxRCIntText +Mtaconsole*confPopupToggle.fromHoriz: confPopupLabel + +Mtaconsole*compatPopupLabel.fromVert: confPopupLabel +Mtaconsole*compatPopupLabel.label: Compatiblity with 5.0 + +Mtaconsole*compatPopupToggle.fromVert: confPopupLabel +Mtaconsole*compatPopupToggle.fromHoriz: compatPopupLabel + +Mtaconsole*inboundPopupLabel.fromVert: compatPopupLabel +Mtaconsole*inboundPopupLabel.label: Badness for Inactive Inbounds + +Mtaconsole*inboundPopupToggle.fromVert: compatPopupLabel +Mtaconsole*inboundPopupToggle.fromHoriz: inboundPopupLabel + +Mtaconsole*heurLabel.label: Display heuristic used +Mtaconsole*heurLabel.fromVert: inboundPopupLabel + +Mtaconsole*heurToggle.fromVert: inboundPopupLabel +Mtaconsole*heurToggle.fromHoriz: heurLabel +Mtaconsole*heurToggle.accelerators: #override\n\ +MetaH: set() notify() unset()\n + +Mtaconsole*percentForm.fromVert: heurToggle +Mtaconsole*percentForm.right: ChainRight +Mtaconsole*percentForm.bottom: ChainBottom + +Mtaconsole*percentLabel.label: Percentage of bad mtas to display + +Mtaconsole*percentText.fromHoriz: percentLabel + +Mtaconsole*numBadMtasLabel.label: Minimum number of bad mtas to display +Mtaconsole*numBadMtasLabel.fromVert: percentText + +Mtaconsole*numBadMtasText.fromVert: percentText +Mtaconsole*numBadMtasText.fromHoriz: numBadMtasLabel + +Mtaconsole*lineForm.fromVert: heurToggle +Mtaconsole*lineForm.right: ChainRight +Mtaconsole*lineForm.bottom: ChainBottom + +Mtaconsole*lineLabel.label: Maximum number of vertical lines per channel + +Mtaconsole*lineText.fromHoriz: lineLabel + +!connect popup + +Mtaconsole*connectForm*Label.borderWidth: 0 +Mtaconsole*connectForm*Label.resizable: True + +Mtaconsole*connectForm*Command.resizable: True + +Mtaconsole*connectForm*Text*editType: edit +Mtaconsole*connectForm*Text*resizable: True +Mtaconsole*connectForm*Text*translations: #override\n\ +Up: previousField()\n\ +Down: nextField()\n\ +Tab: nextField()\n\ +: thisField() select-start()\n + +Mtaconsole*connectOk.label: ok +Mtaconsole*connectOk.accelerators: #override\n\ +Return: set() notify() unset()\n + +Mtaconsole*connectNotok.label: notok +Mtaconsole*connectNotok.fromHoriz: connectOk +Mtaconsole*connectNotok.accelerators: #override\n\ +CtrlC: set() notify() unset()\n + +Mtaconsole*connectToLabel.label: Connect to +Mtaconsole*connectToLabel.fromVert: connectOk + +Mtaconsole*connectToText.fromVert: connectOk +Mtaconsole*connectToText.fromHoriz: connectToLabel + +Mtaconsole*taiFileLabel.fromVert: connectToText +Mtaconsole*taiFileLabel.label: Tailor file + +Mtaconsole*taiFileText.fromVert: connectToText +Mtaconsole*taiFileText.fromHoriz: taiFileLabel + +Mtaconsole*authLabel.label: Authentication +Mtaconsole*authLabel.fromVert: taiFileText + +Mtaconsole*authToggle.fromVert: taiFileText +Mtaconsole*authToggle.fromHoriz: authLabel +Mtaconsole*authToggle.accelerators: #override\n\ +MetaA: set() notify() unset()\n + +Mtaconsole*userLabel.label: User name +Mtaconsole*userLabel.fromVert: authToggle + +Mtaconsole*userText.fromVert: authToggle +Mtaconsole*userText.fromHoriz: userLabel + +Mtaconsole*passwdLabel.label: User passwd +Mtaconsole*passwdLabel.fromVert: userText + +Mtaconsole*passwdText.fromHoriz: passwdLabel +Mtaconsole*passwdText.fromVert: userText +!wide enough for up to eight characters in normalfont (see above) +Mtaconsole*passwdText.width: 120 diff --git a/Src/MTAconsole/README b/Src/MTAconsole/README new file mode 100644 index 0000000..b320b28 --- /dev/null +++ b/Src/MTAconsole/README @@ -0,0 +1,10 @@ +There is known but elusive bug somewhere in the MTAconsole. +Occasionally the MTAconsole falls over and core dumps within the +routine XawFormDoLayout (). +This appears to happen if there is a substantial decrease in the +number of mtas displayed for a particular channel while the console is +in monitor mode. +Any help in diagnosing this problem would be very welcome. +Please note that this does not appear to make the MTAconsole unusable. +In our experience, the problem occurs infrequently. + diff --git a/Src/MTAconsole/assoc.c b/Src/MTAconsole/assoc.c new file mode 100644 index 0000000..221f632 --- /dev/null +++ b/Src/MTAconsole/assoc.c @@ -0,0 +1,1227 @@ +/* routines to start and stop associations */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/assoc.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/assoc.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: assoc.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "console.h" +#include "Qmgr-ops.h" +#include "qmgr.h" + +static char *myservice = "pp qmgr"; +extern char *myname; +int remoteStop(); +static void initiate_responder(); +static IFP startfnx; +static IFP stopfnx; +int sd = -1; +static int tryForAuth; +static struct client_dispatch *channelread_op, + *channelcontrol_op, + *mtaread_op, + *mtacontrol_op, + *readchannelmtamessage_op, + *msgcontrol_op, + *quecontrol_op, + *qmgrStatus_op, + *quit_op; +extern caddr_t retryMask; +extern Authentication authentication; +extern char *Qinformation, *Qversion; +extern Widget qversion; +extern int compat; + +/* CLIENT OPERATIONS */ +extern int do_channelread(); +extern int do_channelcontrol(); +extern int do_mtaread(); +extern int do_mtacontrol(); +extern int do_readchannelmtamessage(); +extern int do_msgcontrol(); +extern int do_quecontrol(); +int do_quit(); + +/* CLIENT RESULTS */ +extern int channelread_result(); +extern int channelcontrol_result(); +extern int mtaread_result(); +extern int mtacontrol_result(); +extern int readchannelmtamessage_result(); +extern int msgcontrol_result(); +extern int quecontrol_result(); +extern int qmgrStatus_result(); + +/* CLIENT ERRORS */ +static int general_error(); + +#define channelread_error general_error +#define channelcontrol_error general_error +#define mtaread_error general_error +#define mtacontrol_error general_error +#define readchannelmtamessage_error general_error +#define msgcontrol_error general_error +#define quecontrol_error general_error +#define qmgrStatus_error general_error + +/* CLIENT STRUCTURE */ + +struct client_dispatch client_dispatches[] = { +{ + "channelread", operation_Qmgr_channelread, +#ifdef PEPSY_VERSION + do_channelread, &_ZUNIV_mod, _ZUTCTimeUNIV, +#else + do_channelread, free_UNIV_UTCTime, +#endif + channelread_result, channelread_error, + "read information on channels" +}, +{ + "channelcontrol", operation_Qmgr_channelcontrol, +#ifdef PEPSY_VERSION + do_channelcontrol, &_ZQmgr_mod, _ZChannelControlQmgr, +#else + do_channelcontrol, free_Qmgr_ChannelControl, +#endif + channelcontrol_result, channelcontrol_error, + "control channel" +}, +{ + "mtaread", operation_Qmgr_mtaread, +#ifdef PEPSY_VERSION + do_mtaread, &_ZQmgr_mod, _ZMtaReadQmgr, +#else + do_mtaread, free_Qmgr_MtaRead, +#endif + mtaread_result, mtaread_error, + "read information on mtas" +}, +{ + "mtacontrol", operation_Qmgr_mtacontrol, +#ifdef PEPSY_VERSION + do_mtacontrol, &_ZQmgr_mod, _ZMtaControlQmgr, +#else + do_mtacontrol, free_Qmgr_MtaControl, +#endif + mtacontrol_result, mtacontrol_error, + "control mta" +}, +{ + "readchannelmtamessage", operation_Qmgr_readChannelMtaMessage, +#ifdef PEPSY_VERSION + do_readchannelmtamessage, &_ZQmgr_mod, _ZMsgReadQmgr, +#else + do_readchannelmtamessage, free_Qmgr_MsgRead, +#endif + readchannelmtamessage_result, readchannelmtamessage_error, + "read a set of messages" +}, +{ + "msgcontrol", operation_Qmgr_msgcontrol, +#ifdef PEPSY_VERSION + do_msgcontrol, &_ZQmgr_mod, _ZMsgControlQmgr, +#else + do_msgcontrol, free_Qmgr_MsgControl, +#endif + msgcontrol_result, msgcontrol_error, + "control msg" +}, +{ + "quecontrol", operation_Qmgr_qmgrControl, +#ifdef PEPSY_VERSION + do_quecontrol, &_ZQmgr_mod, _ZQMGRControlQmgr, +#else + do_quecontrol, free_Qmgr_QMGRControl, +#endif + quecontrol_result, quecontrol_error, + "control qmgr" +}, +{ + "qmgrStatus", operation_Qmgr_qmgrStatus, NULLIFP, +#ifdef PEPSY_VERSION + &_ZQmgr_mod, _ZQmgrStatusQmgr, +#else + free_Qmgr_QmgrStatus, +#endif + qmgrStatus_result, qmgrStatus_error, + "control qmgr" +}, +{ + "quit", 0, do_quit, +#ifdef PEPSY_VERSION + NULL, 0, NULLIFP, NULLIFP, +#else + NULLIFP, NULLIFP, NULLIFP, +#endif + "terminate the association and exit" +}, +{ + NULL +} +}; + +/* SERVER OPERATIONS */ +extern int op_channelread(); +extern int op_mtaread(); +extern int op_readchannelmtamessage(); + +/* SERVER STRUCTURE */ +static struct server_dispatch server_dispatches[] = { + "channelread", operation_Qmgr_channelread, op_channelread, + "mtaread", operation_Qmgr_mtaread, op_mtaread, + "readchannelmtamessage", operation_Qmgr_readChannelMtaMessage, op_readchannelmtamessage, + NULL + }; + +static void acs_advise(), + ros_advise(); +void advise(); +int remoteStop(); +PE passwdpeps[1], *passwdpep = passwdpeps; +int fatal; + +initiate_assoc(argc, argv) +int argc; +char **argv; +{ + struct client_dispatch *ix; + + initiate_responder(argc,argv, PLocalHostName(), myservice, + server_dispatches, + table_Qmgr_Operations, NULLIFP, remoteStop); + + for (ix = client_dispatches; ix->ds_name; ix++){ + if (strcmp(ix -> ds_name, "channelread") == 0) + channelread_op = ix; + else if (strcmp(ix->ds_name, "channelcontrol") == 0) + channelcontrol_op = ix; + else if (strcmp(ix->ds_name, "quit") == 0) + quit_op = ix; + else if (strcmp(ix->ds_name, "mtaread") == 0) + mtaread_op = ix; + else if (strcmp(ix->ds_name, "mtacontrol") == 0) + mtacontrol_op = ix; + else if (strcmp(ix->ds_name, "readchannelmtamessage") == 0) + readchannelmtamessage_op = ix; + else if (strcmp(ix->ds_name, "msgcontrol") == 0) + msgcontrol_op = ix; + else if (strcmp(ix->ds_name, "quecontrol") == 0) + quecontrol_op = ix; + else if (strcmp(ix->ds_name, "qmgrStatus") == 0) + qmgrStatus_op = ix; + } +} + +/* ARGSUSED */ +static void initiate_responder(argc, argv, host, service, dispatches, ops, start, stop) +int argc; +char **argv, + *host, + *service; +struct server_dispatch *dispatches; +struct RyOperation *ops; +IFP start, + stop; +{ + register struct server_dispatch *ds; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + for (ds = dispatches; ds -> ds_name; ds++) + if (RyDispatch (NOTOK, ops, ds -> ds_operation, ds -> ds_vector, roi) + == NOTOK) { + ros_advise (rop, ds -> ds_name); + exit(1); + } + + startfnx = start; + stopfnx = stop; +} + +/* */ +/* connection stuff */ + +/* ARGSUSED */ +int assoc_start (argc, argv, service) +int argc; +char **argv, + *service; +/*struct RyOperation ops[]; +struct client_dispatch *dispatches;*/ +{ + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + AEI aei; + OID ctx, + tmppci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + if ((pa = str2paddr (argv[1])) == NULLPA) { + if ((aei = _str2aei (argv[1], service, QMGR_CTX_OID, + 0, dap_user, dap_passwd)) == NULLAEI) { + fatal = TRUE; + advise (NULLCP, "%s: unknown entity", + argv[1]); + return NOTOK; + } + if ((pa = aei2addr (aei)) == NULLPA) { + fatal = TRUE; + advise (NULLCP, "%s", "address translation failed"); + return NOTOK; + } + } + if ((ctx = oid_cpy (QMGR_AC)) == NULLOID) { + fatal = TRUE; + advise (NULLCP, "%s", "out of memory"); + return NOTOK; + } + + if ((tmppci = oid_cpy (QMGR_PCI)) == NULLOID) { + fatal = TRUE; + advise (NULLCP, "%s", "out of memory"); + return NOTOK; + } + pc -> pc_nctx = 1; + pc -> pc_ctx[0].pc_id = 1; + pc -> pc_ctx[0].pc_asn = tmppci; + pc -> pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (PLocalHostName ())) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + + switch (result = AcAsynAssocRequest (ctx, NULLAEI, NULLAEI, NULLPA, + pa, pc, NULLOID, 0, ROS_MYREQUIRE, + SERIAL_NONE, 0, sf, passwdpep, 1, + NULLQOS, acc, aci, 1)) { + case NOTOK: + acs_advise (aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; +#ifdef CONNECTING_1 + case CONNECTING_1: + case CONNECTING_2: + sd = acc -> acc_sd; + ACCFREE (acc); + PP_TRACE (("Association initiated")); + return result; +#else + case OK: + sd = acc -> acc_sd; + ACCFREE (acc); + PP_TRACE (("Association initiated")); + return OK; +#endif + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + set_failmode (acc); + ACCFREE (acc); + return NOTOK; + } + sd = acc -> acc_sd; + + set_authmode(acc); + + ACCFREE (acc); + + if (RoSetService (sd, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + return NOTOK; + } + PP_TRACE (("Service set")); + return DONE; + default: + advise (NULLCP, "%s", "Bad response from AcAsynAssocRequest"); + return NOTOK; + } +} + +set_failmode (acc) +struct AcSAPconnect *acc; +{ + struct type_Qmgr_BindError *be; + char *info = NULLCP; + be = NULL; + + /* failed by qmgr so no point in retrying connect */ + if (acc -> acc_result == ACS_PERMANENT) + fatal = TRUE; + + if (acc->acc_ninfo >= 1) { + if (decode_Qmgr_BindError (acc->acc_info[0], 1, + NULLVP, NULLIP, &be) == NOTOK) + PP_LOG(LLOG_EXCEPTIONS, ("failed to parse connect data [%s]", + PY_pepy)); + else { + if (be -> information != NULL) + info = qb2str (be -> information); + + advise (NULLCP, + "Association rejected [%s] (%s)", + (be -> reason == int_Qmgr_reason_badCredentials) ? "Bad Credentials" : "Congested", + (info != NULLCP) ? info : ""); + if (info != NULLCP) free(info); + } + } else + advise (NULLCP, + "Association rejected: [%s]", + AcErrString (acc -> acc_result)); + +} + +set_authmode (acc) +struct AcSAPconnect *acc; +{ + struct type_Qmgr_BindResult *br; + + br = NULL; + authentication = limited; + if (Qversion != NULLCP) { + free(Qversion); + Qversion = NULLCP; + } + if (Qinformation != NULLCP) { + free (Qinformation); + Qinformation = NULLCP; + } + + if (acc->acc_ninfo >= 1) { + if (decode_Qmgr_BindResult (acc->acc_info[0], 1, + NULLVP, NULLIP, &br) == NOTOK) + PP_LOG(LLOG_EXCEPTIONS, ("failed to parse connect data [%s]", + PY_pepy)); + else { + switch (br->result) { + case int_Qmgr_result_acceptedFullAccess: + authentication = full; + break; + case int_Qmgr_result_acceptedLimitedAccess: + default: + authentication = limited; + break; + } + if (br -> information != NULL) + Qinformation = qb2str (br -> information); + + if (br -> version != NULL) { + Qversion = qb2str (br -> version); + XtVaSetValues (qversion, + XtNlabel, Qversion, + NULL); + free(Qversion); + Qversion = NULLCP; + } + + free_Qmgr_BindResult(br); + } + } +} + +int acsap_retry (fd) +int fd; +{ + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + PP_TRACE (("acsap_retry(%d)", fd)); + switch (result = AcAsynRetryRequest (fd, acc, aci)) { +#ifdef CONNECTING_1 + case CONNECTING_1: + case CONNECTING_2: + ACCFREE (acc); + return result; +#else + case OK: + ACCFREE (acc); + return OK; +#endif + case NOTOK: + acs_advise (aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + set_failmode(acc); + ACCFREE (acc); + return NOTOK; + } + sd = acc -> acc_sd; + + set_authmode(acc); + + ACCFREE (acc); + if (RoSetService (sd, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + return NOTOK; + } + return DONE; + default: + advise (NULLCP, "%s", "Bad response from AcAsynRetryRequest"); + return NOTOK; + } +} + +int assoc_release (ad) +int ad; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + +#ifdef CONNECTING_1 + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) { +#else + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, acr, aci) == NOTOK) { +#endif + acs_advise (aca, "A-RELEASE.REQUEST"); + return DONE; + } + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (ad, NULLPEP, 0, aci); + advise (NULLCP, "Release rejected by peer: %d", + acr -> acr_reason); + } + + ACRFREE (acr); + PP_TRACE (("Association released")); + + return DONE; +} + +/* */ +/* work routines */ +extern State connectState; +static jmp_buf toplevel; + +static int invoke (ad, ops, ds, args) +int ad; +struct RyOperation ops[]; +register struct client_dispatch *ds; +char **args; +{ + int result; + caddr_t in; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + in = NULL; + + if (ds -> ds_argument && (*ds -> ds_argument) (ad, ds, args, &in) == NOTOK) + return 0; + + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + return (*stopfnx) (ad, (struct AcSAPfinish *) 0); + break; + case DONE: + (void) AcUAbortRequest (ad, NULLPEP, 0, &acis); + (void) RyLose (ad, roi); + return NOTOK; + } + + if (connectState != connected) + return NOTOK; + + switch (result = RyStub (ad, ops, ds -> ds_operation, RyGenID (ad), + NULLIP, in, ds -> ds_result, + ds -> ds_error, ROS_SYNC, roi)) { + case NOTOK: /* failure */ + if (ROS_FATAL(rop->rop_reason)) { + ros_advise (rop, "STUB"); + emergency_disconnect(ad); + } + break; + + case OK: /* got a result/error response */ + break; + + case DONE: /* got RO-END? */ + advise (NULLCP, "%s", "got RO-END.INDICATION"); + connectState = notconnected; + /* NOTREACHED */ + + default: + advise (NULLCP, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + } + +#ifdef PEPSY_VERSION + if (ds -> ds_fr_mod && in) + fre_obj (in, ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod); +#else + if (ds -> ds_free && in) + (*ds -> ds_free)(in); +#endif + return OK; +} + +extern Operations currentop; + +my_invoke(op, args) +Operations op; +char **args; +{ + currentop = op; + StartWait(); + switch (op) { + case chanread: + invoke(sd, table_Qmgr_Operations, + channelread_op,(char **) NULL); + update_time_label(); + break; + case chanstop: + case chanstart: + case chanclear: + case chancacheadd: + invoke(sd, table_Qmgr_Operations, + channelcontrol_op, args); + break; + case mtaread: + invoke(sd, table_Qmgr_Operations, + mtaread_op, args); + break; + case mtastop: + case mtastart: + case mtaclear: + case mtacacheadd: + invoke(sd, table_Qmgr_Operations, + mtacontrol_op, args); + break; + case readchannelmtamessage: + invoke(sd, table_Qmgr_Operations, + readchannelmtamessage_op, args); + break; + case msgstop: + case msgstart: + case msgclear: + case msgcacheadd: + invoke(sd, table_Qmgr_Operations, + msgcontrol_op, args); + break; + case quit: + invoke(sd, table_Qmgr_Operations, + quit_op, (char **) NULL); + break; + case connect: + EndWait(); + return do_connect(args); + case disconnect: + do_disconnect(); + break; + case quecontrol: + invoke(sd, table_Qmgr_Operations, + quecontrol_op, args); + break; + case qmgrStatus: + invoke(sd, table_Qmgr_Operations, + qmgrStatus_op, args); + EndWait(); + return 0; + default: + break; + } + InitRefreshTimeOut((unsigned long) 0); + EndWait(); + return 0; +} + +/* */ +/* advising routines */ + +static void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", + AcErrString (aca -> aca_reason)); + + advise (NULLCP, "%s: %s (source %d)", event, buffer, + aca -> aca_source); +} + +int ros_work (fd) +int fd; +{ + int result; + caddr_t out; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + return (*stopfnx) (fd, (struct AcSAPfinish *) 0); + break; + case DONE: + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + return NOTOK; + } + + switch (result = RyWait (fd, NULLIP, &out, OK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + case OK: + case DONE: + ros_indication (fd, roi); + break; + + default: + advise (NULLCP, "unknown return from RoWaitRequest=%d", result); + } + return OK; +} + +ros_indication (ad, roi) +int ad; +register struct RoSAPindication *roi; +{ + int reply, + result; + + switch (roi -> roi_type) { + case ROI_INVOKE: + case ROI_RESULT: + case ROI_ERROR: + advise (NULLCP, "unexpected indication type=%d", + roi -> roi_type); + break; + + case ROI_UREJECT: + { + register struct RoSAPureject *rou = + &roi -> roi_ureject; + + if (rou -> rou_noid) + advise (NULLCP, + "RO-REJECT-U.INDICATION/%d: %s", + ad, RoErrString (rou -> rou_reason)); + else + advise (NULLCP, + "RO-REJECT-U.INDICATION/%d: %s (id=%d)", + ad, RoErrString (rou -> rou_reason), + rou -> rou_id); + } + break; + + case ROI_PREJECT: + { + register struct RoSAPpreject *rop = &roi -> roi_preject; + connectState = notconnected; + if (ROS_FATAL (rop -> rop_reason)) { + ros_adios (rop, "RO-REJECT-P.INDICATION"); + emergency_disconnect(ad); + } + ros_advise (rop, "RO-REJECT-P.INDICATION"); + } + break; + + case ROI_FINISH: + { + register struct AcSAPfinish *acf = &roi -> roi_finish; + struct AcSAPindication acis; + register struct AcSAPabort *aca = &acis.aci_abort; + + advise (NULLCP, "A-RELEASE.INDICATION/%d: %d", + ad, acf -> acf_reason); + + reply = stopfnx ? (*stopfnx) (ad, acf) : ACS_ACCEPT; + + result = AcRelResponse (ad, reply, ACR_NORMAL, NULLPEP, 0, + &acis); + + ACFFREE (acf); + + if (result == NOTOK) + acs_advise (aca, "A-RELEASE.RESPONSE"); + else + if (reply != ACS_ACCEPT) + break; + longjmp (toplevel, DONE); + } + /* NOTREACHED */ + + default: + advise (NULLCP, "unknown indication type=%d", roi -> roi_type); + } +} + +ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + longjmp (toplevel, NOTOK); +} + +static void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", + RoErrString (rop -> rop_reason)); + + advise (NULLCP, "%s: %s", event, buffer); +} + +extern Widget header, + error, + refresh_command; +extern int autoReconnect, + userConnected, + errorUp; +extern char *hostname; + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + char buffer[BUFSIZ], + headerbuf[BUFSIZ]; + + va_start (ap); + asprintf (buffer, ap); + if (header != NULL) { + XtSetMappedWhenManaged(error, True); + errorUp = 5; + } + if (header == NULL) + printf("%s\n",buffer); + else if (connectState == notconnected && + autoReconnect == TRUE + && fatal == FALSE) { + sprintf(headerbuf,"Attempting to reconnect to %s", + hostname); + XtVaSetValues(header, + XtNlabel, headerbuf, + NULL); + XtVaSetValues(error, + XtNlabel, buffer, + NULL); + } else { + XtVaSetValues(error, + XtNlabel, buffer, + NULL); + } + va_end (ap); +} +#else +/* VARARGS2 */ + +void advise(what, fmt) +char *what, + *fmt; +{ + advise(what,fmt); +} +#endif + +/* */ +/* error routine */ + +/* ARGSUSED */ +static general_error (ad, id, err, parameter, roi) +int ad, + id, + err; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + + if (err == RY_REJECT) { + advise (NULLCP, "%s", RoErrString ((int) parameter)); + return OK; + } + + if ((rye = finderrbyerr (table_Qmgr_Errors, err)) != NULL) + advise (NULLCP, "Error: %s", rye -> rye_name); + else + advise (NULLCP, "Error: %d", err); + + return OK; +} + +/* */ + +/* ARGSUSED */ +int remoteStop(fd, dummy) +int fd; +struct AcSAPfinish *dummy; +{ + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + + /* x release */ + connectState = notconnected; + + SensitizeButtons(False); + TermRefreshTimeOut(); + TermConnectRetry(); + TermListen(); + + if (autoReconnect == FALSE) + userConnected = FALSE; + /* isode release */ + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + + if (autoReconnect == TRUE && userConnected == TRUE) { + clear_displays(); + XtVaSetValues(refresh_command, + XtNlabel, "Reconnect", + NULL); + InitConnectTimeOut(); + MapVolume(False); + } else { + XtVaSetValues(header, + XtNlabel, NO_CONNECTION, + NULL); + ResetForDisconnect(); + } + return NOTOK; +} + +/* ARGSUSED */ +emergency_disconnect(ad) +int ad; +{ + char headerbuf[BUFSIZ]; + + connectState = notconnected; + SensitizeButtons(False); + TermRefreshTimeOut(); + TermConnectRetry(); + TermListen(); + + if (autoReconnect == FALSE) + userConnected = FALSE; + if (autoReconnect == TRUE && userConnected == TRUE) { + clear_displays(); + XtVaSetValues(refresh_command, + XtNlabel, "Reconnect", + NULL); + sprintf(headerbuf,"Attempting to reconnect to %s", + hostname); + XtVaSetValues(header, + XtNlabel, headerbuf, + NULL); + InitConnectTimeOut(); + MapVolume(False); + } else { + XtVaSetValues(header, + XtNlabel, NO_CONNECTION, + NULL); + ResetForDisconnect(); + } + +} + +/* */ + + +/* disconnect from current host with part of a quit */ +do_disconnect() +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (connectState == connected) { + /* Disconnect(sd) */ + TermListen(); + connectState = notconnected; + +#ifdef CONNECTING_1 + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) { +#else + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, acr, aci) == NOTOK) { +#endif + acs_advise (aca, "A-RELEASE.REQUEST"); + return; + } + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + advise (NULLCP, "Release rejected by peer: %d", acr -> acr_reason); + } + + ACRFREE (acr); + sd = -1; + } else if (autoReconnect == TRUE) { + TermConnectTimeOut(); + XtVaSetValues(header, + XtNlabel, NO_CONNECTION, + NULL); + autoReconnect = FALSE; + } +} + +/* ARGSUSED */ +int do_quit (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args, + **arg; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (ad >= 0) { +#ifdef CONNECTING_1 + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) +#else + if (AcRelRequest (ad, ACF_NORMAL, NULLPEP, 0, acr, aci) == NOTOK) +#endif + acs_advise (aca, "A-RELEASE.REQUEST"); + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (ad, NULLPEP, 0, aci); + advise (NULLCP, "Release rejected by peer: %d", acr -> acr_reason); + } + ad = -1; + } + terminate_display(); + exit (0); + +} + +/* */ + +do_connect(phost) +char **phost; +{ + char *targv[2]; + int result; + + targv[0] = myname; + targv[1] = *phost; + fatal = FALSE; + switch(result = assoc_start(2, targv, myservice)) { +#ifdef CONNECTING_1 + case CONNECTING_1: + case CONNECTING_2: + Connecting(result); + break; +#else + case OK: + retryMask = (caddr_t) XtInputWriteMask; + Connecting(result); + break; +#endif + case DONE: + Connected(); + break; + case NOTOK: + default: + NotConnected(); + break; + } + return result; +} + +char buf[BUFSIZ]; +extern Widget header, + error, + qcontrol_command, + connect_command, + refresh_command, + statistics; +extern Mode mode; + +Connected() +{ + sprintf(buf, "Connected to %s (%s)", + (Qinformation != NULLCP && *Qinformation != '\0') ? Qinformation : hostname, + (authentication == full) ? "full authorisation" : "limited authorisation"); + XtVaSetValues(header, + XtNlabel, buf, + NULL); + display_time_label(); +/* if (authentication != full && tryForAuth == TRUE) + advise(NULLCP, "%s", + "Failed to gain authorised connection"); + else + XtSetMappedWhenManaged(error, False); */ + MapButtons(authentication == full); + if (full == authentication + && monitor == mode) + XtSetMappedWhenManaged (qcontrol_command, False); + SensitizeButtons(True); + XtVaSetValues(connect_command, + XtNlabel, "disconnect", + NULL); + XtVaSetValues(refresh_command, + XtNlabel, "refresh", + NULL); + XtSetMappedWhenManaged(error, False); + errorUp = 0; + connectState = connected; + TaiInit(); + InitListen(sd); + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + InitRefreshTimeOut((unsigned long) 500); + TermConnectTimeOut(); + userConnected = TRUE; +} + +extern Widget time_label; + +NotConnected() +{ + char headerbuf[BUFSIZ]; + connectState = notconnected; + undisplay_time_label(); + TermRefreshTimeOut(); + MapButtons(False); + MapVolume(False); + if (autoReconnect == TRUE + && fatal == FALSE) { + XtVaSetValues(refresh_command, + XtNlabel, "reconnect", + NULL); + XtVaSetValues(connect_command, + XtNlabel, "disconnect", + NULL); + sprintf(headerbuf, "Attempting to reconnect to %s",hostname); + XtVaSetValues(header, + XtNlabel, headerbuf, + NULL); + InitConnectTimeOut(); + } else { + XtVaSetValues(header, + XtNlabel, NO_CONNECTION, + NULL); + userConnected = FALSE; + ResetForDisconnect(); + } + +} + +Connecting(res) +int res; +{ + connectState = connecting; + sprintf(buf,"Connecting to %s",hostname); + XtVaSetValues(header, + XtNlabel, buf, + NULL); + XtVaSetValues(connect_command, + XtNlabel, "disconnect", + NULL); + InitConnectRetry(sd, res); +} + +struct type_Qmgr_BindArgument *ba; + +fillin_passwdpep(user, passwd, auth) +char *user, + *passwd; +int auth; +{ + + if (*passwdpep != NULL) { + pe_free(*passwdpep); + free_Qmgr_BindArgument(ba); + *passwdpep = NULL; + } + + ba = (struct type_Qmgr_BindArgument *) smalloc (sizeof *ba); + + if (auth != TRUE) { + /* no authentication */ + ba -> offset = type_Qmgr_BindArgument_noAuthentication; + tryForAuth = FALSE; + } else { + ba -> offset = type_Qmgr_BindArgument_weakAuthentication; + ba -> un.weakAuthentication = + (struct type_Qmgr_WeakAuthentication *) + smalloc(sizeof(struct type_Qmgr_WeakAuthentication)); + ba -> un.weakAuthentication->username = str2qb(user, strlen(user), 1); + if (passwd != NULLCP && *passwd != '\0') + ba -> un.weakAuthentication->passwd = str2qb(passwd, strlen(passwd), 1); + else + ba -> un.weakAuthentication->passwd = NULL; + tryForAuth = TRUE; + } + + if (encode_Qmgr_BindArgument(passwdpep, 1, NULLCP, 0, ba) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("failed to encode BindArgument [%s]", PY_pepy)); + *passwdpep = NULLPE; + free_Qmgr_BindArgument(ba); + exit(1); + } + (*passwdpep)->pe_context = 3; +} diff --git a/Src/MTAconsole/auto.c b/Src/MTAconsole/auto.c new file mode 100644 index 0000000..c2a93bb --- /dev/null +++ b/Src/MTAconsole/auto.c @@ -0,0 +1,450 @@ +/* auto.c:routines for auto things */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/auto.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/auto.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: auto.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +unsigned long timeoutFor = 300000, + inactiveFor = 600000, + connectFor, + connectInit = 300000, + connectInc = 60000, + connectMax = 600000; +int backoff = TRUE; +caddr_t retryMask = (caddr_t) XtInputWriteMask; +XtIntervalId refreshId = 0; +XtIntervalId refreshStatusId = 0; +XtIntervalId connectId = 0; +XtIntervalId inactiveId = 0; +extern XtAppContext appContext; +extern Display *disp; +extern Widget top; +extern char *hostname; +extern void ChangeMode(); +extern int autoReconnect, + userConnected, + autoRefresh; +extern State connectState; + +static int InitRefreshStatusTimeOut(), TermRefreshStatusTimeOut(); + +char *top_of_refresh_list(); + +/* ARGSUSED */ +ConnectTimeOut(data, id) +caddr_t data; /* NOT USED */ +XtIntervalId *id; +{ + /* try connect */ + connectId = 0; + if (connectState == notconnected && autoReconnect == TRUE) { + construct_event(connect); + } +} + +InitConnectTimeOut() +{ + if (connectId != 0) XtRemoveTimeOut(connectId); + if (connectState == notconnected && autoReconnect == TRUE) { + connectFor = connectInit; + connectId = XtAppAddTimeOut(appContext, + (userConnected == TRUE) ? connectFor : 500, + ConnectTimeOut, + NULL); + } +} + +TermConnectTimeOut() +{ + if (connectId != 0) { + XtRemoveTimeOut(connectId); + connectId = 0; + } +} + +/* */ +extern Mode mode; +extern int errorUp; +extern Widget error; + +/* ARGSUSED */ +Inactive(data, id) +caddr_t data; +XtIntervalId *id; +{ + inactiveId = 0; + if (mode == control && connectState == connected) + ChangeMode((Widget)NULL, (caddr_t) NULL, (caddr_t) NULL); +} + + +ResetInactiveTimeout() +{ + if (errorUp > 0) { + errorUp--; + if (errorUp == 0) + XtSetMappedWhenManaged(error, False); + } + if (inactiveId != 0) XtRemoveTimeOut(inactiveId); + if (mode == control && connectState == connected) + inactiveId = XtAppAddTimeOut(appContext, + inactiveFor, + Inactive, + NULL); + else + inactiveId = 0; +} + +/* */ +extern int compat; +extern Widget statistics; +/* ARGSUSED */ +RefreshTimeOut(data,id) +caddr_t data; +XtIntervalId *id; +{ + refreshId = 0; + if (connectState == connected ) { + construct_event(chanread); + if (autoRefresh == TRUE) + refreshId = XtAppAddTimeOut(appContext, + timeoutFor, + RefreshTimeOut, + NULL); + } +} + +InitRefreshTimeOut(tx) +unsigned long tx; +{ + if (refreshId != 0) XtRemoveTimeOut(refreshId); + if (autoRefresh == TRUE && connectState == connected) { + refreshId = XtAppAddTimeOut(appContext, + (tx == 0) ? timeoutFor : tx, + RefreshTimeOut, + NULL); + if (!compat) + InitRefreshStatusTimeOut(tx); + } else + refreshId = 0; +} + +TermRefreshTimeOut() +{ + if (refreshId != 0){ + XtRemoveTimeOut(refreshId); + refreshId = 0; + } + TermRefreshStatusTimeOut(); +} + +/* */ + +/* ARGSUSED */ +static RefreshStatusTimeOut(data,id) +caddr_t data; +XtIntervalId *id; +{ + refreshStatusId = 0; + if (connectState == connected ) { + my_invoke(qmgrStatus, (char **) NULL); + refreshStatusId = XtAppAddTimeOut(appContext, + timeoutFor / 2, + RefreshStatusTimeOut, + NULL); + } +} + +static InitRefreshStatusTimeOut(tx) +unsigned long tx; +{ + if (refreshStatusId != 0) XtRemoveTimeOut(refreshStatusId); + if (connectState == connected) + refreshStatusId = XtAppAddTimeOut(appContext, + (tx == 0) ? (timeoutFor/2) : tx / 2, + RefreshStatusTimeOut, + NULL); + else + refreshStatusId = 0; +} + +static TermRefreshStatusTimeOut() +{ + if (refreshStatusId != 0){ + XtRemoveTimeOut(refreshStatusId); + refreshStatusId = 0; + } +} + +/* */ + +int construct_event(op) +Operations op; +{ + XClientMessageEvent event; + + event.type = ClientMessage; + event.send_event = True; + event.display = disp; + event.window = XtWindow(top); + event.format = 8; + event.data.b[0] = (char) op; + + XSendEvent(disp, + XtWindow(top), + False, + NoEventMask, + (XEvent *) &event); +/* if (result == 0) + temp = result;*/ +} + +int construct_refresh_event(widget) +Widget widget; +{ + XClientMessageEvent event; + + event.type = ResizeRequest; + event.send_event = True; + event.display = disp; + event.window = XtWindow(widget); + + XSendEvent(disp, + XtWindow(widget), + False, + VisibilityChangeMask, + (XEvent *)&event); +/* XSync(XtDisplay(widget), False);*/ +} + +/* ARGSUSED */ +void client_msg_handler(w, client_data, event) +Widget w; +caddr_t client_data; +XClientMessageEvent *event; +{ + char *name; + extern char *msginfo_args[]; + if (event -> type == ClientMessage && + connectState == connected) { + switch ((Operations) event -> data.b[0]) { + case chanread: + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + my_invoke(chanread, (char **) NULL); + break; + case mtaread: + if ((name = top_of_refresh_list()) != NULLCP) { + my_invoke(mtaread, &name); + construct_event(mtaread); + } + + break; + case readchannelmtamessage: + my_invoke(readchannelmtamessage, msginfo_args); + break; + + default: + break; + } + + } else if (event -> type == ClientMessage && + connectState == notconnected && + autoReconnect == TRUE && + (Operations) event -> data.b[0] == connect) { + XSync(disp, 0); + Connect(hostname); + if (connectState == notconnected) { + if (backoff == TRUE && connectFor < connectMax) + connectFor += connectInc; + } + } +} + +/* */ +/* refresh list stuff */ +typedef struct mta_refresh_struct { + char *name; + struct mta_refresh_struct *next; +} Mta_refresh_struct; + +struct mta_refresh_struct *mta_refresh_list = NULL; + +Mta_refresh_struct *new_mta_refresh_struct(name) +char *name; +{ + Mta_refresh_struct * ret = + (Mta_refresh_struct *) calloc(1, sizeof (Mta_refresh_struct)); + ret -> name = strdup(name); + return ret; +} + +free_mta_refresh_list(list) +Mta_refresh_struct *list; +{ + if (list == NULL) + return; + + if (list -> next != NULL) + free_mta_refresh_list(list -> next); + + if (list -> name != NULLCP) + free(list -> name); + + free((char *) list); +} + +clear_mta_refresh_list() +{ + + free_mta_refresh_list(mta_refresh_list) ; + mta_refresh_list = NULL; +} + +add_mta_refresh_list(name) +char *name; +{ + Mta_refresh_struct *ix = mta_refresh_list; + + if (mta_refresh_list == NULL) + mta_refresh_list = new_mta_refresh_struct(name); + else { + while (ix -> next != NULL) + ix = ix -> next; + ix -> next = new_mta_refresh_struct(name); + } +} + +char *top_of_refresh_list() +{ + if (mta_refresh_list != NULL) + return mta_refresh_list -> name; + return NULLCP; +} + +char *pop_from_mta_refresh_list() +{ + char *ret = NULL; + Mta_refresh_struct *temp; + + if ((temp = mta_refresh_list) != NULL) { + ret = temp -> name; + mta_refresh_list = mta_refresh_list -> next; + free((char *) temp); + } + + return ret; +} + +/* */ +XtInputId retryId = 0, + assocId = 0; + +/* ARGSUSED */ +ConnectRetry(data, fd, id) +caddr_t data; +int *fd; +XtInputId *id; +{ + int result; + int myfd = *fd; + + + XtRemoveInput(*id); + retryId = 0; + switch( result = acsap_retry(myfd)) { +#ifdef CONNECTING_1 + case CONNECTING_1: + case CONNECTING_2: + Connecting(result); + break; +#else + case OK: + retryMask = (caddr_t) XtInputReadMask; + Connecting(result); + break; +#endif + case DONE: + Connected(); + break; + case NOTOK: + default: + NotConnected(); + break; + } +} + +TermConnectRetry() +{ + if (retryId != 0) { + XtRemoveInput(retryId); + retryId = 0; + } +} + +InitConnectRetry(sd, res) +int sd, + res; +{ + XSync(disp, 0); +#ifdef CONNECTING_1 + if (res == CONNECTING_1) + retryMask = (caddr_t) XtInputWriteMask; + else + retryMask = (caddr_t) XtInputReadMask; +#endif + + retryId = XtAppAddInput(appContext, + sd, + retryMask, + ConnectRetry, + NULL); +} + + + +/* */ + +/* ARGSUSED */ +Listen(data, fd, id) +caddr_t data; /* unused */ +int *fd; /* where to read from */ +XtInputId *id; /* unused */ +{ + if (ros_work(*fd) == NOTOK) + return; +} + +InitListen(fd) +int fd; +{ + /* set Listen to listen on fd */ + if (assocId != 0) XtRemoveInput(assocId); + assocId = XtAppAddInput(appContext, fd, + XtInputReadMask, + Listen, + NULL); +} + +/* ARGSUSED */ +TermListen() +{ + /* unset Listen which is listening on fd */ + if (assocId != 0) { + XtRemoveInput(assocId); + assocId = 0; + } +} diff --git a/Src/MTAconsole/back.bit b/Src/MTAconsole/back.bit new file mode 100644 index 0000000..b33360e --- /dev/null +++ b/Src/MTAconsole/back.bit @@ -0,0 +1,8 @@ +#define back_width 16 +#define back_height 16 +#define back_x_hot -1 +#define back_y_hot -1 +static char back_bits[] = { + 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x04, 0x04, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x10, 0x10, + 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x01, 0x01}; diff --git a/Src/MTAconsole/badness.c b/Src/MTAconsole/badness.c new file mode 100644 index 0000000..309e58c --- /dev/null +++ b/Src/MTAconsole/badness.c @@ -0,0 +1,956 @@ +/* badness.c: routines calculating and using "badness" */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: badness.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +#define DEFAULT_TOTAL_NUMBER 10000.0 +#define DEFAULT_TOTAL_VOLUME 1000000.0 +struct tailor *tailors = NULL; +extern double atof(); +extern char tailorfile[]; +extern int max_vert_lines; +extern time_t currentTime; +extern char *compress(); +double ub_total_number = DEFAULT_TOTAL_NUMBER, + ub_total_volume = DEFAULT_TOTAL_VOLUME; +extern Display *disp; + +/* */ + +static double parse_ub(ub) +char *ub; +{ + double pre; + char *end; + pre = strtod(ub, &end); + + while (*end != '\0' && isspace(*end)) end++; + if (*end != '\0') { + switch (*end) { + case 'h': + pre *= 60.0; + break; + case 'd': + pre *= 24.0 * 60.0; + break; + case 'k': + pre *= 1000.0; + break; + case 'M': + pre *= 1000000.0; + break; + default: + break; + } + } + return pre; +} + +static void add_total_ubs(entry) +char *entry; +{ + char *ix, *str, *margv[20]; + int i, margc; + char *buf = strdup(entry); + + if ((ix = index(buf, ':')) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect console tailor file entry '%s'",buf)); + free(buf); + return; + } + ix++; + compress(ix, ix); + margc = sstr2arg(ix, 20, margv, ","); + i = 0; + while (i < margc) { + if ((ix = index(margv[i], '<')) != NULL) { + *ix = '\0'; + str = margv[i]; + ix++; + while(*ix != '\0' && isspace(*ix)) ix++; + while(*str != '\0' && isspace(*str)) str++; + if (*ix == '\0' || *str == '\0') + return; + if (strncmp(str, "num", 3) == 0) + ub_total_number = parse_ub(ix); + else if (strncmp(str, "vol", 3) == 0) + ub_total_volume = parse_ub(ix); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown console tailor variable '%s'", + str)); + } + i++; + } + free(buf); +} + +static struct tailor *tailor_new(entry) +char *entry; +{ + struct tailor *ret; + char *ix, *str, *margv[20]; + int i, margc; + char *buf = strdup(entry); + ret = (struct tailor *) calloc(1, sizeof(*ret)); + + if ((ix = index(buf, ':')) == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Incorrect console tailor file entry '%s'",buf)); + free((char *) ret); + free(buf); + return NULL; + } + *ix = '\0'; + ret->key = strdup(buf); + ix++; + compress(ix, ix); + margc = sstr2arg(ix, 20, margv, ","); + + i = 0; + while (i < margc) { + if ((ix = index(margv[i], '<')) != NULL) { + *ix = '\0'; + str = margv[i]; + ix++; + while (*ix != '\0' && isspace(*ix)) ix++; + while (*str != '\0' && isspace(*str)) str++; + if (*ix == '\0' || *str == '\0') + return NULL; + + if (strncmp(str, "num", 3) == 0) + ret->ub_number = parse_ub(ix); + else if (strncmp(str, "vol", 3) == 0) + ret->ub_volume = parse_ub(ix); + else if (strncmp(str, "age", 3) == 0) + ret->ub_age = parse_ub(ix); + else if (strncmp(str, "las", 3) == 0) + ret->ub_last = parse_ub(ix); + else + PP_LOG(LLOG_EXCEPTIONS, + ("Unknown console tailor variable '%s'", + str)); + } + i++; + } + free(buf); + return ret; +} + +static void tailor_add(plist, new) +struct tailor **plist, *new; +{ + new->next = *plist; + *plist = new; +} + +void tailor_free(list) +struct tailor *list; +{ + if (list->key) free(list->key); + if (list->next) tailor_free(list->next); + free((char *) list); +} + +/* */ + +struct tailor *find_tailor(name, list) +char *name; +struct tailor *list; +{ + while (list != NULL + && strcmp(list->key, name) != 0) + list = list->next; + return list; +} + +/* */ +#include "tai_defs.inc" +extern char *myname; + +static void tailor_add_one_default(plist, type, hardwired) +struct tailor **plist; +char *type, + *hardwired; +{ + char *temp, + buf[BUFSIZ]; + if (find_tailor(type, *plist) == NULL) { + if ((temp = XGetDefault(disp, myname, type)) != NULL) { + sprintf(buf, "%s:%s",type,temp); + tailor_add(plist, tailor_new(buf)); + } else if ((temp = XGetDefault(disp, + APPLICATION_CLASS, + type)) != NULL) { + sprintf(buf, "%s:%s",type,temp); + tailor_add(plist, tailor_new(buf)); + } else + tailor_add(plist,tailor_new(hardwired)); + } +} + +static void tailor_add_defaults(plist) +struct tailor **plist; +{ + /* mts defaults */ + tailor_add_one_default(plist, "mtsin-chan", default_mtsin_chan); + tailor_add_one_default(plist, "mtsout-chan", default_mtsout_chan); + tailor_add_one_default(plist, "mtsboth-chan", default_mtsboth_chan); + tailor_add_one_default(plist, "mtsin-mta", default_mtsin_mta); + tailor_add_one_default(plist, "mtsout-mta", default_mtsout_mta); + tailor_add_one_default(plist, "mtsboth-mta", default_mtsboth_mta); + tailor_add_one_default(plist, "mtsin-msg", default_mtsin_msg); + tailor_add_one_default(plist, "mtsout-msg", default_mtsout_msg); + tailor_add_one_default(plist, "mtsboth-msg", default_mtsboth_msg); + + /* mta defaults */ + tailor_add_one_default(plist, "mtain-chan", default_mtain_chan); + tailor_add_one_default(plist, "mtaout-chan", default_mtaout_chan); + tailor_add_one_default(plist, "mtaboth-chan", default_mtaboth_chan); + tailor_add_one_default(plist, "mtain-mta", default_mtain_mta); + tailor_add_one_default(plist, "mtaout-mta", default_mtaout_mta); + tailor_add_one_default(plist, "mtaboth-mta", default_mtaboth_mta); + tailor_add_one_default(plist, "mtain-msg", default_mtain_msg); + tailor_add_one_default(plist, "mtaout-msg", default_mtaout_msg); + tailor_add_one_default(plist, "mtaboth-msg", default_mtaboth_msg); + + /* internal defaults */ + tailor_add_one_default(plist, "internal-chan", default_internal_chan); + tailor_add_one_default(plist, "internal-mta", default_internal_mta); + tailor_add_one_default(plist, "internal-msg", default_internal_msg); + + /* passive defaults */ + tailor_add_one_default(plist, "passive-chan", default_passive_chan); + tailor_add_one_default(plist, "passive-mta", default_passive_mta); + tailor_add_one_default(plist, "passive-msg", default_passive_msg); +} + + +/* */ + +TaiInit() +{ + FILE *fp = NULL; + char buf[BUFSIZ]; + + /* read in console tailor file */ + if (tailorfile[0] != '\0') { + if ((fp = fopen(tailorfile, "r")) == NULL + && tailorfile[0] != '/') { + char *home; + /* try relative to home directory */ + if ((home = getenv("HOME")) != NULLCP) { + (void) sprintf(buf, "%s/%s", + home, tailorfile); + fp = fopen(buf, "r"); + } + } + + if (fp != NULL) { + while (fgets(buf, BUFSIZ, fp) != NULLCP) { + compress(buf, buf); + if (buf[0] == '\n' || buf[0] == '\0' + || buf[0] == '#') + continue; + if (strncmp(buf,"totals", strlen("totals")) == 0) + add_total_ubs(buf); + else + tailor_add(&tailors, tailor_new(buf)); + } + fclose(fp); + } + } + tailor_add_defaults(&tailors); +} + +/* */ + +add_tailor_to_chan(chan) +struct chan_struct *chan; +{ + char buf[BUFSIZ]; + + sprintf(buf, "%s-chan", chan->channelname); + + if ((chan->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-chan", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + chan->tai = find_tailor(buf, tailors); + } +} + +add_tailor_to_mta(chan, mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + char buf[BUFSIZ]; + + sprintf(buf, "%s-mta", chan->channelname); + + if ((mta->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-mta", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + mta->tai = find_tailor(buf, tailors); + } +} + +add_tailor_to_msg(chan, msg) +struct chan_struct *chan; +struct msg_struct *msg; +{ + char buf[BUFSIZ]; + + if (chan == NULL) + return; + + sprintf(buf, "%s-msg", chan->channelname); + + if ((msg->tai = find_tailor(buf, tailors)) == NULL) { + /* no explicit try defaults */ + + char *type = NULL, + *dir = NULL; + + switch (chan->chantype) { + case int_Qmgr_chantype_mta: + type = strdup("mta"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_mts: + type = strdup("mts"); + if (chan->outbound > 0 && chan->inbound > 0) + dir = strdup("both"); + else if (chan->inbound > 0) + dir = strdup("in"); + else if (chan->outbound > 0) + dir = strdup("out"); + break; + + case int_Qmgr_chantype_internal: + type = strdup("internal"); + break; + + case int_Qmgr_chantype_passive: + default: + type = strdup("passive"); + break; + } + + sprintf(buf, "%s%s-msg", + type, + (dir == NULL) ? "" : dir); + + if (type) free(type); + if (dir) free(dir); + msg->tai = find_tailor(buf, tailors); + } +} + +/* */ + +int volBadness(vol) +int vol; +{ + int retval = 0; + if (ub_total_volume != 0.0) + retval = (int) (vol*100/ub_total_volume); + if (vol != 0 && retval == 0) + retval = 1; + return retval; +} + +int numBadness(num) +int num; +{ + int retval = 0; + if (ub_total_number != 0.0) + retval = (int) (num*100/ub_total_number); + if (num != 0 && retval == 0) + return 1; + return retval; +} + +extern int displayInactIns; + +int chanBadness(chan) +struct chan_struct *chan; +{ + double average_db = 0.0, + age, + last; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = chan->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for channel '%s'", chan->channelname)); + return 0; + } + + if ((chan->inbound <= 0 || displayInactIns == FALSE) + && chan->numberMessages == 0 + && chan->numberReports == 0) + return 0; + + if (tai->ub_number != 0.0) { + if ((chan->numberMessages + chan->numberReports) >= tai->ub_number) + return max_bad_channel; + average_db += ((chan->numberMessages+chan->numberReports) * 100)/ tai->ub_number; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (chan->volumeMessages >= tai->ub_volume) + return max_bad_channel; + average_db += (chan->volumeMessages * 100)/tai->ub_volume; + noFactors++; + } + + if (tai->ub_age != 0.0) { + if (chan->oldestMessage != 0 && + (chan->numberMessages != 0 || chan->numberReports != 0)) + age = (currentTime-chan->oldestMessage) / 60.0; + else + age = 0.0; + if (age >= tai->ub_age) + return max_bad_channel; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_last != 0.0) { + if (chan->status->lastSuccess != 0) + last = (currentTime - chan->status->lastSuccess)/60.0; + else + last = 0.0; + if (last >= tai->ub_last) + return max_bad_channel; + if (last >= tai->ub_last/2) { + average_db += (last * 100)/tai->ub_last; + noFactors++; + } + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_channel / (noFactors * 100)); + + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ + +int mtaBadness(mta) +struct mta_struct *mta; +{ + double average_db = 0.0, + age, + last; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = mta->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for mta '%s'", mta->mta)); + return 0; + } + + if (mta->numberMessages == 0 && mta->numberReports == 0) + return 0; + + if (tai->ub_number != 0.0) { + if (mta->numberMessages+mta->numberReports >= tai->ub_number) + return max_bad_mta; + average_db += ((mta->numberMessages+mta->numberReports) * 100)/ tai->ub_number; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (mta->volumeMessages >= tai->ub_volume) + return max_bad_mta; + average_db += (mta->volumeMessages * 100)/tai->ub_volume; + noFactors++; + } + + if (tai->ub_age != 0.0) { + if (mta->oldestMessage != 0 + && (mta->numberMessages != 0 || mta->numberReports != 0)) + age = (currentTime-mta->oldestMessage) / 60.0; + else + age = 0; + if (age >= tai->ub_age) + return max_bad_mta; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_last != 0.0) { + if (mta->status->lastSuccess != 0) + last = (currentTime - mta->status->lastSuccess)/60.0; + else + last = 0; + if (last >= tai->ub_last) + return max_bad_mta; + if (last >= tai->ub_last/2) { + average_db += (last * 100)/tai->ub_last; + noFactors++; + } + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_mta / (noFactors * 100)); + + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ + +int msgBadness(msg) +struct msg_struct *msg; +{ + double average_db = 0.0, + age; + + int average = 0, + noFactors = 0; + + register struct tailor *tai = msg->tai; + + if (tai == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("No tailoring for msg '%s'", msg->msginfo->queueid)); + return 0; + } + + if (msg->msginfo->expiryTime != 0 + && (currentTime - msg->msginfo->expiryTime) >= 0) + /* expired so max_bad_msg ?? */ + return max_bad_msg; + + if (tai->ub_age != 0.0) { + age = (currentTime-msg->msginfo->age) / 60.0; + if (age >= tai->ub_age) + return max_bad_msg; + average_db += (age * 100)/tai->ub_age; + noFactors++; + } + + if (tai->ub_volume != 0.0) { + if (msg->msginfo->size > tai->ub_volume) + return max_bad_msg; + average_db += (msg->msginfo->size * 100) / tai->ub_volume; + noFactors++; + } + + /* scale up those that don't use all factors */ + if (noFactors != 0) + average = (int) (average_db * max_bad_msg / (noFactors * 100)); + if (average == 0 && average_db != 0.0) + return 1; + return average; +} + +/* */ +/* colour routines */ +extern struct color_item *colors; +extern XColor white, + black; +extern Pixel fg, bg; +extern int num_colors; + +unsigned long volcolourOf(vol) +int vol; +{ + int bad, + ix; + bad = volBadness(vol); + if (bad == 0) + return bg; + else { + ix = bad*num_colors/ub_total_volume; + if (ix >= num_colors) + ix = num_colors-1; + return colors[ix].colour.pixel; + } +} + +unsigned long numcolourOf(num) +int num; +{ + int bad, + ix; + bad = numBadness(num); + if (bad == 0) + return bg; + else { + ix = bad*num_colors/ub_total_number; + if (ix >= num_colors) + ix = num_colors-1; + return colors[ix].colour.pixel; + } +} + +unsigned long chancolourOf (chan) +struct chan_struct *chan; +{ + int bad, + ix; + /* find nearest index to chanBadness(chan)'s value */ + /* always round up at moment */ + bad = chanBadness(chan); + if (bad == 0) + /* output white border colour */ + return bg; + else { + ix = bad*num_colors/max_bad_channel; + if (ix >= num_colors) + ix = num_colors-1; + return colors[ix].colour.pixel; + } +} + +unsigned long mtacolourOf (mta) +struct mta_struct *mta; +{ + int bad, + ix; + /* find nearest index to mtaBadness(mta)'s value */ + /* always round up at moment */ + bad = mtaBadness(mta); + if (bad == 0) + /* output white border colour */ + return bg; + else { + ix = bad*num_colors/max_bad_mta; + if (ix >= num_colors) + ix = num_colors-1; + return colors[ix].colour.pixel; + } +} + +unsigned long msgcolourOf (msg) +struct msg_struct *msg; +{ + int bad, + ix; + /* find nearest index to msgBadness(msg)'s value */ + /* always round up at moment */ + bad = msgBadness(msg); + if (bad == 0) + return bg; + else { + ix = bad*num_colors/max_bad_msg; + if (ix >= num_colors) + ix = num_colors-1; + return colors[ix].colour.pixel; + } + +} + +/* */ +/* border routines */ +extern int max_chan_border, + max_mta_border, + max_msg_border; + +int chanborderOf(chan) +struct chan_struct *chan; +{ + int bad, + wid; + bad = chanBadness(chan); + if (bad == 0) + return 1; + else { + wid = max_chan_border*bad/max_bad_channel + 1; + if (wid > max_chan_border) + wid = max_chan_border; + return wid; + } +} + + +int mtaborderOf(mta) +struct mta_struct *mta; +{ + int bad, + wid; + bad = mtaBadness(mta); + if (bad == 0) + return 1; + else { + wid = max_mta_border*bad/max_bad_mta + 1; + if (wid > max_mta_border) + wid = max_mta_border; + return wid; + } +} + +int msgborderOf(msg) +struct msg_struct *msg; +{ + int bad, + wid; + bad = msgBadness(msg); + if (bad == 0) + return 1; + else { + wid = max_msg_border*bad/max_bad_msg + 1; + if (wid > max_msg_border) + wid = max_msg_border; + return wid; + } +} + +/* */ + +/* ordering routines */ +extern int num_channels; +extern struct chan_struct **ordered_list; + +static int channel_compare(one, two) +struct chan_struct **one, + **two; +/* return -1 if one worse state then two */ +{ + int onebad, + twobad; + onebad = chanBadness((*one)); + twobad = chanBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_display_channels() +/* order display_list */ +{ + qsort((char *) &(ordered_list[0]),num_channels, + sizeof(ordered_list[0]),(IFP)channel_compare); +} + + +static int mta_compare (one, two) +struct mta_struct **one, + **two; +/* returns -1 if ione in worse state than two */ +{ + int onebad, + twobad; + onebad = mtaBadness((*one)); + twobad = mtaBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_mtas(plist,num) +struct mta_struct ***plist; +int num; +{ + struct mta_struct **temp = *plist; + qsort((char *)&(temp[0]),num,sizeof(temp[0]),(IFP)mta_compare); +} + +extern int number_msgs; +extern struct msg_struct **global_msg_list; + +static int msg_compare (one, two) +struct msg_struct **one, + **two; +/* returns -1 if ione in worse state than two */ +{ + int onebad, + twobad; + onebad = msgBadness((*one)); + twobad = msgBadness((*two)); + if (onebad < twobad) + return 1; + else if (onebad > twobad) + return -1; + else + return 0; +} + +order_msgs() +{ + qsort((char *) &(global_msg_list[0]),number_msgs, + sizeof(global_msg_list[0]),(IFP)msg_compare); +} + +/* */ + +int NumVertLines(chan) +struct chan_struct *chan; +{ + int ret = 1 + (max_vert_lines * chanBadness(chan))/max_bad_channel; + return ret; +} + +extern XFontStruct *disabledFont, + *activeFont, + *normalFont; + +XFontStruct *chanFont(chan) +struct chan_struct *chan; +{ + if (chan == NULL) + return normalFont; + + if (chan->status->enabled == FALSE) + return disabledFont; + else if (chan->numberActiveProcesses > 0) + return activeFont; + else + return normalFont; +} + +XFontStruct *mtaFont(mta) +struct mta_struct *mta; +{ + if (mta == NULL) + return normalFont; + + if (mta->status->enabled == FALSE) + return disabledFont; + else if (mta -> active) + return activeFont; + else + return normalFont; +} + +XFontStruct *msgFont(msg) +struct msg_struct *msg; +{ + struct recip *ix; + + if (msg == NULL) + return normalFont; + + ix = msg->reciplist; + + while (ix != NULL) { + if (ix -> status -> enabled == FALSE) + return disabledFont; + ix = ix -> next; + } + return normalFont; +} diff --git a/Src/MTAconsole/bops.c b/Src/MTAconsole/bops.c new file mode 100644 index 0000000..2dbd0d8 --- /dev/null +++ b/Src/MTAconsole/bops.c @@ -0,0 +1,1400 @@ +/* bops.c: various buttons routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/bops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/bops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: bops.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" +extern int autoReconnect, + userConnected; +extern State connectState; +extern struct chan_struct *find_channel(); +extern struct mta_struct *find_mta(); +extern struct msg_struct *find_msg(); +extern Widget top; +extern char *reverse_mta(); +extern int uk_order; +extern int compat; +extern int displayInactIns; +extern Heuristic heuristic, + newheur; + +void SetAuthDisplay(); + +/* ARGSUSED */ +void Refresh(w, client_data, call_data) +Widget w; +caddr_t client_data; /* unused */ +caddr_t call_data; /* unused */ +{ +/* StartWait();*/ + if (connectState == connected) { + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + my_invoke(chanread, (char **) NULL); + } else if (autoReconnect == TRUE && userConnected == TRUE) { + TermConnectTimeOut(); + ConnectTimeOut((caddr_t) NULL,(XtIntervalId *) NULL); + } + ResetInactiveTimeout(); +/* EndWait();*/ +} + +extern time_t parsetime(); +Operations currentop; +extern struct chan_struct *currentchan; +extern struct mta_struct *currentmta; +extern struct msg_struct *currentmsg; +extern int confirm, read_currentchan; +extern char *hostname; +extern Popup_menu *yesno, + *one, + *two, + *three; +int forceDown = FALSE; + +/* ARGSUSED */ +void Command(w, op, call_data) +Widget w; +Operations op; +caddr_t call_data; /* unused */ +{ + char *title; + int x, y; + Popup_menu *popup = NULL; + Window r_child; + + ResetInactiveTimeout(); + XtVaGetValues(w, + XtNlabel, &title, + NULL); + + if (strcmp(title, "all") == 0) { + if (op == chaninfo) + chan_display_all(); + else if (op == mtainfo) + mta_display_all(); + else if (op == msginfo) + msg_display_all(); + return; + } + + currentop = op; +/* StartWait(); */ + /* should pop up template hereabouts */ + switch (op) { + case quit: + if (confirm == TRUE) { + popup = yesno; + } else { + Quit(); + } + break; + case connect: + case disconnect: + if (strcmp(title, "connect") == 0) { + currentop = connect; + popup = one; + textdisplay(&(one->tuple[0]), + (hostname == NULL) ? "" : hostname); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Connect to ", + NULL); + } else { + currentop = disconnect; + if (confirm == TRUE) { + popup = yesno; + } else { + Disconnect(); + } + } + break; + case chanstart: + if (currentchan == NULL) { + textdisplay(&(one->tuple[0]), ""); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Enable channel", + NULL); + popup = one; + } else + ChanControl(currentop, currentchan->channelname, + (char *) NULL); + break; + case chanstop: + if (currentchan == NULL) { + textdisplay(&(one->tuple[0]), ""); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Disable channel", + NULL); + popup = one; + } else + ChanControl(currentop, currentchan->channelname, + (char *) NULL); + break; + case chanclear: + if (currentchan == NULL) { + textdisplay(&(one->tuple[0]), ""); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Remove delay on channel", + NULL); + popup = one; + } else + ChanControl(currentop, currentchan->channelname, + (char *) NULL); + break; + case chancacheadd: + popup = two; + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Add delay (in s m h d and/or w)", + NULL); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + textdisplay(&(two->tuple[0]), ""); + break; + + case chaninfo: + if (currentchan == NULL) { + textdisplay(&(one->tuple[0]), ""); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Info on channel", + NULL); + popup = one; + } else + ChanInfo(currentchan->channelname); + break; + + case channext: + ChanNext(); + break; + + case chanprev: + ChanPrev(); + break; + + case chandownforce: + if (currentchan == NULL) { + textdisplay (&(one->tuple[0]), ""); + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Downward force attempt on channel", + NULL); + popup = one; + } else { + forceDown = TRUE; + ChanDownForce (currentchan); + forceDown = FALSE; + } + break; + + case mtastart: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Enable mta ", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + (char *) NULL); + popup = two; + } else + MtaControl(currentop, + currentmta->mta, + currentchan->channelname, + (char *) NULL); + break; + + case mtastop: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Disable mta ", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + popup = two; + } else + MtaControl(currentop, + currentmta->mta, + currentchan->channelname, + (char *) NULL); + break; + case mtaclear: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Remove delay on mta", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + popup = two; + } else + MtaControl(currentop, + currentmta->mta, + currentchan->channelname, + (char *) NULL); + + break; + case mtaforce: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Force attempt of mta", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + popup = two; + } else + MtaForce(currentmta, + currentchan); + + break; + + case mtadownforce: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Downward force attempt of mta", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + popup = two; + } else { + forceDown = TRUE; + MtaDownForce(currentchan, + currentmta); + forceDown = FALSE; + } + break; + case mtacacheadd: + popup = three; + XtVaSetValues(three->tuple[0].label, + XtNlabel, "Add delay (in s m h d and/or w)", + NULL); + textdisplay(&(three->tuple[0]), ""); + XtVaSetValues(three->tuple[1].label, + XtNlabel, "For mta", + NULL); + textdisplay(&(three->tuple[1]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(three->tuple[2].label, + XtNlabel,"On channel", + NULL); + textdisplay(&(three->tuple[2]), + (currentchan == NULL) ? "" : currentchan->channelname); + break; + case mtainfo: + if (currentmta == NULL + || currentchan == NULL) { + textdisplay(&(two->tuple[0]), + (currentmta == NULL) ? "" : currentmta->mta); + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Info on mta", + NULL); + textdisplay(&(two->tuple[1]), + (currentchan == NULL) ? "" : currentchan->channelname); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "On channel", + NULL); + popup = two; + } else + MtaInfo(currentmta->mta, + currentchan->channelname); + break; + + case mtanext: + MtaNext(); + break; + + case mtaprev: + MtaPrev(); + break; + + case msgstart: + popup = two; + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Thaw message", + NULL); + textdisplay(&(two->tuple[0]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + textdisplay(&(two->tuple[1]), ""); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "User list (,) *=all", + NULL); + break; + case msgstop: + popup = two; + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Freeze message ", + NULL); + textdisplay(&(two->tuple[0]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + textdisplay(&(two->tuple[1]), ""); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "User list (,) *=all", + NULL); + break; + case msgclear: + popup = two; + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Remove delay on message", + NULL); + textdisplay(&(two->tuple[0]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + textdisplay(&(two->tuple[1]), ""); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "User list (,) *=all", + NULL); + break; + case msgforce: + if (currentmta == NULL) { + popup = three; + XtVaSetValues(three->tuple[0].label, + XtNlabel, "Force Attempt on Message", + NULL); + textdisplay(&(three->tuple[0]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + XtVaSetValues(three->tuple[1].label, + XtNlabel, "User list (,) *=all", + NULL); + textdisplay(&(three->tuple[1]),""); + XtVaSetValues(three->tuple[2].label, + XtNlabel, "On Mta", + NULL); + textdisplay(&(three->tuple[2]),""); + } else { + /* know what mta is */ + popup = two; + XtVaSetValues(two->tuple[0].label, + XtNlabel, "Force Attempt on Message", + NULL); + textdisplay(&(two->tuple[0]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + XtVaSetValues(two->tuple[1].label, + XtNlabel, "User list (,) *=all", + NULL); + textdisplay(&(two->tuple[1]),""); + } + break; + case msginfo: + if (currentmsg == NULL) { + popup = one; + XtVaSetValues(one->tuple[0].label, + XtNlabel, "Info on message", + NULL); + textdisplay(&(one->tuple[0]), ""); + } else + MsgInfo(currentmsg->msginfo->queueid); + + break; + + case msgnext: + MsgNext(); + break; + + case msgprev: + MsgPrev(); + break; + + case msgcacheadd: + popup = three; + XtVaSetValues(three->tuple[0].label, + XtNlabel, "Add delay (in s m h d and/or w)", + NULL); + textdisplay(&(three->tuple[0]), ""); + XtVaSetValues(three->tuple[1].label, + XtNlabel, "To message", + NULL); + textdisplay(&(three->tuple[1]), + (currentmsg == NULL) ? "" : currentmsg->msginfo->queueid); + XtVaSetValues(three->tuple[2].label, + XtNlabel, "User list (,) *=all", + NULL); + textdisplay(&(three->tuple[2]), ""); + break; + default: + popup = one; + XtVaSetValues(one->tuple[0].label, + XtNlabel, "WHAT ????????", + NULL); + break; + } +/* EndWait();*/ + if (popup != NULL) { + XTranslateCoordinates(XtDisplay(w),XtWindow(w), + XDefaultRootWindow(XtDisplay(w)),0,0, + &x,&y, + &r_child); + Popup(popup,currentop,x,y); + } + +} + +extern Popup_menu *connectpopup; +extern int newauth, + auth; +extern char password[], + username[], + tailorfile[]; + +/* ARGSUSED */ +void Connectbutton(w, op, call_data) +Widget w; +Operations op; +caddr_t call_data; /* unused */ +{ + char *title; + int x, y; + Popup_menu *popup = NULL; + Window r_child; + + XtVaGetValues(w, + XtNlabel, &title, + NULL); + + currentop = op; + if (strcmp(title, "connect") == 0) { + currentop = connect; + newauth = auth; + SetAuthDisplay(newauth); + popup = connectpopup; + textdisplay(&(connectpopup->tuple[0]), + (hostname == NULL) ? "" : hostname); + textdisplay(&(connectpopup->tuple[1]), + (tailorfile[0] == '\0') ? "" : tailorfile); + } else { + currentop = disconnect; + if (confirm == TRUE) { + popup = yesno; + } else { + Disconnect(); + } + } + if (popup != NULL) { + XTranslateCoordinates(XtDisplay(w),XtWindow(w), + XDefaultRootWindow(XtDisplay(w)),0,0, + &x,&y, + &r_child); + Popup(popup,currentop,x,y); + } +} + +Mode mode = monitor; +extern Widget mode_command, channel_label, qcontrol_command; +extern Authentication authentication; +extern void ChanToggle(); + +/* ARGSUSED */ +void ChangeMode(w, client_data, call_data) +Widget w; +caddr_t client_data; +caddr_t call_data; +{ + extern Widget channel_form, + monitor_viewport, + control_form; +/* StartWait();*/ + if (mode == monitor) { + XtVaSetValues(mode_command, + XtNlabel, "monitor", + NULL); + mode = control; + toggle_info_displays(); + reset_label(channel_label); + XtSetMappedWhenManaged(monitor_viewport, False); + XtSetMappedWhenManaged(control_form, True); + XtSetMappedWhenManaged(channel_form, True); + if (authentication == full && connectState == connected) + XtSetMappedWhenManaged(qcontrol_command, True); + if (currentchan != NULL && read_currentchan != 0) { + clear_mta_refresh_list(); + add_mta_refresh_list(currentchan->channelname); + construct_event(mtaread); + } + } else { + XtVaSetValues(mode_command, + XtNlabel, "control", + NULL); + mode = monitor; + ChanToggle(); + XtSetMappedWhenManaged(monitor_viewport, True); + XtSetMappedWhenManaged(control_form, False); + XtSetMappedWhenManaged(channel_form, False); + if (authentication == full) + XtSetMappedWhenManaged(qcontrol_command, False); + if (connectState == connected) { + if (!compat) + my_invoke(qmgrStatus, (char **) NULL); + my_invoke(chanread,(char **) NULL); + } + } +/* EndWait();*/ + ResetInactiveTimeout(); +} + +extern unsigned long timeoutFor, + inactiveFor, + connectInit, + connectInc, + connectMax; +extern char *unparsetime(); +extern Popup_menu *config; +extern Widget refresh_toggle, + reconnect_toggle, + backoff_toggle, + confirm_toggle, + compat_toggle, + inbounds_toggle, + heur_toggle; +extern int autoRefresh, + autoReconnect, + backoff, + percent, + lower_bound_mtas, + max_vert_lines; +extern int newautoRefresh, + newautoReconnect, + newbackoff, + newconfirm, + newcompat, + newdisplayInactIns; +int newint; +unsigned long newTimes; +extern XColor white, black; +extern Pixel bg, fg; + +/* ARGSUSED */ +void Configure(w, client_data, call_data) +Widget w; +caddr_t client_data; /* unused */ +caddr_t call_data; /* unused */ +{ + int x,y,i; + Window r_child; + char number[BUFSIZ], *str; + + newautoRefresh = autoRefresh; + newautoReconnect = autoReconnect; + newbackoff = backoff; + newconfirm = confirm; + newcompat = compat; + newdisplayInactIns = displayInactIns; + newheur = heuristic; + XawFormDoLayout (config->form, False); + textdisplay(&(config->tuple[REFRESH]), + unparsetime(timeoutFor / 1000 )); + textdisplay(&(config->tuple[INACTIVE]), + unparsetime(inactiveFor / 1000)); + textdisplay(&(config->tuple[START]), + unparsetime(connectInit / 1000 )); + textdisplay(&(config->tuple[BACKOFF]), + unparsetime(connectInc / 1000 )); + textdisplay(&(config->tuple[CONNECTMAX]), + unparsetime(connectMax / 1000 )); + sprintf(number, "%d", percent); + textdisplay(&(config->tuple[PERCENT]),number); + sprintf(number, "%d", lower_bound_mtas); + textdisplay(&(config->tuple[MINBADMTA]), number); + sprintf(number, "%d", max_vert_lines); + textdisplay(&(config->tuple[LINEMAX]), number); + + XtSetKeyboardFocus(config->form, config->tuple[REFRESH].text); + XtVaSetValues(config->tuple[REFRESH].text, + XtNborderColor, fg, + NULL); + XtVaSetValues (refresh_toggle, + XtNlabel, (autoRefresh == TRUE) ? "enabled" : "disabled", + NULL); + XtVaSetValues (reconnect_toggle, + XtNlabel, (autoReconnect == TRUE) ? "enabled" : "disabled", + NULL); + XtVaSetValues (backoff_toggle, + XtNlabel, (backoff == TRUE) ? "enabled" : "disabled", + NULL); + XtVaSetValues (confirm_toggle, + XtNlabel, (confirm == TRUE) ? "enabled" : "disabled", + NULL); + XtVaSetValues (compat_toggle, + XtNlabel, (compat == TRUE) ? "enabled" : "disabled", + NULL); + XtVaSetValues (inbounds_toggle, + XtNlabel, (displayInactIns == TRUE) ? "enabled" : "disabled", + NULL); + + switch (heuristic) { + case percentage: + str = PERCENT_BASED; + break; + case all: + str = ALL_BASED; + break; + case chanonly: + str = CHANONLY_BASED; + break; + default: + heuristic = line; + case line: + str = LINE_BASED; + break; + } + XtVaSetValues (heur_toggle, + XtNlabel, str, + NULL); + + for (i = 1; i < config->numberOftuples; i++) + XtVaSetValues(config->tuple[i].text, + XtNborderColor, bg, + NULL); + XawFormDoLayout (config->form, True); + XTranslateCoordinates(XtDisplay(w),XtWindow(w), + XDefaultRootWindow(XtDisplay(w)),0,0,&x,&y, + &r_child); + Popup(config, unknown, x, y); +} + +/* ARGSUSED */ +void popup_NOTOK(w, op, call_data) +Widget w; +Operations *op; +caddr_t call_data; +{ + Popup_menu *popup; + + switch(*op) { + case quit: + case disconnect: + popup = yesno; + break; + case connect: + popup = connectpopup; + break; + case chanread: + case chanstop: + case chanstart: + case chanclear: + case chaninfo: + case chandownforce: + case msginfo: + popup = one; + break; + case chancacheadd: + case mtaread: + case mtastop: + case mtastart: + case mtaclear: + case msgstop: + case msgstart: + case msgclear: + case mtainfo: + case mtaforce: + case mtadownforce: + popup = two; + break; + case mtacacheadd: + case msgcacheadd: + popup = three; + break; + case msgforce: + if (currentmta == NULL) + popup = three; + else + popup = two; + break; + default: + popup = config; + break; + } + ResetInactiveTimeout(); + if (popup != NULL) + Popdown(popup); +} + +/* ARGSUSED */ +void popup_OK(w, op, call_data) +Widget w; +Operations *op; +caddr_t call_data; +{ + Popup_menu *popup = NULL; + struct chan_struct *chan; + char *str0, *str1, *str2; + char *ch; + + XSync(XtDisplay(w), 0); + switch(*op) { + case quit: + Quit(); + popup = yesno; + break; + case disconnect: + Disconnect(); + popup = yesno; + break; + case chanstop: + case chanstart: + case chanclear: + XtVaGetValues(one->tuple[0].text, + XtNstring, &str0, + NULL); + if (str0[0] != '\0') { + ChanControl(*op, str0, (char *) NULL); + popup = one; + } + break; + case chancacheadd: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + if (str0[0] != '\0' + && str1[0] != '\0') { + ChanControl(*op, str1, str0); + popup = two; + } + break; + case chaninfo: + XtVaGetValues(one->tuple[0].text, + XtNstring, &str0, + NULL); + + if (str0[0] != '\0') { + ChanInfo(str0); + popup = one; + } + break; + case chandownforce: + XtVaGetValues(one->tuple[0].text, + XtNstring, &str0, + NULL); + if (str0[0] != '\0') { + if ((chan = find_channel(str0)) != NULL){ + forceDown = TRUE; + ChanDownForce(chan); + forceDown = FALSE; + popup = one; + } + } + break; + case msgstop: + case msgstart: + case msgclear: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' && str1[0] != '\0') { + MsgControl(*op, str0, + str1, (char *) NULL); + popup = two; + } + break; + case msgforce: + if (currentchan == NULL) + break; + if (currentmta == NULL) { + XtVaGetValues(three->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(three->tuple[1].text, + XtNstring, &str1, + NULL); + XtVaGetValues(three->tuple[2].text, + XtNstring, &str2, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0' + && str2[0] != '\0') { + struct mta_struct *mta = NULL; + struct msg_struct *msg = NULL; + char *ch = NULL; + + ch = (uk_order) ? reverse_mta(str2) : str2; + if ((mta = find_mta(currentchan, + ch)) != NULL + && (msg = find_msg(str0)) != NULL) { + MsgForce(msg, str1, + mta, currentchan); + popup = three; + } + if (uk_order && ch != str2) free(ch); + } + } else { + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0') { + struct msg_struct *msg; + if ((msg = find_msg(str0)) != NULL) { + MsgForce(msg, str1, + currentmta, currentchan); + popup = two; + } + } + } + break; + case msgcacheadd: + XtVaGetValues(three->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(three->tuple[1].text, + XtNstring, &str1, + NULL); + XtVaGetValues(three->tuple[2].text, + XtNstring, &str2, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0' + && str2[0] != '\0') { + MsgControl(*op, str1, + str2, str0); + popup = three; + } + break; + + case msginfo: + XtVaGetValues(one->tuple[0].text, + XtNstring, &str0, + NULL); + + if (str0[0] != '\0') { + MsgInfo(str0); + popup = one; + } + break; + case mtaclear: + case mtastop: + case mtastart: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0') { + ch = (uk_order) ? reverse_mta(str0) : str0; + MtaControl(*op, ch, + str1, (char *) NULL); + if (uk_order && ch != str0) free (ch); + popup = two; + } + break; + case mtaforce: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0') { + struct mta_struct *mta; + struct chan_struct *chan; + ch = (uk_order) ? reverse_mta(str0) : str0; + if ((chan = find_channel(str1)) != NULL + && (mta = find_mta(chan, + ch)) != NULL) { + MtaForce(mta, chan); + popup = two; + } + if (uk_order && ch != str0) free(ch); + } + break; + + case mtadownforce: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0') { + struct mta_struct *mta; + struct chan_struct *chan; + if ((chan = find_channel(str1)) != NULL) { + if (chan->num_mtas == 0) + my_invoke(mtaread, + &(chan->channelname)); + ch = (uk_order) ? reverse_mta(str0) : str0; + if((mta = find_mta(chan, + ch)) != NULL) { + forceDown = TRUE; + MtaDownForce(chan, mta); + forceDown = FALSE; + popup = two; + } + if (uk_order && ch != str0) free(ch); + } + } + break; + + case mtainfo: + XtVaGetValues(two->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(two->tuple[1].text, + XtNstring, &str1, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0') { + ch = (uk_order) ? reverse_mta(str0) : str0; + MtaInfo(ch, str1); + if (uk_order && ch != str0) free(ch); + popup = two; + } + break; + case mtacacheadd: + XtVaGetValues(three->tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues(three->tuple[1].text, + XtNstring, &str1, + NULL); + XtVaGetValues(three->tuple[2].text, + XtNstring, &str2, + NULL); + + if (str0[0] != '\0' + && str1[0] != '\0' + && str2[0] != '\0') { + ch = (uk_order) ? reverse_mta(str1) : str1; + MtaControl(*op, ch, + str2, str0); + if (uk_order && ch != str1) free(ch); + popup = three; + } + + default: + break; + } + ResetInactiveTimeout(); + if (popup != NULL) + Popdown(popup); + else + XBell(XtDisplay(w), 50); +} + + +/* configure buttons */ +#define MINTIMEOUT 30000 /* 1/2 min */ + +extern Widget runChans_sc, qOps_sc, msgOutPs_sc, msgInPs_sc; + +settimeoutFor(str) +char *str; +{ + newTimes = (unsigned long) (parsetime(str) * 1000); + if (newTimes > MINTIMEOUT) + timeoutFor = newTimes; +} + +extern Widget statistics; + +/* ARGSUSED */ +void config_OK(w, client_data, call_data) +Widget w; +caddr_t client_data; +caddr_t call_data; +{ + char *str; + int ok = TRUE, + do_reset_refresh = FALSE, + do_reset_reconnect = FALSE; + + if (newautoRefresh != autoRefresh) { + autoRefresh = newautoRefresh; + do_reset_refresh = TRUE; + } + + XtVaGetValues (config->tuple[REFRESH].text, + XtNstring, &str, + NULL); + newTimes = (unsigned long) (parsetime(str) * 1000); + + if (newTimes != timeoutFor) { + if (newTimes < MINTIMEOUT) { + /* BEEP */ + timeoutFor = MINTIMEOUT; + textdisplay(&(config->tuple[REFRESH]), + unparsetime(timeoutFor / 1000)); + ok = FALSE; + } else { + timeoutFor = newTimes; + do_reset_refresh = TRUE; + } + XtVaSetValues(runChans_sc, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtVaSetValues(qOps_sc, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + if (statistics != NULL) { + XtVaSetValues(msgInPs_sc, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtVaSetValues(msgOutPs_sc, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + } + + } + + XtVaGetValues (config->tuple[INACTIVE].text, + XtNstring, &str, + NULL); + newTimes = (unsigned long) (parsetime(str) * 1000); + + if (newTimes != inactiveFor) + inactiveFor = newTimes; + + XtVaGetValues (config->tuple[START].text, + XtNstring, &str, + NULL); + newTimes = (unsigned long) (parsetime(str) * 1000); + + if (newTimes != connectInit) { + connectInit = newTimes; + do_reset_reconnect = TRUE; + } + + XtVaGetValues (config->tuple[BACKOFF].text, + XtNstring, &str, + NULL); + newTimes = (unsigned long) (parsetime(str) * 1000); + + if (newTimes != connectInc) { + connectInc = newTimes; + do_reset_reconnect = TRUE; + } + + XtVaGetValues (config->tuple[CONNECTMAX].text, + XtNstring, &str, + NULL); + newTimes = (unsigned long) (parsetime(str) * 1000); + + if (newTimes != connectMax) { + connectMax = newTimes; + do_reset_reconnect = TRUE; + } + + + if (newautoReconnect != autoReconnect) { + autoReconnect = newautoReconnect; + do_reset_reconnect = TRUE; + } + + if (newbackoff != backoff) { + backoff = newbackoff; + do_reset_reconnect = TRUE; + } + + if (newconfirm != confirm) + confirm = newconfirm; + if (newcompat != compat) { + if (statistics != NULL) { + compat = newcompat; + redo_statistics_compat(); + } else + ok = FALSE; + + } + if (newdisplayInactIns != displayInactIns) + displayInactIns = newdisplayInactIns; + + if (newheur != heuristic) + heuristic = newheur; + switch (heuristic) { + case percentage: + XtVaGetValues (config->tuple[PERCENT].text, + XtNstring, &str, + NULL); + if ((newint = atoi(str)) != 0) + percent = newint; + XtVaGetValues (config->tuple[MINBADMTA].text, + XtNstring, &str, + NULL); + if ((newint = atoi(str)) != 0) + lower_bound_mtas = newint; + break; + case line: + XtVaGetValues (config->tuple[LINEMAX].text, + XtNstring, &str, + NULL); + if ((newint = atoi(str)) != 0) + max_vert_lines = newint; + break; + default: + break; + } + if (do_reset_refresh == TRUE + && connectState == connected) + InitRefreshTimeOut((unsigned long) 500); + if (do_reset_reconnect == TRUE + && connectState != connected + && userConnected == TRUE) InitConnectTimeOut(); + ResetInactiveTimeout(); + if (ok == TRUE) + Popdown(config); + else + XBell(XtDisplay(w), 50); + +} + +extern Popup_menu *currentpopup, + *qcontrol; + +extern Widget line_form, percent_form; + +/* ARGSUSED */ +void heurToggle (w, pheur, call_data) +Widget w; +Heuristic *pheur; +caddr_t call_data; +{ + if (currentpopup != config) + return; + switch (*pheur) { + case percentage: + *pheur = line; + XtVaSetValues(w, + XtNlabel, LINE_BASED, + NULL); + XtSetMappedWhenManaged (line_form, True); + XtSetMappedWhenManaged (percent_form, False); + break; + + case line: + *pheur = all; + XtVaSetValues(w, + XtNlabel, ALL_BASED, + NULL); + XtSetMappedWhenManaged (line_form, False); + XtSetMappedWhenManaged (percent_form, False); + break; + + case all: + *pheur = chanonly; + XtVaSetValues(w, + XtNlabel, CHANONLY_BASED, + NULL); + XtSetMappedWhenManaged (line_form, False); + XtSetMappedWhenManaged (percent_form, False); + break; + case chanonly: + *pheur = percentage; + XtVaSetValues (w, + XtNlabel, PERCENT_BASED, + NULL); + XtSetMappedWhenManaged (line_form, False); + XtSetMappedWhenManaged (percent_form, True); + break; + } +} + +extern Widget auth_toggle; + +/* ARGSUSED */ +void configToggle(w, pint, call_data) +Widget w; +int *pint; +caddr_t call_data; +{ + if (currentpopup == NULL) + return; + if (*pint == TRUE) { + /* enabled -> disabled */ + *pint = FALSE; + XtVaSetValues(w, + XtNlabel, "disabled", + NULL); + if (w == auth_toggle + && currentpopup->selected != 0) { + XtSetKeyboardFocus(top, + currentpopup->tuple[0].text); + XtSetKeyboardFocus(currentpopup->form, + currentpopup->tuple[0].text); + XtVaSetValues(currentpopup->tuple[0].text, + XtNborderColor, fg, + NULL); + XtVaSetValues(currentpopup->tuple[currentpopup->selected].text, + XtNborderColor, bg, + NULL); + currentpopup->selected = 0; + } + + } else { + /* disabled -> enabled */ + *pint = TRUE; + XtVaSetValues(w, + XtNlabel, "enabled", + NULL); + } + if (w == auth_toggle) + SetAuthDisplay(*pint); + ResetInactiveTimeout(); +} + +void SetAuthDisplay(bool) +int bool; +{ + XtSetMappedWhenManaged(connectpopup->tuple[2].label, bool); + XtSetMappedWhenManaged(connectpopup->tuple[3].label, bool); + XtSetMappedWhenManaged(connectpopup->tuple[2].text, bool); + XtSetMappedWhenManaged(connectpopup->tuple[3].text, bool); + if (bool == TRUE) { + textdisplay(&(connectpopup->tuple[2]), + (username == NULL) ? "" : username); + password[0] = '\0'; + textdisplay(&(connectpopup->tuple[3]),""); + } +} + +/* ARGSUSED */ +void connectpopup_OK(w, client_data, call_data) +Widget w; +caddr_t client_data; +caddr_t call_data; +{ + char *str0, *str1, *str2; + if (newauth != auth) + auth = newauth; + + XtVaGetValues (connectpopup -> tuple[0].text, + XtNstring, &str0, + NULL); + XtVaGetValues (connectpopup -> tuple[2].text, + XtNstring, &str2, + NULL); + if (str0[0] == '\0' + || (auth == TRUE && str2[0] == '\0')) { + XBell(XtDisplay(w), 50); + return; + } + + XtVaGetValues (connectpopup -> tuple[1].text, + XtNstring, &str1, + NULL); + if (str1[0] == '\0') + tailorfile[0] = '\0'; + else + strcpy(tailorfile, str1); + + if (str2[0] != '\0') + strcpy(username, str2); + fillin_passwdpep(username, password, auth); + StartWait(); + Connect(str0); + EndWait(); + ResetInactiveTimeout(); + Popdown(connectpopup); +} + +/* ARGSUSED */ +void QControlPopup(w, op, call_data) +Widget w; +int op; +caddr_t call_data; +{ + int x,y; + Window r_child; + + XTranslateCoordinates(XtDisplay(w),XtWindow(w), + XDefaultRootWindow(XtDisplay(w)),0,0,&x,&y, + &r_child); + ResetInactiveTimeout(); + Popup(qcontrol, unknown, x, y); + +} +extern int msgs_ub; +/* ARGSUSED */ +void MsgsShowAll (w, client_data, call_data) +Widget w; +caddr_t client_data, + call_data; +{ + msgs_ub = False; + control_display_msgs(); + msgs_ub = True; +} + +/* ARGSUSED */ +void QControl(w, op, call_data) +Widget w; +int op; +caddr_t call_data; +{ + my_invoke(quecontrol, (char **) op); + ResetInactiveTimeout(); + Popdown(qcontrol); +} + +/* */ +extern Widget channel_commands, + mta_commands, + msg_commands, + qcontrol_command; + +SensitizeButtons(bool) +int bool; +{ + XtSetSensitive(qcontrol_command,bool); + XtSetSensitive(channel_commands,bool); + XtSetSensitive(mta_commands,bool); + XtSetSensitive(msg_commands,bool); +} + + + diff --git a/Src/MTAconsole/console.h b/Src/MTAconsole/console.h new file mode 100644 index 0000000..8e52d11 --- /dev/null +++ b/Src/MTAconsole/console.h @@ -0,0 +1,264 @@ +/* console.h: include file for MTA console */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/console.h,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: console.h,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_MTACONSOLE_CONSOLE +#define _H_MTACONSOLE_CONSOLE + + +#include "util.h" +#include +#include "Qmgr-types.h" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct procStatus { + char enabled; /* boolean TRUE or FALSE */ + time_t lastAttempt, + cachedUntil, + lastSuccess; +} ProcStatus; + + +typedef struct tailor { + char *key; + double ub_number, + ub_volume, + ub_age, + ub_last; + struct tailor *next; +} TailorInfo; + + + +/* 4 factors (num, vol, age, last) == max 400 % */ +#define max_bad_channel 400 + +/* 4 factors (num, vol, age, last) == max 400 % */ +#define max_bad_mta 400 + +/* 2 factors (vol, age) == max 200 % */ +#define max_bad_msg 200 + + + +typedef struct permsginfo { + char *queueid; + char *originator; + char *contenttype; + char *eit; + int priority; + int size; + time_t expiryTime; + time_t deferredTime; + time_t age; + int errorCount; + char *inChannel; + char *uaContentId; +} Permsginfo; + + + +typedef struct recip { + int id; + char *recipient; + char *mta; + char *actChan; + char *chansOutstanding; + struct procStatus *status; + char *info; + struct recip *next; +} Recip; + + + +typedef struct msg_struct { + struct permsginfo *msginfo; + struct recip *reciplist; + struct tailor *tai; +} Msg_struct; + + + +typedef struct mta_struct { + char *mta; + time_t oldestMessage; + int numberMessages, + numberReports, + volumeMessages; + struct procStatus *status; + int priority; + char active; + char *info; + struct tailor *tai; +} Mta_struct; + + + +typedef struct chan_struct { + char *channelname, + *channeldescrip; + time_t oldestMessage; + int numberMessages, + deltaMessages, + numberReports, + deltaReports, + deltaVolume, + volumeMessages, + numberActiveProcesses; + struct procStatus *status; + int priority; + struct mta_struct **mtalist; + int num_mtas; + int given_num_mtas; + int deltaMtas; + int display_num; + int inbound; + int outbound; + int chantype; + int maxprocs; + struct tailor *tai; +} Chan_struct; + + +typedef struct mta_disp_struct { + Widget widget; + struct mta_struct *mta; +} Mta_disp_struct; + + + +typedef struct msg_disp_struct { + Widget widget; + struct msg_struct *msg; +} Msg_disp_struct; + + + +typedef struct monitor_item { + Widget form, + chan, + box; + Mta_disp_struct **mtas; + int num_allocd; /* num allocd for mtas */ + int num_mtas; /* num of mtas actual being displayed */ + struct chan_struct **channel; /* actual being displayed */ +} Monitor_item; + + + +typedef struct color_item { + int badness; + XColor colour; +} Color_item; + + + +typedef enum { + unknown, + quit, connect, disconnect, quecontrol, qmgrStatus, + chanread, chanstop, chanstart, + chancacheadd, chandownforce, chanclear, chaninfo, + channext, chanprev, + mtaread, mtastop, mtastart, + mtacacheadd, mtaforce, mtadownforce, mtaclear, mtainfo, + mtanext, mtaprev, + readchannelmtamessage, msgstop, msgstart, + msgcacheadd, msgforce, msgclear, msginfo, + msgnext, msgprev, + mtacontrol +} Operations; + + + +typedef struct popup_tuple { + Widget label, + text; +} Popup_tuple; + + + +typedef struct popup_menu { + Widget popup, + form; + int numberOftuples, + selected; + Operations op; + Popup_tuple *tuple; +} Popup_menu; + + + +/* -- defines for config --- */ +#define REFRESH 0 +#define INACTIVE 1 +#define START 2 +#define BACKOFF 3 +#define CONNECTMAX 4 +#define PERCENT 5 +#define MINBADMTA 6 +#define LINEMAX 7 + + +typedef enum { percentage, line, all, chanonly } Heuristic; +typedef enum { notconnected, connecting, connected} State; +typedef enum { limited, full} Authentication; +typedef enum { inactive, green, yellow, red} Colour; +typedef enum { control, monitor} Mode; + + +#define APPLICATION_CLASS "Mtaconsole" +#define MAX_EDIT_STRING 100 +#define NO_CONNECTION "Unconnected" + + + +typedef struct server_dispatch { + char *ds_name; + int ds_operation; + IFP ds_vector; +} Server_dispatch; + + + +typedef struct client_dispatch { + char *ds_name; + int ds_operation; + IFP ds_argument; + modtyp *ds_fr_mod; + int ds_fr_index; + IFP ds_result; + IFP ds_error; + char *ds_help; +} Client_dispatch; + + +#define PERCENT_BASED "percent based" +#define LINE_BASED "line based" +#define ALL_BASED "all" +#define CHANONLY_BASED "channel only" + +#endif diff --git a/Src/MTAconsole/create.c b/Src/MTAconsole/create.c new file mode 100644 index 0000000..db0d37d --- /dev/null +++ b/Src/MTAconsole/create.c @@ -0,0 +1,2030 @@ +/* create.c: creation for all X widgets */ +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/create.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/create.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: create.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +#define TOTAL_WIDTH 600 +#define VP_HEIGHT 120 + +static void create_commandwidgets(); +static void create_channelwidgets(); +static void create_mtawidgets(); +static void create_msgwidgets(); +static void create_controlwidgets(); +static void create_monitorwidgets(); +static void create_popupwidgets(); +extern char *myname; +Widget top, + mainform, + topform, + nextform, + mainvpane, + channel_form, + mta_form, + msg_form, + switchform, + header = NULL, + error = NULL, + statistics = NULL, + monitor_viewport, + control_form; +int errorUp = 0; + +extern char *ppversion; +extern void client_msg_handler(); +extern XFontStruct *normalFont; +int strlen_msgall; + +Arg argList[10]; + +/* ARGSUSED */ +create_widgets(display, context) +Display *display; +XtAppContext context; +{ + Dimension ht; + + XtSetArg(argList[0], XtNfont, normalFont); + + XtAddEventHandler(top, NoEventMask, TRUE, client_msg_handler, NULL); + + mainform = XtVaCreateManagedWidget("mainform", + formWidgetClass, + top, + NULL); + + mainvpane = XtVaCreateManagedWidget("mainvpane", + panedWidgetClass, + mainform, + NULL); + + create_commandwidgets(); + create_channelwidgets(); + + switchform = XtVaCreateManagedWidget("switchForm", + formWidgetClass, + mainvpane, + NULL); + create_controlwidgets(); + create_popupwidgets(context); + XtRealizeWidget(top); + XtVaGetValues(topform, + XtNheight, &ht, + NULL); + XtVaSetValues(topform, + XtNmin, ht, + XtNmax, ht, + NULL); + XtVaGetValues(nextform, + XtNheight, &ht, + NULL); + XtVaSetValues(nextform, + XtNmin, ht, + XtNmax, ht, + NULL); + XtVaGetValues(channel_form, + XtNheight, &ht, + NULL); + XtVaSetValues(channel_form, + XtNmin, ht, + XtNmax, ht, + NULL); + XtVaGetValues(mta_form, + XtNheight, &ht, + NULL); + XtVaSetValues(mta_form, + XtNmin, ht, + XtNmax, ht, + NULL); + XtVaGetValues(msg_form, + XtNheight, &ht, + NULL); + XtVaSetValues(msg_form, + XtNmin, ht, + XtNmax, ht, + NULL); + create_monitorwidgets(); + XtInstallAllAccelerators(mainform, mainform); + MapButtons(False); /* can't see before connect */ + MapVolume(False); +} + +Widget quit_command, + connect_command, + refresh_command, + mode_command, + config_command, + qcontrol_command, + total_volume_label, + total_number_label, + time_label, + runChans_label, qOps_label, msgInPs_label, msgOutPs_label, + runChans_sc, qOps_sc, msgInPs_sc, msgOutPs_sc, + compat_stat_pane; + +extern void Refresh(), + Command(), + Connectbutton(), + Configure(), + QControlPopup(), + ChangeMode(), + setLoad(); +extern double runnableChans, opsPerSec, msgsInPerSec, msgsOutPerSec; + +extern XFontStruct *normalFont; +extern unsigned long timeoutFor; +extern int compat; + +static void create_commandwidgets() +{ + Widget pane, form, mainpane; + + topform = XtVaCreateManagedWidget("generalCommands", + formWidgetClass, + mainvpane, + NULL); + + refresh_command = XtVaCreateManagedWidget("refreshCommand", + commandWidgetClass, + topform, + XtNlabel, "refresh", + NULL); + if (normalFont != NULL) + XtSetValues(refresh_command, argList, 1); + + XtAddCallback(refresh_command, XtNcallback, Refresh, NULL); + + quit_command = XtVaCreateManagedWidget("quitCommand", + commandWidgetClass, + topform, + XtNlabel, "quit", + NULL); + XtAddCallback(quit_command, XtNcallback, Command, quit); + if (normalFont != NULL) + XtSetValues(quit_command, argList, 1); + + connect_command = XtVaCreateManagedWidget("connectCommand", + commandWidgetClass, + topform, + XtNlabel, "connect", + NULL); + XtAddCallback(connect_command, XtNcallback, Connectbutton, connect); + if (normalFont != NULL) + XtSetValues(connect_command,argList, 1); + + mode_command = XtVaCreateManagedWidget("modeCommand", + commandWidgetClass, + topform, + XtNlabel, "control", + NULL); + XtAddCallback(mode_command, XtNcallback, ChangeMode, NULL); + if (normalFont != NULL) + XtSetValues(mode_command,argList, 1); + + config_command = XtVaCreateManagedWidget("configCommand", + commandWidgetClass, + topform, + XtNlabel, "configuration", + NULL); + XtAddCallback(config_command, XtNcallback, Configure, NULL); + if (normalFont != NULL) + XtSetValues(config_command,argList, 1); + + qcontrol_command = XtVaCreateManagedWidget("qcontrolCommand", + commandWidgetClass, + topform, + XtNlabel, "Qmgr control", + NULL); + XtAddCallback(qcontrol_command, XtNcallback, QControlPopup, NULL); + if (normalFont != NULL) + XtSetValues(qcontrol_command,argList, 1); + + nextform = XtVaCreateManagedWidget("statusForm", + formWidgetClass, + mainvpane, + NULL); + + mainpane = XtVaCreateManagedWidget("statusMainPane", + panedWidgetClass, + nextform, + NULL); + pane = XtVaCreateManagedWidget("statusPane", + panedWidgetClass, + mainpane, + NULL); + form = XtVaCreateManagedWidget("statusForm1", + formWidgetClass, + pane, + NULL); + runChans_label = XtVaCreateManagedWidget("runChans", + labelWidgetClass, + form, + NULL); + if (normalFont != NULL) + XtSetValues(runChans_label,argList, 1); + + runChans_sc = XtVaCreateManagedWidget("runChansStripChart", + stripChartWidgetClass, + form, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtAddCallback(runChans_sc, XtNgetValue, setLoad, &runnableChans); + + form = XtVaCreateManagedWidget("statusForm2", + formWidgetClass, + pane, + NULL); + + qOps_label = XtVaCreateManagedWidget("qOps", + labelWidgetClass, + form, + NULL); + if (normalFont != NULL) + XtSetValues(qOps_label,argList, 1); + + qOps_sc = XtVaCreateManagedWidget("qOpsStripChart", + stripChartWidgetClass, + form, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtAddCallback(qOps_sc, XtNgetValue, setLoad, &opsPerSec); + + if (!compat) { + compat_stat_pane = pane = XtVaCreateManagedWidget("statusPane2", + panedWidgetClass, + mainpane, + NULL); + form = XtVaCreateManagedWidget("statusForm3", + formWidgetClass, + pane, + NULL); + msgInPs_label = XtVaCreateManagedWidget("msgInPs", + labelWidgetClass, + form, + NULL); + if (normalFont != NULL) + XtSetValues(msgInPs_label,argList, 1); + + msgInPs_sc = XtVaCreateManagedWidget("msgInPsStripChart", + stripChartWidgetClass, + form, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtAddCallback(msgInPs_sc, XtNgetValue, setLoad, &msgsInPerSec); + + form = XtVaCreateManagedWidget("statusForm4", + formWidgetClass, + pane, + NULL); + + msgOutPs_label = XtVaCreateManagedWidget("msgOutPs", + labelWidgetClass, + form, + NULL); + if (normalFont != NULL) + XtSetValues(msgOutPs_label,argList, 1); + + msgOutPs_sc = XtVaCreateManagedWidget("msgOutPsStripChart", + stripChartWidgetClass, + form, + XtNupdate, (int) (timeoutFor / 2000), + NULL); + XtAddCallback(msgOutPs_sc, XtNgetValue, setLoad, &msgsOutPerSec); + } + form = XtVaCreateManagedWidget("statusFormEnd", + formWidgetClass, + nextform, + NULL); + total_volume_label = XtVaCreateManagedWidget("totalVolume", + labelWidgetClass, + form, + XtNlabel, "Total volume", + NULL); + if (normalFont != NULL) + XtSetValues(total_volume_label,argList, 1); + + total_number_label = XtVaCreateManagedWidget("totalNumber", + labelWidgetClass, + form, + XtNlabel, "Total number of messages", + NULL); + if (normalFont != NULL) + XtSetValues(total_number_label,argList, 1); + + time_label = XtVaCreateManagedWidget("timeLabel", + labelWidgetClass, + form, + XtNlabel, "qmgr status", + NULL); + if (normalFont != NULL) + XtSetValues(time_label,argList, 1); + + header = XtVaCreateManagedWidget("headerLabel", + labelWidgetClass, + form, + XtNlabel, NO_CONNECTION, + NULL); + if (normalFont != NULL) + XtSetValues(header,argList, 1); + + + error = XtVaCreateManagedWidget("errorLabel", + labelWidgetClass, + form, + XtNlabel, NO_CONNECTION, + NULL); + if (normalFont != NULL) + XtSetValues(error,argList, 1); + + if (!compat) { + statistics = XtVaCreateManagedWidget("statLabel", + labelWidgetClass, + form, + XtNlabel, "Qmgr\nstatistics\n\n", + NULL); + if (normalFont != NULL) + XtSetValues(statistics,argList, 1); + errorUp = 0; + } +} + + +Widget channels, + channel_header, + channel_commands, + channel_stop, + channel_start, + channel_clear, + channel_cacheadd, + channel_downforce, + channel_label, + channel_info, + channel_next, + channel_prev, + channel_all, + channel_viewport, + channel_all_form, + channel_all_list; + +extern struct chan_struct *currentchan; +extern int max_chan_border, + read_currentchan; +char *curlabel, + *channel_info_str, + *create_channel_header(); +int channel_info_strlen; + +static void create_channelwidgets() +{ + Widget temp_form; + char *str; + + channel_form = XtVaCreateManagedWidget("channelForm", + formWidgetClass, + mainvpane, + NULL); + + channel_header = XtVaCreateManagedWidget("channelHeader", + labelWidgetClass, + channel_form, + NULL); + if (normalFont != NULL) + XtSetValues(channel_header,argList, 1); + + XtVaGetValues(channel_header, + XtNlabel, &str, + NULL); + + /* check for ap defaults */ + if (lexequ(str, "channelHeader") == 0) { + printf("The application defaults aren't installed!\n"); + exit(1); + } + channel_commands = XtVaCreateManagedWidget("channelCommands", + boxWidgetClass, + channel_form, + NULL); + + channel_info = XtVaCreateManagedWidget("channelInfo", + commandWidgetClass, + channel_commands, + XtNlabel, "info", + NULL); + if (normalFont != NULL) + XtSetValues(channel_info,argList, 1); + XtAddCallback(channel_info, XtNcallback, Command, chaninfo); + + channel_next = XtVaCreateManagedWidget("channelNext", + commandWidgetClass, + channel_commands, + NULL); + if (normalFont != NULL) + XtSetValues(channel_next,argList, 1); + XtAddCallback(channel_next, XtNcallback, Command, channext); + + channel_prev = XtVaCreateManagedWidget("channelPrev", + commandWidgetClass, + channel_commands, + NULL); + if (normalFont != NULL) + XtSetValues(channel_prev,argList, 1); + XtAddCallback(channel_prev, XtNcallback, Command, chanprev); + + + channel_stop = XtVaCreateManagedWidget("channelStop", + commandWidgetClass, + channel_commands, + XtNlabel, "disable", + NULL); + if (normalFont != NULL) + XtSetValues(channel_stop,argList, 1); + + XtAddCallback(channel_stop, XtNcallback, Command, chanstop); + + channel_start = XtVaCreateManagedWidget("channelStart", + commandWidgetClass, + channel_commands, + XtNlabel, "enable", + NULL); + if (normalFont != NULL) + XtSetValues(channel_start,argList, 1); + + XtAddCallback(channel_start, XtNcallback, Command, chanstart); + + channel_clear = XtVaCreateManagedWidget("channelClear", + commandWidgetClass, + channel_commands, + NULL); + if (normalFont != NULL) + XtSetValues(channel_clear,argList, 1); + + XtAddCallback(channel_clear, XtNcallback, Command, chanclear); + + channel_cacheadd = XtVaCreateManagedWidget("channelCacheadd", + commandWidgetClass, + channel_commands, + NULL); + if (normalFont != NULL) + XtSetValues(channel_cacheadd,argList, 1); + + XtAddCallback(channel_cacheadd, XtNcallback, Command, chancacheadd); + + channel_downforce = XtVaCreateManagedWidget("channelDownforce", + commandWidgetClass, + channel_commands, + NULL); + if (normalFont != NULL) + XtSetValues(channel_downforce,argList, 1); + + XtAddCallback (channel_downforce, XtNcallback, Command, chandownforce); + + + currentchan = NULL; + read_currentchan = 0; + curlabel = create_channel_header(); + channel_label = XtVaCreateManagedWidget("channelLabel", + labelWidgetClass, + channel_form, + XtNlabel, curlabel, + NULL); + free(curlabel); + if (normalFont != NULL) + XtSetValues(channel_label,argList, 1); + + temp_form = XtVaCreateManagedWidget("channelForm2", + formWidgetClass, + mainvpane, + NULL); + + channel_viewport = XtVaCreateManagedWidget("channelViewport", + viewportWidgetClass, + temp_form, + NULL); + + channels = XtVaCreateManagedWidget("channels", + boxWidgetClass, + channel_viewport, + XtNvSpace, (2*max_chan_border +1), + NULL); + + channel_all = XtVaCreateManagedWidget("channelAllViewport", + viewportWidgetClass, + temp_form, + NULL); + channel_all_form = XtVaCreateManagedWidget("channelAll", + formWidgetClass, + channel_all, + NULL); + /* channel info widgets */ + channel_all_list = XtVaCreateManagedWidget("channelAllList", + listWidgetClass, + channel_all_form, + NULL); + if (normalFont != NULL) + XtSetValues(channel_all_list, argList, 1); + + XtSetMappedWhenManaged(channel_form, False); + XtSetSensitive(channel_commands,FALSE); +} + +Widget control_vpane; + +static void create_controlwidgets() +{ + control_form = XtVaCreateManagedWidget("controlForm", + formWidgetClass, + switchform, + NULL); + + control_vpane = XtVaCreateManagedWidget("controlVpane", + panedWidgetClass, + control_form, + NULL); + create_mtawidgets(); + create_msgwidgets(); +} + +Widget mta_divider, + mta_commands, + mta_stop, + mta_start, + mta_clear, + mta_cacheadd, + mta_force, + mta_downforce, + mta_label, + mta_info, + mta_next, + mta_prev, + mta_all, + mta_all_form, + mta_all_list, + mta_viewport, + mtas; +extern struct mta_struct *currentmta; +extern int read_currentmta; +extern int max_mta_border; +extern char *create_mta_header(); +char *mta_info_str; +int mta_info_strlen; + +static void create_mtawidgets() +{ + Widget temp_form; + + mta_form = XtVaCreateManagedWidget("mtaForm", + formWidgetClass, + control_vpane, + NULL); + + mta_divider = XtVaCreateManagedWidget("mtaDivider", + labelWidgetClass, + mta_form, + NULL); + if (normalFont != NULL) + XtSetValues(mta_divider,argList, 1); + + mta_commands = XtVaCreateManagedWidget("mtaCommands", + boxWidgetClass, + mta_form, + NULL); + XtSetSensitive(mta_commands, FALSE); + + mta_info = XtVaCreateManagedWidget("mtaInfo", + commandWidgetClass, + mta_commands, + XtNlabel, "info", + NULL); + if (normalFont != NULL) + XtSetValues(mta_info,argList, 1); + + XtAddCallback(mta_info, XtNcallback, Command, mtainfo); + + mta_next = XtVaCreateManagedWidget("mtaNext", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_next,argList, 1); + + XtAddCallback(mta_next, XtNcallback, Command, mtanext); + + mta_prev = XtVaCreateManagedWidget("mtaPrev", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_prev,argList, 1); + + XtAddCallback(mta_prev, XtNcallback, Command, mtaprev); + + mta_stop = XtVaCreateManagedWidget("mtaStop", + commandWidgetClass, + mta_commands, + XtNlabel, "disable", + NULL); + if (normalFont != NULL) + XtSetValues(mta_stop,argList, 1); + + XtAddCallback(mta_stop, XtNcallback, Command, mtastop); + + mta_start = XtVaCreateManagedWidget("mtaStart", + commandWidgetClass, + mta_commands, + XtNlabel, "enable", + NULL); + if (normalFont != NULL) + XtSetValues(mta_start,argList, 1); + + XtAddCallback(mta_start, XtNcallback, Command, mtastart); + + mta_clear = XtVaCreateManagedWidget("mtaClear", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_clear,argList, 1); + + XtAddCallback(mta_clear, XtNcallback, Command, mtaclear); + + mta_cacheadd = XtVaCreateManagedWidget("mtaCacheadd", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_cacheadd,argList, 1); + + XtAddCallback(mta_cacheadd, XtNcallback, Command, mtacacheadd); + + mta_force = XtVaCreateManagedWidget("mtaForce", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_force,argList, 1); + + XtAddCallback(mta_force, XtNcallback, Command, mtaforce); + + mta_downforce = XtVaCreateManagedWidget("mtaDownforce", + commandWidgetClass, + mta_commands, + NULL); + if (normalFont != NULL) + XtSetValues(mta_downforce,argList, 1); + + XtAddCallback (mta_downforce, XtNcallback, Command, mtadownforce); + + currentmta = NULL; + read_currentmta = 0; + curlabel = create_mta_header(); + mta_label = XtVaCreateManagedWidget("mtaLabel", + labelWidgetClass, + mta_form, + XtNlabel, curlabel, + NULL); + free(curlabel); + if (normalFont != NULL) + XtSetValues(mta_label,argList, 1); + + temp_form = XtVaCreateManagedWidget("mtaForm2", + formWidgetClass, + control_vpane, + NULL); + + mta_viewport = XtVaCreateManagedWidget("mtaViewport", + viewportWidgetClass, + temp_form, + NULL); + mtas = XtVaCreateManagedWidget("mtas", + boxWidgetClass, + mta_viewport, + XtNdefaultDistance, (2*max_mta_border+1), + NULL); + mta_all = XtVaCreateManagedWidget("mtaAllViewport", + viewportWidgetClass, + temp_form, + NULL); + mta_all_form = XtVaCreateManagedWidget("mtaAll", + formWidgetClass, + mta_all, + NULL); + mta_all_list = XtVaCreateManagedWidget("mtaAllList", + listWidgetClass, + mta_all_form, + NULL); + if (normalFont != NULL) + XtSetValues(mta_all_list, argList, 1); +} + +Widget msg_divider, + msg_commands, + msg_stop, + msg_start, + msg_clear, + msg_cacheadd, + msg_force, + msg_label, + msg_info, + msg_next, + msg_prev, + msg_all, + msg_all_form, + msg_all_list, + msgs_showall, + msg_viewport, + msgs; + +extern struct msg_struct *currentmsg; +extern char *create_msg_header(); +extern void MsgsShowAll(); +char *msg_info_str; +int msg_info_strlen; + +static void create_msgwidgets() +{ + Widget temp_form; + + msg_form = XtVaCreateManagedWidget("msgForm", + formWidgetClass, + control_vpane, + NULL); + + msg_divider = XtVaCreateManagedWidget("msgDivider", + labelWidgetClass, + msg_form, + NULL); + if (normalFont != NULL) + XtSetValues(msg_divider,argList, 1); + + msg_commands = XtVaCreateManagedWidget("msgCommands", + boxWidgetClass, + msg_form, + NULL); + XtSetSensitive(msg_commands, FALSE); + + msg_info = XtVaCreateManagedWidget("msgInfo", + commandWidgetClass, + msg_commands, + XtNlabel, "info", + NULL); + if (normalFont != NULL) + XtSetValues(msg_info,argList, 1); + XtAddCallback(msg_info, XtNcallback, Command, msginfo); + + msg_next = XtVaCreateManagedWidget("msgNext", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msg_next,argList, 1); + XtAddCallback(msg_next, XtNcallback, Command, msgnext); + + msg_prev = XtVaCreateManagedWidget("msgPrev", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msg_prev,argList, 1); + XtAddCallback(msg_prev, XtNcallback, Command, msgprev); + + msgs_showall = XtVaCreateManagedWidget("msgShowall", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msgs_showall,argList, 1); + XtAddCallback(msgs_showall, XtNcallback, MsgsShowAll, NULL); + + msg_stop = XtVaCreateManagedWidget("msgStop", + commandWidgetClass, + msg_commands, + XtNlabel, "freeze", + NULL); + if (normalFont != NULL) + XtSetValues(msg_stop,argList, 1); + XtAddCallback(msg_stop, XtNcallback, Command, msgstop); + + msg_start = XtVaCreateManagedWidget("msgStart", + commandWidgetClass, + msg_commands, + XtNlabel, "thaw", + NULL); + if (normalFont != NULL) + XtSetValues(msg_start,argList, 1); + XtAddCallback(msg_start, XtNcallback, Command, msgstart); + + msg_clear = XtVaCreateManagedWidget("msgClear", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msg_clear,argList, 1); + XtAddCallback(msg_clear, XtNcallback, Command, msgclear); + + msg_cacheadd = XtVaCreateManagedWidget("msgCacheadd", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msg_cacheadd,argList, 1); + + XtAddCallback(msg_cacheadd, XtNcallback, Command, msgcacheadd); + + msg_force = XtVaCreateManagedWidget("msgForce", + commandWidgetClass, + msg_commands, + NULL); + if (normalFont != NULL) + XtSetValues(msg_force,argList, 1); + + XtAddCallback(msg_force, XtNcallback, Command, msgforce); + + currentmsg = NULL; + curlabel = create_msg_header(); + msg_label = XtVaCreateManagedWidget("msgLabel", + labelWidgetClass, + msg_form, + XtNlabel, curlabel, + NULL); + free(curlabel); + if (normalFont != NULL) + XtSetValues(msg_label,argList, 1); + temp_form = XtVaCreateManagedWidget("msgForm2", + formWidgetClass, + control_vpane, + NULL); + + msg_viewport = XtVaCreateManagedWidget("msgViewport", + viewportWidgetClass, + temp_form, + NULL); + msgs = XtVaCreateManagedWidget("msgs", + formWidgetClass, + msg_viewport, + NULL); + + msg_all = XtVaCreateManagedWidget("msgAllViewport", + viewportWidgetClass, + temp_form, + NULL); + msg_all_form = XtVaCreateManagedWidget("msgAll", + formWidgetClass, + msg_all, + NULL); + msg_all_list = XtVaCreateManagedWidget("msgAllList", + listWidgetClass, + msg_all_form, + NULL); + if (normalFont != NULL) + XtSetValues(msg_all_list, argList, 1); +} + +Widget monitor_form; + +static void create_monitorwidgets() +{ + Dimension wid, + ht; + XtVaGetValues(control_form, + XtNwidth, &wid, + XtNheight, &ht, + NULL); + + monitor_viewport = XtVaCreateWidget("monitorViewport", + viewportWidgetClass, + switchform, + XtNwidth, wid, /*TOTAL_WIDTH,*/ + XtNheight, ht, /* (2*VP_HEIGHT+4*26),*/ + NULL); + + monitor_form = XtVaCreateManagedWidget("monitorForm", + formWidgetClass, + monitor_viewport, + XtNwidth, wid, + XtNheight, ht, + NULL); + XtManageChild(monitor_viewport); + XtSetMappedWhenManaged(monitor_viewport, True); + XtSetMappedWhenManaged(control_form, False); +} + +/* */ +/* popups */ + +Popup_menu *yesno, + *one, + *two, + *three, + *config, + *connectpopup, + *qcontrol; +Widget qversion, + refresh_toggle, + reconnect_toggle, + backoff_toggle, + confirm_toggle, + compat_toggle, + inbounds_toggle, + heur_toggle, + percent_form, + line_form, + auth_toggle; + +extern void previousField(), + nextField(), + thisField(), + myinsert_char(), + mydelete_char(), + mymenupopdown(), + curChan(), + excl_curChan(), + readChan(), + curMta(), + excl_curMta(), + readMta(), + curMsg(), + excl_curMsg(), + readMsg(), + chanMode(), + chanModeRead(), + chanRefresh(), + mtaMode(), + mtaModeRead(), + mtaRefresh(), + QControl(), + popup_OK(), + popup_NOTOK(), + config_OK(), + connectpopup_OK(), + configToggle(), + heurToggle(); +extern int autoRefresh, + autoReconnect, + backoff, + confirm, + compat, + displayInactIns, + auth; +int newautoRefresh, + newautoReconnect, + newbackoff, + newconfirm, + newcompat, + newdisplayInactIns, + newauth; +Heuristic newheur; +extern Heuristic heuristic; +unsigned long newTimes; + +XtActionsRec actionTable[] = { +{"previousField", previousField}, +{"nextField", nextField}, +{"thisField", thisField}, +{"myinsert_char", myinsert_char}, +{"mydelete_char", mydelete_char}, +{"mymenupopdown", mymenupopdown}, +{"curChan", curChan}, +{"excl_curChan", excl_curChan}, +{"readChan", readChan}, +{"curMta", curMta}, +{"excl_curMta", excl_curMta}, +{"readMta", readMta}, +{"curMsg", curMsg}, +{"excl_curMsg", excl_curMsg}, +{"readMsg", readMsg}, +{"chanMode", chanMode}, +{"chanModeRead", chanModeRead}, +{"chanRefresh", chanRefresh}, +{"mtaMode", mtaMode}, +{"mtaModeRead", mtaModeRead}, +{"mtaRefresh", mtaRefresh}, +}; + +XtTranslations channel_monitorTranslations, + mta_monitorTranslations, + passwdTranslations; + +/*static char *channel_translationTable = + ": curChan() readChan()\n\ + : excl_curChan()\n\ + : readChan()\n";*/ +static char *channel_monitortranslationTable = + ": chanModeRead()\n\ + : chanMode()\n\ + : chanRefresh()\n"; +/*static char *mta_translationTable = + ": curMta() readMta()\n\ + : excl_curMta()\n\ + : readMta()\n";*/ +static char *mta_monitortranslationTable = + ": mtaModeRead()\n\ + : mtaMode()\n\ + : mtaRefresh()\n"; +/*static char *msg_translationTable = + ": curMsg() readMsg()\n\ + : excl_curMsg()\n\ + : readMsg()\n";*/ +/*static char *text_translationTable = + "Up: previousField()\n\ + Down: nextField()\n\ + Tab: nextField()\n\ + : thisField() select-start()\n";*/ +static char *passwd_translationTable = + "Up: previousField()\n\ + Down: nextField()\n\ + Tab: nextField()\n\ + : thisField()\n\ + Delete: mydelete_char()\n\ + BackSpace: mydelete_char()\n\ + : myinsert_char()\n"; +/*static char *qcontrol_translationTable = + ": mymenupopdown()\n\ + : mymenupopdown()\n";*/ + +/*static char *OKAcceleratorTable = + "#override\n\ +Return: set() notify()";*/ + +static void create_defaultHostspopup() +{ +} + +static void create_popupwidgets(context) +XtAppContext context; +{ + Widget OKwg, + NOTOKwg, + label, + version; + Arg arg[2]; + int i; + char *str = NULL; + extern char password[]; + + XtAppAddActions(context, actionTable, XtNumber(actionTable)); + passwdTranslations = XtParseTranslationTable(passwd_translationTable); + channel_monitorTranslations = XtParseTranslationTable(channel_monitortranslationTable); + mta_monitorTranslations = XtParseTranslationTable(mta_monitortranslationTable); + create_defaultHostspopup(); + + XtSetArg(arg[0], XtNallowShellResize, True); + XtSetArg(arg[1], XtNinput, True); + + qcontrol = (Popup_menu *) calloc(1, sizeof(*qcontrol)); + qcontrol->popup = XtCreatePopupShell("qcontrol", + overrideShellWidgetClass, + qcontrol_command, + arg, + 2); + qcontrol->form = XtVaCreateManagedWidget("qcontrolForm", + boxWidgetClass, + qcontrol->popup, + NULL); + + label = XtVaCreateManagedWidget("increaseMaxChannels", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_increasemaxchans); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + label = XtVaCreateManagedWidget("decreaseMaxChannels", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_decreasemaxchans); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("enableSubmission", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_enableSubmission); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("disableSubmission", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_disableSubmission); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("enableAll", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_enableAll); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("disableAll", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_disableAll); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("rereadQ", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_rereadQueue); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("restartQmgr", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_restart); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("gracefulStop", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_gracefulTerminate); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + label = XtVaCreateManagedWidget("emergencyStop", + commandWidgetClass, + qcontrol->form, + NULL); + XtAddCallback(label, XtNcallback, + QControl, int_Qmgr_QMGROp_abort); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + yesno = (Popup_menu *) calloc(1, sizeof(*yesno)); + + yesno->popup = XtCreatePopupShell("yesno_popup", + transientShellWidgetClass, + quit_command, + arg, + 2); + + yesno->form = XtVaCreateManagedWidget("yesnoForm", + formWidgetClass, + yesno->popup, + NULL); + + OKwg = XtVaCreateManagedWidget("yesnoOK", + commandWidgetClass, + yesno->form, + NULL); + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + yesno->op = unknown; + XtAddCallback(OKwg, XtNcallback, popup_OK, &(yesno->op)); + + NOTOKwg = XtVaCreateManagedWidget("yesnoNotok", + commandWidgetClass, + yesno->form, + NULL); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(yesno->op)); + XtInstallAllAccelerators(yesno->form, yesno->form); + + one = (Popup_menu *) calloc(1, sizeof(*one)); + one->tuple = (Popup_tuple *) calloc(1, sizeof(Popup_tuple)); + one->numberOftuples = 1; + one->popup = XtCreatePopupShell("onetext_popup", + transientShellWidgetClass, + quit_command, + arg, + 2); + + one->form = XtVaCreateManagedWidget("oneForm", + formWidgetClass, + one->popup, + NULL); + + OKwg = XtVaCreateManagedWidget("oneOk", + commandWidgetClass, + one->form, + NULL); + one->op = unknown; + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + XtAddCallback(OKwg, XtNcallback, popup_OK, &(one->op)); + + NOTOKwg = XtVaCreateManagedWidget("oneNotok", + commandWidgetClass, + one->form, + NULL); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(one->op)); + + one->tuple[0].label = XtVaCreateManagedWidget("oneLabelOne", + labelWidgetClass, + one->form, + XtNlabel, "clear cache on channel ", + NULL); + if (normalFont != NULL) + XtSetValues(one->tuple[0].label,argList, 1); + + if (normalFont != NULL) + one->tuple[0].text = XtVaCreateManagedWidget("oneTextOne", + asciiTextWidgetClass, + one->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNfont, normalFont, + NULL); + else + one->tuple[0].text = XtVaCreateManagedWidget("oneTextOne", + asciiTextWidgetClass, + one->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + NULL); + + XtInstallAllAccelerators(one->tuple[0].text, one->form); + + two = (Popup_menu *) calloc(1, sizeof(*two)); + two->tuple = (Popup_tuple *) calloc(2, sizeof(Popup_tuple)); + two->numberOftuples = 2; + two->popup = XtCreatePopupShell("twotext_popup", + transientShellWidgetClass, + quit_command, + arg, + 2); + two->form = XtVaCreateManagedWidget("twoForm", + formWidgetClass, + two->popup, + NULL); + OKwg = XtVaCreateManagedWidget("twoOk", + commandWidgetClass, + two->form, + NULL); + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + two->op = unknown; + XtAddCallback(OKwg, XtNcallback, popup_OK, &(two->op)); + + NOTOKwg = XtVaCreateManagedWidget("twoNotok", + commandWidgetClass, + two->form, + NULL); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(two->op)); + + two->tuple[0].label = XtVaCreateManagedWidget("twoLabelOne", + labelWidgetClass, + two->form, + XtNlabel, "clear cache on channel", + NULL); + if (normalFont != NULL) + XtSetValues(two->tuple[0].label,argList, 1); + + if (normalFont != NULL) + two->tuple[0].text = XtVaCreateManagedWidget("twoTextOne", + asciiTextWidgetClass, + two->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNfont, normalFont, + NULL); + else + two->tuple[0].text = XtVaCreateManagedWidget("twoTextOne", + asciiTextWidgetClass, + two->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + NULL); + + two->tuple[1].label = XtVaCreateManagedWidget("twoLabelTwo", + labelWidgetClass, + two->form, + XtNlabel, "clear cache on channel", + NULL); + if (normalFont != NULL) + XtSetValues(two->tuple[1].label,argList, 1); + + if (normalFont != NULL) + two->tuple[1].text = XtVaCreateManagedWidget("twoTextTwo", + asciiTextWidgetClass, + two->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNfont, normalFont, + NULL); + else + two->tuple[1].text = XtVaCreateManagedWidget("twoTextTwo", + asciiTextWidgetClass, + two->form, + XtNresize, XawtextResizeWidth, + XtNscrollVertical, XawtextScrollWhenNeeded, + NULL); + + XtInstallAllAccelerators(two->tuple[0].text, two->form); + XtInstallAllAccelerators(two->tuple[1].text, two->form); + + three = (Popup_menu *) calloc(1, sizeof(*three)); + three->op = unknown; + three->tuple = (Popup_tuple *) calloc(3, sizeof(Popup_tuple)); + three->numberOftuples = 3; + three->popup = XtCreatePopupShell("threetext_popup", + transientShellWidgetClass, + quit_command, + arg, + 2); + three->form = XtVaCreateManagedWidget("threeForm", + formWidgetClass, + three->popup, + XtNborderWidth, 0, + NULL); + OKwg = XtVaCreateManagedWidget("threeOk", + commandWidgetClass, + three->form, + NULL); + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + XtAddCallback(OKwg, XtNcallback, popup_OK, &(three->op)); + + NOTOKwg = XtVaCreateManagedWidget("threeNotok", + commandWidgetClass, + three->form, + NULL); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(three->op)); + + three->tuple[0].label = XtVaCreateManagedWidget("threeLabelOne", + labelWidgetClass, + three->form, + XtNlabel, "clear cache on channel", + NULL); + + if (normalFont != NULL) + XtSetValues(three->tuple[0].label,argList, 1); + if (normalFont != NULL) + three->tuple[0].text = XtVaCreateManagedWidget("threeTextOne", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + three->tuple[0].text = XtVaCreateManagedWidget("threeTextOne", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + three->tuple[1].label = XtVaCreateManagedWidget("threeLabelTwo", + labelWidgetClass, + three->form, + XtNlabel, "clear cache on channel", + NULL); + if (normalFont != NULL) + XtSetValues(three->tuple[1].label,argList, 1); + + if (normalFont == NULL) + three->tuple[1].text = XtVaCreateManagedWidget("threeTextTwo", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + three->tuple[1].text = XtVaCreateManagedWidget("threeTextTwo", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + three->tuple[2].label = XtVaCreateManagedWidget("threeLabelThree", + labelWidgetClass, + three->form, + XtNlabel, "clear cache on channel", + NULL); + if (normalFont != NULL) + XtSetValues(three->tuple[2].label,argList, 1); + if (normalFont == NULL) + three->tuple[2].text = XtVaCreateManagedWidget("threeTextThree", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + three->tuple[2].text = XtVaCreateManagedWidget("threeTextThree", + asciiTextWidgetClass, + three->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + XtInstallAllAccelerators(three->tuple[0].text, three->form); + XtInstallAllAccelerators(three->tuple[1].text, three->form); + XtInstallAllAccelerators(three->tuple[2].text, three->form); + + config = (Popup_menu *) calloc(1, sizeof(*config)); + config->op = unknown; + config->numberOftuples = 8; + config->tuple = (Popup_tuple *) calloc((unsigned)config->numberOftuples, + sizeof(Popup_tuple)); + + config->popup = XtCreatePopupShell("config_popup", + transientShellWidgetClass, + config_command, + arg, + 2); + config->form = XtVaCreateManagedWidget("configForm", + formWidgetClass, + config->popup, + NULL); + + OKwg = XtVaCreateManagedWidget("configOk", + commandWidgetClass, + config->form, + NULL); + XtAddCallback(OKwg, XtNcallback, config_OK, NULL); + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + + NOTOKwg = XtVaCreateManagedWidget("configNotok", + commandWidgetClass, + config->form, + NULL); + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(config->op)); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + + label = XtVaCreateManagedWidget("versionLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + version = XtVaCreateManagedWidget("configVersion", + labelWidgetClass, + config->form, + XtNlabel, ppversion, + NULL); + if (normalFont != NULL) + XtSetValues(version,argList, 1); + + label = XtVaCreateManagedWidget("qmgrVersionLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + qversion = XtVaCreateManagedWidget("qmgrVersion", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(qversion,argList, 1); + + label = XtVaCreateManagedWidget("autoRefreshLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + refresh_toggle = XtVaCreateManagedWidget("autoRefreshToggle", + commandWidgetClass, + config->form, + XtNlabel, (autoRefresh == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(refresh_toggle,argList, 1); + + XtAddCallback(refresh_toggle, XtNcallback, configToggle, &newautoRefresh); + + config->tuple[REFRESH].label = XtVaCreateManagedWidget("refreshIntervalLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[REFRESH].label,argList, 1); + + if (normalFont == NULL) + config->tuple[REFRESH].text = XtVaCreateManagedWidget("refreshIntervalText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[REFRESH].text = XtVaCreateManagedWidget("refreshIntervalText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + config->tuple[INACTIVE].label = XtVaCreateManagedWidget("inactiveLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[INACTIVE].label,argList, 1); + + if (normalFont == NULL) + config->tuple[INACTIVE].text = XtVaCreateManagedWidget("inactiveText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[INACTIVE].text = XtVaCreateManagedWidget("inactiveText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + label = XtVaCreateManagedWidget("autoReconnectLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + reconnect_toggle = XtVaCreateManagedWidget("autoReconnectToggle", + commandWidgetClass, + config->form, + XtNlabel, (autoReconnect == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(reconnect_toggle,argList, 1); + XtAddCallback(reconnect_toggle, XtNcallback, configToggle, &newautoReconnect); + + config->tuple[START].label = XtVaCreateManagedWidget("arStartLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[START].label,argList, 1); + + if (normalFont == NULL) + config->tuple[START].text = XtVaCreateManagedWidget("arStartText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[START].text = XtVaCreateManagedWidget("arStartText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + label = XtVaCreateManagedWidget("backOffLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + backoff_toggle = XtVaCreateManagedWidget("backOffToggle", + commandWidgetClass, + config->form, + XtNlabel, (backoff == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(backoff_toggle,argList, 1); + + XtAddCallback(backoff_toggle, XtNcallback, configToggle, &newbackoff); + + config->tuple[BACKOFF].label = XtVaCreateManagedWidget("boIncLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[BACKOFF].label,argList, 1); + + + if (normalFont == NULL) + config->tuple[BACKOFF].text = XtVaCreateManagedWidget("boIncText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[BACKOFF].text = XtVaCreateManagedWidget("boIncText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + config->tuple[CONNECTMAX].label = XtVaCreateManagedWidget("maxRCIntLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[CONNECTMAX].label,argList, 1); + + if (normalFont == NULL) + config->tuple[CONNECTMAX].text = XtVaCreateManagedWidget("maxRCIntText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[CONNECTMAX].text = XtVaCreateManagedWidget("maxRCIntText", + asciiTextWidgetClass, + config->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + label = XtVaCreateManagedWidget("confPopupLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + confirm_toggle = XtVaCreateManagedWidget ("confPopupToggle", + commandWidgetClass, + config->form, + XtNlabel, (confirm == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(confirm_toggle,argList, 1); + XtAddCallback(confirm_toggle, XtNcallback, configToggle, &newconfirm); + + label = XtVaCreateManagedWidget("compatPopupLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + compat_toggle = XtVaCreateManagedWidget ("compatPopupToggle", + commandWidgetClass, + config->form, + XtNlabel, (compat == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(compat_toggle,argList, 1); + XtAddCallback(compat_toggle, XtNcallback, configToggle, &newcompat); + + label = XtVaCreateManagedWidget("inboundPopupLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + inbounds_toggle = XtVaCreateManagedWidget ("inboundPopupToggle", + commandWidgetClass, + config->form, + XtNlabel, (displayInactIns == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(inbounds_toggle,argList, 1); + XtAddCallback(inbounds_toggle, XtNcallback, configToggle, &newdisplayInactIns); + + label = XtVaCreateManagedWidget ("heurLabel", + labelWidgetClass, + config->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + + switch (heuristic) { + case percentage: + str = PERCENT_BASED; + break; + case all: + str = ALL_BASED; + break; + default: + heuristic = line; + case line: + str = LINE_BASED; + break; + case chanonly: + str = CHANONLY_BASED; + break; + } + heur_toggle = XtVaCreateManagedWidget("heurToggle", + commandWidgetClass, + config->form, + XtNlabel, str, + NULL); + newheur = heuristic; + if (normalFont != NULL) + XtSetValues(heur_toggle,argList, 1); + XtAddCallback(heur_toggle, XtNcallback, heurToggle, &newheur); + + percent_form = XtVaCreateManagedWidget("percentForm", + formWidgetClass, + config->form, + NULL); + + config->tuple[PERCENT].label = XtVaCreateManagedWidget ("percentLabel", + labelWidgetClass, + percent_form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[PERCENT].label,argList, 1); + if (normalFont == NULL) + config->tuple[PERCENT].text = XtVaCreateManagedWidget("percentText", + asciiTextWidgetClass, + percent_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[PERCENT].text = XtVaCreateManagedWidget("percentText", + asciiTextWidgetClass, + percent_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + config->tuple[MINBADMTA].label = XtVaCreateManagedWidget ("numBadMtasLabel", + labelWidgetClass, + percent_form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[MINBADMTA].label,argList, 1); + if (normalFont == NULL) + config->tuple[MINBADMTA].text = XtVaCreateManagedWidget("numBadMtasText", + asciiTextWidgetClass, + percent_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + config->tuple[MINBADMTA].text = XtVaCreateManagedWidget("numBadMtasText", + asciiTextWidgetClass, + percent_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + line_form = XtVaCreateManagedWidget("lineForm", + formWidgetClass, + config->form, + NULL); + config->tuple[LINEMAX].label = XtVaCreateManagedWidget ("lineLabel", + labelWidgetClass, + line_form, + NULL); + if (normalFont != NULL) + XtSetValues(config->tuple[LINEMAX].label,argList, 1); + if (normalFont == NULL) + config->tuple[LINEMAX].text = XtVaCreateManagedWidget("lineText", + asciiTextWidgetClass, + line_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else config->tuple[LINEMAX].text = XtVaCreateManagedWidget("lineText", + asciiTextWidgetClass, + line_form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + switch (heuristic) { + case percentage: + XtSetMappedWhenManaged (line_form, FALSE); + break; + case line: + XtSetMappedWhenManaged (percent_form, FALSE); + break; + case all: + case chanonly: + XtSetMappedWhenManaged (line_form, FALSE); + XtSetMappedWhenManaged (percent_form, FALSE); + break; + } + + + for (i = 0; i < config->numberOftuples; i++) { + XtInstallAllAccelerators(config->tuple[i].text, config->form); + } + + connectpopup = (Popup_menu *) calloc(1, sizeof(Popup_menu)); + connectpopup->op = connect; + connectpopup->tuple = (Popup_tuple *) calloc(4, sizeof(Popup_tuple)); + connectpopup->numberOftuples = 4; + + connectpopup->popup = XtCreatePopupShell("connectpopup", + transientShellWidgetClass, + connect_command, + arg, + 2); + connectpopup->form = XtVaCreateManagedWidget("connectForm", + formWidgetClass, + connectpopup->popup, + NULL); + OKwg = XtVaCreateManagedWidget("connectOk", + commandWidgetClass, + connectpopup->form, + NULL); + XtAddCallback(OKwg, XtNcallback, connectpopup_OK, NULL); + if (normalFont != NULL) + XtSetValues(OKwg,argList, 1); + NOTOKwg = XtVaCreateManagedWidget("connectNotok", + commandWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(NOTOKwg,argList, 1); + XtAddCallback(NOTOKwg, XtNcallback, popup_NOTOK, &(connectpopup->op)); + + connectpopup->tuple[0].label = XtVaCreateManagedWidget("connectToLabel", + labelWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(connectpopup->tuple[0].label,argList, 1); + if (normalFont != NULL) + connectpopup->tuple[0].text = XtVaCreateManagedWidget("connectToText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + else + connectpopup->tuple[0].text = XtVaCreateManagedWidget("connectToText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + connectpopup->tuple[1].label = XtVaCreateManagedWidget("taiFileLabel", + labelWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(connectpopup->tuple[1].label,argList, 1); + if (normalFont == NULL) + connectpopup->tuple[1].text = XtVaCreateManagedWidget("taiFileText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); + else + connectpopup->tuple[1].text = XtVaCreateManagedWidget("taiFileText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + label = XtVaCreateManagedWidget("authLabel", + labelWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(label,argList, 1); + auth_toggle = XtVaCreateManagedWidget("authToggle", + commandWidgetClass, + connectpopup->form, + XtNlabel, (auth == TRUE) ? "enabled" : "disabled", + NULL); + if (normalFont != NULL) + XtSetValues(auth_toggle,argList, 1); + XtAddCallback(auth_toggle, XtNcallback, configToggle, &newauth); + + connectpopup->tuple[2].label = XtVaCreateManagedWidget("userLabel", + labelWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(connectpopup->tuple[2].label,argList, 1); +if (normalFont == NULL) + connectpopup->tuple[2].text = XtVaCreateManagedWidget("userText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); +else + connectpopup->tuple[2].text = XtVaCreateManagedWidget("userText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + + connectpopup->tuple[3].label = XtVaCreateManagedWidget("passwdLabel", + labelWidgetClass, + connectpopup->form, + NULL); + if (normalFont != NULL) + XtSetValues(connectpopup->tuple[3].label,argList, 1); +if (normalFont == NULL) + connectpopup->tuple[3].text = XtVaCreateManagedWidget("passwdText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + NULL); +else + connectpopup->tuple[3].text = XtVaCreateManagedWidget("passwdText", + asciiTextWidgetClass, + connectpopup->form, + XtNscrollVertical, XawtextScrollWhenNeeded, + XtNresize, XawtextResizeWidth, + XtNfont, normalFont, + NULL); + XtOverrideTranslations(connectpopup->tuple[3].text, passwdTranslations); + XtInstallAllAccelerators(connectpopup->tuple[0].text, + connectpopup->form); + XtInstallAllAccelerators(connectpopup->tuple[1].text, + connectpopup->form); + XtInstallAllAccelerators(connectpopup->tuple[2].text, + connectpopup->form); + XtInstallAllAccelerators(connectpopup->tuple[3].text, + connectpopup->form); +} + +MapVolume(bool) +int bool; +{ + XtSetMappedWhenManaged(total_volume_label, bool); + XtSetMappedWhenManaged(total_number_label, bool); +} + +MapButtons(bool) +int bool; +{ + /* various buttons that need auth */ + XtSetMappedWhenManaged(qcontrol_command, bool); + + XtSetMappedWhenManaged(channel_stop, bool); + XtSetMappedWhenManaged(channel_start, bool); + XtSetMappedWhenManaged(channel_cacheadd, bool); + XtSetMappedWhenManaged(channel_downforce, bool); + XtSetMappedWhenManaged(channel_clear, bool); + + XtSetMappedWhenManaged(mta_stop, bool); + XtSetMappedWhenManaged(mta_start, bool); + XtSetMappedWhenManaged(mta_cacheadd, bool); + XtSetMappedWhenManaged(mta_force, bool); + XtSetMappedWhenManaged(mta_downforce, bool); + XtSetMappedWhenManaged(mta_clear, bool); + + XtSetMappedWhenManaged(msg_stop, bool); + XtSetMappedWhenManaged(msg_start, bool); + XtSetMappedWhenManaged(msg_cacheadd, bool); + XtSetMappedWhenManaged(msg_force, bool); + XtSetMappedWhenManaged(msg_clear, bool); +} diff --git a/Src/MTAconsole/data.c b/Src/MTAconsole/data.c new file mode 100644 index 0000000..df04ff1 --- /dev/null +++ b/Src/MTAconsole/data.c @@ -0,0 +1,746 @@ +/* data.c: routines to deal with data structures */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/data.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/data.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: data.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" +#include "Qmgr-types.h" + +extern time_t convert_time(); +struct chan_struct *find_channel(); +struct mta_struct *find_mta(); +struct procStatus *create_status(); +void update_status(); +/* */ +/* channel */ +static void create_channel_list(); +static void update_channel_list(); +static struct chan_struct *create_channel(); +static void update_channel(); + +struct monitor_item **display_list = NULL; +struct chan_struct **globallist = NULL, + **ordered_list = NULL, + *currentchan = NULL; +int num_channels, + read_currentchan = 0; +int firstChanRead; +int total_number_messages, + total_number_reports, + total_volume, + delta_volume, + delta_messages, + delta_reports; +extern int forceDown; +extern int uk_order; +extern int compat; + +channel_list(new) +struct type_Qmgr_PrioritisedChannelList *new; +{ + if (compat) { + total_number_messages = 0; + total_number_reports = 0; + total_volume = 0; + } + if (globallist == NULL) { + create_channel_list(new); + firstChanRead = TRUE; + } else { + update_channel_list(new); + firstChanRead = FALSE; + } +} + +static int chantype_compare(one, two) +struct chan_struct **one, + **two; +{ + register int onetype, twotype; + + onetype = (*one)->chantype; + twotype = (*two)->chantype; + + if (onetype != twotype) { + if (onetype == int_Qmgr_chantype_mta) + return -1; + if (twotype == int_Qmgr_chantype_mta) + return 1; + if (onetype == int_Qmgr_chantype_mts) + return -1; + if (twotype == int_Qmgr_chantype_mts) + return 1; + if (onetype == int_Qmgr_chantype_internal) + return -1; + if (twotype == int_Qmgr_chantype_internal) + return 1; + } + + /* order on inbound and outbound */ + if ((*one)->inbound == (*two)->inbound + && (*one)->outbound == (*two) -> outbound) + return 0; + if ((*one)->outbound > (*two) -> outbound) + return -1; + if ((*one)->outbound < (*two)->outbound) + return 1; + if ((*one)->inbound > (*two) -> inbound) + return -1; + if ((*one)->inbound < (*two)->inbound) + return 1; + return 0; +} + +static void create_channel_list(list) +struct type_Qmgr_PrioritisedChannelList *list; +/* calloc and fillin in globallist */ +{ + struct type_Qmgr_PrioritisedChannelList *ix = list; + int i, + num = 0; + + while (ix != NULL) { + num++; + + ix = ix->next; + } + + num_channels = num; + globallist = (struct chan_struct **) calloc((unsigned) num, + sizeof(struct chan_struct *)); + ordered_list = (struct chan_struct **) calloc((unsigned) num, + sizeof(struct chan_struct *)); + display_list = (struct monitor_item **) calloc((unsigned) num, + sizeof(struct monitor_item *)); + resize_chan_array(num); + + ix = list; + i = 0; + while ((ix != NULL) + && (i < num)) { + globallist[i] = create_channel(ix); + i++; + ix = ix->next; + } + + qsort((char *) &(globallist[0]), num, + sizeof(globallist[0]), (IFP)chantype_compare); + + i = 0; + while (i < num) { + ordered_list[i] = globallist[i]; + display_list[i] = (struct monitor_item *) calloc(1, sizeof(struct monitor_item)); + display_list[i]->channel = &(ordered_list[i]); + i++; + } +} + +extern time_t boottime; + +static struct chan_struct *create_channel(chan) +struct type_Qmgr_PrioritisedChannelList *chan; +{ + struct chan_struct *temp; + struct type_Qmgr_ChannelInfo *info; + + temp = (struct chan_struct *) calloc(1, sizeof(*temp)); + info = chan->PrioritisedChannel->channel; + + temp->channelname = qb2str(info->channel); + temp->channeldescrip = qb2str(info->channelDescription); + + temp->oldestMessage = convert_time(info->oldestMessage); + temp->numberMessages = info->numberMessages; + temp->numberReports = info->numberReports; + temp->volumeMessages = info->volumeMessages; + temp->given_num_mtas = info->numberMtas; + if (compat) { + total_volume += temp->volumeMessages; + total_number_reports += temp->numberReports; + total_number_messages += temp->numberMessages; + } + temp->numberActiveProcesses = info->numberActiveProcesses; + temp->status = create_status(info->status); + if (temp->status->lastSuccess == 0) + temp->status->lastSuccess = boottime; + temp->priority = chan->PrioritisedChannel->priority->parm; + temp->inbound = bit_test(info->direction, bit_Qmgr_direction_inbound); + temp->outbound = bit_test(info->direction, bit_Qmgr_direction_outbound); + temp->chantype = info->chantype; + temp->maxprocs = info->maxprocs; + + add_tailor_to_chan(temp); + return temp; +} + +static void update_channel_list(new) +struct type_Qmgr_PrioritisedChannelList *new; +{ + struct type_Qmgr_PrioritisedChannelList *ix = new; + char *name = NULL; + struct chan_struct *chan; + + while (ix != NULL) { + if (name != NULL) free(name); + name = qb2str(ix->PrioritisedChannel->channel->channel); + + chan = find_channel(name); + if (chan == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: can not find channel %s",name)); + abort(); + } + update_channel(chan,ix); + ix = ix->next; + } +} + +static void update_channel(old, new) +struct chan_struct *old; +struct type_Qmgr_PrioritisedChannelList *new; +{ + struct type_Qmgr_ChannelInfo *info; + + info = new->PrioritisedChannel->channel; + /* name and description don't change */ + old->oldestMessage = convert_time(info->oldestMessage); + old->deltaMessages = info->numberMessages - old->numberMessages; + old->numberMessages = info->numberMessages; + old->deltaReports = info->numberReports - old->numberReports; + old->numberReports = info->numberReports; + old->deltaVolume = info->volumeMessages-old->volumeMessages; + old->volumeMessages = info->volumeMessages; + old->deltaMtas = info->numberMtas - old->given_num_mtas; + old->given_num_mtas = info->numberMtas; + if (compat) { + total_volume += old->volumeMessages; + total_number_reports += old->numberReports; + total_number_messages += old->numberMessages; + } + old->numberActiveProcesses = info->numberActiveProcesses; + update_status(old->status,info->status); + old->priority = new->PrioritisedChannel->priority->parm; + old->maxprocs = info->maxprocs; +} + +free_channel_list() +{ + int i =0; + if (globallist == NULL) + return; + while (i < num_channels) { + free(globallist[i]->channelname); + free(globallist[i]->channeldescrip); + free ((char *)globallist[i]->status); + if (globallist[i]->mtalist != NULL) + free_mta_list(&(globallist[i]->mtalist), + &(globallist[i]->num_mtas)); + i++; + } + free((char *) globallist); + free((char *) ordered_list); + ordered_list = NULL; + globallist = NULL; +} + +struct chan_struct *find_channel(name) +char *name; +{ + int i = 0; + while ((i < num_channels) && + (lexequ(globallist[i]->channelname, name) != 0)) + i++; + + if (i >= num_channels) + return NULL; + else + return globallist[i]; +} + +/* */ +/* mtas */ +static void update_mta_list(); +static struct mta_struct **create_mta_list(); +static struct mta_struct *create_mta(); + +struct mta_struct *currentmta = NULL; +int read_currentmta = 0; + +struct chan_struct *mta_list(new, channame) +struct type_Qmgr_PrioritisedMtaList *new; +char *channame; +{ + struct chan_struct *chan; + + if (channame == NULLCP) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: mta_list no channel name given")); + abort(); + } + + chan = find_channel(channame); + if (chan == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: can not find channel %s", channame)); + abort(); + } + + free_mta_list(&(chan->mtalist), &(chan->num_mtas)); + chan->mtalist = NULL; + chan->num_mtas = 0; + if (new != NULL) + update_mta_list(new, chan); + else + update_channel_from_mtas(chan, 0, 0, 0, 0); + return chan; +} + +static void update_mta_list(new, chan) +struct type_Qmgr_PrioritisedMtaList *new; +struct chan_struct *chan; +{ + int numberMsgs = 0, + numberDrs = 0, + numberMtas = 0, + volume = 0; + chan->mtalist = create_mta_list(new,&numberMtas, + &numberDrs,&numberMsgs,&volume, + chan); + update_channel_from_mtas(chan, numberMsgs, numberDrs, numberMtas, volume); +} + +static struct mta_struct **create_mta_list(list, pnum, pdr, pmsgnum, pvolume, chan) +struct type_Qmgr_PrioritisedMtaList *list; +int *pnum, + *pdr, + *pmsgnum, + *pvolume; +struct chan_struct *chan; +{ + struct type_Qmgr_PrioritisedMtaList *ix = list; + struct mta_struct **mtalist; + int i; + while (ix != NULL) { + (*pnum)++; + + ix = ix->next; + } + + mtalist = (struct mta_struct **) calloc( (unsigned)(*pnum), + sizeof(struct mta_struct *)); + + ix = list; + i = 0; + *pmsgnum = 0; + *pdr = 0; + + while ((ix != NULL) + && ( i < (*pnum))) { + mtalist[i] = create_mta(ix->PrioritisedMta, chan); + *pmsgnum += mtalist[i]->numberMessages; + *pdr += mtalist[i]->numberReports; + *pvolume += mtalist[i]->volumeMessages; + i++; + ix = ix->next; + } + return mtalist; +} + +static struct mta_struct *create_mta(mta, chan) +struct type_Qmgr_PrioritisedMta *mta; +struct chan_struct *chan; +{ + struct mta_struct *temp; + struct type_Qmgr_MtaInfo *info = mta->mta; + + temp = (struct mta_struct *) malloc(sizeof(*temp)); + + temp->mta = qb2str(info->mta); + temp->oldestMessage = convert_time(info->oldestMessage); + temp->numberMessages = info->numberMessage; + temp->numberReports = info->numberDRs; + temp->volumeMessages = info->volumeMessages; + temp->status = create_status(info->status); + temp->priority = mta->priority->parm; + temp->active = info->active; + if (info -> info != NULL) + temp -> info = qb2str(info -> info); + else + temp -> info = NULLCP; + add_tailor_to_mta(chan, temp); + if (forceDown == TRUE) + MtaDownForce(chan, temp); + return temp; +} + +update_mta(old, info) +struct mta_struct *old; +struct type_Qmgr_MtaInfo *info; +{ + /* name doesn't change */ + old->oldestMessage = convert_time(info->oldestMessage); + old->numberMessages = info->numberMessage; + old->numberReports = info->numberDRs; + old->volumeMessages = info->volumeMessages; + old->active = info->active; + if (old -> info) + free (old -> info); + if (info -> info != NULL) + old -> info = qb2str(info -> info); + else + old -> info = NULLCP; + update_status(old->status,info->status); +} + +/* ordering routines */ +struct mta_struct *find_mta(chan, name) +struct chan_struct *chan; +char *name; +{ + int i = 0; + while ((i < chan->num_mtas) && + (strcmp(chan->mtalist[i]->mta, name) != 0)) + i++; + if (i >= chan->num_mtas) + return NULL; + else + return chan->mtalist[i]; +} + +/* garbage collection routine */ + +free_mta_list(plist, pnum) +struct mta_struct ***plist; +int *pnum; +{ + int i = 0; + + while(i < (*pnum)){ + if ((*plist) [i] != NULL) { + free((*plist)[i]->mta); + if ((*plist)[i]->info != NULLCP) + free((*plist)[i] -> info); + free((char *) (*plist)[i]->status); + } + i++; + } + if (*plist != NULL) + free((char *) (*plist)); + *plist = NULL; + *pnum = 0; +} + +/* */ +/* msgs */ +struct msg_struct **global_msg_list = NULL, + *currentmsg = NULL; +int number_msgs = 0; +static struct msg_struct **create_msg_list(); + +msg_list(new) +struct type_Qmgr_MsgList *new; +{ + free_msg_list(); + global_msg_list = create_msg_list(new->msgs); +} + + +static char *create_eits(eit) +struct type_Qmgr_EncodedInformationTypes *eit; +{ + struct type_Qmgr_EncodedInformationTypes *ix; + char *str, + buf[BUFSIZ]; + int first; + if (eit == NULL) + return NULL; + ix =eit; + first = True; + + while (ix != NULL) { + str = qb2str(ix->PrintableString); + if (first == True) { + sprintf(buf,"%s",str); + first = False; + } else + sprintf(buf,"%s, %s",buf, str); + free(str); + ix = ix->next; + } + return strdup(buf); +} + +static struct permsginfo *create_msginfo(info) +struct type_Qmgr_PerMessageInfo *info; +{ + struct permsginfo *temp; + + temp = (struct permsginfo *) calloc(1,sizeof(*temp)); + + temp->queueid = qb2str(info->queueid); + temp -> originator = qb2str(info->originator); + if (info->contenttype != NULL) + temp->contenttype = qb2str(info->contenttype); + else + temp->contenttype = NULL; + temp->eit = create_eits(info->eit); + temp->age = convert_time(info->age); + temp->size = info->size; + temp->priority = info->priority->parm; + if (info->expiryTime == NULL) + temp->expiryTime = 0; + else + temp->expiryTime = convert_time(info->expiryTime); + if (info->deferredTime == NULL) + temp->deferredTime = 0; + else + temp->deferredTime = convert_time(info->deferredTime); + if (info->optionals & opt_Qmgr_PerMessageInfo_errorCount) + temp->errorCount = info->errorCount; + if (info->inChannel != NULL) + temp->inChannel = qb2str(info->inChannel); + else + temp->inChannel = NULLCP; + if (info->uaContentId != NULL) + temp -> uaContentId = qb2str(info->uaContentId); + else + temp -> uaContentId = NULLCP; + return temp; +} + +static char *create_chans(list, done, pfirst) +struct type_Qmgr_ChannelList *list; +int done; +char **pfirst; +{ + int count; + char buf[BUFSIZ], + *str; + + struct type_Qmgr_ChannelList *ix; + count = 0; + ix = list; + while (count < done && ix != NULL) { + ix = ix->next; + count++; + } + if (ix == NULL) + /* all done waiting for delivery notifcation */ + return NULL; + + str = qb2str(ix->Channel); + sprintf(buf,"%s",str); + free(str); + *pfirst = qb2str(ix->Channel); + ix = ix->next; + + while (ix != NULL) { + str = qb2str(ix->Channel); + sprintf(buf, "%s, %s",buf,str); + free(str); + ix = ix->next; + } + return strdup(buf); +} + +static struct recip *create_recip(recip) +struct type_Qmgr_RecipientInfo *recip; +{ + struct recip *temp; + + temp = (struct recip *) calloc(1,sizeof(*temp)); + + temp->id = recip->id->parm; + + temp -> recipient = qb2str(recip->user); + temp->mta = qb2str(recip->mta); + temp->chansOutstanding = create_chans(recip->channelList, + recip->channelsDone, + &temp->actChan); + temp->status = create_status(recip->procStatus); + if (recip -> info != NULL) + temp -> info = qb2str (recip -> info); + return temp; +} + + +static struct recip *create_reciplist(list) +struct type_Qmgr_RecipientList *list; +{ + struct recip *head = NULL, + *tail = NULL, + *temp; + + while (list != NULL) { + if (list->RecipientInfo->id != 0) { + temp = create_recip(list->RecipientInfo); + if (head == NULL) + tail = head = temp; + else { + tail->next = temp; + tail = temp; + } + } + list = list->next; + } + return head; +} + +static struct msg_struct *create_msg(msg) +struct type_Qmgr_MsgStruct *msg; +{ + struct msg_struct *temp; + + temp = (struct msg_struct *) calloc(1, sizeof(*temp)); + temp->msginfo = create_msginfo(msg->messageinfo); + temp->reciplist = create_reciplist(msg->recipientlist); + add_tailor_to_msg(currentchan,temp); + if (forceDown == TRUE) + MsgDownForce(temp); + return temp; +} + +static struct msg_struct **create_msg_list(list) +struct type_Qmgr_MsgStructList *list; +{ + struct type_Qmgr_MsgStructList *ix = list; + struct msg_struct **msglist; + int i; + number_msgs = 0; + while (ix != NULL) { + number_msgs++; + ix = ix->next; + } + + msglist = (struct msg_struct **) calloc((unsigned) number_msgs, + sizeof(struct msg_struct *)); + + ix = list; + i = 0; + while ((ix != NULL) + & (i < number_msgs)) { + msglist[i] = create_msg(ix->MsgStruct); + i++; + ix = ix->next; + } + return msglist; +} + +free_msg_list() +{ + int i = 0; + if (global_msg_list == NULL || number_msgs == 0) + return; + + while (i < number_msgs) { + free_permsginfo(global_msg_list[i]->msginfo); + free_reciplist(global_msg_list[i]->reciplist); + i++; + } + free((char *) global_msg_list); + global_msg_list = NULL; + number_msgs = 0; +} + +free_permsginfo(info) +struct permsginfo *info; +{ + free(info->queueid); + free(info->originator); + if (info->eit != NULL) free(info->eit); + if (info->inChannel != NULL) free(info->inChannel); + if (info->uaContentId != NULLCP) free(info->uaContentId); + free((char *) info); +} + +free_reciplist(list) +struct recip *list; +{ + struct recip *ix = list, + *temp; + + while (ix != NULL) { + if (ix->recipient) free(ix->recipient); + if (ix->mta != NULL) free(ix->mta); + if (ix->actChan != NULL) free(ix->actChan); + if (ix->chansOutstanding != NULL) free(ix->chansOutstanding); + if (ix -> info != NULL) free(ix->info); + free((char *) ix->status); + temp = ix; + ix = ix->next; + free((char *) temp); + } +} + + +struct recip *find_recip(msg, id) +struct msg_struct *msg; +int id; +{ + struct recip *ix; + if (msg == NULL) + return NULL; + ix = msg->reciplist; + + while (ix != NULL + && ix -> id != id) + ix = ix->next; + return ix; +} + +struct msg_struct *find_msg(qid) +char *qid; +{ + int i = 0; + + while ((i < number_msgs) && + (strcmp(global_msg_list[i]->msginfo->queueid,qid) != 0)) + i++; + if (i >= number_msgs) + return NULL; + else + return global_msg_list[i]; +} + +/* */ +/* misc */ +struct procStatus *create_status(status) +struct type_Qmgr_ProcStatus *status; +{ + struct procStatus *temp; + + temp = (struct procStatus *) malloc(sizeof(*temp)); + + temp->enabled = status->enabled; + temp->lastAttempt = convert_time(status->lastAttempt); + temp->cachedUntil = convert_time(status->cachedUntil); + temp->lastSuccess = convert_time(status->lastSuccess); + return temp; +} + +void update_status(old, new) +struct procStatus *old; +struct type_Qmgr_ProcStatus *new; +{ + time_t tmp; + old->enabled = new->enabled; + + old->lastAttempt = convert_time(new->lastAttempt); + + old->cachedUntil = convert_time(new->cachedUntil); + + if ((tmp = convert_time(new->lastSuccess)) != 0) + old->lastSuccess = tmp; +} diff --git a/Src/MTAconsole/display.c b/Src/MTAconsole/display.c new file mode 100644 index 0000000..5dac488 --- /dev/null +++ b/Src/MTAconsole/display.c @@ -0,0 +1,1990 @@ +/* display.c : display routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/display.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/display.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: display.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" +extern Pixmap backpixmap; +extern Mode mode; +extern int max_horiz_mtas; +extern State connectState; +extern char *time_t2RFC(), + *vol2str(), + *itoa(), + *msginfo_args[3], + *Qinformation, + *Qversion; +extern time_t time(); +void ChanToggle(), + MtaToggle(), + MsgToggle(); +extern unsigned long chancolourOf(), + mtacolourOf(), + msgcolourOf(); +extern XFontStruct *chanFont(), + *mtaFont(), + *msgFont(), + *normalFont, + *disabledFont; +extern Heuristic heuristic; +/* */ +/* channels */ +extern void Channel(); +extern struct chan_struct *currentchan, + **globallist; +extern Widget channel_all, + channels, + channel_info, + channel_viewport, + channel_label, + monitor_form, + monitor_viewport, + switchform, + qversion; +extern int max_vert_lines, + read_currentchan, + monitor_form_managed; +Widget *channel_array = NULL; +int actual_nchans_present = 0, + num_channels, + chan_info_shown = FALSE; +extern struct monitor_item **display_list; +extern int compat; + +static void redisplay_channel(); +static void monitor_display_channels(); +static void undisplay_monitor(); +static char *create_channel_display_string(); +static char *create_channel_monitor_string(); +static char *time_t2str(); +static void resize_info_list(); + +extern char *reverse_mta(), *reverse_adr(); +extern int total_volume, delta_volume, + total_number_messages, delta_messages, + total_number_reports, delta_reports; +extern Widget total_number_label, total_volume_label; +extern unsigned long volcolourOf(), numcolourOf(); + +display_totals() +{ + char buf[BUFSIZ], num[15]; + + if (total_volume == 0 + || (total_number_messages == 0 + && total_number_reports == 0)) { + MapVolume(False); + return; + } + num2unit(total_volume, num); + (void) sprintf(buf, "Volume = %s", num); + if (!compat && delta_volume) { + num2unit(delta_volume, num); + (void) sprintf(buf, "%s (%s%s)", + buf, + (delta_volume > 0) ? "+" : "", + num); + } + + XtVaSetValues(total_volume_label, + XtNlabel, buf, + XtNborderColor, volcolourOf(total_volume), + NULL); + + (void) sprintf(buf, "%d msg%s", + total_number_messages, + (total_number_messages == 1) ? "" : "s"); + if (!compat && delta_messages) + (void) sprintf(buf, "%s (%s%d)", + buf, + (delta_messages > 0) ? "+" : "", + delta_messages); + (void) sprintf(buf, "%s + %d report%s", + buf, total_number_reports, + (total_number_reports == 1) ? "" : "s"); + if (!compat && delta_reports) + (void) sprintf(buf, "%s (%s%d)", + buf, + (delta_reports > 0) ? "+" : "", + delta_reports); + + XtVaSetValues(total_number_label, + XtNlabel, buf, + XtNborderColor, numcolourOf(total_number_messages+total_number_reports), + NULL); + MapVolume(True); +} + +char *create_channel_header() +{ + char *str; + char buf[BUFSIZ]; + if (currentchan == NULL) + str = strdup("No current channel"); + else { + sprintf(buf, "Current channel : %s : %s", + currentchan->channelname, currentchan->channeldescrip); + str = strdup(buf); + } + return str; +} + +#define ssformat "%-*s %s" +#define sdformat "%-*s %s" +#define plus_ssformat "%s\n%-*s %s" +#define plus_sdformat "%s\n%-*s %d" + +#define tab 30 + +extern Widget channel_all_list; + +char *channel_info_list[100]; + +set_info_list(list, ix, str) +char *list[]; +int ix; +char *str; +{ + if (list[ix]) free(list[ix]); + list[ix] = str; +} + +chan_display_info(chan) +struct chan_struct *chan; +{ + char *str, buf[BUFSIZ]; + int ix = 0; + XFontStruct *font; + + set_info_list(channel_info_list, ix++, strdup(chan->channelname)); + set_info_list(channel_info_list, ix++, strdup(chan->channeldescrip)); + if (chan->status->cachedUntil != 0) { + set_info_list(channel_info_list, ix++, strdup("Delayed until")); + str = time_t2RFC(chan->status->cachedUntil); + set_info_list(channel_info_list, ix++, str); + } + if (chan->oldestMessage != 0 && + (chan->numberMessages != 0 || chan->numberReports != 0)) { + set_info_list(channel_info_list, ix++, strdup("Oldest message")); + str = time_t2str(time((time_t *)0) - chan->oldestMessage); + set_info_list(channel_info_list, ix++, str); + } + + if (chan->numberMessages != 0) { + set_info_list(channel_info_list, ix++, strdup("number of messages")); + str = itoa(chan->numberMessages); + set_info_list(channel_info_list, ix++, str); + } + + if (chan->numberReports != 0) { + set_info_list(channel_info_list, ix++, strdup("number of reports")); + str = itoa(chan->numberReports); + set_info_list(channel_info_list, ix++, str); + } + + if (chan->volumeMessages != 0) { + char num[15]; + set_info_list(channel_info_list, ix++, strdup("Volume")); + num2unit(chan->volumeMessages, num); + str = strdup(num); + set_info_list(channel_info_list, ix++, str); + } + + if (chan->numberActiveProcesses != 0) { + set_info_list(channel_info_list, ix++, strdup("number of active processes")); + str = itoa(chan->numberActiveProcesses); + set_info_list(channel_info_list, ix++, str); + } + + set_info_list(channel_info_list, ix++, strdup("status")); + + set_info_list(channel_info_list, ix++, + strdup((chan->status->enabled == TRUE) ? "enabled" : "disabled")); + + if (chan->status->lastAttempt != 0) { + set_info_list(channel_info_list, ix++, strdup("last attempt")); + str = time_t2RFC(chan->status->lastAttempt); + set_info_list(channel_info_list, ix++, str); + } + + if (chan->status->lastSuccess != 0) { + set_info_list(channel_info_list, ix++, strdup("last success")); + str = time_t2RFC(chan->status->lastSuccess); + set_info_list(channel_info_list, ix++, str); + } + + set_info_list(channel_info_list, ix++, strdup("priority")); + switch (chan->priority) { + case int_Qmgr_Priority_low: + str = strdup("low"); + break; + case int_Qmgr_Priority_high: + str = strdup("high"); + break; + case int_Qmgr_Priority_normal: + default: + str = strdup("normal"); + break; + } + set_info_list(channel_info_list, ix++, str); + + set_info_list(channel_info_list, ix++, strdup("maximum number of processes")); + if (chan -> maxprocs == 0) + sprintf(buf, "unlimited"); + else + sprintf(buf, "%d", chan->maxprocs); + set_info_list(channel_info_list, ix++, strdup(buf)); + + XawListChange(channel_all_list, + channel_info_list, + ix, 0, True); + + if ((font = chanFont(chan)) != NULL) + XtVaSetValues(channel_all_list, + XtNfont, font, + NULL); + + XtVaSetValues(channel_info, + XtNlabel, "all", + NULL); + + XtSetMappedWhenManaged(channel_all, True); + XtSetMappedWhenManaged(channel_viewport, False); + chan_info_shown = TRUE; +} + + +chan_display_all() +{ + XtVaSetValues(channel_info, + XtNlabel, "info", + NULL); + XtSetMappedWhenManaged(channel_viewport, True); + XtSetMappedWhenManaged(channel_all, False); + chan_info_shown = FALSE; +} + + +display_channels() +{ + clear_mta_refresh_list(); + control_display_channels(); + if (mode == monitor) + monitor_display_channels(); + if (compat) + display_totals(); +} + +control_display_channels() +{ + int i = 0; + char *str = NULL; + XFontStruct *font; + for (i = 0; i < num_channels; i++) + XtSetMappedWhenManaged(channel_array[i], False); + i = 0; + while (i < num_channels) { + str = create_channel_display_string(globallist[i]); + XtVaSetValues(channel_array[i], + XtNlabel, str, + XtNborderColor, chancolourOf(globallist[i]), + XtNborderWidth, chanborderOf(globallist[i]), + XtNbackgroundPixmap, + (globallist[i]->status->enabled == FALSE) ? backpixmap : ParentRelative, + NULL); + if ((font = chanFont(globallist[i])) != NULL) + XtVaSetValues(channel_array[i], + XtNfont, font, + NULL); + + free(str); + i++; + } + for (i = 0; i < num_channels; i++) + XtSetMappedWhenManaged(channel_array[i], True); + if (chan_info_shown == TRUE + && currentchan != NULL) + chan_display_info(currentchan); + if (currentchan != NULL && mode == control && read_currentchan != 0) { + clear_mta_refresh_list(); + if (heuristic != chanonly) { + add_mta_refresh_list(currentchan->channelname); + construct_event(mtaread); + } + } +} + +/* called when channel number of msgs gets out of step with total */ +/* mtas number of msgs i.e. msgs go out or come in between chanread */ +/* and subsequent mtareads */ + +redisplay_control_channel(num) +int num; +{ + char *str = NULL; + + XtSetMappedWhenManaged(channel_array[num], False); + str = create_channel_display_string(globallist[num]); + XtVaSetValues(channel_array[num], + XtNlabel, str, + XtNborderColor, chancolourOf(globallist[num]), + XtNborderWidth, chanborderOf(globallist[num]), + XtNbackgroundPixmap,(globallist[num]->status->enabled == FALSE) ? backpixmap : ParentRelative, + NULL); + free(str); + XtSetMappedWhenManaged(channel_array[num], True); +} + +static void monitor_display_channels() +{ + int num_displayed = 0, + i; + + order_display_channels(); + XtUnmanageChild(monitor_form); + while ((num_displayed < num_channels) + && (chanBadness(*(display_list[num_displayed]->channel)) != 0)) { + monitor_channel(num_displayed); + num_displayed++; + } + + i = num_displayed; + + while (i < num_channels + && display_list[i]->chan != NULL) { + undisplay_monitor(display_list[i]); + i++; + } + XtManageChild(monitor_form); + construct_event(mtaread); +} + +static void undisplay_monitor(item) +struct monitor_item *item; +{ + int i = 0; + if (item->form != NULL) { + XtDestroyWidget(item->form); + item -> chan = NULL; + if (item->mtas != NULL) { + while (i < item -> num_allocd + && item->mtas[i] != NULL) { + item->mtas[i] = NULL; + i++; + } + } + item->box = NULL; + item->form = NULL; + } +} + +monitor_channel(num) +int num; +{ + + struct chan_struct *actualchan; + int managed = TRUE; + char *str; + XFontStruct *font; + /* display display_list[num] */ + actualchan = *(display_list[num]->channel); + actualchan->display_num = num; + + XawFormDoLayout (monitor_form, False); + + if (connectState == connected) { + if (display_list[num]->form == NULL) { + /* need to create form */ + display_list[num]->form = XtVaCreateWidget("MonitorChannelForm", + formWidgetClass, + monitor_form, + XtNborderColor, chancolourOf(actualchan), + XtNfromVert, (num == 0) ? NULL : display_list[num-1]->form, + XtNfromHoriz, NULL, + XtNresizable, TRUE, + NULL); + managed = FALSE; + } + if (display_list[num]->chan != NULL) { + XtUnmanageChild(display_list[num]->chan); + str = create_channel_monitor_string(actualchan); + XtVaSetValues(display_list[num]->chan, + XtNborderColor, chancolourOf(actualchan), + XtNborderWidth, chanborderOf(actualchan), + XtNlabel, str, + XtNbackgroundPixmap, (actualchan->status->enabled == FALSE) + ? backpixmap : ParentRelative, + NULL); + if ((font = chanFont(actualchan)) != NULL) + XtVaSetValues(display_list[num]->chan, + XtNfont, font, + NULL); + + XtManageChild(display_list[num]->chan); + free(str); + } else { + str = create_channel_monitor_string(actualchan); + display_list[num]->chan = + XtVaCreateManagedWidget("MonitorChannel", + labelWidgetClass, + display_list[num]->form, + XtNresizable, TRUE, + XtNborderColor, chancolourOf(actualchan), + XtNborderWidth, chanborderOf(actualchan), + XtNlabel, str, + XtNbackgroundPixmap, (actualchan->status->enabled == FALSE) + ? backpixmap : ParentRelative, + XtNfromVert, NULL, + XtNfromHoriz, NULL, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + XtNjustify, XtJustifyRight, + NULL); + if ((font = chanFont(actualchan)) != NULL) + XtVaSetValues(display_list[num]->chan, + XtNfont, font, + NULL); + free(str); + + } + if (managed == FALSE) + XtManageChild(display_list[num]->form); + XawFormDoLayout(display_list[num]->form, False); + XtVaSetValues(display_list[num]->form, + XtNborderColor, chancolourOf(actualchan), + NULL); + if (heuristic != chanonly + && (actualchan->numberMessages > 0 + || actualchan->numberReports > 0 + || actualchan->volumeMessages > 0)) + add_mta_refresh_list(actualchan->channelname); + } + if (display_list[num]->box != NULL) + XtUnmanageChild(display_list[num]->box); + XawFormDoLayout(display_list[num]->form, True); + XawFormDoLayout(monitor_form, True); +} + +static char *create_channel_display_string(chan) +struct chan_struct *chan; +{ + char str[BUFSIZ]; + + sprintf(str,"%s",chan->channelname); + if (chan -> numberActiveProcesses > 1) + sprintf(str, "%s (%d)", + str, chan->numberActiveProcesses); + sprintf(str,"%s: %d", + str,chan->numberMessages); + if (chan->numberReports != 0) + sprintf(str,"%s + %d", str, chan->numberReports); + if (chan->given_num_mtas != 0) + sprintf(str,"%s/%d",str, chan->given_num_mtas); + return strdup(str); +} + +static char *create_channel_monitor_string(chan) +struct chan_struct *chan; +{ + char str[BUFSIZ]; + + sprintf(str,"%s : %d %s", + chan->channelname, + chan->numberMessages, + (chan->numberMessages == 1) ? "msg" : "msgs"); + + if (chan->numberReports != 0) + sprintf(str, "%s and %d %s", + str, + chan->numberReports, + (chan->numberReports == 1) ? "DR" : "DRs"); + + sprintf(str, "%s on %d %s", + str, + chan->given_num_mtas, + (chan->given_num_mtas == 1) ? "mta" : "mtas"); + + if (chan -> numberActiveProcesses > 0) { + sprintf (str, "%s, %d process%s active", str, + chan -> numberActiveProcesses, + chan -> numberActiveProcesses > 1 ? "es" : ""); + } + + if (chan->deltaMessages || chan->deltaReports || + chan->deltaMtas || chan->deltaVolume) { + sprintf(str, "%s, net change:", str); + if (chan->deltaMessages) + sprintf(str, "%s %s%d msg%s", str, + (chan->deltaMessages > 0) ? "+" : "", + chan->deltaMessages, (chan->deltaMessages == 1 || chan->deltaMessages == -1) ? "" : "s"); + if (chan->deltaReports) + sprintf(str, "%s %s%d report%s", str, + (chan->deltaReports > 0) ? "+" : "", + chan->deltaReports, (chan->deltaReports == 1 || chan->deltaReports == -1) ? "" : "s"); + if (chan->deltaMtas) + sprintf(str, "%s %s%d mta%s", str, + (chan->deltaMtas > 0) ? "+" : "", + chan->deltaMtas, (chan->deltaMtas == 1 || chan->deltaMtas == -1) ? "" : "s"); + + if (chan->deltaVolume) { + char num[15]; + num2unit(chan->deltaVolume, num); + sprintf(str, "%s (%s%s)", str, + (chan->deltaVolume > 0) ? "+" : "", + num); + } + } + return strdup(str); +} + +resize_chan_array(num) +int num; /* number of channels that will be displayed */ +{ + int i = num; + char *str; + + XtSetMappedWhenManaged(channels, False); + while (i < actual_nchans_present) { + XtUnmanageChild(channel_array[i]); + i++; + } + + XSync(XtDisplay(channels), False); + + i = num; + while (i < actual_nchans_present) { + XtDestroyWidget(channel_array[i]); + i++; + } + + if (num == 0) { + if (channel_array != NULL) { + free ((char *) channel_array); + channel_array = NULL; + } + } else if (actual_nchans_present == 0) + /* haven't got any so malloc first lot */ + channel_array = (Widget *) calloc((unsigned) num, + sizeof(Widget)); + else if (actual_nchans_present != num) + /* need some more */ + channel_array = (Widget *) realloc((char *) channel_array, + (unsigned) (num * sizeof(Widget))); + while (actual_nchans_present < num) { + str = itoa(actual_nchans_present); + channel_array[actual_nchans_present] = + XtVaCreateManagedWidget(NULL, + labelWidgetClass, + channels, + XtNborderWidth, 2, + XtNlabel, str, + NULL); + actual_nchans_present++; + free(str); + } + actual_nchans_present = num; + XtSetMappedWhenManaged(channels, True); +} + +/* */ +/* mtas */ +extern struct mta_struct *currentmta; +extern int read_currentmta; +extern int max_mta_border; +extern void Mta(); +extern Widget mtas, + mta_all, + mta_all_list, + mta_info, + mta_viewport, + mta_label; + +struct mta_disp_struct *mta_array = NULL; +int actual_nmtas_present = 0, + num_mtas_displayed = 0, + mta_info_shown = FALSE; +static char *create_mta_display_string(); +extern int mta_info_strlen; +extern int uk_order; + +char *mta_info_list[100]; + +mta_display_info(chan,mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + char *str; + char buf[BUFSIZ]; + int ix = 0; + XFontStruct *font; + + str = (uk_order) ? reverse_mta(mta->mta) : strdup(mta->mta); + set_info_list(mta_info_list, ix++, str); + + sprintf(buf, "on channel '%s'", chan->channelname); + set_info_list(mta_info_list, ix++, strdup(buf)); + + if (mta->status->cachedUntil != 0) { + set_info_list(mta_info_list, ix++, strdup("Delayed until")); + str = time_t2RFC(mta->status->cachedUntil); + set_info_list(mta_info_list, ix++, str); + } + + if (mta->info != NULLCP) { + set_info_list(mta_info_list, ix++, strdup("Error Information")); + set_info_list(mta_info_list, ix++, strdup(mta->info)); + } + + set_info_list(mta_info_list, ix++, strdup("Oldest message")); + str = time_t2str(time((time_t *) 0) - mta->oldestMessage); + set_info_list(mta_info_list, ix++, str); + + if (mta->numberMessages != 0) { + set_info_list(mta_info_list, ix++, strdup("Number of messages")); + str = itoa(mta->numberMessages); + set_info_list(mta_info_list, ix++, str); + } + if (mta->numberReports != 0) { + set_info_list(mta_info_list, ix++, strdup("Number of reports")); + str = itoa(mta->numberReports); + set_info_list(mta_info_list, ix++, str); + } + + set_info_list(mta_info_list, ix++, strdup("Volume")); + str = vol2str(mta->volumeMessages); + set_info_list(mta_info_list, ix++, str); + + if (mta -> active) { + set_info_list(mta_info_list, ix++, strdup("active")); + set_info_list(mta_info_list, ix++, strdup("processes running")); + } + + set_info_list(mta_info_list, ix++, strdup("Status")); + set_info_list(mta_info_list, ix++, + strdup((mta->status->enabled == TRUE) ? "enabled" : "disabled")); + + if (mta->status->lastAttempt != 0) { + set_info_list(mta_info_list, ix++, strdup("Last attempt")); + str = time_t2RFC(mta->status->lastAttempt); + set_info_list(mta_info_list, ix++, str); + } + + if (mta->status->lastSuccess != 0) { + set_info_list(mta_info_list, ix++, strdup("Last success")); + str = time_t2RFC(mta->status->lastSuccess); + set_info_list(mta_info_list, ix++, str); + } + + set_info_list(mta_info_list, ix++, strdup("Priority")); + switch (mta->priority) { + case int_Qmgr_Priority_low: + str = strdup("low"); + break; + default: + case int_Qmgr_Priority_normal: + str = strdup("normal"); + break; + case int_Qmgr_Priority_high: + str = strdup("high"); + break; + } + set_info_list(mta_info_list, ix++, str); + + XawListChange(mta_all_list, + mta_info_list, + ix, 0, True); + + if ((font = mtaFont(mta)) != NULL) + XtVaSetValues(mta_all_list, + XtNfont, font, + NULL); + + XtVaSetValues(mta_info, + XtNlabel, "all", + NULL); + XtSetMappedWhenManaged(mta_all, True); + XtSetMappedWhenManaged(mta_viewport, False); + mta_info_shown = TRUE; +} + +mta_display_all() +{ + XtVaSetValues(mta_info, + XtNlabel, "info", + NULL); + XtSetMappedWhenManaged(mta_viewport, True); + XtSetMappedWhenManaged(mta_all, False); + mta_info_shown = FALSE; +} + +display_empty_mta_list(chan) +struct chan_struct *chan; +{ + /* reset counters */ + if (chan != NULL && chan->mtalist != NULL) + free_mta_list(&(chan->mtalist), &(chan->num_mtas)); + XtUnmanageChild(mtas); + XtSetMappedWhenManaged(mtas, False); + resize_mta_array(0); + XtSetMappedWhenManaged(mtas, True); + XtManageChild(mtas); + reset_label(mta_label); + MtaToggle(); + MsgToggle(); +} + +display_mtas(chan) +struct chan_struct *chan; +{ + if (mode == monitor) + monitor_display_mtas(chan); + else + control_display_mtas(chan); +} + +control_display_mtas(chan) +struct chan_struct *chan; +{ + int i; + char *str; + XFontStruct *font; + + XtSetMappedWhenManaged(mtas, False); + XtUnmanageChild(mtas); + + resize_mta_array(chan->num_mtas); + + i = 0; + while (i < num_mtas_displayed) { + mta_array[i].mta = chan->mtalist[i]; + str = create_mta_display_string(mta_array[i].mta); + XtSetMappedWhenManaged(mta_array[i].widget, True); + XtUnmanageChild(mta_array[i].widget); + XtVaSetValues(mta_array[i].widget, + XtNlabel, str, + XtNborderColor, mtacolourOf(mta_array[i].mta), + XtNborderWidth, mtaborderOf(mta_array[i].mta), + XtNfromVert, (i == 0) ? NULL : mta_array[i-1].widget, + XtNbackgroundPixmap, + (mta_array[i].mta->status->enabled == FALSE) ? backpixmap : ParentRelative, + NULL); + if ((font = mtaFont(mta_array[i].mta)) != NULL) + XtVaSetValues(mta_array[i].widget, + XtNfont, font, + NULL); + + XtManageChild(mta_array[i].widget); + free(str); + i++; + } + if (mta_info_shown == TRUE + && currentchan != NULL + && currentmta != NULL) + mta_display_info(currentchan, currentmta); + if (currentchan != NULL + && read_currentmta != 0 + && currentmta != NULL) { + msginfo_args[0] = currentchan->channelname; + msginfo_args[1] = currentmta->mta; + if (is_loc_chan(currentchan) == TRUE) + /* local */ + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + construct_event(readchannelmtamessage); + } else + display_empty_msg_list(); + XtManageChild(mtas); + XtSetMappedWhenManaged(mtas, True); +} + +int oldnum; +extern int percent, + lower_bound_mtas; + +static void resize_and_zero (pbuf, pnum, num, size) +char **pbuf; +int *pnum; +int num; +unsigned size; +{ + if (*pbuf == NULLCP) + *pbuf = calloc((unsigned)num, size); + else { + *pbuf = realloc(*pbuf, + (unsigned) (num * size)); + if (num > *pnum) + bzero (((*pbuf) + (*pnum)*size), + (unsigned) (num-(*pnum))*size); + } + *pnum = num; +} + + + +monitor_display_mtas(chan) +struct chan_struct *chan; +{ + int num_displayed = 0, + line_num = 0, + bigestBorderWidth = 0, horiz; + int max_allowed, num_alloced; + int num_vert_lines = 0, max_num; + + Dimension vp_len, chan_len, dist, longest_len, + line_len = 0; + Widget abovewidget = NULL; + int temp; + + XawFormDoLayout(monitor_form, False); + XawFormDoLayout(display_list[chan->display_num]->form, False); + XtVaSetValues(monitor_form, + XtNleft, XtRubber, + XtNright, XtRubber, + XtNtop, XtRubber, + XtNbottom, XtRubber, + NULL); + XtVaSetValues(display_list[chan->display_num]->form, + XtNleft, XtRubber, + XtNright, XtRubber, + XtNtop, XtRubber, + XtNbottom, XtRubber, + NULL); + + if (display_list[chan->display_num]->box == NULL) { + display_list[chan->display_num]->box = + XtVaCreateWidget("MonitorMTAForm", + formWidgetClass, + display_list[chan->display_num]->form, + XtNresizable, TRUE, + XtNborderWidth, 0, + XtNfromHoriz, NULL, + XtNfromVert, display_list[chan->display_num]->chan, + XtNbackgroundPixmap, ParentRelative, + XtNvertDistance, 0, + NULL); + } + XtVaSetValues(display_list[chan->display_num]->box, + XtNleft, XtRubber, + XtNright, XtRubber, + XtNtop, XtRubber, + XtNbottom, XtRubber, + NULL); + + XawFormDoLayout(display_list[chan->display_num]->box, False); + + XtVaGetValues(switchform, + XtNwidth, &vp_len, + NULL); + XtVaGetValues(display_list[chan->display_num]->chan, + XtNwidth, &chan_len, + NULL); + XtVaGetValues(display_list[chan->display_num]->form, + XtNdefaultDistance, &temp, + NULL); + XtVaGetValues(display_list[chan->display_num]->box, + XtNhorizDistance, &horiz, + NULL); + dist = (Dimension) temp; + longest_len = vp_len-3*dist-horiz-20; + /* -20 is fudge for scrollbar */ + + switch (heuristic) { + case chanonly: + break; + case percentage: + max_allowed = (chan->num_mtas * chanBadness(chan) * percent) / (max_bad_channel * 100); + num_alloced = (max_allowed < lower_bound_mtas) ? lower_bound_mtas : max_allowed; + + if (display_list[chan->display_num]->num_allocd < num_alloced) + resize_and_zero (&(display_list[chan->display_num]->mtas), + &display_list[chan->display_num]->num_allocd, + num_alloced, + sizeof(Mta_disp_struct *)); + + while (num_displayed < chan->num_mtas + && mtaBadness(chan->mtalist[num_displayed]) != 0 + && (num_displayed < lower_bound_mtas + || num_displayed < max_allowed)) { + if (monitor_mta(chan->display_num, + chan->mtalist[num_displayed], + num_displayed, + &line_num, + &line_len, + &abovewidget, + longest_len, + dist, + max_allowed, + &bigestBorderWidth) == OK) + num_displayed++; + } + break; + case line: + num_vert_lines = NumVertLines(chan); + if (num_vert_lines <= 0) num_vert_lines = 1; + max_num = num_vert_lines * max_horiz_mtas; + if (max_num == 0) max_num++; + + if (display_list[chan->display_num]->num_allocd < max_num) + resize_and_zero(&(display_list[chan->display_num]->mtas), + &(display_list[chan->display_num]->num_allocd), + max_num, + sizeof(Mta_disp_struct *)); + + while (num_displayed < max_num + && line_num < num_vert_lines + && (num_displayed < chan->num_mtas) + && (mtaBadness(chan->mtalist[num_displayed]) != 0)) { + if (monitor_mta(chan->display_num, + chan->mtalist[num_displayed], + num_displayed, + &line_num, + &line_len, + + &abovewidget, + longest_len, + dist, + num_vert_lines, + &bigestBorderWidth) == OK) + num_displayed++; + } + break; + case all: + if (display_list[chan->display_num]->num_allocd < + chan->num_mtas) + resize_and_zero(&(display_list[chan->display_num]->mtas), + &(display_list[chan->display_num]->num_allocd), + chan->num_mtas, + sizeof(Mta_disp_struct *)); + + while (num_displayed < chan->num_mtas + && mtaBadness(chan->mtalist[num_displayed]) != 0) { + if (monitor_mta(chan->display_num, + chan->mtalist[num_displayed], + num_displayed, + &line_num, + &line_len, + + &abovewidget, + longest_len, + dist, + num_vert_lines, + &bigestBorderWidth) == OK) + num_displayed++; + } + break; + } + + + oldnum = display_list[chan->display_num]->num_mtas; + + display_list[chan->display_num]->num_mtas = num_displayed; + + while (num_displayed < display_list[chan->display_num] -> num_allocd + && display_list[chan->display_num]->mtas[num_displayed] != NULL + && display_list[chan->display_num]->mtas[num_displayed]->widget != NULL) { + undisplay_mta_monitor(&(display_list[chan->display_num]->mtas[num_displayed]->widget)); + num_displayed++; + } + + if (display_list[chan->display_num]->num_mtas == 0) { + undisplay_mta_monitor(&(display_list[chan->display_num]->box)); + XawFormDoLayout(display_list[chan->display_num]->form, True); + XtVaSetValues(display_list[chan->display_num]->form, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + XawFormDoLayout(monitor_form, True); + XtVaSetValues(monitor_form, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + return; + } + XawFormDoLayout(display_list[chan->display_num]->box, True); + + XtManageChild(display_list[chan->display_num]->box); + XtVaSetValues(display_list[chan->display_num]->box, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + XawFormDoLayout(display_list[chan->display_num]->form, True); + XtVaSetValues(display_list[chan->display_num]->form, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + XawFormDoLayout(monitor_form, True); + XtVaSetValues(monitor_form, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); +} + +undisplay_mta_monitor(pwidget) +Widget *pwidget; +{ + if (*pwidget != NULL) { +/* XtDestroyWidget(*pwidget); + *pwidget = NULL; +*/ + if (XtIsManaged (*pwidget)) + XtUnmanageChild (*pwidget); + } +} + +monitor_mta(chan_display_num, + mta, + num, + pline_num, + pline_len, + pvert, + longest, + dist, + linesAllowed, + borderWidth_ub) +int chan_display_num; +struct mta_struct *mta; +int num; +int *pline_num; +Dimension *pline_len; +Widget *pvert; +Dimension longest, + dist; +int linesAllowed; +int *borderWidth_ub; +{ + char *str; + Widget horiz = NULL; + Widget *w; + Dimension widget_width; + Dimension borderWidth = mtaborderOf(mta); + XFontStruct *font; + + str = create_mta_display_string(mta); + + if (display_list[chan_display_num]->mtas[num] == NULL) + /* need to create widget */ + display_list[chan_display_num]->mtas[num] = + (Mta_disp_struct *) calloc(1, sizeof(Mta_disp_struct)); + + display_list[chan_display_num]->mtas[num]->mta = mta; + + w = &display_list[chan_display_num]->mtas[num]->widget; + if (*w == NULL) { + *w = XtVaCreateManagedWidget("MonitorMTA", + labelWidgetClass, + display_list[chan_display_num] ->box, + XtNresizable, TRUE, + XtNborderWidth, borderWidth, + XtNlabel, str, + XtNborderColor, mtacolourOf(mta), + XtNbackgroundPixmap, + (mta->status->enabled == FALSE) ? backpixmap : ParentRelative, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + } else { + XtVaSetValues (*w, + XtNborderWidth, borderWidth, + XtNlabel, str, + XtNborderColor, mtacolourOf(mta), + XtNbackgroundPixmap, + (mta->status->enabled == FALSE ? + backpixmap : ParentRelative), + NULL); + } + free(str); + + if ((font = mtaFont(mta)) != NULL) + XtVaSetValues(*w, + XtNfont, font, + NULL); + + XtVaGetValues(*w, + XtNwidth, &widget_width, + NULL); + + if (*pline_len+dist+widget_width > longest) { + /* new line */ + (*pline_num)++; + if (heuristic == line && (*pline_num) >= linesAllowed) { + undisplay_mta_monitor(w); + return NOTOK; + } + if (num == 0) /* problems ? */ + *pvert = NULL; + else + *pvert = display_list[chan_display_num]-> + mtas[num-1]->widget; + horiz = NULL; + (*pline_len) = dist+widget_width; + } else { + if (num == 0) + horiz = NULL; + else + horiz = display_list[chan_display_num]-> + mtas[num-1]->widget; + (*pline_len) += dist+widget_width; + } + + XtVaSetValues(*w, + XtNfromVert, *pvert, + XtNfromHoriz, horiz, + NULL); + if (!XtIsManaged (*w)) + XtManageChild(*w); + if ((int) borderWidth > *borderWidth_ub) + *borderWidth_ub = borderWidth; + return OK; +} + +char *create_mta_header() +{ + /* takes from current channel and current mta */ + char *str; + char *ch; + char buf[BUFSIZ]; + if (currentmta == NULL + || currentchan == NULL) + str = strdup("No current mta"); + else { + ch = (uk_order) ? + reverse_mta(currentmta -> mta) : currentmta -> mta; + sprintf(buf, "Current mta : %s on %s", + ch, currentchan->channelname); + if (uk_order && ch != currentmta -> mta) free(ch); + str = strdup(buf); + } + + return str; +} + +static char *create_mta_display_string(mta) +struct mta_struct *mta; +{ + char str[BUFSIZ]; + char *ch; + + ch = (uk_order)? reverse_mta(mta->mta) : mta->mta; + sprintf(str, "%s : %d",ch, mta->numberMessages); + if (uk_order && ch != mta->mta) free(ch); + if (mta->numberReports != 0) + sprintf(str, "%s + %d", str, mta->numberReports); + return strdup(str); +} + +resize_mta_array(num) +int num; /* new number of mtas */ +{ + + int i = num; + + while (i < actual_nmtas_present) { + XtSetMappedWhenManaged(mta_array[i].widget, False); + XtUnmanageChild(mta_array[i].widget); + XtDestroyWidget(mta_array[i].widget); + i++; + } + if (num == 0) { + if (mta_array != NULL) { + free((char *) mta_array); + mta_array = NULL; + } + } else if (actual_nmtas_present == 0) + mta_array = (struct mta_disp_struct *) + calloc((unsigned int) num, + sizeof(struct mta_disp_struct)); + else if (num != actual_nmtas_present) + mta_array = (struct mta_disp_struct *) + realloc((char *) mta_array, + (unsigned int) (num * sizeof(struct mta_disp_struct))); + while (actual_nmtas_present < num) { + mta_array[actual_nmtas_present].mta = NULL; + mta_array[actual_nmtas_present].widget = + XtVaCreateManagedWidget(NULL, + labelWidgetClass, + mtas, + XtNresizable, TRUE, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + XtNborderWidth, 2, + NULL); + actual_nmtas_present++; + } + actual_nmtas_present = num; + num_mtas_displayed = num; +} + +/* */ +/* msgs */ +extern struct msg_struct *currentmsg, + **global_msg_list; +extern int max_msg_border; +extern void Msg(); +extern Widget msg_all, + msg_all_list, + msgs, + msg_info, + msg_viewport, + msg_label; +extern int number_msgs, + msg_info_strlen; + +struct msg_disp_struct *msg_array = NULL; +int actual_nmsgs_present = 0, + num_msgs_displayed = 0, + msg_info_shown = FALSE; +static char *create_msg_display_string(); + +char **msg_info_list; +int msg_info_list_size = 0; + +msg_display_info(msg) +struct msg_struct *msg; +{ + struct recip *ix; + char *str, buf[BUFSIZ]; + XFontStruct *font; + int i = 0; + + if (msg_info_list_size == 0) + resize_info_list(&msg_info_list, &msg_info_list_size); + + set_info_list(msg_info_list, i++, strdup(msg->msginfo->queueid)); + set_info_list(msg_info_list, i++, strdup(" ")); + + set_info_list(msg_info_list, i++, strdup("Originator")); + str = (uk_order) ? reverse_adr(msg->msginfo->originator) + : strdup(msg->msginfo->originator); + set_info_list(msg_info_list, i++, str); + + if (msg->msginfo->size != 0) { + set_info_list(msg_info_list, i++, strdup("Size")); + num2unit(msg->msginfo->size, buf); + set_info_list(msg_info_list, i++, strdup(buf)); + } + if (msg->msginfo->uaContentId != NULLCP) { + set_info_list(msg_info_list, i++, strdup("UA content ID")); + set_info_list(msg_info_list, i++, strdup(msg->msginfo->uaContentId)); + } + + if (msg->msginfo->inChannel != NULLCP) { + set_info_list(msg_info_list, i++, strdup("Inbound channel")); + set_info_list(msg_info_list, i++, strdup(msg->msginfo->inChannel)); + } + + ix = msg->reciplist; + if (ix != NULL) ix = ix->next; + while (ix != NULL) { + /* make sure have enough space for next recip */ + if (i + 20 >= msg_info_list_size) + resize_info_list(&msg_info_list, &msg_info_list_size); + + set_info_list(msg_info_list, i++, strdup(" ")); + set_info_list(msg_info_list, i++, strdup(" ")); + + set_info_list(msg_info_list, i++, strdup("To")); + str = (uk_order) ? reverse_adr(ix -> recipient) + : strdup(ix -> recipient); + sprintf(buf, "%s (id %d)", str, ix->id); + free(str); + set_info_list(msg_info_list, i++, strdup(buf)); + + if (ix->info != NULLCP) { + set_info_list(msg_info_list, i++, strdup("Error Information")); + set_info_list(msg_info_list, i++, strdup(ix->info)); + } + + if (ix->chansOutstanding == NULL) { + set_info_list(msg_info_list, i++, strdup(" ")); + set_info_list(msg_info_list, i++, strdup("awaiting DRs")); + } else { + set_info_list(msg_info_list, i++, strdup("Remaining channels")); + set_info_list(msg_info_list, i++, strdup(ix->chansOutstanding)); + } + + if (ix->status->cachedUntil != 0) { + set_info_list(msg_info_list, i++, strdup("Delayed until")); + str = time_t2RFC(ix->status->cachedUntil); + set_info_list(msg_info_list, i++, str); + } + + set_info_list(msg_info_list, i++, strdup("Status")); + set_info_list(msg_info_list, i++, + strdup((ix->status->enabled == TRUE) ? "enabled" : "disabled")); + + if (ix->status->lastAttempt != 0) { + set_info_list(msg_info_list, i++, strdup("Last attempt")); + str = time_t2RFC(ix->status->lastAttempt); + set_info_list(msg_info_list, i++, str); + } + + if (ix->status->lastSuccess != 0) { + set_info_list(msg_info_list, i++, strdup("Last success")); + str = time_t2RFC(ix->status->lastSuccess); + set_info_list(msg_info_list, i++, str); + } + ix = ix->next; + } + /* make sure have enough space for rest of info */ + if (i + 10 >= msg_info_list_size) + resize_info_list(&msg_info_list, &msg_info_list_size); + + set_info_list(msg_info_list, i++, strdup(" ")); + set_info_list(msg_info_list, i++, strdup(" ")); + + if (msg->msginfo->contenttype != NULLCP) { + set_info_list(msg_info_list, i++, strdup("Content type")); + set_info_list(msg_info_list, i++, strdup(msg->msginfo->contenttype)); + } + + if (msg->msginfo->eit != NULL) { + set_info_list(msg_info_list, i++, strdup("Eits")); + set_info_list(msg_info_list, i++, strdup(msg->msginfo->eit)); + } + + set_info_list(msg_info_list, i++, strdup("Age")); + str = time_t2str(time((time_t *) 0) - msg->msginfo->age); + set_info_list(msg_info_list, i++, str); + + if (msg->msginfo->expiryTime != 0) { + set_info_list(msg_info_list, i++, strdup("Expiry time")); + str = time_t2RFC(msg->msginfo->expiryTime); + set_info_list(msg_info_list, i++, str); + } + + if (msg->msginfo->deferredTime != 0) { + set_info_list(msg_info_list, i++, strdup("Deferred until")); + str = time_t2RFC(msg->msginfo->deferredTime); + set_info_list(msg_info_list, i++, str); + } + + set_info_list(msg_info_list, i++, strdup("Priority")); + switch (msg->msginfo->priority) { + case int_Qmgr_Priority_low: + str = strdup("low"); + break; + case int_Qmgr_Priority_normal: + default: + str = strdup("normal"); + break; + case int_Qmgr_Priority_high: + str = strdup("high"); + break; + } + set_info_list(msg_info_list, i++, str); + + if (msg->msginfo->errorCount != 0) { + set_info_list(msg_info_list, i++, strdup("Number of errors")); + str = itoa(msg->msginfo->errorCount); + set_info_list(msg_info_list, i++, str); + } + + + XawListChange(msg_all_list, + msg_info_list, + i, 0, True); + + XtVaSetValues(msg_info, + XtNlabel, "all", + NULL); + + XtSetMappedWhenManaged(msg_all, True); + XtSetMappedWhenManaged(msg_viewport, False); + if ((font = msgFont(msg)) != NULL) + XtVaSetValues(msg_info, + XtNfont, font, + NULL); + msg_info_shown = TRUE; +} + +msg_display_all() +{ + XtVaSetValues(msg_info, + XtNlabel, "info", + NULL); + XtSetMappedWhenManaged(msg_viewport, True); + XtSetMappedWhenManaged(msg_all, False); + msg_info_shown = FALSE; +} + +display_msgs() +{ + if (mode == control) + control_display_msgs(); +} + +int display_empty_msg_list() +{ + int i; + + for (i = 0; i < actual_nmsgs_present; i++) { + msg_array[i].msg = NULL; + XtSetMappedWhenManaged(msg_array[i].widget, False); + } + currentmsg = NULL; + reset_label(msg_label); + MtaToggle(); + MsgToggle(); +} + +int control_msgs_ub = 10, + msgs_ub = True; +extern Widget msgs_showall; + +control_display_msgs() +{ + int i; + char *str; + XFontStruct *font; + XtUnmanageChild(msgs); + XawFormDoLayout(msgs, False); + + for (i = 0; i < actual_nmsgs_present; i++) + XtSetMappedWhenManaged(msg_array[i].widget, False); + resize_msg_array((msgs_ub == True && number_msgs > control_msgs_ub) ? control_msgs_ub : number_msgs); + + i = 0; + while (i < num_msgs_displayed) { + msg_array[i].msg = global_msg_list[i]; + str = create_msg_display_string(global_msg_list[i]); + XtSetMappedWhenManaged(msg_array[i].widget, True); + XtUnmanageChild(msg_array[i].widget); + font = msgFont(msg_array[i].msg); + XtVaSetValues(msg_array[i].widget, + XtNlabel, str, + XtNbackgroundPixmap, + (font != NULL && font == disabledFont) ? backpixmap : ParentRelative, + XtNborderColor, msgcolourOf(msg_array[i].msg), + XtNborderWidth, msgborderOf(msg_array[i].msg), + NULL); + if (font != NULL) + XtVaSetValues(msg_array[i].widget, + XtNfont, font, + NULL); + + XtManageChild(msg_array[i].widget); + free(str); + i++; + } + if (msgs_ub == True && num_msgs_displayed < number_msgs) + XtSetMappedWhenManaged(msgs_showall, True); + else + XtSetMappedWhenManaged(msgs_showall, False); + + if (msg_info_shown == TRUE + && currentmsg != NULL) + msg_display_info(currentmsg); + XawFormDoLayout(msgs, True); + XtManageChild(msgs); +} + +monitor_display_msgs() +{ +} + +char *create_msg_header() +{ + /* takes from current msg */ + char *str; + char buf[BUFSIZ]; + if (currentmsg == NULL) + str = strdup("No current message"); + else { + sprintf(buf, "Current msg : %s", + currentmsg->msginfo->queueid); + str = strdup(buf); + } + + return str; +} + +resize_msg_array(num) +int num; /* new number of msgs */ +{ + int i = num; +/* if (control_msgs_ub < actual_nmsgs_present)*/ + + while (i < actual_nmsgs_present) { + XtSetMappedWhenManaged(msg_array[i].widget, False); + XtDestroyWidget(msg_array[i].widget); + i++; + } + + if (num == 0) { + if (msg_array != NULL) { + free ((char *) msg_array); + msg_array = NULL; + } + } else if (actual_nmsgs_present == 0) + msg_array = (struct msg_disp_struct *) + calloc((unsigned int) num, + sizeof(struct msg_disp_struct)); + else if (actual_nmsgs_present != num) + msg_array = (struct msg_disp_struct *) + realloc((char *) msg_array, + (unsigned int) (num * sizeof(struct msg_disp_struct))); + + while (actual_nmsgs_present < num) { + msg_array[actual_nmsgs_present].msg = NULL; + msg_array[actual_nmsgs_present].widget = + XtVaCreateManagedWidget(NULL, + labelWidgetClass, + msgs, + XtNfromVert, (actual_nmsgs_present == 0) ? NULL : msg_array[actual_nmsgs_present-1].widget, + XtNfromHoriz, NULL, + XtNresizable, TRUE, + XtNborderWidth, 2, + XtNleft, XtChainLeft, + XtNright, XtChainLeft, + XtNtop, XtChainTop, + XtNbottom, XtChainTop, + NULL); + actual_nmsgs_present++; + } + actual_nmsgs_present = num; + num_msgs_displayed = num; +} + +static char *create_msg_display_string(msg) +struct msg_struct *msg; +{ + char str[BUFSIZ]; + char *ch1, *ch2; + + if (msg->reciplist == NULL + || msg->reciplist->next == NULL) + /* delivery report */ + sprintf(str,"dr (%s) to %s", + msg->msginfo->queueid, + msg->msginfo->originator); + else { + struct recip *ix = msg->reciplist; + int found = 0; + + while (ix != NULL && found == 0) { + if (ix->actChan != NULL + && currentchan != NULL + && strcmp(ix->actChan, + currentchan->channelname) == 0) { + /* channel matches */ + if (is_loc_chan(currentchan) == TRUE) { + if (ix->recipient && currentmta + && strcmp(ix->recipient, currentmta->mta) == 0) + found = 1; + } else if (ix->mta != NULL + && currentmta != NULL + && strcmp(ix->mta, + currentmta->mta) == 0) + /* mta matches */ + found = 1; + } + if (found == 0) + ix = ix->next; + } + if (ix != NULL && ix->id == 0) { + /* delivery report ? */ + ch1 = (uk_order) ? reverse_adr(ix -> recipient) + : ix -> recipient; + sprintf(str, "dr (%s) to %s", + msg->msginfo->queueid, + ch1); + if (uk_order && ch1 != ix -> recipient) free(ch1); + } else { + if (ix == NULL) ix = msg->reciplist->next; + + ch1 = (uk_order) ? reverse_adr(ix -> recipient) : ix -> recipient; + ch2 = (uk_order) ? reverse_adr(msg->msginfo->originator) : msg->msginfo->originator; + + sprintf(str, "%s to %s from %s", + msg->msginfo->queueid, + ch1, ch2); + if (uk_order) { + if (ch1 != ix -> recipient) free(ch1); + if (ch2 != msg->msginfo->originator) free(ch2); + } + } + } + + return strdup(str); +} + +reset_label(hdr) +Widget hdr; +{ + char *str = NULL; + XFontStruct *font = normalFont; + if (hdr == channel_label) { + str = create_channel_header(); + font = chanFont(currentchan); + } else if (hdr == mta_label) { + str = create_mta_header(); + font = mtaFont(currentmta); + } else if (hdr == msg_label) { + str = create_msg_header(); + font = msgFont(currentmsg); + } + XtVaSetValues(hdr, + XtNlabel, str, + NULL); + if (font != NULL) + XtVaSetValues(hdr, + XtNfont, font, + NULL); + + if (str) free(str); +} + +/* */ +extern Widget connect_command, + refresh_command; +extern struct tailor *tailors; +extern void tailor_free(); + +ResetForDisconnect() +{ + /* change disconnect to connect */ + XtVaSetValues(connect_command, + XtNlabel, "connect", + NULL); + XtVaSetValues(refresh_command, + XtNlabel, "refresh", + NULL); + if (tailors) { + tailor_free(tailors); + tailors = NULL; + } + MapButtons(False); + MapVolume(False); + undisplay_time_label(); + + if (connectState == connected) + clear_displays(); + if (Qinformation != NULLCP) { + free(Qinformation); + Qinformation = NULLCP; + } + if (Qversion != NULLCP) { + free(Qversion); + Qversion = NULLCP; + XtVaSetValues(qversion, + XtNlabel, "???", + NULL); + } +} + +clear_displays() +{ + /* unmap all displays */ + /* deal with channel display */ + clear_monitor(); + clear_channel_display(); + clear_control(); + +} + +clear_monitor() +{ + int i = 0, + j = 0; + XawFormDoLayout(monitor_form, False); + if (display_list != NULL) { + while (i < num_channels) { + if (display_list[i] != NULL) { + if (display_list[i]->form) + XawFormDoLayout(display_list[i]->form, False); + if (display_list[i]->box) + XawFormDoLayout(display_list[i]->box, False); + if (display_list[i]->chan != NULL) { + XtDestroyWidget(display_list[i]->chan); + j = 0; + while (j < display_list[i] -> num_allocd + && display_list[i]->mtas[j] != NULL) { + if (display_list[i]->mtas[j]->widget != NULL) + XtDestroyWidget(display_list[i]->mtas[j]->widget); + free((char *) display_list[i]->mtas[j]); + j++; + } + if (display_list[i]->mtas) + free((char *) display_list[i]->mtas); + } + if (display_list[i]->box != NULL) + XtDestroyWidget(display_list[i]->box); + if (display_list[i]->form != NULL) + XtDestroyWidget(display_list[i]->form); + } + free((char *) display_list[i]); + i++; + } + free((char *) display_list); + display_list = NULL; + } + XawFormDoLayout(monitor_form, True); +} + +clear_control() +{ + /* destructive clear removing channel, mta, msg displays */ + /* and freeing globallist */ + clear_mta_display(); + clear_msg_display(); +} + +clear_channel_display() +{ + int i; + free_channel_list(); + currentchan = NULL; + resize_chan_array(0); + reset_label(channel_label); + ChanToggle(); + for (i = 0; i < actual_nchans_present; i++) { + if (channel_array[i] != NULL) + XtSetMappedWhenManaged(channel_array[i], False); + } +} + +clear_mta_display() +{ + int i; + + XtSetMappedWhenManaged(mta_viewport, False); + XtSetMappedWhenManaged(mtas, False); + XtUnmanageChild(mtas); + resize_mta_array(0); + XtManageChild(mtas); + XtSetMappedWhenManaged(mtas, True); + XtSetMappedWhenManaged(mta_viewport, True); + currentmta = NULL; + read_currentmta = 0; + reset_label(mta_label); + MtaToggle(); + for (i = 0; i < actual_nmtas_present; i++) { + if (mta_array[i].widget != NULL) + XtSetMappedWhenManaged(mta_array[i].widget, False); + } +} + +clear_msg_display() +{ + int i; + + resize_msg_array(0); + currentmsg = NULL; + reset_label(msg_label); + MsgToggle(); + if (msg_info_shown == TRUE) + msg_display_all(); + for (i = 0; i < actual_nmsgs_present; i++) { + if (msg_array[i].widget != NULL) + XtSetMappedWhenManaged(msg_array[i].widget, False); + } +} + +void ChanToggle() +{ + if (chan_info_shown == TRUE) + chan_display_all(); +} + +void MtaToggle() +{ + if (mta_info_shown == TRUE) + mta_display_all(); +} + +void MsgToggle() +{ + if (msg_info_shown == TRUE) + msg_display_all(); +} + +toggle_info_displays() +{ + ChanToggle(); + MtaToggle(); + MsgToggle(); +} + +/* */ +textdisplay(tuple, str) +Popup_tuple *tuple; +char *str; +{ + XtVaSetValues (tuple -> text, XtNstring, str == NULLCP ? "" : str, 0); +} + +extern Widget top; +terminate_display() +{ + XtDestroyWidget(top); +/* XtDestroyWidget(popup);*/ +} + +update_channel_from_mtas(chan, nmsgs, ndrs, nmtas, volume) +struct chan_struct *chan; +int nmsgs, + ndrs, + nmtas, + volume; +{ + int changed = FALSE; + + if (chan -> numberMessages != nmsgs) { + if (compat) + total_number_messages + += nmsgs - chan -> numberMessages; + chan -> numberMessages = nmsgs; + changed = TRUE; + } + + if (chan -> numberReports != ndrs) { + if (compat) + total_number_reports += ndrs - chan -> numberReports; + chan -> numberReports = ndrs; + changed = TRUE; + } + + if (chan -> num_mtas != nmtas) { + chan -> num_mtas = nmtas; + changed = TRUE; + } + if (chan -> volumeMessages != volume) { + if (compat) + total_volume += volume - chan -> volumeMessages; + chan -> volumeMessages = volume; + changed = TRUE; + } + + if (chan->given_num_mtas != chan -> num_mtas) { + chan -> given_num_mtas = chan->num_mtas; + changed = TRUE; + } + + + if (changed == TRUE) { + redisplay_channel(chan); + if (compat) + display_totals(); + } +} + +static void redisplay_channel(chan) +struct chan_struct *chan; +{ + int i = 0; + char *str; + + /* do control display */ + while (i < num_channels && globallist[i] != chan) + i++; + + if (i < num_channels) { + str = create_channel_display_string(globallist[i]); + XtVaSetValues(channel_array[i], + XtNlabel, str, + XtNborderColor, chancolourOf(globallist[i]), + XtNborderWidth, chanborderOf(globallist[i]), + XtNbackgroundPixmap, + (globallist[i]->status->enabled == FALSE) ? backpixmap : ParentRelative, + NULL); + free(str); + } + + if (mode == monitor) { + /* do monitor display */ + str = create_channel_monitor_string(chan); + XtVaSetValues(display_list[chan->display_num] -> chan, + XtNlabel, str, + XtNborderColor, chancolourOf(chan), + XtNborderWidth, chanborderOf(chan), + XtNbackgroundPixmap, (chan->status->enabled == FALSE) ? backpixmap : ParentRelative, + NULL); + free(str); + } +} + +static char *time_t2str(in) +time_t in; +{ + char buf[BUFSIZ]; + time_t result; + buf[0] = '\0'; + + if (in < 0) + return strdup("still in the womb"); + + if ((result = in / (60 * 60 * 24)) != 0) { + sprintf(buf, "%d day%s", + result, + (result == 1) ? "" : "s"); + in = in % (60 * 60 * 24); + } + + if ((result = in / (60 * 60)) != 0) { + sprintf(buf, + (buf[0] == '\0') ? "%s%d hr%s" : "%s %d hr%s", + buf, + result, + (result == 1) ? "" : "s"); + in = in % (60 * 60); + } + if ((result = in / 60) != 0) { + sprintf(buf, + (buf[0] == '\0') ? "%s%d min%s" : "%s %d min%s", + buf, + result, + (result == 1) ? "" : "s"); + in = in % 60; + } + + if (buf[0] == '\0' && in != 0) + sprintf(buf, "%d sec%s", + in, + (in == 1) ? "" : "s"); + if (buf[0] == '\0') + sprintf(buf, "just born"); + return strdup(buf); +} + +static void resize_info_list(plist, psize) +char ***plist; +int *psize; +{ + if (*psize == 0) { + *psize += BUFSIZ; + *plist = (char **) calloc(*psize, sizeof(char *)); + } else { + *psize += BUFSIZ; + *plist = (char **) realloc(*plist, + (unsigned) (*psize) * sizeof(char *)); + } +} diff --git a/Src/MTAconsole/drive.c b/Src/MTAconsole/drive.c new file mode 100644 index 0000000..5863f35 --- /dev/null +++ b/Src/MTAconsole/drive.c @@ -0,0 +1,347 @@ +/* drive.c: driving routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/drive.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/drive.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: drive.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +#ifdef notdef +#include "IntrinsicP.h" +#include "TranslateI.h" +#include "ConvertI.h" +#include "InitialI.h" +#endif +#include +#include + +struct stat statbuf; +#define MAXMTAS 10 /* shouldn't get anything longer than that ? */ + +#define DEFAULT_NORMALFONT "*-medium-r-normal--14-*" +#define DEFAULT_ACTIVEFONT "*-bold-r-normal--14-*" +#define DEFAULT_DISABLEDFONT "*-medium-i-normal--14-*" + +typedef struct _cmdLineResources { + int percentage; + int lowerbound; + int totalnumber; + int totalvolume; + int maxvert; + Boolean confirm; + Boolean ukorder; + Boolean compat; + Boolean ignoreInactiveInbounds; + int ncolours; + char *connectHost; + char *heuristic; + XFontStruct *defaultFont; + char *refresh; + char *inactive; +} CmdLineResources; + +static CmdLineResources cmdLine_resources; + +static XtResource resources[] = { +{"xtDefaultFont", "XtDefaultFont", XtRFontStruct, sizeof(XFontStruct *), + XtOffset(struct _cmdLineResources *, defaultFont), + XtRImmediate, (caddr_t) 0}, +{"percentage", "Percentage", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, percentage), + XtRImmediate, (caddr_t) 0}, +{"lowerbound", "Lowerbound", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, lowerbound), + XtRImmediate, (caddr_t) 0}, +{"totalnumber", "Totalnumber", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, totalnumber), + XtRImmediate, (caddr_t) 0}, +{"totalvolume", "Totalvolume", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, totalvolume), + XtRImmediate, (caddr_t) 0}, +{"maxvert", "Maxvert", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, maxvert), + XtRImmediate, (caddr_t) 0}, +{"confirm", "Confirm", XtRBoolean, sizeof(Boolean), + XtOffset(struct _cmdLineResources *, confirm), + XtRImmediate, (caddr_t) TRUE}, +{"ukorder", "UkOrder", XtRBoolean, sizeof(Boolean), + XtOffset(struct _cmdLineResources *, ukorder), + XtRImmediate, (caddr_t) FALSE}, +{"ncolours", "Ncolours", XtRInt, sizeof(int), + XtOffset(struct _cmdLineResources *, ncolours), + XtRImmediate, (caddr_t) 0}, +{"connectHost", "ConnectHost", XtRString, sizeof(String), + XtOffset(struct _cmdLineResources *, connectHost), + XtRImmediate, (caddr_t) NULLCP}, +{"compat", "Compat", XtRBoolean, sizeof(Boolean), + XtOffset(struct _cmdLineResources *, compat), + XtRImmediate, (caddr_t) FALSE}, +{"ignoreInactiveInbounds", "IgnoreInactiveInbounds", XtRBoolean, sizeof(Boolean), + XtOffset(struct _cmdLineResources *, ignoreInactiveInbounds), + XtRImmediate, (caddr_t) FALSE}, +{"heuristic", "Heuristic", XtRString, sizeof(String), + XtOffset(struct _cmdLineResources *, heuristic), + XtRImmediate, (caddr_t) NULLCP}, +{"refresh", "Refresh", XtRString, sizeof(String), + XtOffset(struct _cmdLineResources *, refresh), + XtRImmediate, (caddr_t) NULLCP}, +{"inactiveTime", "InactiveTime", XtRString, sizeof(String), + XtOffset(struct _cmdLineResources *, inactive), + XtRImmediate, (caddr_t) NULLCP}, +}; + +static XrmOptionDescRec options[] = { +{"-percentage", "percentage", XrmoptionSepArg, 0}, +{"-lowerbound", "lowerbound", XrmoptionSepArg, 0}, +{"-number", "totalnumber", XrmoptionSepArg, 0}, +{"-volume", "totalvolume", XrmoptionSepArg, 0}, +{"-downLines", "maxvert", XrmoptionSepArg, 0}, +{"-NoConfirm", "confirm", XrmoptionNoArg, "False"}, +{"-ukorder", "ukorder", XrmoptionNoArg, "True"}, +{"-colours", "ncolours", XrmoptionSepArg, 0}, +{"-Queue", "connectHost", XrmoptionSepArg, NULLCP}, +{"-compat", "compat", XrmoptionNoArg, "True"}, +{"-ignoreInactiveInbounds", "ignoreInactiveInbounds", XrmoptionNoArg, "True"}, +{"-heuristic", "heuristic", XrmoptionSepArg, NULLCP}, +{"-refresh", "refresh", XrmoptionSepArg, NULLCP}, +{"-inactiveTime", "inactiveTime",XrmoptionSepArg, NULLCP}, +}; + +XtAppContext appContext; +Display *disp; +char *hostname, + tailorfile[MAXPATHLENGTH]; +int confirm = TRUE, + uk_order = FALSE, + doConnect = FALSE, + userConnected = FALSE, + autoRefresh = TRUE, + compat = FALSE, + displayInactIns = TRUE, + autoReconnect = TRUE, + auth = FALSE, + lower_bound_mtas, + percent; +Heuristic heuristic; +State connectState = notconnected; +Authentication authentication = limited; +char *Qinformation = NULLCP, + *Qversion = NULLCP; +extern unsigned long timeoutFor, inactiveFor; +time_t currentTime; +XFontStruct *disabledFont = NULL, + *activeFont = NULL, + *normalFont = NULL, + *defaultFont = NULL; + +static void general_initialise(); +extern Widget header, error, top; +#define WAIT_CONNECTION "Please wait for connection to the queue manager" + +char *myname; +char password[100], + username[100]; + +extern double ub_total_number, ub_total_volume; +extern ConnectRetry(); + +main(argc, argv) +int argc; +char **argv; +{ + int uid; + struct passwd *pwd; + uid = getuid(); + pwd = getpwuid(uid); + strcpy(username, pwd->pw_name); + strcpy(password, "dummy"); + strcpy(tailorfile,".MTAconsole"); + if ((myname = rindex (argv[0], '/')) != NULL) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + fillin_passwdpep(username, NULLCP, 0); + general_initialise(argc, argv); + initiate_assoc(argc, argv); + create_widgets(disp, appContext); + + SetColours(disp, XtWindow(top)); + if (doConnect == TRUE) { + XtVaSetValues(header, + XtNlabel, WAIT_CONNECTION, + NULL); + InitConnectTimeOut(); + } + XtAppMainLoop(appContext); +} + +#define DEFAULT_MAX_BORDER 5 +#define DEFAULT_NUM_COLORS 10 +#define DEFAULT_UL_MAX_LINES 4 +int max_chan_border = DEFAULT_MAX_BORDER, + max_mta_border = DEFAULT_MAX_BORDER, + max_msg_border = DEFAULT_MAX_BORDER; +int num_colors = DEFAULT_NUM_COLORS; +int max_horiz_mtas, + max_vert_lines; + +extern time_t parsetime(); +extern void advise(); + +static void general_initialise(argc, argv) +int argc; +char **argv; +{ + char buf[BUFSIZ]; + Arg arg[1]; + extern int optind; + extern char *optarg; + extern Widget top; + + gethostname(buf,BUFSIZ); + hostname = strdup(buf); + + isodetailor(myname, 1); + + XtToolkitInitialize(); + + appContext = XtCreateApplicationContext(); + + disp = XtOpenDisplay(appContext, + (String) NULL, + (String) myname, + (String) APPLICATION_CLASS, + options, XtNumber(options), + &argc, + argv); + if (disp == NULL) { + printf("%s\n", "unable to open display"); + exit(1); + } + /* to get round bug in XtRemoveInput */ + XtRemoveInput(XtAppAddInput(appContext, + 0, + XtInputReadMask, + ConnectRetry, + NULL)); + + XtSetArg(arg[0], XtNinput, True); + /* create top level */ + top = XtAppCreateShell(myname, + APPLICATION_CLASS, + applicationShellWidgetClass, + disp, + arg, + 0); + + + if (DisplayCells (disp, DefaultScreen(disp)) <= 2) + num_colors = 1; + else + max_chan_border = max_mta_border = 2; + + max_horiz_mtas = MAXMTAS; + max_vert_lines = DEFAULT_UL_MAX_LINES; + heuristic = line; + lower_bound_mtas = 20; + percent = 50; + + XtGetApplicationResources (top, &cmdLine_resources, + resources, XtNumber(resources), NULL, 0); + + + if (cmdLine_resources.defaultFont) { + defaultFont = cmdLine_resources.defaultFont; + } + + if (cmdLine_resources.percentage) { + percent = cmdLine_resources.percentage; + } + if (cmdLine_resources.lowerbound) { + lower_bound_mtas = cmdLine_resources.lowerbound; + } + if (cmdLine_resources.totalnumber) + ub_total_number = cmdLine_resources.totalnumber; + if (cmdLine_resources.totalvolume) + ub_total_volume = cmdLine_resources.totalvolume; + if (cmdLine_resources.maxvert) + max_vert_lines = cmdLine_resources.maxvert; + confirm = cmdLine_resources.confirm; + uk_order = cmdLine_resources.ukorder; + if (cmdLine_resources.ncolours) + num_colors = cmdLine_resources.ncolours; + if (cmdLine_resources.connectHost) { + doConnect = TRUE; + hostname = strdup(cmdLine_resources.connectHost); + } + compat = cmdLine_resources.compat; + displayInactIns = (cmdLine_resources.ignoreInactiveInbounds == TRUE) ? + FALSE : TRUE; + if (cmdLine_resources.heuristic != NULLCP) { + if (lexequ(cmdLine_resources.heuristic, "all") == 0) + heuristic = all; + else if (lexnequ(cmdLine_resources.heuristic, + "percent", strlen("percent")) == 0) + heuristic = percentage; + else if (lexequ(cmdLine_resources.heuristic, + "line") == 0) + heuristic = line; + else if (lexequ(cmdLine_resources.heuristic, "mtaonly") == 0 + || lexequ(cmdLine_resources.heuristic, "chanonly") == 0) + heuristic = chanonly; + } + if (cmdLine_resources.refresh != NULLCP) + settimeoutFor(cmdLine_resources.refresh); + if (cmdLine_resources.inactive != NULLCP) + inactiveFor = parsetime(cmdLine_resources.inactive) * 1000; + setfonts(); +} + +XFontStruct *get_three_choice_font(font, one, two, three) +char *font, *one, *two, *three; +{ + char *retstr; + XFontStruct *retfont; + + if ((retstr = XGetDefault(disp, one, font)) != NULLCP + && (retfont = XLoadQueryFont(disp, retstr)) != NULL) + return retfont; + if ((retstr = XGetDefault(disp, two, font)) != NULLCP + && (retfont = XLoadQueryFont(disp, retstr)) != NULL) + return retfont; + if ((retfont = XLoadQueryFont(disp, three)) != NULL) + return retfont; + if (defaultFont == NULL) { + printf("Unable to load font '%s'\n", font); + exit(0); + } + return defaultFont; +} + +setfonts () +{ + normalFont = get_three_choice_font("normalfont", + myname, + APPLICATION_CLASS, + DEFAULT_NORMALFONT); + activeFont = get_three_choice_font("activefont", + myname, + APPLICATION_CLASS, + DEFAULT_NORMALFONT); + disabledFont = get_three_choice_font("disabledfont", + myname, + APPLICATION_CLASS, + DEFAULT_NORMALFONT); +} diff --git a/Src/MTAconsole/make b/Src/MTAconsole/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/MTAconsole/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/MTAconsole/misc.c b/Src/MTAconsole/misc.c new file mode 100644 index 0000000..a01b526 --- /dev/null +++ b/Src/MTAconsole/misc.c @@ -0,0 +1,277 @@ +/* misc.c : routines that wouldn't fit anywhere else */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/misc.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/misc.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: misc.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" +#include + +#include "back.bit" +Pixmap backpixmap; + +struct color_item *colors = NULL; +XColor white, + exact_white, + black, + exact_black; +Pixel fg, + bg; +extern int compat; + +create_pixmaps(disp) +Display *disp; +{ + Window root; + root = XDefaultRootWindow(disp); + backpixmap = XCreatePixmapFromBitmapData(disp, root, + back_bits, back_width, back_height, + fg, + bg, + XDefaultDepth(disp,XDefaultScreen(disp))); +} + +static Colormap color_map; + +extern int num_colors; +extern Widget quit_command; + +#define MAX_COLOR_VALUE 65535 + +/* setup the colours used */ +/* ARGSUSED */ +SetColours(disp, win) +Display *disp; +Window win; +{ + int i, + badness; + Colormap cmap2; + double fract; + + XtVaGetValues (quit_command, + XtNbackground, &bg, + XtNforeground, &fg, + NULL); + + color_map = DefaultColormap(disp, + XDefaultScreen(disp)); + + XAllocNamedColor(disp, color_map, + "white", + &white, + &exact_white); + + XAllocNamedColor(disp, color_map, + "black", + &black, + &exact_black); + + colors = (struct color_item *) calloc((unsigned) num_colors, + sizeof(struct color_item)); + if (num_colors == 1) { + colors[0].badness = 0; + colors[0].colour.pixel = fg; + } else { + for (i = 0; i < num_colors; i++) { + badness = (i * max_bad_channel/num_colors); + colors[i].badness = badness; + + colors[i].colour.pixel = 0; + colors[i].colour.blue = 0; + + if (badness > max_bad_channel/2) + colors[i].colour.red = MAX_COLOR_VALUE; + else { + fract = (double) badness * 2.0 / (double) max_bad_channel; + colors[i].colour.red = fract * MAX_COLOR_VALUE; + } + if (colors[i].colour.red > MAX_COLOR_VALUE) + colors[i].colour.red = MAX_COLOR_VALUE; + + if (max_bad_channel - badness > max_bad_channel/2) + colors[i].colour.green = MAX_COLOR_VALUE; + else { + fract = ((double) (max_bad_channel - badness) * 2.0) / (double) max_bad_channel; + colors[i].colour.green = fract * MAX_COLOR_VALUE; + } + if (colors[i].colour.green > MAX_COLOR_VALUE) + colors[i].colour.green = MAX_COLOR_VALUE; + + colors[i].colour.flags = DoRed | DoGreen | DoBlue; + } + for (i = 0; i < num_colors; i++) { + if (XAllocColor(disp, color_map, &(colors[i].colour)) == 0) { + cmap2 = XCopyColormapAndFree(disp, color_map); + for (; i < num_colors; i++) + XAllocColor(disp, + cmap2, + &(colors[i].colour)); + color_map = cmap2; + break; + } + } + XSetWindowColormap(disp, win, color_map); + } + create_pixmaps(disp); +} + +char *stripstr(str) +char *str; +{ + char *ret, + *ix; + + ix = str; + while (*ix != '\0' && isspace(*ix)) ix++; + ret = ix; + while(*ix != '\0' && *ix != '\n') ix++; + if (*ix == '\n') *ix = '\0'; + + return ret; +} + +int is_loc_chan(chan) +struct chan_struct *chan; +{ + if (chan->chantype == int_Qmgr_chantype_mts + && chan->outbound > 0) + return TRUE; + else + return FALSE; +} + +extern Display *disp; +extern Widget top; +Window waitWindow = NULL; + +StartWait() +{ + if (waitWindow == (Window)NULL) { + XSetWindowAttributes attributes; + attributes.cursor = XCreateFontCursor(disp, XC_watch); + attributes.do_not_propagate_mask = (KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + PointerMotionMask); + waitWindow = XCreateWindow(disp, + XtWindow(top), + 0, 0, + XDisplayWidth(disp, + XDefaultScreen(disp)), + XDisplayHeight(disp, + XDefaultScreen(disp)), + (unsigned int) 0, + CopyFromParent, + InputOnly, + CopyFromParent, + (CWDontPropagate | CWCursor), + &attributes); + } + (void) XMapRaised(disp, waitWindow); + (void) XFlush(disp); +} + +EndWait() +{ + (void) XUnmapWindow(disp, waitWindow); +} + +extern Widget time_label; +extern Widget statistics; + +undisplay_time_label() +{ + XtSetMappedWhenManaged(time_label, False); + if (statistics != NULL) + XtSetMappedWhenManaged(statistics, False); +} + +extern Widget compat_stat_pane; + +redo_statistics_compat() +{ + if (statistics != NULL) { + if (compat) { + XtSetMappedWhenManaged(compat_stat_pane, False); + XtSetMappedWhenManaged(statistics, False); + } else { + XtSetMappedWhenManaged(statistics, True); + XtSetMappedWhenManaged(compat_stat_pane, True); + } + } +} + +display_time_label() +{ + update_time_label(); + XtSetMappedWhenManaged(time_label, True); + if (!compat && statistics != NULL) + XtSetMappedWhenManaged(statistics, True); +} + +extern time_t currentTime; +extern char *time_t2RFC(); +extern int currChans, maxChans; +extern int messagesIn, messagesOut, addrIn, addrOut; +extern time_t boottime; + +update_time_label() +{ + char *str, buf[BUFSIZ]; + time(¤tTime); + str = time_t2RFC(currentTime); + (void) sprintf(buf, "%d channel%s running (max %d) at %s", + currChans, (currChans == 1) ? "" : "s", + maxChans, str); + free(str); + XtVaSetValues(time_label, + XtNlabel, buf, + NULL); + + if (!compat && statistics != NULL) { +#define NUMBUF 15 + char adIn[NUMBUF], mgIn[NUMBUF], adOut[NUMBUF], mgOut[NUMBUF]; + str = time_t2RFC(boottime); + num2unit(addrIn, adIn); + num2unit(messagesIn, mgIn); + num2unit(addrOut, adOut); + num2unit(messagesOut, mgOut); + (void) sprintf(buf, "running since %s\nInbound %s Message%s to %s Recipient%s\nOutbound %s Message%s to %s Recipient%s", + str, mgIn, (messagesIn != 1) ? "s" : "", + adIn, (addrIn != 1) ? "s" : "", + mgOut, (messagesOut != 1) ? "s" : "", + adOut, (addrOut != 1) ? "s" : ""); + free(str); + XtVaSetValues(statistics, + XtNlabel, buf, + NULL); + } +} + +extern State connectState; + +/* ARGSUSED */ +void setLoad (w, ptr_load, load) +Widget w; +double *ptr_load; +double *load; +{ + if (connectState == connected) + *load = *ptr_load / 100; + else + *load = 0; +} + diff --git a/Src/MTAconsole/ops.c b/Src/MTAconsole/ops.c new file mode 100644 index 0000000..0e879dc --- /dev/null +++ b/Src/MTAconsole/ops.c @@ -0,0 +1,766 @@ +/* ops.c: encoding and decoding routines for qmgr interaction */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/ops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/ops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: ops.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" +#include "Qmgr-types.h" +#include + +extern Widget channel_label, + mta_label, + msg_label; +extern struct chan_struct **globallist, + *currentchan, + *find_channel(); +extern char *mystrtotime(); +extern int forceDown; + +time_t boottime = 0; +int messagesIn = 0, messagesOut = 0, addrIn = 0, addrOut = 0, + maxChans = 0, currChans = 0; +double opsPerSec = 0.0, runnableChans = 0.0, + msgsInPerSec = 0.0, msgsOutPerSec = 0.0; + +/* */ +/* channel operations */ + +#define CHAN_READ_INTERVAL 60 /* in secs */ + +CMD_TABLE chantbl_commands [] = { + "start", (int) chanstart, + "stop", (int) chanstop, + "clear", (int) chanclear, + "info", (int) chaninfo, + "cache add", (int) chancacheadd, + 0, 0 + }; + +/* ARGSUSED */ +int do_channelread (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_UNIV_UTCTime **arg; +{ + char *str; + UTC utc; + + utc = (UTC) malloc (sizeof(struct UTCtime)); + utc->ut_flags = UT_SEC; + + utc->ut_sec = CHAN_READ_INTERVAL; + + str = utct2str(utc); + *arg = str2qb (str, strlen(str), 1); + return OK; +} + +/* ARGSUSED */ +int do_channelcontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_ChannelControl **arg; +/* args[0] = channel */ +/* args[1] = stop,start,clear,cacheadd */ +/* args[2] = time */ +{ + char *timestr; + *arg = (struct type_Qmgr_ChannelControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + switch (cmd_srch(args[1], chantbl_commands)) { + case chanstart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case chanstop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case chanclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case chancacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[2]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for channels", + args[1])); + return NOTOK; + } + return OK; +} + +extern time_t time(); + +extern int firstChanRead; +extern Widget top, channel_viewport; + +/* ARGSUSED */ +int channelcontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_PrioritisedChannelList *result; +struct RoSAPindication *roi; +{ + Dimension width, + height; + extern time_t currentTime; + time(¤tTime); + channel_list(result); + + if (globallist != NULL) { + display_channels(); + if (firstChanRead == TRUE) { + XtVaGetValues(channel_viewport, + XtNwidth, &width, + XtNheight, &height, + NULL); + XtVaSetValues(channel_viewport, + XtNheight, height-1, + XtNwidth, width-1, + NULL); + } + reset_label(channel_label); + return OK; + } else { + currentchan = NULL; + } + reset_label(channel_label); + return NOTOK; +} + +extern int compat; + +/* ARGSUSED */ +int channelread_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_ChannelReadResult *result; +struct RoSAPindication *roi; +{ + Dimension width, + height; + extern time_t currentTime; + time(¤tTime); + + if (compat) { + runnableChans = (double) result->load1; + opsPerSec = (double) result->load2; + currChans = (int) result->currchans; + maxChans = (int) result->maxchans; + } + channel_list(result->channels); + + if (globallist != NULL) { + display_channels(); + if (firstChanRead == TRUE) { + XtVaGetValues(channel_viewport, + XtNwidth, &width, + XtNheight, &height, + NULL); + XtVaSetValues(channel_viewport, + XtNheight, height-1, + XtNwidth, width-1, + NULL); + } + reset_label(channel_label); + return OK; + } else { + currentchan = NULL; + } + reset_label(channel_label); + return NOTOK; +} + +/* ARGSUSED */ +int op_channelread (ad, ryo, rox, in, roi) +int ad; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + register struct type_Qmgr_ChannelReadResult *arg; + + arg = (struct type_Qmgr_ChannelReadResult *) in; + + channel_list(arg->channels); + + if (compat) { + runnableChans = (double) arg->load1; + opsPerSec = (double) arg -> load2; + currChans = arg->currchans; + maxChans = arg->maxchans; + } + if (globallist != NULL) { + display_channels(); + return OK; + } else { + currentchan = NULL; + } + reset_label(channel_label); + return NOTOK; +} + +/* */ +/* mtas */ +extern struct mta_struct *find_mta(), + *currentmta; +extern struct chan_struct *mta_list(); +extern Mode mode; + +#define MTA_READ_INTERVAL 60 /* in secs */ + +CMD_TABLE mtatbl_commands [] = { + "start", (int) mtastart, + "stop", (int) mtastop, + "clear", (int) mtaclear, + "info", (int) mtainfo, + "cache add", (int) mtacacheadd, + 0, 0 + }; + +/* ARGSUSED */ +int do_mtaread (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; /* args[0] is channel name */ +struct type_Qmgr_MtaRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MtaRead *) malloc(sizeof(**arg)); + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MTA_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + return OK; +} + +/* ARGSUSED */ +int do_mtacontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_MtaControl **arg; +/* args[0] = channel */ +/* args[1] = mta */ +/* args[2] = stop,start,clear,cacheadd */ +/* args[3] = time */ +{ + char *timestr; + *arg = (struct type_Qmgr_MtaControl *) malloc(sizeof(**arg)); + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + (*arg)->channel = str2qb(args[0], + strlen(args[0]), + 1); + (*arg)->mta = str2qb(args[1], + strlen(args[1]), + 1); + + switch (cmd_srch(args[2], mtatbl_commands)) { + case mtastart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case mtastop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case mtaclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case mtacacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[3]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for mtas", + args[2])); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +int mtacontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_MtaInfo *result; +struct RoSAPindication *roi; +{ + char *chan_name, + *name; + struct chan_struct *chan; + struct mta_struct *mta; + + chan_name = qb2str(result->channel); + chan = find_channel(chan_name); + + if (chan == NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("console: mtacontrol_result can't find channel %s",chan_name)); + return NOTOK; + } + + name = qb2str(result->mta); + mta = find_mta(chan, name); + + if (mta == NULL) { + if (forceDown != TRUE) + PP_NOTICE(("can not find mta %s on channel %s", + name, chan_name)); + free(chan_name); + free(name); + return OK; + } else { + update_mta(mta,result); + } + + currentchan = chan; + + order_mtas(&(chan->mtalist),chan->num_mtas); + display_mtas(chan); + reset_label(mta_label); + free(chan_name); + free(name); + return OK; +} + +extern char *pop_from_mta_refresh_list(); + +/* ARGSUSED */ +int mtaread_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_PrioritisedMtaList *result; +struct RoSAPindication *roi; +{ + struct chan_struct *chan; + char *mtaname = NULL; + char *channame; + + channame = pop_from_mta_refresh_list(); + + if (currentmta != NULL) + mtaname = strdup(currentmta->mta); + chan = mta_list(result, channame); + free(channame); + + if (forceDown == TRUE + && chan != currentchan) { + if (chan != NULL) { + free_mta_list(&(chan->mtalist), &(chan->num_mtas)); + chan->mtalist = NULL; + chan->num_mtas = 0; + } + return OK; + } + if ((mode == monitor && chan != NULL) + || (mode == control && chan != NULL && chan == currentchan)) { + order_mtas(&(chan->mtalist),chan->num_mtas); + if (mtaname != NULL) { + /* reset currentmta */ + currentmta = find_mta(chan, mtaname); + free(mtaname); + } + reset_label(mta_label); + display_mtas(chan); + return OK; + } else if (mode == control) { + display_empty_mta_list(currentchan); + currentmta = NULL; + display_empty_msg_list(); + reset_label(mta_label); + return OK; + } else { + /* fill in here */ + PP_LOG(LLOG_EXCEPTIONS, + ("MTAconsole in confused state")); + } + return NOTOK; +} + +/* ARGSUSED */ +int op_mtaread (ad, ryo, rox, in, roi) +int ad; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + register struct type_Qmgr_PrioritisedMtaList *arg; + struct chan_struct *chan; + char *mtaname=NULL, + *channame; + arg = (struct type_Qmgr_PrioritisedMtaList *) in; + channame = pop_from_mta_refresh_list(); + if (currentmta != NULL) + mtaname = strdup(currentmta->mta); + currentmta = NULL; + chan = mta_list(arg, channame); + free(channame); + if (chan != NULL) { + order_mtas(&(chan->mtalist),chan->num_mtas); + if (mtaname != NULL) { + /* reset currentmta */ + currentmta = find_mta(chan, mtaname); + free(mtaname); + } + reset_label(mta_label); + display_mtas(chan); + return OK; + } + reset_label(mta_label); + return NOTOK; +} + +/* */ +/* msgs */ +struct msg_struct *currentmsg, + **global_msg_list, + *find_msg(); +struct type_Qmgr_UserList *create_userlist(); +struct type_Qmgr_FilterList *fillinfilters(); +#define MSG_READ_INTERVAL 60 /* in secs */ + +CMD_TABLE msgtbl_commands [] = { + "start", (int) msgstart, + "stop", (int) msgstop, + "clear", (int) msgclear, + "info", (int) msginfo, + "cache add", (int) msgcacheadd, + 0, 0 + }; + +/* ARGSUSED */ +int do_msgcontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_MsgControl **arg; +/* args[0] = qid */ +/* args[1] = time */ +/* args[2] = stop, start, clear cacheadd*/ +/* args[3..] = NULL terminated list of users */ +{ + char *timestr; + *arg = (struct type_Qmgr_MsgControl *) malloc(sizeof(**arg)); + + (*arg)->qid = str2qb(args[0], + strlen(args[0]), + 1); + + (*arg)->users = create_userlist(args[0], &(args[3])); + + (*arg)->control = (struct type_Qmgr_Control *) + malloc(sizeof(struct type_Qmgr_Control)); + + switch (cmd_srch(args[2], msgtbl_commands)) { + case msgstart: + (*arg)->control->offset = type_Qmgr_Control_start; + break; + case msgstop: + (*arg)->control->offset = type_Qmgr_Control_stop; + break; + case msgclear: + (*arg)->control->offset = type_Qmgr_Control_cacheClear; + break; + case msgcacheadd: + (*arg)->control->offset = type_Qmgr_Control_cacheAdd; + timestr = mystrtotime(args[1]); + (*arg)->control->un.cacheAdd = str2qb(timestr,strlen(timestr),1); + free(timestr); + break; + default: + PP_LOG(LLOG_EXCEPTIONS, + ("console : '%s' unknown control param for msgs", + args[1])); + return NOTOK; + } + return OK; +} + +extern char *msginfo_args[3]; + +/* ARGSUSED */ +msgcontrol_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +struct type_Qmgr_Pseudo__newmessage *result; +struct RoSAPindication *roi; +{ + if (currentchan != NULL + && currentmta != NULL) { + msginfo_args[0] = currentchan->channelname; + msginfo_args[1] = currentmta->mta; + if (is_loc_chan(currentchan) == TRUE) + /* local */ + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + construct_event(readchannelmtamessage); + } + return OK; +} + +/* ARGSUSED */ +int do_readchannelmtamessage (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +char **args; +/* args[0] = chan args[1] = mta or name in case of local chan */ +struct type_Qmgr_MsgRead **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_MsgRead *) malloc(sizeof(**arg)); + bzero ((char *) *arg, sizeof(**arg)); + /* fillin time */ + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = MSG_READ_INTERVAL; + str = utct2str(utc); + (*arg)->time = str2qb(str, strlen(str), 1); + if (args[0] != NULLCP) + (*arg)->channel = str2qb(args[0], strlen(args[0]), 1); + if (args[1] != NULLCP) + (*arg)->mta = str2qb(args[1], strlen(args[1]), 1); + return OK; +} + +/* ARGSUSED */ +int readchannelmtamessage_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +register struct type_Qmgr_MsgList *result; +struct RoSAPindication *roi; +{ + char *msgname = NULL; + if (currentmsg != NULL) + msgname = strdup(currentmsg->msginfo->queueid); + msg_list(result); + + if (forceDown == TRUE) { + free_msg_list(); + global_msg_list = NULL; + } + + if (global_msg_list != NULL){ + order_msgs(); + if (msgname != NULL) { + /* reset currentmsg */ + currentmsg = find_msg(msgname); + free(msgname); + } + reset_label(msg_label); + display_msgs(); + return OK; + } else { + display_empty_msg_list(); + } + reset_label(msg_label); + return NOTOK; +} + +/* ARGSUSED */ +int op_readchannelmtamessage (ad, ryo, rox, in, roi) +int ad; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + register struct type_Qmgr_MsgList *arg; + char *msgname = NULL; + arg = (struct type_Qmgr_MsgList *) in; + if (currentmsg != NULL) + msgname = strdup(currentmsg->msginfo->queueid); + currentmsg = NULL; + msg_list(arg); + + if (global_msg_list != NULL){ + order_msgs(); + if (msgname != NULL) { + /* reset currentmsg */ + currentmsg = find_msg(msgname); + free(msgname); + } + reset_label(msg_label); + display_msgs(); + return OK; + } + reset_label(msg_label); + return NOTOK; + +} + + +struct type_Qmgr_FilterList *fillinfilters(args) +char **args; +/* args[0] = chan args[1] = mta or name in case of local chan */ +{ + struct type_Qmgr_FilterList *retval = + (struct type_Qmgr_FilterList *) calloc(1, sizeof(*retval)); + + retval->Filter = + (struct type_Qmgr_Filter *) calloc(1, sizeof(*retval->Filter)); + + retval->Filter->channel = str2qb(args[0], strlen(args[0]), 1); + if (args[1] != NULLCP) { + if (args[2] == (char *) 1) + retval->Filter->recipient = str2qb(args[1], strlen(args[1]), 1); + else + retval->Filter->mta = str2qb(args[1], strlen(args[1]), 1); + } + return retval; +} + + +struct type_Qmgr_UserList *create_userlist(qid, argv) +char *qid, + **argv; +{ + struct type_Qmgr_UserList *temp, + *head = NULL, + *tail = NULL; + int i = 0; + struct msg_struct *msg; + struct recip *ix; + + if (strcmp(argv[i], "*") == 0) { + if ((msg = find_msg(qid)) == NULL) + return NULL; + ix = msg -> reciplist; + while (ix != NULL) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) + malloc(sizeof(struct type_Qmgr_RecipientId)); + temp->RecipientId->parm = ix -> id; + ix = ix -> next; + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = tail->next; + } + } + } else { + while (argv[i] != NULL) { + temp = (struct type_Qmgr_UserList *) + calloc (1, sizeof(*temp)); + temp->RecipientId = (struct type_Qmgr_RecipientId *) + malloc(sizeof(struct type_Qmgr_RecipientId)); + temp->RecipientId->parm = atoi(argv[i++]); + + if (head == NULL) + head = tail = temp; + else { + tail->next = temp; + tail = tail->next; + } + } + } + return head; +} + +/* ARGSUSED */ +int do_quecontrol (ad, ds, args, arg) +int ad; +struct client_dispatch *ds; +int args; +struct type_Qmgr_QMGROp **arg; +{ + *arg = (struct type_Qmgr_QMGROp *) malloc(sizeof(**arg)); + (*arg)->parm = args; + return OK; +} + +/* ARGSUSED */ +int quecontrol_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_Pseudo__qmgrControl *result; +struct RoSAPindication *roi; +{ + return OK; +} + +extern int total_volume, total_number_messages, total_number_reports; +extern int delta_volume, delta_messages, delta_reports; + +/* ARGSUSED */ +int qmgrStatus_result (ad, id, dummy, result, roi) +int ad, + id, + dummy; +struct type_Qmgr_QmgrStatus *result; +struct RoSAPindication *roi; +{ + if (result) { + if (result->boottime) + boottime = convert_time(result->boottime); + messagesIn = result->messagesIn; + messagesOut = result->messagesOut; + addrIn = result->addrIn; + addrOut = result->addrOut; + opsPerSec = (double) result->opsPerSec; + runnableChans = (double) result->runnableChans; + msgsInPerSec = (double) result->msgsInPerSec; + msgsOutPerSec = (double) result->msgsOutPerSec; + maxChans = result->maxChans; + currChans = result->currChans; + delta_volume = result->totalVolume - total_volume; + total_volume = result->totalVolume; + delta_messages = result->totalMsgs - total_number_messages; + total_number_messages = result->totalMsgs; + delta_reports = result->totalDrs - total_number_reports; + total_number_reports = result->totalDrs; + /* refresh display */ + update_time_label(); + display_totals(); + } + return OK; +} + diff --git a/Src/MTAconsole/parse.c b/Src/MTAconsole/parse.c new file mode 100644 index 0000000..da258dc --- /dev/null +++ b/Src/MTAconsole/parse.c @@ -0,0 +1,275 @@ +/* parse.c: various parsing routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/parse.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/parse.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: parse.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +/* convert a given string to time */ + +char *unparsetime(mytime) +unsigned long mytime; +{ + char buf[BUFSIZ]; + unsigned long result; + buf[0] = '\0'; + if ((result = mytime / (60 * 60 * 24)) != 0) { + sprintf(buf, "%d d",result); + mytime = mytime % (60 * 60 *24); + } + + if ((result = mytime / (60 * 60)) != 0) { + sprintf(buf, (buf[0] == '\0') ? "%s%d h" : "%s %d h", + buf, result); + mytime = mytime % (60 * 60); + } + + if ((result = mytime / 60 ) != 0) { + sprintf(buf, (buf[0] == '\0') ? "%s%d m" : "%s %d m", + buf, result); + mytime = mytime % (60); + } + + if (mytime != 0) + sprintf(buf, (buf[0] == '\0') ? "%s%d s" : "%s %d s", + buf, mytime); + + return strdup(buf); +} + +time_t parsetime(s) +char *s; +{ + int n; + if (s == NULLCP || *s == NULL) return 0; + while(*s != NULL && isspace(*s)) s++; + n = 0; + while (*s != NULL && isdigit(*s)) { + n = n * 10 + *s - '0'; + s++; + } + while (*s != NULL && isspace(*s)) s++; + if (*s != NULL && isalpha(*s)) { + switch (*s) { + case 's': + case 'S': + break; + case 'm': + case 'M': + n *= 60; + break; + case 'h': + case 'H': + n *= 3600; + break; + case 'd': + case 'D': + n *= 86400; + break; + case 'w': + case 'W': + n *= 604800; + break; + default: + break; + } + return n + parsetime(s+1); + } + else return n + parsetime(s); +} + +extern time_t time(); + +char *mystrtotime(str) +char *str; +{ + UTC utc; + time_t newsecs; + time_t current; + char *retval; + + newsecs = parsetime(str); + time(¤t); + + current += newsecs; + + utc = time_t2utc(current); + + retval = utct2str(utc); + free((char *) utc); + return strdup(retval); +} + +#define MaxCharPerInt 16 + +/* convert integer to string */ +char *itoa(i) +int i; +{ + char buf[MaxCharPerInt]; + + sprintf(buf,"%d",i); + + return strdup(buf); + +} + +/* convert number to volume */ + +char *vol2str(vol) +int vol; +{ + char buf[BUFSIZ]; + + num2unit(vol, buf); + return strdup(buf); +} + +time_t convert_time(qb) +struct type_UNIV_UTCTime *qb; +{ + char *str; + time_t temp; + if (qb == NULL) + return 0; + str = qb2str(qb); + temp = utc2time_t(str2utct(str, strlen(str))); + free(str); + return temp; +} + +char *time_t2RFC(in) +time_t in; +{ + char buf[BUFSIZ]; + struct tm *tm; + struct UTCtime uts; + struct timeval dummy; + struct timezone time_zone; + + tm = localtime (&in); + tm2ut (tm, &uts); + uts.ut_flags |= UT_ZONE; + gettimeofday(&dummy, &time_zone); + uts.ut_zone = time_zone.tz_minuteswest; + UTC2rfc(&uts, buf); + return strdup(buf); +} + + +/* */ + +/* reordering of domains and addresses */ + +char * +reverse_adr(adr) +char *adr; +{ + extern char *rindex(); + + char *ret = malloc(strlen(adr) + 1), savech; + char *ix = adr, *iy = ret, *dom_end, *cix, *last, *dot; + int cont; + while (*ix != '\0') { + switch (*ix) { + case '@': + case '%': + /* start of domain so reverse */ + *iy++ = *ix++; + dom_end = ix; + cont = TRUE; + while (*dom_end != '\0' + && cont == TRUE) { + switch(*dom_end) { + case ',': + case ':': + cont = FALSE; + break; + default: + dom_end++; + break; + } + } + /* domain stretches from ix -> dom_end */ + + last = dom_end; + while (last != ix) { + savech = *last; + *last = '\0'; + if ((dot = rindex(ix, '.')) == NULLCP) { + dot = ix; + cix = dot; + } else + cix = dot + 1; + *last = savech; + do + { + *iy++ = *cix++; + } while (cix != last); + + if (dot != ix) { + *iy++ = '.'; + last = dot; + } else + last = ix; + } + ix = dom_end; + break; + + default: + *iy++ = *ix++; + break; + } + } + *iy = '\0'; + return ret; +} + +char * +reverse_mta(mta) +char *mta; +{ + extern char *index(); + char *adr, *ret, *ix; + char buf[BUFSIZ]; + (void) sprintf(buf, "foo@%s", mta); + ret = reverse_adr(buf); + ix = index (ret, '@'); + adr = strdup(++ix); + free(ret); + return adr; +} + +num2unit(num, buf) +int num; +char *buf; +{ + int absolute; + + absolute = (num < 0) ? -num : num; + + if (absolute > 1000000) + (void) sprintf(buf, "%s%.2f M", + (num < 0) ? "-" : "", + (double) absolute / 1000000.0); + else if (absolute > 1000) + (void) sprintf(buf, "%s%.2f k", + (num < 0) ? "-" : "", + (double) absolute / 1000.0); + else + (void) sprintf(buf, "%s%d", + (num < 0) ? "-" : "", + absolute); +} diff --git a/Src/MTAconsole/popup.c b/Src/MTAconsole/popup.c new file mode 100644 index 0000000..8b09e87 --- /dev/null +++ b/Src/MTAconsole/popup.c @@ -0,0 +1,300 @@ +/* popup.c: pop up and down routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/popup.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/popup.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: popup.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +extern Popup_menu *yesno, + *one, + *two, + *three, + *config, + *qcontrol; +extern Widget refresh_toggle, + reconnect_toggle, + backoff_toggle, + top, + mainform; +extern XColor black, + white; +extern Pixel bg, fg; +Popup_menu *currentpopup = NULL; +extern Operations currentop; +extern Heuristic newheur; + +Popup(this, op, x,y) +Popup_menu *this; +Operations op; +int x, + y; +{ + int i; + currentpopup = this; + this->op = op; + XtVaSetValues(this->popup, + XtNx, x, + XtNy, y, + NULL); + if (this != yesno + && this != qcontrol) { + switch (currentop) { + case msgclear: + case msgstart: + case msgstop: + case msgforce: + this->selected = 1; + break; + default: + this->selected = 0; + break; + } + + for (i = 0; i < this -> numberOftuples; i++) + if (i != this -> selected) + XtVaSetValues(this->tuple[i].text, + XtNborderColor, bg, + NULL); + XtSetKeyboardFocus(this->form, + this->tuple[this->selected].text); + XtSetKeyboardFocus(top, + this->tuple[this->selected].text); + XtVaSetValues(this->tuple[this->selected].text, + XtNborderColor, fg, + NULL); + + } else { + XtSetKeyboardFocus(top, this->form); + } + XtPopup(this->popup, XtGrabExclusive); +} + +Popdown(this) +Popup_menu *this; +{ + currentpopup = NULL; + if (this != NULL) { + XtPopdown(this->popup); + XtSetKeyboardFocus(top, mainform); + } +} + +/* */ +/* routines to move selected fields in popups */ + +extern int newauth; +extern Popup_menu *connectpopup; + +/* ARGSUSED */ +void previousField(w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int old; + + if (currentpopup == NULL + || currentpopup->numberOftuples < 2) + return; + + old = currentpopup->selected; + + currentpopup->selected--; + if (currentpopup->selected < 0) { + if (currentpopup == connectpopup + && newauth == False) + currentpopup->selected = 1; + else if (currentpopup == config) { + switch(newheur) { + case percentage: + currentpopup->selected = MINBADMTA; + break; + case line: + currentpopup->selected = LINEMAX; + break; + case all: + currentpopup->selected = CONNECTMAX; + break; + case chanonly: + currentpopup->selected = CONNECTMAX; + break; + } + } else + currentpopup->selected = + currentpopup->numberOftuples -1; + } else if (currentpopup == config + && old == LINEMAX + && newheur == line) + currentpopup->selected = CONNECTMAX; + + XtSetKeyboardFocus(top, + currentpopup->tuple[currentpopup->selected].text); + XtSetKeyboardFocus(currentpopup->form, + currentpopup->tuple[currentpopup->selected].text); + XtVaSetValues(currentpopup->tuple[currentpopup->selected].text, + XtNborderColor, fg, + NULL); + XtVaSetValues(currentpopup->tuple[old].text, + XtNborderColor, bg, + NULL); +} + +/* ARGSUSED */ +void thisField(w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int ix; + + if (currentpopup == NULL + || currentpopup->numberOftuples < 2) + return; + + ix = 0; + while (ix < currentpopup->numberOftuples + && currentpopup->tuple[ix].text != w) + ix++; + + if (ix >= currentpopup->numberOftuples) + return; + + XtVaSetValues(currentpopup->tuple[currentpopup->selected].text, + XtNborderColor, bg, + NULL); + currentpopup->selected = ix; + XtVaSetValues(currentpopup->tuple[currentpopup->selected].text, + XtNborderColor, fg, + NULL); + XtSetKeyboardFocus(top, + currentpopup->tuple[currentpopup->selected].text); + XtSetKeyboardFocus(currentpopup->form, + currentpopup->tuple[currentpopup->selected].text); +} + +/* ARGSUSED */ +void nextField(w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int old; + + if (currentpopup == NULL + || currentpopup->numberOftuples < 2) + return; + + old = currentpopup->selected; + + currentpopup->selected++; + + if (currentpopup->selected >= currentpopup->numberOftuples) + currentpopup->selected = 0; + + if (currentpopup == connectpopup + && newauth == False + && currentpopup->selected > 1) + currentpopup->selected = 0; + + if (currentpopup == config + && currentpopup->selected > CONNECTMAX) { + switch (newheur) { + case percentage: + if (currentpopup->selected > MINBADMTA) + currentpopup->selected = 0; + break; + case line: + currentpopup->selected = LINEMAX; + break; + case all: + case chanonly: + currentpopup->selected = 0; + } + } + + + XtSetKeyboardFocus(top, + currentpopup->tuple[currentpopup->selected].text); + XtSetKeyboardFocus(currentpopup->form, + currentpopup->tuple[currentpopup->selected].text); + XtVaSetValues(currentpopup->tuple[currentpopup->selected].text, + XtNborderColor, fg, + NULL); + XtVaSetValues(currentpopup->tuple[old].text, + XtNborderColor, bg, + NULL); +} + +/* ARGSUSED */ +void mymenupopdown(w, event) +Widget w; +XEvent *event; +{ + Popdown(currentpopup); +} + +extern char password[]; +#define STRBUFSIZE 100 +static XComposeStatus compose_status = {NULL, 0}; +/* ARGSUSED */ +void myinsert_char(w, event) +Widget w; +XKeyEvent *event; +{ + char strbuf[STRBUFSIZE], + xbuf[STRBUFSIZE]; + int ix; + KeySym keycode; + int length, passwdlen; + length = XLookupString(event, strbuf, STRBUFSIZE, + &keycode, &compose_status); + if (length == 0) return; + passwdlen = strlen(password); + strncat(password, strbuf, length); + password[length+passwdlen] = '\0'; + + for (ix = 0; ix < length + passwdlen; ix++) + xbuf[ix] = 'X'; + xbuf[ix] = NULL; +#ifdef notdef + if (length == 1 && strbuf[0] == '\?') + text.ptr = &strbuf[0]; + else + text.ptr = &xbuf[0]; +#endif + XtVaSetValues (w, XtNstring, xbuf, 0); +} + +/* ARGSUSED */ +void mydelete_char(w, event) +Widget w; +XEvent *event; +{ + char xbuf[STRBUFSIZE]; + int ix; + int passwdlen; + + passwdlen = strlen(password) -1; + if (passwdlen >= 0) { + password[passwdlen] = '\0'; + for (ix = 0; ix < passwdlen; ix++) + xbuf[ix] = 'X'; + xbuf[passwdlen] = '\0'; + textdisplay(&(connectpopup->tuple[3]), xbuf); + } +} diff --git a/Src/MTAconsole/tai_defs.inc b/Src/MTAconsole/tai_defs.inc new file mode 100644 index 0000000..d5440c2 --- /dev/null +++ b/Src/MTAconsole/tai_defs.inc @@ -0,0 +1,31 @@ +#define default_mtsin_chan "mtsin-chan:last<2h" +#define default_mtsin_mta "mtsin-mta:last<2h" +#define default_mtsin_msg "mtsin-msg:last<2h" + +#define default_mtsout_chan "mtsout-chan:age<2h,num<500,vol<1M,last<2h" +#define default_mtsout_mta "mtsout-mta:age<2h,num<500,vol<1M,last<2h" +#define default_mtsout_msg "mtsout-msg:age<2h,vol<1M" + +#define default_mtsboth_chan "mtsboth-chan:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_mta "mtsboth-mta:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_msg "mtsboth-msg:age<2h,vol<1M" + +#define default_mtain_chan "mtain-chan:last<2h" +#define default_mtain_mta "mtain-mta:last<2h" +#define default_mtain_msg "mtain-msg:last<2h" + +#define default_mtaout_chan "mtaout-chan:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaout_mta "mtaout-mta:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaout_msg "mtaout-msg:age<48h,vol<10M" + +#define default_mtaboth_chan "mtaboth-chan:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaboth_mta "mtaboth-mta:age<48h,vol<10M,num<1k,last<2h" +#define default_mtaboth_msg "mtaboth-msg:age<48h,vol<10M" + +#define default_internal_chan "internal-chan:age<20,vol<1M,num<10,last<20" +#define default_internal_mta "internal-mta:age<20,vol<1M,num<10,last<20" +#define default_internal_msg "internal-msg:age<20,vol<1M" + +#define default_passive_chan "passive-chan:age<20,vol<1M,num<10,last<20" +#define default_passive_mta "passive-mta:age<20,vol<1M,num<10,last<20" +#define default_passive_msg "passive-msg:age<20,vol<1M" diff --git a/Src/MTAconsole/workops.c b/Src/MTAconsole/workops.c new file mode 100644 index 0000000..892d66b --- /dev/null +++ b/Src/MTAconsole/workops.c @@ -0,0 +1,1026 @@ +/* workops.c: routines that do work */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/workops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/MTAconsole/RCS/workops.c,v 6.0 1991/12/18 20:26:48 jpo Rel $ + * + * $Log: workops.c,v $ + * Revision 6.0 1991/12/18 20:26:48 jpo + * Release 6.0 + * + */ + + + +#include "console.h" + +extern CMD_TABLE chantbl_commands[], + mtatbl_commands[], + msgtbl_commands[]; +extern char *strdup(), *itoa(), + *stripstr(), + *rcmd_srch(); +extern void ChanToggle(), MtaToggle(), MsgToggle(), ChangeMode(); +extern struct recip *find_recip(); + +/* ARGUSED */ +ChanForce(chan) +struct chan_struct *chan; +{ + char *args[3]; + + args[0] = chan->channelname; + args[2] = NULLCP; + if (chan->status->enabled != TRUE) { + args[1] = rcmd_srch((int) chanstart, chantbl_commands); + my_invoke(chanstart, args); + } + if (chan->status->cachedUntil != 0) { + args[1] = rcmd_srch((int) chanclear, chantbl_commands); + my_invoke(chanclear, args); + } +} + +extern struct chan_struct *currentchan, **globallist; +extern int num_channels; +extern struct mta_struct *currentmta; +extern struct msg_struct *currentmsg; + +ChanNext() +{ + if (currentchan == NULL) + currentchan = globallist[0]; + else { + int i = 0; + while (i < num_channels + && currentchan != globallist[i]) i++; + if (i < num_channels-1) + currentchan = globallist[i+1]; + else + currentchan = globallist[0]; + } + currentmta = NULL; + currentmsg = NULL; + refresh_control_channel(); +} + +ChanPrev() +{ + if (currentchan == NULL) + currentchan = globallist[num_channels - 1]; + else { + int i = 0; + while (i < num_channels + && currentchan != globallist[i]) i++; + if (i == 0) + currentchan = globallist[num_channels - 1]; + else + currentchan = globallist[i - 1]; + } + currentmta = NULL; + currentmsg = NULL; + refresh_control_channel(); +} + +extern Widget channel_label, mta_label, msg_label; +extern int read_currentchan, chan_info_shown, mta_info_shown, msg_info_shown; + +refresh_control_channel() +{ + reset_label(channel_label); + reset_label(mta_label); + reset_label(msg_label); + if (read_currentchan) { + add_mta_refresh_list(currentchan->channelname); + construct_event(mtaread); + } + if (chan_info_shown == TRUE) + chan_display_info(currentchan); +} + +ChanDownForce (chan) +struct chan_struct *chan; +{ + add_mta_refresh_list(chan->channelname); + my_invoke(mtaread, &(chan->channelname)); + ChanForce (chan); +} + +/* ARGSUSED */ +ChanControl(op, channel, mytime) +Operations op; +char *channel, + *mytime; +{ + char *str, + *chan, + **args; + str = strdup(channel); + chan = stripstr(str); + args = (char **) calloc(3, sizeof(char *)); + args[0] = chan; + args[1] = rcmd_srch((int) op, chantbl_commands); + args[2] = mytime; + my_invoke(op, args); + free((char *) args); + free(str); +} + +/* ARGSUSED */ +MtaForce(mta, chan) +struct mta_struct *mta; +struct chan_struct *chan; +{ + char *args[4]; + args[0] = chan->channelname; + args[1] = mta->mta; + args[3] = NULLCP; + + if (mta->status->enabled != TRUE) { + args[2] = rcmd_srch((int) mtastart,mtatbl_commands); + my_invoke(mtastart, args); + } + if (mta->status->cachedUntil != 0) { + args[2] = rcmd_srch((int) mtaclear,mtatbl_commands); + my_invoke(mtaclear, args); + } + ChanForce(chan); +} + +extern char *msginfo_args[]; + +MtaDownForce (chan, mta) +struct chan_struct *chan; +struct mta_struct *mta; +{ + msginfo_args[0] = chan->channelname; + msginfo_args[1] = mta->mta; + if (is_loc_chan(chan) == TRUE) + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + my_invoke (readchannelmtamessage, msginfo_args); + /* reset after message down force */ + msginfo_args[0] = chan->channelname; + msginfo_args[1] = mta->mta; + if (is_loc_chan(chan) == TRUE) + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + if (mta->status->enabled != TRUE) { + msginfo_args[2] = rcmd_srch((int) mtastart,mtatbl_commands); + my_invoke(mtastart, msginfo_args); + } + if (mta->status->cachedUntil != 0) { + msginfo_args[2] = rcmd_srch((int) mtaclear,mtatbl_commands); + my_invoke(mtaclear, msginfo_args); + } +} + +/* ARGSUSED */ +MtaControl(op, givenmta, givenchan, time) +Operations op; +char *givenmta, + *givenchan, + *time; +{ + char *str1, + *str2, + *mta, + *chan, + **args; + + /* get selection and all that */ + str1 = strdup(givenmta); + mta = stripstr(str1); + + str2 = strdup(givenchan); + chan = stripstr(str2); + + args = (char **) calloc(4, sizeof(char *)); + args[0] = chan; + args[1] = mta; + args[2] = rcmd_srch((int) op, mtatbl_commands); + args[3] = time; + my_invoke(op,args); + free((char *) args); + free(str1); + free(str2); +} + +/* ARGSUSED */ +MsgForce(msg, usrs, mta, chan) +struct msg_struct *msg; +char *usrs; +struct mta_struct *mta; +struct chan_struct *chan; +{ + char *usrlist[20], + **args; + int numberUsrs = 0, force; + int i = 0, ix, all; + struct recip *temp; + if (msg == NULL + || msg->msginfo == NULL) return; + + if (strcmp(usrs, "*") == 0) { + all = TRUE; + for (temp = msg->reciplist, numberUsrs = 0; + temp != NULL; temp = temp -> next, numberUsrs++) + continue; + } else { + all = FALSE; + numberUsrs = sstr2arg(usrs, 20, usrlist, ","); + } + + args = (char **) calloc((unsigned)(4+numberUsrs), sizeof(char *)); + args[0] = msg->msginfo->queueid; + args[1] = NULL; + + ix = 3; + force = FALSE; + + if (all == TRUE) { + for (temp = msg->reciplist; temp != NULL; temp = temp -> next) + if (temp->status + && temp->status->enabled != TRUE) { + args[ix++] = itoa(temp->id); + force = TRUE; + } + } else { + while (i < numberUsrs && ix < (3+numberUsrs)) { + if ((temp = find_recip(msg, atoi(usrlist[i]))) != NULL + && temp->status + && temp->status->enabled != TRUE) { + args[ix++] = usrlist[i]; + force = TRUE; + } + i++; + } + } + if (force == TRUE) { + args[ix] = NULLCP; + args[2] = rcmd_srch((int) msgstart, msgtbl_commands); + my_invoke(msgstart, args); + } + + ix = 3; + i = 0; + force = FALSE; + + if (all == TRUE) { + for (temp = msg->reciplist; temp != NULL; temp = temp -> next) + if (temp->status + && temp->status->cachedUntil != 0) { + args[ix++] = itoa(temp->id); + force = TRUE; + } + } else { + while (i < numberUsrs && ix < (3+numberUsrs)) { + if ((temp = find_recip(msg, atoi(usrlist[i]))) != NULL + && temp->status + && temp->status->cachedUntil != 0) { + args[ix++] = usrlist[i]; + force = TRUE; + } + i++; + } + } + if (force == TRUE) { + args[ix] = NULLCP; + args[2] = rcmd_srch((int) msgclear, msgtbl_commands); + my_invoke(msgstart, args); + } + free((char *) args); + MtaForce(mta, chan); +} + +MsgDownForce (msg) +struct msg_struct *msg; +{ + struct recip *ix; + int recip_count = 0, i, j, force; + char **args; + + if (msg == NULL + || msg->msginfo == NULL) return; + + for (ix = msg -> reciplist; ix != NULL; + recip_count++, ix = ix -> next) + continue; + + args = (char **) calloc((unsigned)(4+recip_count), + sizeof(char *)); + args[0] = msg->msginfo->queueid; + args[1] = NULL; + i = 3; + ix = msg -> reciplist; + force = FALSE; + while (ix != NULL) { + if (ix -> status + && ix -> status -> enabled != TRUE) { + args[i++] = itoa(ix->id); + + force = TRUE; + } + ix = ix -> next; + } + if (force == TRUE) { + args[i] = NULLCP; + args[2] = rcmd_srch((int) msgstart, msgtbl_commands); + my_invoke(msgstart, args); + } + for (j = 3; j < i; j++) + if (args[j] != NULLCP) { + free(args[j]); + args[j] = NULLCP; + } + i = 3; + ix = msg -> reciplist; + force = FALSE; + while (ix != NULL) { + if (ix -> status + && ix -> status -> cachedUntil != 0) { + args[i++] = itoa(ix->id); + + force = TRUE; + } + ix = ix -> next; + } + if (force == TRUE) { + args[i] = NULLCP; + args[2] = rcmd_srch((int) msgclear, msgtbl_commands); + my_invoke(msgstart, args); + } + for (j = 3; j < i; j++) + if (args[j] != NULLCP) { + free(args[j]); + args[j] = NULLCP; + } + free ((char *) args); +} + +MsgControl(op, msg, usrs, time) +Operations op; +char *msg; +char *usrs; +char *time; +{ + char *str0, + *str1, + *qid, + *usrlist[20], + **args; + int numberUsrs, + i = 0, + ix; + + /* arg1 = QID arg2 = time arg3 = control arg4.. = userlist */ + + /* get selection and all that */ + str0 = strdup(msg); + qid = stripstr(str0); + + str1 = strdup(usrs); + numberUsrs = sstr2arg(str1, 20, usrlist, ","); + + args = (char **) calloc((unsigned)(4+numberUsrs), sizeof(char *)); + args[0] = qid; + args[1] = time; + args[2] = rcmd_srch((int) op, msgtbl_commands); + ix = 3; + while(i < numberUsrs && ix < (3+numberUsrs)) + args[ix++] = usrlist[i++]; + my_invoke(op, args); + free((char *) args); + free(str0); + free(str1); +} + +/* */ + +extern struct chan_struct *find_channel(); + +/* ARGSUSED */ +ChanInfo(channel) +char *channel; +{ + struct chan_struct *chan; + char *channame, + *str; + + str = strdup(channel); + channame = stripstr(str); + + if ((chan = find_channel(channame)) != NULL) { + chan_display_info(chan); + } else { + /* put out error message */ + PP_LOG(LLOG_EXCEPTIONS, + ("MTAcosnole confused: Unable to find '%s'", + channame)); + } + free(str); +} + +extern struct mta_struct *find_mta(); + +/* ARGSUSED */ +MtaInfo(mtain, channel) +char *mtain, + *channel; +{ + struct chan_struct *chan; + struct mta_struct *mta; + char *mtaname, + *channame, + *str1, + *str2; + + str1 = strdup(channel); + channame = stripstr(str1); + str2 = strdup(mtain); + mtaname = stripstr(str2); + + if (((chan = find_channel(channame)) != NULL) + && ((mta = find_mta(chan, mtaname)) != NULL)) { + mta_display_info(chan, mta); + } else { + /* put out error message */ + PP_LOG(LLOG_EXCEPTIONS, + ("MTAconsole confused: unable to find channel/mta pair '%s/%s'", + channame, mtaname)); + } + free(str1); + free(str2); + +} + +extern struct msg_struct *find_msg(); +/* ARGSUSED */ +MsgInfo(msgin) +char *msgin; +{ + struct msg_struct *msg; + char *qid, + *str; + str = strdup(msgin); + qid = stripstr(str); + + if ((msg = find_msg(qid)) != NULL) + msg_display_info(msg); + free(str); + +} + +/* */ +extern State connectState; +extern int userConnected, + autoReconnect; +extern Widget header, error; +extern char *hostname; + +/* ARGSUSED */ +Disconnect() +{ + /* put out required message */ + XtVaSetValues(header, + XtNlabel, NO_CONNECTION, + NULL); + XtSetMappedWhenManaged(error, False); + userConnected = FALSE; + TermRefreshTimeOut(); + TermConnectRetry(); + TermConnectTimeOut(); + ResetForDisconnect(); + my_invoke(disconnect, &hostname); + SensitizeButtons(False); +} + +/* ARGSUSED */ +Connect(host) +char *host; +{ + char *str, + *convertedstr; + + str = strdup(host); + + convertedstr = stripstr(host); + + if (strcmp(hostname, convertedstr) != 0) { + free(hostname); + hostname = strdup(convertedstr); + } + free(str); + + if (autoReconnect == TRUE) userConnected = TRUE; + + my_invoke(connect, &hostname); +} + +/* ARGSUSED */ +Quit() +{ + my_invoke(quit,(char **) NULL); +} + +/* */ + +extern struct chan_struct *currentchan, + **globallist; +extern struct mta_struct *currentmta; +extern struct monitor_item **display_list; +extern int read_currentchan; +extern int read_currentmta; +extern Widget *channel_array; +extern int num_channels; +extern Widget channel_label; +extern Widget mta_label; +extern Mode mode; +extern struct msg_struct *currentmsg; +extern Widget msg_label; + +/* ARGSUSED */ +void curChan (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < num_channels + && channel_array[i] != w) i++; + + if (i < num_channels) { + if (mode == monitor) + ChangeMode((Widget)NULL, (caddr_t) NULL, + (caddr_t) NULL); + + if (currentchan != globallist[i]) { + read_currentmta = 0; + currentmta = NULL; + currentmsg = NULL; + currentchan = globallist[i]; + } + } + reset_label(channel_label); + reset_label(mta_label); + reset_label(msg_label); +} + +/* ARGSUSED */ +void excl_curChan (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < num_channels + && channel_array[i] != w) i++; + + read_currentchan = 0; + if (i < num_channels) { + if (mode == monitor) + ChangeMode((Widget)NULL, + (caddr_t) NULL, (caddr_t) NULL); + + if (currentchan != NULL) + display_empty_mta_list(currentchan); + display_empty_msg_list(); + + if (currentchan == globallist[i]) + /* deselect it */ + currentchan = NULL; + else + currentchan = globallist[i]; + + currentmta = NULL; + currentmsg = NULL; + read_currentmta = 0; + MtaToggle(); + MsgToggle(); + } + reset_label(channel_label); + reset_label(mta_label); + reset_label(msg_label); +} + +/* ARGSUSED */ +void chanRefresh (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + struct chan_struct *chan; + + while (i < num_channels && display_list[i]->chan != w) + i++; + + if (i < num_channels) { + chan = *(display_list[i]->channel); + add_mta_refresh_list (chan->channelname); + construct_event(mtaread); + } +} + +/* ARGSUSED */ +void chanModeRead (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + + while (i < num_channels && display_list[i]->chan != w) + i++; + + if (i < num_channels) { + read_currentchan = 1; + currentchan = *(display_list[i]->channel); + reset_label(channel_label); + ChangeMode(w, (caddr_t) NULL, (caddr_t) NULL); + } +} + +/* ARGSUSED */ +void chanMode (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + + while (i < num_channels && display_list[i]->chan != w) + i++; + + if (i < num_channels) { + read_currentchan = 0; + currentchan = *(display_list[i]->channel); + reset_label(channel_label); + ChangeMode(w, (caddr_t) NULL, (caddr_t) NULL); + } +} + +/* ARGSUSED */ +void readChan (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + ResetInactiveTimeout(); + if (currentchan != NULL) { + ChanToggle(); + MtaToggle(); + MsgToggle(); + read_currentchan = 1; + if (mode == control) { + clear_mta_refresh_list(); + add_mta_refresh_list(currentchan->channelname); + construct_event(mtaread); + } + } +} + +char *msginfo_args[3]; +extern struct mta_disp_struct *mta_array; +int actual_nmtas_present; + +MtaNext() +{ + if (currentchan == NULL || + actual_nmtas_present == 0) + return; + if (currentmta == NULL) + currentmta = mta_array[0].mta; + else { + int i = 0; + while (i < actual_nmtas_present + && currentmta != mta_array[i].mta) i++; + if (i >= actual_nmtas_present-1) + currentmta = mta_array[0].mta; + else + currentmta = mta_array[i+1].mta; + } + currentmsg = NULL; + refresh_mta_control(); +} + +MtaPrev() +{ + if (currentchan == NULL || + actual_nmtas_present == 0) + return; + if (currentmta == NULL) + currentmta = mta_array[actual_nmtas_present-1].mta; + else { + int i = 0; + while (i < actual_nmtas_present + && currentmta != mta_array[i].mta) i++; + if (i == 0) + currentmta = mta_array[actual_nmtas_present-1].mta; + else + currentmta = mta_array[i-1].mta; + } + currentmsg = NULL; + refresh_mta_control(); +} + +refresh_mta_control() +{ + reset_label(mta_label); + reset_label(msg_label); + if (currentchan != NULL + && currentmta != NULL) { + if (read_currentmta) { + msginfo_args[0] = currentchan->channelname; + msginfo_args[1] = currentmta->mta; + if (currentchan->chantype == int_Qmgr_chantype_mts + && currentchan->outbound > 0) + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + my_invoke(readchannelmtamessage, msginfo_args); + } + + if (mta_info_shown == TRUE) + mta_display_info(currentchan, currentmta); + } +} + +/* ARGSUSED */ +void curMta (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < actual_nmtas_present + && mta_array[i].widget != w) i++; + + if (i < actual_nmtas_present && currentmta != mta_array[i].mta) { + currentmta = mta_array[i].mta; + currentmsg = NULL; + } + reset_label(mta_label); + reset_label(msg_label); +} + +/* ARGSUSED */ +void excl_curMta (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < actual_nmtas_present + && mta_array[i].widget != w) i++; + read_currentmta = 0; + + if (i < actual_nmtas_present) { + + display_empty_msg_list(); + + if (currentmta == mta_array[i].mta) + /* deselect it */ + currentmta = NULL; + else + currentmta = mta_array[i].mta; + + currentmsg = NULL; + MsgToggle(); + } + reset_label(mta_label); + reset_label(msg_label); +} + +/* ARGSUSED */ +void mtaRefresh (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0,j = 0, found = 0; + struct chan_struct *chan; + + while (i < num_channels + && found == 0) { + j = 0; + while (j < display_list[i]->num_mtas + && found == 0) { + if (display_list[i]->mtas[j]->widget == w) + found = 1; + else + j++; + } + if (found == 0) + i++; + } + if (found == 1) { + chan = *(display_list[i]->channel); + add_mta_refresh_list (chan->channelname); + construct_event(mtaread); + } +} + +/* ARGSUSED */ +void mtaModeRead (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0,j = 0, found = 0; + + while (i < num_channels + && found == 0) { + j = 0; + while (j < display_list[i]->num_mtas + && found == 0) { + if (display_list[i]->mtas[j]->widget == w) + found = 1; + else + j++; + } + if (found == 0) + i++; + } + if (found == 1) { + read_currentchan = 1; + currentchan = *(display_list[i]->channel); + read_currentmta = 1; + currentmta = display_list[i]->mtas[j]->mta; + ChangeMode(w, (caddr_t) NULL, (caddr_t) NULL); + } +} + +/* ARGSUSED */ +void mtaMode (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0,j = 0, found = 0; + + while (i < num_channels + && found == 0) { + j = 0; + while (j < display_list[i]->num_mtas + && found == 0) { + if (display_list[i]->mtas[j]->widget == w) + found = 1; + else + j++; + } + if (found == 0) + i++; + } + if (found == 1) { + read_currentchan = 1; + currentchan = *(display_list[i]->channel); + read_currentmta = 0; + currentmta = display_list[i]->mtas[j]->mta; + ChangeMode(w, (caddr_t) NULL, (caddr_t) NULL); + } +} + +/* ARGSUSED */ +void readMta (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + ResetInactiveTimeout(); + MtaToggle(); + MsgToggle(); + if (currentchan != NULL && currentmta != NULL) { + msginfo_args[0] = currentchan->channelname; + read_currentmta = 1; + msginfo_args[1] = currentmta->mta; + if (currentchan->chantype == int_Qmgr_chantype_mts + && currentchan->outbound > 0) + msginfo_args[2] = (char *) 1; + else + msginfo_args[2] = (char *) 0; + my_invoke(readchannelmtamessage, msginfo_args); + } +} + +extern struct msg_disp_struct *msg_array; +extern int actual_nmsgs_present; + + +MsgNext() +{ + if (actual_nmsgs_present == 0) + return; + if (currentmsg == NULL) + currentmsg = msg_array[0].msg; + else { + int i = 0; + while (i < actual_nmsgs_present + && msg_array[i].msg != currentmsg) i++; + + if (i >= actual_nmsgs_present-1) + currentmsg = msg_array[0].msg; + else + currentmsg = msg_array[i+1].msg; + } + refresh_msg_control(); +} + +MsgPrev() +{ + if (actual_nmsgs_present == 0) + return; + if (currentmsg == NULL) + currentmsg = msg_array[actual_nmsgs_present-1].msg; + else { + int i = 0; + while (i < actual_nmsgs_present + && msg_array[i].msg != currentmsg) i++; + + if (i == 0) + currentmsg = msg_array[actual_nmsgs_present-1].msg; + else + currentmsg = msg_array[i-1].msg; + } + refresh_msg_control(); +} + +refresh_msg_control() +{ + reset_label(msg_label); + if (currentmsg && msg_info_shown) + msg_display_info(currentmsg); +} + +/* ARGSUSED */ +void curMsg (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < actual_nmsgs_present + && msg_array[i].widget != w) i++; + + if (i < actual_nmsgs_present) { + currentmsg = msg_array[i].msg; + } + reset_label(msg_label); +} + +/* ARGSUSED */ +void excl_curMsg (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + int i = 0; + ResetInactiveTimeout(); + while (i < actual_nmsgs_present + && msg_array[i].widget != w) i++; + + if (i < actual_nmsgs_present) { + if (currentmsg == msg_array[i].msg) { + /* deselect it */ + MsgToggle(); + currentmsg = NULL; + } else + currentmsg = msg_array[i].msg; + } + reset_label(msg_label); +} + +/* ARGSUSED */ +void readMsg (w, event, params, num_params) +Widget w; +XEvent *event; +char **params; +int num_params; +{ + if (currentmsg != NULL) + msg_display_info(currentmsg); +} diff --git a/Src/Makefile b/Src/Makefile new file mode 100644 index 0000000..d8880e3 --- /dev/null +++ b/Src/Makefile @@ -0,0 +1,28 @@ +# Makefile governing the 'core' pp programs +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/RCS/Makefile,v 6.0 1991/12/18 20:28:20 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:20 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = submit qmgr pptsapd MTAconsole LINEconsole lconsole + +target: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +all define depend clean tidy install lint: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done diff --git a/Src/lconsole/Makefile b/Src/lconsole/Makefile new file mode 100644 index 0000000..76150e2 --- /dev/null +++ b/Src/lconsole/Makefile @@ -0,0 +1,135 @@ +# Makefile for line based console +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/Makefile,v 6.0 1991/12/18 20:27:16 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:27:16 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = lconsole.c functions.c channel.c mtas.c msgs.c show.c +OBJS = lconsole.o functions.o channel.o mtas.o msgs.o show.o + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: lconsole + +lconsole: xlconsole + @true + +xlconsole: $(OBJS) $(LIBPP) + $(CC) -o $@ $(LDOPTIONS) $(OBJS) $(LIBPP) $(LIBSYS) $(LM) + +install: inst-xlconsole + +inst-xlconsole: $(CMDDIR)/lconsole +$(CMDDIR)/lconsole: xlconsole + -$(BACKUP) $@ zxlconsole + rm -f $@ + $(INSTALL) xlconsole $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "lconsole installed normally"; echo "" + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) $(LM) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) $(LM) + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old xlconsole + +lint: l-lconsole + +l-lconsole: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +lconsole.o: lconsole.c +lconsole.o: lconsole.h +lconsole.o: ../../h/util.h +lconsole.o: ../../h/config.h +lconsole.o: ../../h/ll_log.h +lconsole.o: ../../h/qmgr-int.h +functions.o: functions.c +functions.o: lconsole.h +functions.o: ../../h/util.h +functions.o: ../../h/config.h +functions.o: ../../h/ll_log.h +functions.o: ../../h/qmgr.h +functions.o: ../../h/Qmgr-types.h +functions.o: ../../h/Qmgr-ops.h +functions.o: ../../h/qmgr-int.h +channel.o: channel.c +channel.o: lconsole.h +channel.o: ../../h/util.h +channel.o: ../../h/config.h +channel.o: ../../h/ll_log.h +channel.o: ../../h/qmgr.h +channel.o: ../../h/Qmgr-types.h +channel.o: ../../h/Qmgr-ops.h +channel.o: ../../h/qmgr-int.h +mtas.o: mtas.c +mtas.o: lconsole.h +mtas.o: ../../h/util.h +mtas.o: ../../h/config.h +mtas.o: ../../h/ll_log.h +mtas.o: ../../h/qmgr.h +mtas.o: ../../h/Qmgr-types.h +mtas.o: ../../h/Qmgr-ops.h +mtas.o: ../../h/qmgr-int.h +msgs.o: msgs.c +msgs.o: lconsole.h +msgs.o: ../../h/util.h +msgs.o: ../../h/config.h +msgs.o: ../../h/ll_log.h +msgs.o: ../../h/qmgr.h +msgs.o: ../../h/Qmgr-types.h +msgs.o: ../../h/Qmgr-ops.h +msgs.o: ../../h/qmgr-int.h +show.o: show.c +show.o: lconsole.h +show.o: ../../h/util.h +show.o: ../../h/config.h +show.o: ../../h/ll_log.h +show.o: ../../h/qmgr.h +show.o: ../../h/Qmgr-types.h +show.o: ../../h/Qmgr-ops.h +show.o: ../../h/qmgr-int.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/lconsole/channel.c b/Src/lconsole/channel.c new file mode 100644 index 0000000..24079f9 --- /dev/null +++ b/Src/lconsole/channel.c @@ -0,0 +1,275 @@ +/* channel.c: channel functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/channel.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/channel.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: channel.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr.h" +#include "qmgr-int.h" +#include +#ifdef BSD42 +#include +#endif + +#define plural(n,s) ((n) == 1 ? "" : (s)) + +static CMD_TABLE *chanlist; +static char *chantolist; + + + +static void display_chan_info (cip) +ChannelInfo *cip; +{ + printf ("%*sChannel %s (%s)\n", indent * 2, "", + cip -> channelname, + cip -> channeldescrip); + indent ++; + printf ("%*s%s message%s, ", indent *2, "", + datasize (cip -> numberMessages, ""), + plural(cip -> numberMessages,"s")); + printf ("%s delivery report%s, ", + datasize (cip->numberReports, ""), + plural(cip->numberReports,"s")); + printf ("%s MTA%s, ", + datasize(cip->numberMtas, ""), plural(cip->numberMtas, "s")); + printf ("%s data\n", + datasize (cip -> volumeMessages, "")); + if (cip -> numberActiveProcesses != 0) { + printf ("%*s%d process%s running", indent * 2, "", + cip -> numberActiveProcesses, + plural(cip->numberActiveProcesses, "es")); + if (cip -> maxprocs > 0) + printf ("(max %d)", cip -> maxprocs); + putchar ('\n'); + } + display_status (cip -> status); + if (cip -> oldestMessage && (cip -> numberMessages > 0 || + cip -> numberReports > 0)) + printf ("%*sOldest message is %s", + indent * 2, "", + ctime (&cip->oldestMessage)); + indent --; +} + +static void display_all_chans (chans) +ChannelInfo *chans; +{ + ChannelInfo *cip; + int width, w; + int count; + char **cpp; + + for (count = 0, cip = chans; cip; cip = cip -> next) + count ++; + cpp = (char **) smalloc (count * sizeof (char *)); + + for (width = count = 0, cip = chans; cip; cip = cip -> next) { + char buf[BUFSIZ]; + char c[2]; + + c[1] = NULL; + c[0] = ':'; + + if (cip -> numberActiveProcesses > 0) + c[0] = '*'; + if (cip -> status -> enabled == 0) + c[0] = '!'; + + if (cip -> numberReports != 0) + (void) sprintf (buf, "%s%s%d+%d", + cip -> channelname, c, + cip -> numberMessages, + cip -> numberReports); + else if (cip -> numberMessages != 0) + (void) sprintf (buf, "%s%s%d", + cip -> channelname, c, + cip -> numberMessages); + else (void) sprintf (buf, "%s%s", cip -> channelname, + c[0] == ':' ? "" : c); + if ((w = strlen (buf)) > width) + width = w; + cpp[count++] = strdup (buf); + } + w = ncols (stdout) / (width+1); + for (count = 0, cip = chans; cip; cip = cip -> next) { + printf ("%-*s%s", width, cpp[count], + (count + 1) % w == 0 ? "\n" : " "); + free (cpp[count++]); + } + if (count % w != 0) + putchar ('\n'); + + free ((char *)cpp); +} + +static void build_chanlist(chan) +ChannelInfo *chan; +{ + ChannelInfo *cip; + int count; + + for (count = 0, cip = chan; cip; cip = cip -> next) + count ++; + + chanlist = (CMD_TABLE *) calloc ((unsigned)count + 1, + sizeof *chanlist); + + for (count = 0, cip = chan; cip; cip = cip -> next) { + chanlist[count].cmd_key = strdup (cip -> channelname); + chanlist[count].cmd_value = count; + count ++; + } + chanlist[count].cmd_key = NULLCP; + chanlist[count].cmd_value = NOTOK; +} + +void free_chanlist () +{ + CMD_TABLE *ct; + + if (chanlist == NULL) + return; + + for (ct = chanlist; ct -> cmd_key; ct++) + free(ct -> cmd_key); + free ((char *)chanlist); + chanlist = NULL; +} + +static int channel_noprint; + +/* ARGSUSED */ +int chan_update (chan, id) +ChannelInfo *chan; +int id; +{ + ChannelInfo *cip; + int found; + char *cp; + + if (chan == NULL) + return NOTOK; + + if (chanlist == NULL) + build_chanlist(chan); + + if (channel_noprint) { + /* do nothing */; + } + else if (chantolist) { + found = 0; + if ((cp = re_comp (chantolist)) != NULLCP) { + advise (NULLCP, "Expression %s: %s", + chantolist, cp); + free_ChannelInfo (chan); + return OK; + } + for (cip = chan; cip; cip = cip -> next) + if (re_exec (cip -> channelname) == 1) { + display_chan_info (cip); + found ++; + } + if (found == 0) + advise (NULLCP, "Channel %s not found", chantolist); + } + else if (chan -> next == NULL) + display_chan_info (chan); + else + display_all_chans (chan); + + free_ChannelInfo(chan); + return OK; +} + +int f_channel (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + + if (*++vec == NULLCP) { + chantolist = NULLCP; + } + else { + chantolist = *vec; + } + + if (initiate_op (console_fd, operation_Qmgr_channelread, + NULLVP, &pid, chan_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + + return OK; +} + +char *fullchanname (str) +char *str; +{ + char *cp; + CMD_TABLE *tp, *fnd = NULL; + int ambig = 0; + int ch; + char *vec[2]; + + if (chanlist == NULL) { + ch = channel_noprint, channel_noprint = 1; + vec[0] = "channel"; + vec[1] = NULLCP; + f_channel (vec); + channel_noprint = ch; + } + + if ((cp = re_comp(str)) != NULLCP) { + advise (NULLCP, "Bad expression %s: %s", str, cp); + return NULLCP; + } + + for (tp = chanlist; tp -> cmd_key; tp ++) + if (lexequ (tp -> cmd_key, str) == 0) { + ambig = 0; + fnd = tp; /* exact match */ + break; + } + else if (re_exec (tp -> cmd_key) == 1) { + if (fnd == NULL) + fnd = tp; + else + ambig = 1; + } + if (ambig) { + char *p, buf[BUFSIZ]; + for (tp = chanlist, p = buf; + tp -> cmd_key; tp ++) { + if (re_exec (tp -> cmd_key) == 1) { + (void) sprintf (p, "%s%s", + p == buf ? "" : ", ", + tp -> cmd_key); + p += strlen(p); + } + } + advise (NULLCP, "%s is ambiguous, it matches %s", str, buf); + return NULLCP; + } + + if (fnd == NULL) + advise (NULLCP, "%s does not match any channel", str); + return fnd ? fnd -> cmd_key : NULLCP; +} + diff --git a/Src/lconsole/functions.c b/Src/lconsole/functions.c new file mode 100644 index 0000000..92982cb --- /dev/null +++ b/Src/lconsole/functions.c @@ -0,0 +1,965 @@ +/* functions.c: things that do the work */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/functions.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/functions.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: functions.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr.h" +#include "qmgr-int.h" +#include +#ifdef BSD42 +#include +#endif + +#define plural(n,s) ((n) == 1 ? "" : (s)) + + +extern int chan_update (); +extern int mta_update (); +extern int msglist_update (); + +extern int f_channel (); +extern int f_mta (); +extern int f_msg (); +extern int f_show (); + +static int f_clear (); +static int f_close (); +static int f_delay (); +static int f_decrease (); +static int f_disable (); +static int f_enable (); +static int f_help (); +static int f_increase (); +static int f_open (); +static int f_quit (); +static int f_rereadqueue (); +static int f_restart (); +static int f_shutdown (); +static int f_source (); +static int f_status (); + +extern char *isodeversion, *ppversion; + +static struct lc_dispatch disp[] = { +{ "?", f_help, LC_NONE, + "give help on a specific command"}, +{ "channel", f_channel, LC_OPEN, + "display channels or information about one"}, +{ "clear", f_clear, LC_AUTH|LC_OPEN, + "clear the delay on a channel, mta or message"}, +{ "close", f_close, LC_OPEN, + "close a connection to a queue manager"}, +{ "decrease", f_decrease, LC_AUTH|LC_OPEN, + "decrease the number of runnable channels"}, +{ "delay", f_delay, LC_AUTH|LC_OPEN, + "delay a channel, mta or message"}, +{ "disable", f_disable, LC_AUTH|LC_OPEN, + "disable a channel, mta, message, all or submission"}, +{ "enable", f_enable, LC_AUTH|LC_OPEN, + "enable a channel, mta, message, all or submission"}, +{ "help", f_help, LC_NONE, + "give help on a specific command"}, +{ "increase", f_increase, LC_AUTH|LC_OPEN, + "increase the number of runnable channels"}, +{ "msg", f_msg, LC_OPEN, + "display msgs or information about a message"}, +{ "mta", f_mta, LC_OPEN, + "display mtas or information about one mta"}, +{ "open", f_open, LC_CLOSE, + "open a connection to a queue manager" }, +{ "quit", f_quit, LC_NONE, + "terminate the connection and exit" }, +{ "rereadqueue", f_rereadqueue, LC_AUTH|LC_OPEN, + "reread the queue"}, +{ "restart", f_restart, LC_AUTH|LC_OPEN, + "restart the queue manager" }, +{ "show", f_show, LC_OPEN, + "show messages meeting certain criteria"}, +{ "shutdown", f_shutdown, LC_AUTH|LC_OPEN, + "shutdown the queue manager"}, +{ "source", f_source, LC_NONE, + "read a file of commands"}, +{ "status", f_status, LC_OPEN, + "print the status of the queue manager"}, +{ NULLCP, NULLIFP, LC_NONE, + NULLCP } +}; + +struct lc_dispatch *getds (name) +char *name; +{ + register int longest, nmatches; + register char *p, *q; + char buffer[BUFSIZ]; + register struct lc_dispatch *ds, *fs; + + longest = nmatches = 0; + for (ds = disp; p = ds -> name; ds++) { + for (q = name; *q == *p++; q++) + if (*q == NULL) + return ds; + if (*q == NULL) + if (q - name > longest) { + longest = q - name; + nmatches = 1; + fs = ds; + } + else + if (q - name == longest) + nmatches++; + } + + + switch (nmatches) { + case 0: + advise (NULLCP, "unknown operation \"%s\"", name); + return NULL; + + case 1: + return fs; + + default: + for (ds = disp, p = buffer; q = ds -> name; ds++) + if (strncmp (q, name, longest) == 0) { + (void) sprintf (p, "%s \"%s\"", + p != buffer ? "," : "", q); + p += strlen (p); + } + advise (NULLCP, "ambiguous operation, it could be one of:%s", + buffer); + return NULL; + } +} + + +static int f_open (vec) +char **vec; +{ + char buffer[BUFSIZ]; + char prompt[BUFSIZ]; + BindResult *br; + fd_set wfds, rfds; + + free_chanlist (); + + if (*++vec == NULLCP) { + if (getline ("host: ", buffer) == NOTOK || + str2vec (buffer, vec) < 1) + return OK; + } + + if (host) free (host); + host = strdup (*vec); + + if (*++vec == NULLCP && authenticate) { + if (user == NULLCP) + user = strdup (""); + (void) sprintf (prompt, "user (%s:%s): ", host, user); + if (getline (prompt, buffer) == NOTOK) + return OK; + + if (str2vec (buffer, vec) < 1) { + authenticate = 0; + if (user) free (user); + user = NULLCP; + } + } + else if (*vec && **vec) { + if (user != NULLCP) + free (user); + user = strdup(*vec); + authenticate = 1; + } + + if (authenticate && *++vec == NULLCP) { + (void) sprintf (prompt, "password (%s:%s): ", + host, user); + passwd = getpassword (prompt); + passwd = strdup(passwd); + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + if (verbose) { + printf ("Connecting to %s...", host); + (void) fflush(stdout); + } + switch (init_connect (host, user, passwd, authenticate == 1 ? + type_Qmgr_BindArgument_weakAuthentication : + type_Qmgr_BindArgument_noAuthentication, + &console_fd, buffer, &br)) { + default: + case NOTOK: + if (verbose) + printf ("failed: %s\n", buffer); + console_fd = NOTOK; + return NOTOK; + + case CONNECTING_1: + FD_SET (console_fd, &wfds); + break; + + case CONNECTING_2: + FD_SET (console_fd, &rfds); + break; + + case DONE: + break; + } + while (1) { + fd_set ifds, ofds; + ifds = rfds; + ofds = wfds; + + if (xselect (console_fd + 1, &ifds, &ofds, NULLFD, 1) <= 0) { + (void) putchar ('.'); + (void) fflush (stdout); + continue; + } + switch (retry_connect (console_fd, buffer, &br)) { + case NOTOK: + console_fd = NOTOK; + if (verbose) + printf ("failed: %s\n", buffer); + return NOTOK; + + case CONNECTING_1: + FD_CLR (console_fd, &rfds); + FD_SET (console_fd, &wfds); + continue; + + case CONNECTING_2: + FD_CLR (console_fd, &wfds); + FD_SET (console_fd, &rfds); + continue; + + case DONE: + break; + } + break; + } + accessmode = br -> access; + if (realhost) free (realhost); + realhost = strdup (br -> info); + if (remoteversion) free (remoteversion); + remoteversion = strdup(br -> version); + free_BindResult (br); + + if (verbose) + printf ("succeeded\n"); + + return OK; +} + +/* ARGSUSED */ +static int f_close (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + + if (console_fd == NOTOK) + return NOTOK; + + if (release_connect(console_fd, errbuf) != DONE) + return NOTOK; + + free_chanlist (); + console_fd = NOTOK; + return OK; +} + + +/* ARGSUSED */ +static int status_update (st, id) +QmgrStatus *st; +{ + time_t now; + time_t secs; + + (void) time (&now); + secs = now - st -> boottime; + + printf ("Status at %s", ctime (&now)); + printf ("\tConnected to qmgr on %s\n",realhost); + printf ("\tversion %s\n", remoteversion); + printf ("\trunning since %s", ctime(&st->boottime)); + if (accessmode == FULL_ACCESS) + printf ("\tfull access rights\n"); + + printf ("\nSummary\n"); + printf ("Channels: %d channel%s running (maximum of %d)\n", + st -> currChans, plural(st -> currChans,"s"), + st -> maxChans); + printf ("Messages: %s Messages, ", datasize(st -> totalMsgs,"")); + printf ("%s Delivery Reports, ", datasize(st -> totalDRs, "")), + printf ("Volume %s\n", datasize(st -> totalVolume, "b")); + printf ("Load: %.2lf ops/sec %.2lf runnable chans\n", + (double)st -> opsPerSec/100.0, + (double)st -> runnableChans / 100.0); + printf ("%5s %.2lf msgs in/s %.2f msgs out/s\n", "", + (double) st -> msgsInPerSec / 100.0, + (double) st -> msgsOutPerSec / 100.0); + printf ("\n%-10s %10s %10s %10s %10s\n", "", "Total In", "Avrg In/s", + "Total Out", "Avrg Out/s"); + printf ("%-10s %10s %10.2f ", + "Messages", + datasize(st->messagesIn,""), + (double)st -> messagesIn / (double)secs); + printf ("%10s %10.2lf\n", + datasize(st -> messagesOut, ""), + (double) st -> messagesOut / (double)secs); + printf ("%-10s %10s %10.2lf ", + "Addresses", + datasize(st -> addrIn,""), + (double)st -> addrIn / (double)secs); + printf ("%10s %10.2lf\n", + datasize(st -> addrOut, ""), + (double)st -> addrOut / (double)secs); + free_QmgrStatus (st); + return OK; +} + +/* ARGSUSED */ +static int f_status (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + + if (initiate_op (console_fd, operation_Qmgr_qmgrStatus, + NULLVP, &pid, status_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +static int f_increase (vec) +char **vec; +{ + char *av[2]; + int pid; + char errbuf[BUFSIZ]; + + av[1] = NULLCP; + av[0] = QCTRL_INCMAX; + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + +/* ARGSUSED */ +static int f_decrease (vec) +char **vec; +{ + char *av[2]; + int pid; + char errbuf[BUFSIZ]; + + av[1] = NULLCP; + av[0] = QCTRL_DECMAX; + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + +static int f_quit (vec) +char **vec; +{ + if (console_fd != NOTOK) + (void) f_close (vec); + return DONE; +} + + +void display_status (st) +ProcStatus *st; +{ + if (st -> enabled == 0) + printf ("%*sStatus: disabled\n", indent, ""); + + if (st -> lastAttempt) + printf ("%*sLast attempted delivery: %s", + indent * 2, "", + ctime(&st -> lastAttempt)); + + if (st -> lastSuccess) + printf ("%*sLast successful delivery: %s", + indent * 2, "", + ctime(&st->lastSuccess)); + + if (st -> cachedUntil) + printf ("%*sDelayed until %s", indent * 2, "", + ctime (&st -> cachedUntil)); +} + + +#ifndef TIOCGWINSZ +/* ARGSUSED */ +#endif +int ncols (fp) +FILE *fp; +{ +#ifdef TIOCGWINSZ + int i; + struct winsize ws; + + if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK + && (i = ws.ws_col) > 0) + return i; +#endif + + return 80; +} + + +static int f_help (vec) +char **vec; +{ + register int i, j, w; + int columns, width, lines; + register struct lc_dispatch *ds, *es; + + for (width = 0,es = disp; es -> name; es++) { + if ((w = strlen(es->name)) > width) + width = w; + } + + if (*++vec == NULL) { + if ((columns = ncols (stdout) / + (width = (width + 8) & ~7)) == 0) + columns = 1; + lines = ((es - disp) + columns - 1) / columns; + + printf ("Operations:\n"); + for (i = 0; i < lines; i++) + for (j = 0; j < columns; j++) { + ds = disp + j * lines + i; + printf ("%s", ds -> name); + if (ds + lines >= es) { + (void) putchar ('\n'); + break; + } + for (w = strlen (ds -> name); + w < width; w = (w + 8) & ~7) + (void) putchar ('\t'); + } + printf ("\nversion info:\t%s\n\t\t%s\n", + ppversion, isodeversion); + + return OK; + } + + for (; *vec; vec++) + if (strcmp (*vec, "?") == 0) { + for (ds = disp; ds -> name; ds++) + printf ("%-*s\t- %s\n", width, + ds -> name, ds -> help); + + break; + } + else + if (ds = getds (*vec)) + printf ("%-*s\t- %s\n", + width, ds -> name, ds -> help); + + return OK; +} + +/* ARGSUSED */ +static int f_restart (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + + vec[0] = QCTRL_RESTART; + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + vec, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + +static int f_shutdown (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + char *av[2]; + + av[1] = NULLCP; + av[0] = QCTRL_GRACEFUL; + if (*++vec != NULLCP) { + if (strncmp(*vec, "abort", strlen(*vec)) == 0) + vec[0] = QCTRL_ABORT; + } + + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + + +/* ARGSUSED */ +static int f_rereadqueue (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + char *av[2]; + + av[0] = QCTRL_REREAD; + av[1] = NULLCP; + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} + +int tb_match (name, tbl) +char *name; +CMD_TABLE *tbl; +{ + int longest, nmatches; + CMD_TABLE *tp, *stp; + char *q, *p; + + longest = nmatches = 0; + for (tp = tbl; p = tp -> cmd_key; tp ++) { + for (q = name; *q == *p++; q++) + if (*q == NULL) + return tp -> cmd_value; + if (*q == NULL) + if (q - name > longest) { + longest = q - name; + nmatches = 1; + stp = tp; + } + else + if (q - name == longest) + nmatches++; + } + if (nmatches == 0) + return TB_NONE; + if (nmatches == 1) + return stp -> cmd_value; + return TB_AMBIG; +} + +static CMD_TABLE de_tbl[] = { +#define DE_ALL 1 + "all", DE_ALL, +#define DE_SUBMISSION 2 + "submission", DE_SUBMISSION, +#define DE_MESSAGE 3 + "message", DE_MESSAGE, +#define DE_MTA 4 + "mta", DE_MTA, +#define DE_CHANNEL 5 + "channel", DE_CHANNEL, + NULL + }; + +#define OP_DISABLE 1 +#define OP_ENABLE 2 +#define OP_CLEAR 3 + +static int de_generic (vec, type, str, cstr) +char **vec; +int type; +char *str, *cstr; +{ + int style; + char buffer[BUFSIZ], buffer2[BUFSIZ]; + char *av[NVARGS]; + int pid; + char errbuf[BUFSIZ], prompt[BUFSIZ]; + + switch (style = tb_match (*vec, de_tbl)) { + case TB_NONE: + advise (NULLCP, "%s is not a known action", *vec); + return NOTOK; + case TB_AMBIG: + advise (NULLCP, "'%s' is an ambiguous keyword", *vec); + return NOTOK; + + case DE_ALL: + case DE_SUBMISSION: + if (type == OP_DISABLE) { + av[0] = style == DE_ALL ? QCTRL_DISALL : + QCTRL_DISSUB; + } + else if (type == OP_ENABLE) + av[0] = style == DE_ALL ? QCTRL_ENAALL : + QCTRL_ENASUB; + else { + advise (NULLCP, "%s is not a known action", *vec); + return NOTOK; + } + + if (initiate_op (console_fd, operation_Qmgr_qmgrControl, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + case DE_CHANNEL: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s channel: ", str); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + if ((vec[0] = fullchanname(vec[0])) == NULLCP) + return OK; + vec[1] = cstr; + vec[2] = NULLCP; + + if (initiate_op (console_fd, operation_Qmgr_channelcontrol, + vec, &pid, chan_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + case DE_MTA: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "channel containing MTA: "); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + if ((vec[0] = fullchanname(vec[0])) == NULLCP) + return OK; + if (vec[1] == NULLCP) { + (void) sprintf (prompt, + "%s (on channel %s) MTA: ", str, + vec[0]); + if (getline (prompt, buffer2) == NOTOK || + str2vec(buffer2, &vec[1]) < 1) + return OK; + } + + vec[2] = cstr; + vec[3] = NULLCP; + + if (initiate_op (console_fd, operation_Qmgr_mtacontrol, + vec, &pid, mta_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + case DE_MESSAGE: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s message qid: ", str); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, av) < 1) + return OK; + vec[1] = NULLCP; + } + else av[0] = *vec; + av[1] = NULLCP; + av[2] = cstr; + + if (*++vec == NULLCP) { + if (getline ("list of user numbers: ", buffer2) == NOTOK || + str2vec (buffer2, &av[3]) < 1) + return OK; + } + else { + int i = 3; + while(*vec) + av[i++] = *++vec; + av[i] = NULLCP; + } + + if (initiate_op (console_fd, operation_Qmgr_msgcontrol, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + } + return OK; +} + +static int f_enable (vec) +char **vec; +{ + if (*++vec == NULLCP) { + advise (NULLCP, + "enable {all | submission | message [args] | mta [args] | channel [args] }"); + return NOTOK; + } + return de_generic (vec, OP_ENABLE, "enable", CTRL_ENABLE); +} + +static int f_disable (vec) +char **vec; +{ + + if (*++vec == NULLCP) { + advise (NULLCP, + "disable {all | submission | message [args] | mta [args] | channel [args] }"); + return NOTOK; + } + + return de_generic (vec, OP_DISABLE, "disable", CTRL_DISABLE); +} + +static int f_clear (vec) +char **vec; +{ + if (*++vec == NULLCP) { + advise (NULLCP, + "clear {channel | mta | message}"); + return NOTOK; + } + + return de_generic (vec, OP_CLEAR, "clear delay", CTRL_CACHECLEAR); +} + +static int f_delay (vec) +char **vec; +{ + char buffer[BUFSIZ], buffer2[BUFSIZ]; + char *av[NVARGS]; + int pid; + char errbuf[BUFSIZ], prompt[BUFSIZ]; + char *str; + + if (*++vec == NULLCP) { + advise (NULLCP, "Specify one of channel, mta or message"); + return NOTOK; + } + + str = "delay"; + switch (tb_match (*vec, de_tbl)) { + case TB_NONE: + advise (NULLCP, "%s is not a known action", *vec); + return NOTOK; + case TB_AMBIG: + advise (NULLCP, "'%s' is an ambiguous keyword", *vec); + return NOTOK; + + case DE_CHANNEL: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s channel: ", str); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + if ((av[0] = fullchanname(*vec)) == NULLCP) + return OK; + av[1] = CTRL_CACHEADD; + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s channel by: ", str); + if (getline (prompt, buffer2) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + av[2] = *vec; + av[3] = NULLCP; + + if (initiate_op (console_fd, operation_Qmgr_channelcontrol, + av, &pid, chan_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + case DE_MTA: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "channel containing MTA: "); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + if ((av[0] = fullchanname(*vec)) == NULLCP) + return OK; + + if (*++vec == NULLCP) { + (void) sprintf (prompt, + "%s (on channel %s) MTA: ", str, + vec[0]); + if (getline (prompt, buffer2) == NOTOK || + str2vec(buffer2, &vec[1]) < 1) + return OK; + } + av[1] = *vec; + vec[2] = CTRL_CACHEADD; + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s channel by: ", str); + if (getline (prompt, buffer2) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + av[3] = *vec; + av[4] = NULLCP; + + if (initiate_op (console_fd, operation_Qmgr_mtacontrol, + vec, &pid, mta_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + case DE_MESSAGE: + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s message qid: ", str); + if (getline (prompt, buffer) == NOTOK || + str2vec(buffer, av) < 1) + return OK; + vec[1] = NULLCP; + } + else av[0] = *vec; + if (*++vec == NULLCP) { + (void) sprintf (prompt, "%s channel by: ", str); + if (getline (prompt, buffer2) == NOTOK || + str2vec(buffer, vec) < 1) + return OK; + } + av[1] = *vec; + av[2] = CTRL_CACHEADD; + if (*++vec == NULLCP) { + if (getline ("list of user numbers: ", buffer2) == NOTOK || + str2vec (buffer2, &av[3]) < 1) + return OK; + } + else { + int i = 3; + while(*vec) + av[i++] = *++vec; + av[i] = NULLCP; + } + + if (initiate_op (console_fd, operation_Qmgr_msgcontrol, + av, &pid, NULLIFP, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + break; + + } + return OK; +} + +static int f_source (vec) +char **vec; +{ + int sb; + FILE *savein; + char buffer[BUFSIZ]; + + if (*++vec == NULLCP) { + if (getline ("file: ", buffer) == NOTOK || + str2vec (buffer, vec) < 1) + return OK; + } + savein = fp_in; + if ((fp_in = fopen (vec[0], "r")) == NULL) { + fp_in = savein; + advise (vec[0], "Can't open file"); + return OK; + } + sb = batch; + batch = 1; + + interactive (); + + fp_in = savein; + batch = sb; + + return OK; +} diff --git a/Src/lconsole/lconsole.c b/Src/lconsole/lconsole.c new file mode 100644 index 0000000..d488222 --- /dev/null +++ b/Src/lconsole/lconsole.c @@ -0,0 +1,301 @@ +/* lconsole.c: driver and main routine for the line console */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/lconsole.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/lconsole.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: lconsole.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr-int.h" +#include + +static char *myname; + +int verbose; +int authenticate; +int console_fd = NOTOK; +int accessmode = 0; +int indent = 0; + +char *host = NULLCP; +char *realhost = NULLCP; +char *remoteversion = NULLCP; +char *user = NULLCP; +char *passwd = NULLCP; +FILE *fp_in = stdin; +int batch = 0; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + char *vec[NVARGS]; + int vecp; + char *myhost, *mypasswd, *myuser; + char **op = NULLVP; + int status; + + myname = argv[0]; + myhost = mypasswd = myuser = NULLCP; + if (isatty(2)) + verbose = 1; + while((opt = getopt(argc, argv, "bQ:u:p:")) != EOF) + switch (opt) { + case 'Q': + myhost = optarg; + break; + + case 'u': + authenticate = TRUE; + myuser = optarg; + break; + + case 'p': + authenticate = TRUE; + mypasswd = optarg; + break; + + case 'b': + batch = 1; + break; + + default: + fprintf (stderr, "Usage: %s\n", myname); + break; + } + argc -= optind; + argv += optind; + if (argc > 0) + op = argv; + + if (myhost) { + vecp = 0; + vec[vecp++] = "open"; + vec[vecp++] = myhost; + if (myuser) { + vec[vecp++] = myuser; + if (mypasswd) + vec[vecp++] = mypasswd; + } + vec[vecp] = NULLCP; + + if (console_loop (vec, NOTOK) != OK && op) + exit (1); + } + + if(op) { + for (vecp = 0; *op; op ++) + vec[vecp++] = *op; + vec[vecp] = NULLCP; + + if (console_loop (vec, NOTOK) != OK) + status = 1; + } + else + status = interactive (); + + if (console_fd != NOTOK) { + vecp = 0; + vec[vecp++] = "close"; + vec[vecp++] = NULLCP; + + (void) console_loop (vec, NOTOK); + } + + exit(status); /* NOTREACHED */ +} + +int interactive () +{ + char *vec[NVARGS]; + int status; + char buffer[BUFSIZ]; + int i; + + for (;;) { + if (getline ("%s> ", buffer) == NOTOK) + break; + if (buffer[0] == NULL || buffer[0] == '#') + continue; + + for (i = 0; i < NVARGS; i++) + vec[i] = NULLCP; + if (sstr2arg (buffer, NVARGS, vec, " \t") < 1 || + *vec[0] == NULL) + continue; + + switch (console_loop (vec, OK)) { + case NOTOK: + status = 1; + break; + + case OK: + continue; + + case DONE: + status = 0; + break; + } + break; + } + return status; +} + +int console_loop (vec, retval) +char **vec; +int retval; +{ + struct lc_dispatch *ds; + + if ((ds = getds (*vec)) == NULL) + return retval; + + + if (console_fd == NOTOK) { + if (ds -> flags & LC_OPEN) { + advise (NULLCP, "not connected to a queue manager"); + return retval; + } + } + else if (ds -> flags & LC_CLOSE) { + advise (NULLCP, "already connected to a queue manager"); + return retval; + } + if ((ds -> flags & LC_AUTH) && accessmode != FULL_ACCESS) { + advise (NULLCP, "Operation requires full access rights"); + return retval; + } + + switch ((*ds -> fnx)(vec)) { + default: + case NOTOK: + return retval; + + case OK: + return OK; + + case DONE: + return DONE; + } +} + + +int getline (prompt, buffer) +char *prompt, *buffer; +{ + int c; + char *cp, *ep; + + if (!batch) { + printf (prompt, console_fd == NOTOK ? myname : realhost); + (void) fflush (stdout); + } + + for (ep = (cp = buffer) + BUFSIZ - 1; (c = getc (fp_in)) != '\n';) { + if (c == EOF) { + if (!batch) + putchar ('\n'); + clearerr(fp_in); + return NOTOK; + } + if (cp < ep) + *cp ++ = c; + + } + *cp = NULL; + return OK; +} +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + +char *datasize (n, units) +int n; +char *units; +{ + static char dbuf[512]; + + if (n < 1000) + (void) sprintf (dbuf, "%d%s", n, units); + else if (n < 100000) + (void) sprintf (dbuf, "%.2lfK%s", (double)n/1000.0, units); + else + (void) sprintf (dbuf, "%.2lfM%s", (double)n/1000000.0, units); + return dbuf; +} diff --git a/Src/lconsole/lconsole.h b/Src/lconsole/lconsole.h new file mode 100644 index 0000000..210f9e1 --- /dev/null +++ b/Src/lconsole/lconsole.h @@ -0,0 +1,56 @@ +/* lconsole.h: line console definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/lconsole.h,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: lconsole.h,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + * + */ + +#include "util.h" + +extern int verbose; +extern int authenticate; +extern int console_fd; +extern int accessmode; +extern int batch; +extern int indent; + +extern FILE *fp_in; + +extern char *host; +extern char *user; +extern char *passwd; +extern char *realhost; +extern char *remoteversion; + +struct lc_dispatch { + char *name; + IFP fnx; + + int flags; +#define LC_NONE 0x00 +#define LC_OPEN 0x01 +#define LC_CLOSE 0x02 +#define LC_AUTH 0x04 + + char *help; +}; + +struct lc_dispatch *getds(); + +#define NVARGS 10 + +void advise (), adios (); +extern char *datasize (); +extern void display_status (); +extern void free_chanlist (); +extern char *re_comp (); +extern int re_exec (); +extern char *fullchanname (); + +#define TB_AMBIG -1 +#define TB_NONE 0 diff --git a/Src/lconsole/make b/Src/lconsole/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/lconsole/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/lconsole/msgs.c b/Src/lconsole/msgs.c new file mode 100644 index 0000000..7812b4c --- /dev/null +++ b/Src/lconsole/msgs.c @@ -0,0 +1,204 @@ +/* msgs.c: msg functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/msgs.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/msgs.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: msgs.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr.h" +#include "qmgr-int.h" +#include +#ifdef BSD42 +#include +#endif + +#define plural(n,s) ((n) == 1 ? "" : (s)) + +char *msgtolist; + +msg_update() { } + +static void display_all_msgs (mlp) +MsgList *mlp; +{ + MsgInfo *mip, *msgs = mlp -> msgs; + int width, w; + int count; + char **cpp; + + for (count = 0, mip = msgs; mip; mip = mip -> next) + count ++; + cpp = (char **) smalloc (count * sizeof (char *)); + + for (width = count = 0, mip = msgs; mip; mip = mip -> next) { + if ((w = strlen (mip -> permsginfo -> qid)) > width) + width = w; + cpp[count++] = mip -> permsginfo -> qid; + } + w = ncols (stdout) / (width+1); + for (count = 0, mip = msgs; mip; mip = mip -> next) { + printf ("%-*s%s", width, cpp[count], + (count + 1) % w == 0 ? "\n" : " "); + count ++; + } + if (count % w != 0) + putchar ('\n'); + free ((char *)cpp); +} + +static void display_recip_list (rip) +RecipInfo *rip; +{ + Strlist *sl; + int i; + + if (rip == NULL) return; + + if (rip -> id != 0) { + for (sl = rip -> channels, i = 0; i < rip -> channelsDone; i++) + sl = sl -> next; + + printf ("%*sTo: %s (id %d)\n", + indent * 2, "", + rip -> user, rip -> id); + + indent ++; + printf ("%*sMTA %s via channel %s\n", + indent * 2, "", rip -> mta, + sl ? sl -> str : ""); + display_status (rip -> status); + if (rip -> info) + printf ("%*sError Info: %s\n", + indent * 2, "", rip -> info); + indent --; + } + display_recip_list (rip -> next); +} + +void display_msg_info (mip) +MsgInfo *mip; +{ + PerMessageInfo *pmi = mip -> permsginfo; + printf ("%*sMessage id %s\n", + indent * 2, "", pmi -> qid); + indent ++; + printf ("%*sfrom %s\n", indent * 2, "", pmi -> originator); + printf ("%*sSize %s priority %d queued since %s", indent * 2, "", + datasize (pmi -> size, ""), + pmi -> priority, + ctime (&pmi -> age)); + if (pmi -> deferredTime) + printf ("%*sDeferred until %s", + indent * 2, "", ctime(&pmi -> deferredTime)); + printf ("%*sWill expire at %s", indent * 2, "", + ctime(&pmi -> expiryTime)); + if (pmi -> uaContentId) + printf ("%*sUA ID: %s\n", indent * 2, "", pmi -> uaContentId); + if (pmi -> errorCount) + printf ("%*sHas accumulated %d errors\n", indent * 2, "", + pmi -> errorCount); + if (pmi -> numberWarningsSent > 0) + printf ("%*sHas had %d warning%s sent\n", + indent * 2, "", + pmi -> numberWarningsSent, + plural(pmi -> numberWarningsSent, "s")); + + indent ++; + display_recip_list (mip -> recips); + indent --; + indent --; + putchar ('\n'); +} + +/* ARGSUSED */ +int msglist_update(msgl, id) +MsgList *msgl; +int id; +{ + MsgInfo *mip; + int found; + char *cp; + + indent = 0; + if (msgl == NULL) + advise (NULLCP, "No messages found"); + else if (msgtolist) { + found = 0; + if ((cp = re_comp (msgtolist)) != NULLCP) { + advise (NULLCP, "Expression %s: %s", + msgtolist, cp); + free_MsgList (msgl); + return OK; + } + for (mip = msgl -> msgs; mip; mip = mip -> next) + if (re_exec (mip -> permsginfo -> qid) == 1) { + display_msg_info (mip); + found ++; + } + if (found == 0) + advise (NULLCP, "Message %s not found", msgtolist); + } + else if (msgl -> msgs && msgl -> msgs -> next == NULL) + display_msg_info (msgl -> msgs); + else + display_all_msgs (msgl); + + free_MsgList (msgl); + return OK; +} + + +int f_msg (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + char buffer[BUFSIZ], buffer2[BUFSIZ]; + char *av[NVARGS]; + + if (*++vec == NULLCP) { + if (getline ("Channel: ", buffer) == NOTOK || + str2vec (buffer, vec) < 1) + return OK; + } + av[0] = *vec; + if ((av[0] = fullchanname (av[0])) == NULLCP) + return OK; + + if (*++vec == NULLCP) { + if (getline ("Mta: ", buffer2) == NOTOK || + str2vec(buffer2, vec) < 1) + return OK; + } + av[1] = *vec; + + if (*++vec == NULLCP) { + msgtolist = NULLCP; + } + else { + msgtolist = *vec; + *vec = NULLCP; + } + av[2] = NULLCP; + if (initiate_op (console_fd, operation_Qmgr_readChannelMtaMessage, + av, &pid, msglist_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + + return OK; +} diff --git a/Src/lconsole/mtas.c b/Src/lconsole/mtas.c new file mode 100644 index 0000000..4b73f1a --- /dev/null +++ b/Src/lconsole/mtas.c @@ -0,0 +1,181 @@ +/* mta.c: mta functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/mtas.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/mtas.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: mtas.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr.h" +#include "qmgr-int.h" +#include +#ifdef BSD42 +#include +#endif + +#define plural(n,s) ((n) == 1 ? "" : (s)) + +static char *mtatolist; + +static void display_mta_info (mip) +MtaInfo *mip; +{ + printf ("%*sMTA %s on channel %s\n", + indent * 2, "", + mip -> mta, mip -> channel); + indent ++; + printf ("%*s%s message%s, ", indent * 2, "", + datasize (mip -> numberMessages, ""), + plural(mip -> numberMessages,"s")); + printf ("%s delivery report%s, ", + datasize (mip->numberReports, ""), + plural(mip->numberReports,"s")); + printf ("%s data\n", + datasize (mip -> volumeMessages, "")); + if (mip -> active) + printf ("%*sMTA currently being delivered\n", + indent * 2, ""); + display_status (mip -> status); + + if (mip -> oldestMessage && (mip -> numberReports > 0 || + mip -> numberMessages > 0)) + printf ("%*sOldest message is %s", indent * 2, "", + ctime (&mip -> oldestMessage)); + indent --; +} + +static void display_all_mtas (mtas) +MtaInfo *mtas; +{ + MtaInfo *mip; + int width, w; + int count; + char **cpp; + + for (count = 0, mip = mtas; mip; mip = mip -> next) + count ++; + cpp = (char **) smalloc (count * sizeof (char *)); + + for (width = count = 0, mip = mtas; mip; mip = mip -> next) { + char buf[BUFSIZ]; + char c[2]; + + c[1] = NULL; + c[0] = ':'; + if (mip -> active) + c[0] = '*'; + if (mip -> status -> enabled == 0) + c[0] = '!'; + + if (mip -> numberReports != 0) + (void) sprintf (buf, "%s%s%d+%d", + mip -> mta, c, + mip -> numberMessages, + mip -> numberReports); + else if (mip -> numberMessages != 0) + (void) sprintf (buf, "%s%s%d", + mip -> mta, c, + mip -> numberMessages); + else (void) sprintf (buf, "%s%s", mip -> mta, + c[0] == ':' ? "" : c); + if ((w = strlen (buf)) > width) + width = w; + cpp[count++] = strdup (buf); + } + w = ncols (stdout) / (width+1); + for (count = 0, mip = mtas; mip; mip = mip -> next) { + printf ("%-*s%s", width, cpp[count], + (count + 1) % w == 0 ? "\n" : " "); + free (cpp[count++]); + } + if (count % w != 0) + putchar ('\n'); + free ((char *)cpp); + +} + + +/* ARGSUSED */ +int mta_update(mta, id) +MtaInfo *mta; +int id; +{ + int found = 0; + MtaInfo *mip; + char *cp; + + if (mta == NULL) + advise (NULLCP, "No MTA's found"); + else if (mtatolist) { + found = 0; + if ((cp = re_comp (mtatolist)) != NULLCP) { + advise (NULLCP, "Expression %s: %s", + mtatolist, cp); + free_MtaInfo (mta); + return OK; + } + for (mip = mta; mip; mip = mip -> next) { + if (re_exec (mip -> mta) == 1) { + display_mta_info (mip); + found ++; + } + } + if (found == 0) + advise (NULLCP, "MTA %s not found", mtatolist); + } + else if (mta -> next == NULL) + display_mta_info (mta); + else + display_all_mtas (mta); + + free_MtaInfo (mta); + return OK; +} + +int f_mta (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + int pid; + char buffer[BUFSIZ]; + char *av[NVARGS]; + + if (*++vec == NULLCP) { + if (getline ("Channel to list MTA's on: ", buffer) == NOTOK || + str2vec (buffer, av) < 1) + return OK; + vec[1] = NULLCP; + } + else av[0] = *vec; + av[0] = fullchanname (av[0]); + if (av[0] == NULLCP) + return NOTOK; + + if (*++vec == NULLCP) { + mtatolist = NULLCP; + } + else { + mtatolist = *vec; + } + + if (initiate_op (console_fd, operation_Qmgr_mtaread, + av, &pid, mta_update, errbuf) == NOTOK) { + advise (NULLCP, "status operation failed: %s", errbuf); + return NOTOK; + } + + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + + return OK; +} diff --git a/Src/lconsole/show.c b/Src/lconsole/show.c new file mode 100644 index 0000000..f5823a5 --- /dev/null +++ b/Src/lconsole/show.c @@ -0,0 +1,171 @@ +/* show.c: filter matching functions */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/lconsole/RCS/show.c,v 6.0 1991/12/18 20:27:16 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/lconsole/RCS/show.c,v 6.0 1991/12/18 20:27:16 jpo Rel $ + * + * $Log: show.c,v $ + * Revision 6.0 1991/12/18 20:27:16 jpo + * Release 6.0 + * + */ + +#include "lconsole.h" +#include "qmgr.h" +#include "qmgr-int.h" +#include +#ifdef BSD42 +#include +#endif + +#define plural(n,s) ((n) == 1 ? "" : (s)) + +extern char *msgtolist; +extern int msglist_update(); + +static CMD_TABLE tb_filters[] = { +#define F_CONTENT 1 + QFILTER_CONTENT, F_CONTENT, +#define F_EIT 2 + QFILTER_EIT, F_EIT, +#define F_PRIO 3 + QFILTER_PRIO, F_PRIO, +#define F_RECENT 4 + QFILTER_MORERECENT, F_RECENT, +#define F_EARLIER 5 + QFILTER_EARLIER, F_EARLIER, +#define F_MAXSIZE 6 + QFILTER_MAXSIZE, F_MAXSIZE, +#define F_ORIG 7 + QFILTER_ORIG, F_ORIG, +#define F_RECIP 8 + QFILTER_RECIP, F_RECIP, +#define F_CHANNEL 9 + QFILTER_CHANNEL, F_CHANNEL, +#define F_MTA 10 + QFILTER_MTA, F_MTA, +#define F_QUEID 11 + QFILTER_QUEUEID, F_QUEID, +#define F_MPDU 12 + QFILTER_MPDU, F_MPDU, +#define F_UA 13 + QFILTER_UA, F_UA, + NULLCP, NOTOK + }; + +static int rebuild_list (vec) +char **vec; +{ + CMD_TABLE *cmd, *ep; + char *cp; + int i, n, width, w; + int cols, lines; + char buf[BUFSIZ]; + + for(i = 0; vec[i]; i++) { + if ((cp = index(vec[i], '=')) == NULLCP) { + advise (NULLCP, "Missing '=' in %s", vec[i]); + return NOTOK; + } + + *cp ++ = '\0'; + switch (n = tb_match(vec[i], tb_filters)) { + case TB_AMBIG: + n = strlen (vec[i]); + cp = buf; + for (cmd = tb_filters; cmd -> cmd_key; cmd ++) { + if (lexnequ (vec[i], cmd -> cmd_key, n) == 0) { + (void) sprintf (cp, "%s%s", + cp == buf ? "" : ", ", + cmd -> cmd_key); + cp += strlen(cp); + } + } + advise (NULLCP, "%s is ambiguous, it matches %s", + vec[i], buf); + return NOTOK; + + case TB_NONE: + advise (NULLCP, "%s doesn't match any known key, use one of:", + vec[i]); + for (width = 0, ep = tb_filters; ep -> cmd_key; ep++) + if ((n = strlen (ep -> cmd_key)) > width) + width = n; + if ((cols = ncols(stdout) / + (width = (width + 8) & ~7)) == 0) + cols = 1; + lines = ((ep - tb_filters) + cols - 1) / cols; + + for (n = 0; n < lines; n++) + for (i = 0; i < cols; i++) { + cmd = tb_filters + i * lines + n; + printf ("%s", cmd -> cmd_key); + if (cmd + lines >= ep) { + printf ("\n"); + break; + } + for (w = strlen(cmd -> cmd_key); + w < width; w = (w + 8) & ~7) + (void) putchar ('\t'); + } + return NOTOK; + + default: + (void) sprintf (buf, "%s=%s", + rcmd_srch (n, tb_filters), + cp); + vec[i] = strdup(buf); + break; + } + } + return OK; +} + +/* ARGSUSED */ +static int showmsglist(msgl, id) +MsgList *msgl; +int id; +{ + MsgInfo *mip; + + indent = 0; + if (msgl == NULL || msgl -> msgs == NULL) + advise (NULLCP, "No messages found"); + else + for (mip = msgl -> msgs; mip; mip = mip -> next) + display_msg_info (mip); + free_MsgList (msgl); + return OK; +} + +int f_show (vec) +char **vec; +{ + char errbuf[BUFSIZ]; + char buffer[BUFSIZ]; + int pid; + + if (*++vec == NULLCP) { + if (getline ("expression: ", buffer) == NOTOK || + str2vec (buffer, vec) < 1) + return OK; + } + if (rebuild_list(vec) == NOTOK) + return OK; + msgtolist = "."; + if (initiate_op (console_fd, operation_Qmgr_readmsginfo, + vec, &pid, showmsglist, errbuf) == NOTOK) { + advise (NULLCP, "filter operation failed: %s", errbuf); + return NOTOK; + } + while (*vec) + free (*vec++); + if (result_op (console_fd, &pid, errbuf) == NOTOK) { + advise (NULLCP, "result_op: %s", errbuf); + return NOTOK; + } + return OK; +} diff --git a/Src/make b/Src/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Src/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/pptsapd/Makefile b/Src/pptsapd/Makefile new file mode 100644 index 0000000..cfc97ba --- /dev/null +++ b/Src/pptsapd/Makefile @@ -0,0 +1,106 @@ +# Makefile for the pp tsap daemon +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/pptsapd/RCS/Makefile,v 6.0 1991/12/18 20:27:31 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:27:31 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = pptsapd.c +OBJS = pptsapd.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xpptsapd + +pptsapd: xpptsapd +xpptsapd: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-dir $(CMDDIR)/pptsapd + +$(CMDDIR)/pptsapd: xpptsapd + -$(BACKUP) $@ zxpptsapd + rm -f $@ + $(INSTALL) xpptsapd $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "pptsapd installed normally"; echo "" + +xpptsapd-stat: pptsapd-stat.o + $(CC) $(LDFLAGS) -o $@ pptsapd-stat.o $(LIBPP) $(LIBSYS) +inst-dir: $(CMDDIR) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f xpptsapd zxpptsapd core a.out *.old *.BAK + +lint: l-pptsapd +l-pptsapd: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +pptsapd.o: pptsapd.c +pptsapd.o: ../../h/util.h +pptsapd.o: ../../h/config.h +pptsapd.o: ../../h/ll_log.h +pptsapd.o: ../../h/chan.h +pptsapd.o: ../../h/table.h +pptsapd.o: ../../h/list_bpt.h +pptsapd.o: pptsapd.c +pptsapd.o: ../../h/util.h +pptsapd.o: ../../h/config.h +pptsapd.o: ../../h/ll_log.h +pptsapd.o: ../../h/chan.h +pptsapd.o: ../../h/table.h +pptsapd.o: ../../h/list_bpt.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/pptsapd/make b/Src/pptsapd/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/pptsapd/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/pptsapd/pptsapd-stat.c b/Src/pptsapd/pptsapd-stat.c new file mode 100644 index 0000000..bac8eae --- /dev/null +++ b/Src/pptsapd/pptsapd-stat.c @@ -0,0 +1,444 @@ +/* pptsapd.c: pp version of the tsap daemon */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/pptsapd/RCS/pptsapd-stat.c,v 6.0 1991/12/18 20:27:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/pptsapd/RCS/pptsapd-stat.c,v 6.0 1991/12/18 20:27:31 jpo Rel $ + * + * $Log: pptsapd-stat.c,v $ + * Revision 6.0 1991/12/18 20:27:31 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "util.h" +#include "chan.h" +#include +#include +#include +#include +#include "sys.file.h" +#ifndef X_OK +#define X_OK 1 +#endif +#include +#include + +#include + +#ifdef TCP +#include +#endif +#ifdef X25 +#include +#endif +#ifdef CONS +#include +#endif +#ifdef TP4 +#include +#endif +#include +#include +#include + +/* */ + +static int debug = 1; +static int nbits = FD_SETSIZE; + +static char *myname = "pptsapd"; +static char myhost[BUFSIZ]; + +#define NTADDRS FD_SETSIZE + +static struct TSAPaddr *tz; + + +static void adios (), advise (); + +static char *getchanpgm (); +static void tsapd (); +static void ts_adios (); +static void ts_advise (); +static void arginit (); +static void envinit (); +static SFD childserver (); +static int childhit; + +extern int errno; +extern char *pptsapd_addr; +/* */ + +/* ARGSUSED */ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + int vecp; + char *vec[4]; + register struct NSAPaddr *na; + struct TSAPdisconnect tds; + register struct TSAPdisconnect *td = &tds; + + arginit (argv); + envinit (); + + for (na = tz -> ta_addrs; na < &tz->ta_addrs[tz->ta_naddr]; na++) { + switch (na -> na_type) { + case NA_TCP: + advise (LLOG_NOTICE, NULLCP, "listening on TCP %s %d", + na2str (na), ntohs (na -> na_port)); + break; + + case NA_X25: + advise (LLOG_NOTICE, NULLCP, "listening on X.25 %s %s", + na2str (na), + sel2str (na -> na_pid, na -> na_pidlen, 1)); + break; + + case NA_BRG: + advise (LLOG_NOTICE, NULLCP, + "listening on X.25 (BRIDGE) %s %s", na2str (na), + sel2str (na -> na_pid, na -> na_pidlen, 1)); + break; + + case NA_NSAP: + advise (LLOG_NOTICE, NULLCP, "listening on NS %s", + na2str (na)); + break; + + default: + adios (NULLCP, "unknown network type 0x%x", na -> na_type); + /* NOTREACHED */ + } + } + (void) TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, OK, td); + + (void) signal (SIGCHLD, childserver); + + if (tz -> ta_selectlen) + advise (LLOG_NOTICE, NULLCP, " %s", + sel2str (tz -> ta_selector, tz -> ta_selectlen, 1)); + if (TNetListen (tz, td) == NOTOK) + ts_adios (td, LLOG_EXCEPTIONS, "listen failed"); + + for (;;) { + childhit = 0; + if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, NOTOK, td) + == NOTOK) { + if (childhit == 0) + ts_advise (td, LLOG_EXCEPTIONS, "accept failed"); + continue; + } + + if (vecp <= 0) + continue; + + switch (TNetFork (vecp, vec, td)) { + case OK: + tsapd (vecp, vec); + exit (1); + /* NOTREACHED */ + + case NOTOK: + ts_advise (td, LLOG_EXCEPTIONS, "fork failed"); + default: + break; + } + } +} + +/* */ + +static char buffer1[4096]; +static char buffer2[32768]; + + +static void tsapd (vecp, vec) +int vecp; +char **vec; +{ + char buffer[BUFSIZ]; + char buf2[BUFSIZ]; + struct TSAPstart tss; + register struct TSAPstart *ts = &tss; + struct TSAPdisconnect tds; + register struct TSAPdisconnect *td = &tds; + CHAN *chan; + char *program; + +/* begin UGLY */ + (void) strcpy (buffer1, vec[1]); + (void) strcpy (buffer2, vec[2]); +/* end UGLY */ + + if (TInit (vecp, vec, ts, td) == NOTOK) { + ts_advise (td, LLOG_EXCEPTIONS, "T-CONNECT.INDICATION"); + return; + } + + advise (LLOG_NOTICE, NULLCP, + "T-CONNECT.INDICATION: <%d, <%s, %s>, <%s, %s>, %d, %d>", + ts -> ts_sd, + na2str (ts -> ts_calling.ta_addrs), + sel2str (ts -> ts_calling.ta_selector, + ts -> ts_calling.ta_selectlen, 1), + na2str (ts -> ts_called.ta_addrs), + sel2str (ts -> ts_called.ta_selector, + ts -> ts_called.ta_selectlen, 1), + ts -> ts_expedited, ts -> ts_tsdusize); + + if (ts -> ts_called.ta_selectlen == 0) { + (void) sprintf (buffer, "No TSEL present"); + goto out; + } + if ((chan = ch_nm2struct (ts -> ts_called.ta_selector)) == NULL) { + (void) sprintf (buffer, "PP Service %s not found", + ts -> ts_called.ta_selector); + goto out; + } + (void) strcpy (buf2, chan -> ch_progname); + vecp = sstr2arg (buf2, 20, vec, " \t"); + if (vecp <= 0) + goto out; + if ((program = getchanpgm (vec[0])) == NULLCP) { + (void) sprintf (buffer, "Can't locate program %s", vec[0]); + goto out; + } + vec[vecp] = buffer1; + vec[vecp+1] = buffer2; + vec[vecp+2] = NULLCP; + (void) execv (program, vec); + (void) sprintf (buffer, "unable to exec %s (%d args): %s", program, + vecp + 2, sys_errname (errno)); + PP_OPER (NULLCP, ("%s", buffer)); +out: ; + advise (LLOG_EXCEPTIONS, NULLCP, "%s", buffer); + if (strlen (buffer) >= TD_SIZE) + buffer[0] = NULL; + (void) TDiscRequest (ts -> ts_sd, buffer, strlen (buffer) + 1, td); + + exit (1); +} + +static char *getchanpgm (pgm) +char *pgm; +{ + char buf[BUFSIZ]; + static char name[BUFSIZ]; + extern char *cmddfldir, *chndfldir; + + getfpath (cmddfldir, chndfldir, buf); + getfpath (buf, pgm, name); + + return name; +} +/* */ + +static void ts_adios (td, code, event) +register struct TSAPdisconnect *td; +int code; +char *event; +{ + ts_advise (td, code, event); + + exit (1); +} + +static void ts_advise (td, code, event) +register struct TSAPdisconnect *td; +int code; +char *event; +{ + char buffer[BUFSIZ]; + + if (td -> td_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, td -> td_data); + else + (void) sprintf (buffer, "[%s]", TErrString (td -> td_reason)); + + advise (code, NULLCP, "%s: %s", event, buffer); +} + +/* */ + +static void arginit (vec) +char **vec; +{ + register char *ap; + + if (myname = rindex (*vec, '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = *vec; + + sys_init (myname); + isodetailor (myname, 0); + + (void) strcpy (myhost, TLocalHostName ()); + + tz = str2taddr (pptsapd_addr); + for (vec++; ap = *vec; vec++) { + if (*ap == '-') + switch (*++ap) { + case 'c': + if ((ap = *++vec) == NULL || *ap == '-') + adios (NULLCP, "Usage: %s -c address", myname); + tz = str2taddr (*vec); + break; + default: + adios (NULLCP, "Usage: %s [-c address]", myname); + } + } +} + +static void envinit () { + int i, + sd; + + nbits = getdtablesize (); + + if (!(debug = isatty (2))) { + for (i = 0; i < 5; i++) { + switch (fork ()) { + case NOTOK: + sleep (5); + continue; + + case OK: + break; + + default: + _exit (0); + } + break; + } + + (void) chdir ("/"); + + if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) + adios ("/dev/null", "unable to read"); + if (sd != 0) + (void) dup2 (sd, 0), (void) close (sd); + (void) dup2 (0, 1); + (void) dup2 (0, 2); + +#ifdef TIOCNOTTY + if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) { + (void) ioctl (sd, TIOCNOTTY, NULLCP); + (void) close (sd); + } +#else +#ifdef SYS5 + (void) setpgrp (); + (void) signal (SIGINT, SIG_IGN); + (void) signal (SIGQUIT, SIG_IGN); +#endif +#endif + } + else + pp_log_norm -> ll_stat |= LLOGTTY; + +#ifndef sun /* damn YP... */ + for (sd = 3; sd < nbits; sd++) + (void) close (sd); +#endif + + (void) signal (SIGPIPE, SIG_IGN); + + ll_hdinit (pp_log_norm, myname); + advise (LLOG_NOTICE, NULLCP, "starting"); +} + +/* ERRORS */ + +#ifndef lint +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS */ + +static void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + +static SFD childserver (sig, code, sc) +int sig; +long code; +struct sigcontext *sc; +{ + union wait status; + struct rusage rusage; + int pid; + + childhit = 1; + while ((pid = wait3 (&status, WNOHANG, &rusage)) > 0) { + PP_NOTICE (("Pid %d: Resource usage ut %d.%d st %d.%d mrss %d \ +ixrss %d idrss %d isrss %d minflt %d majflt %d nswap %d ib %d ob %d ms %d mr %d ns %d nvcs %d nics %d", + pid, + rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec, + rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec, + rusage.ru_maxrss, rusage.ru_ixrss, rusage.ru_idrss, + rusage.ru_isrss, rusage.ru_minflt, rusage.ru_majflt, + rusage.ru_nswap, rusage.ru_inblock, + rusage.ru_oublock, rusage.ru_msgsnd, + rusage.ru_msgrcv, rusage.ru_nsignals, + rusage.ru_nvcsw, rusage.ru_nivcsw)); + } +} + + diff --git a/Src/pptsapd/pptsapd.c b/Src/pptsapd/pptsapd.c new file mode 100644 index 0000000..c6a5d24 --- /dev/null +++ b/Src/pptsapd/pptsapd.c @@ -0,0 +1,411 @@ +/* pptsapd.c: pp version of the tsap daemon */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/pptsapd/RCS/pptsapd.c,v 6.0 1991/12/18 20:27:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/pptsapd/RCS/pptsapd.c,v 6.0 1991/12/18 20:27:31 jpo Rel $ + * + * $Log: pptsapd.c,v $ + * Revision 6.0 1991/12/18 20:27:31 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "util.h" +#include "chan.h" +#include +#include +#include +#include "sys.file.h" +#ifndef X_OK +#define X_OK 1 +#endif + +#include + +#ifdef TCP +#include +#endif +#ifdef X25 +#include +#endif +#ifdef CONS +#include +#endif +#ifdef TP4 +#include +#endif +#include +#include +#include + +/* */ + +static int debug = 1; +static int nbits = FD_SETSIZE; + +static char *myname = "pptsapd"; + +#define NTADDRS FD_SETSIZE + +static struct TSAPaddr *tz; + + +static void adios (), advise (); + +static char *getchanpgm (); +static void tsapd (); +static void ts_adios (); +static void ts_advise (); +static void arginit (); +static void envinit (); + +extern int errno; +extern char *pptsapd_addr, *pptailor; +/* */ + +/* ARGSUSED */ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + int vecp; + char *vec[4]; + register struct NSAPaddr *na; + struct TSAPdisconnect tds; + register struct TSAPdisconnect *td = &tds; + + arginit (argc, argv); + envinit (); + + for (na = tz -> ta_addrs; na < &tz->ta_addrs[tz->ta_naddr]; na++) { + switch (na -> na_type) { + case NA_TCP: + advise (LLOG_NOTICE, NULLCP, "listening on TCP %s %d", + na2str (na), ntohs (na -> na_port)); + break; + + case NA_X25: + advise (LLOG_NOTICE, NULLCP, "listening on X.25 %s %s", + na2str (na), + sel2str (na -> na_pid, na -> na_pidlen, 1)); + break; + + case NA_BRG: + advise (LLOG_NOTICE, NULLCP, + "listening on X.25 (BRIDGE) %s %s", na2str (na), + sel2str (na -> na_pid, na -> na_pidlen, 1)); + break; + + case NA_NSAP: + advise (LLOG_NOTICE, NULLCP, "listening on NS %s", + na2str (na)); + break; + + default: + adios (NULLCP, "unknown network type 0x%x", na -> na_type); + /* NOTREACHED */ + } + } + if (tz -> ta_selectlen) + advise (LLOG_NOTICE, NULLCP, " %s", + sel2str (tz -> ta_selector, tz -> ta_selectlen, 1)); + if (TNetListen (tz, td) == NOTOK) + ts_adios (td, LLOG_EXCEPTIONS, "listen failed"); + + for (;;) { + if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, NOTOK, td) + == NOTOK) { + ts_advise (td, LLOG_EXCEPTIONS, "accept failed"); + continue; + } + + if (vecp <= 0) + continue; + + switch (TNetFork (vecp, vec, td)) { + case OK: + tsapd (vecp, vec); + exit (1); + /* NOTREACHED */ + + case NOTOK: + ts_advise (td, LLOG_EXCEPTIONS, "fork failed"); + default: + break; + } + } +} + +/* */ + +static char buffer1[4096]; +static char buffer2[32768]; + + +static void tsapd (vecp, vec) +int vecp; +char **vec; +{ + char buffer[BUFSIZ]; + char buf2[BUFSIZ]; + struct TSAPstart tss; + register struct TSAPstart *ts = &tss; + struct TSAPdisconnect tds; + register struct TSAPdisconnect *td = &tds; + CHAN *chan; + char *program; + +/* begin UGLY */ + (void) strcpy (buffer1, vec[1]); + (void) strcpy (buffer2, vec[2]); +/* end UGLY */ + + if (TInit (vecp, vec, ts, td) == NOTOK) { + ts_advise (td, LLOG_EXCEPTIONS, "T-CONNECT.INDICATION"); + return; + } + + advise (LLOG_NOTICE, NULLCP, + "T-CONNECT.INDICATION: <%d, <%s, %s>, <%s, %s>, %d, %d>", + ts -> ts_sd, + na2str (ts -> ts_calling.ta_addrs), + sel2str (ts -> ts_calling.ta_selector, + ts -> ts_calling.ta_selectlen, 1), + na2str (ts -> ts_called.ta_addrs), + sel2str (ts -> ts_called.ta_selector, + ts -> ts_called.ta_selectlen, 1), + ts -> ts_expedited, ts -> ts_tsdusize); + + if (ts -> ts_called.ta_selectlen == 0) { + (void) sprintf (buffer, "No TSEL present"); + goto out; + } + if ((chan = ch_nm2struct (ts -> ts_called.ta_selector)) == NULL) { + (void) sprintf (buffer, "PP Service %s not found", + ts -> ts_called.ta_selector); + goto out; + } + (void) strcpy (buf2, chan -> ch_progname); + vecp = sstr2arg (buf2, 20, vec, " \t"); + if (vecp <= 0) + goto out; + if ((program = getchanpgm (vec[0])) == NULLCP) { + (void) sprintf (buffer, "Can't locate program %s", vec[0]); + goto out; + } + vec[vecp] = buffer1; + vec[vecp+1] = buffer2; + vec[vecp+2] = NULLCP; + (void) execv (program, vec); + (void) sprintf (buffer, "unable to exec %s (%d args): %s", program, + vecp + 2, sys_errname (errno)); + PP_OPER (NULLCP, ("%s", buffer)); +out: ; + advise (LLOG_EXCEPTIONS, NULLCP, "%s", buffer); + if ((int)strlen (buffer) >= TD_SIZE) + buffer[0] = NULL; + (void) TDiscRequest (ts -> ts_sd, buffer, strlen (buffer) + 1, td); + + exit (1); +} + +static char *getchanpgm (pgm) +char *pgm; +{ + char buf[BUFSIZ]; + static char name[BUFSIZ]; + extern char *cmddfldir, *chndfldir; + + getfpath (cmddfldir, chndfldir, buf); + getfpath (buf, pgm, name); + + return name; +} +/* */ + +static void ts_adios (td, code, event) +register struct TSAPdisconnect *td; +int code; +char *event; +{ + ts_advise (td, code, event); + + exit (1); +} + +static void ts_advise (td, code, event) +register struct TSAPdisconnect *td; +int code; +char *event; +{ + char buffer[BUFSIZ]; + + if (td -> td_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, td -> td_data); + else + (void) sprintf (buffer, "[%s]", TErrString (td -> td_reason)); + + advise (code, NULLCP, "%s: %s", event, buffer); +} + +/* */ + +static void arginit (argc, argv) +int argc; +char **argv; +{ + register char *ap; + int opt; + extern char *optarg; + extern int optind; + char *taddr = NULLCP; + + if (myname = rindex (*argv, '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = *argv; + + while ((opt = getopt (argc, argv, "c:t:")) != EOF) { + switch (opt) { + case 'c': + taddr = optarg; + break; + case 't': + pptailor = optarg; + break; + default: + adios (NULLCP, "Usage %s [-t tailor] [-c address]"); + break; + } + } + sys_init (myname); + + if (taddr == NULLCP) + taddr = pptsapd_addr; + if ((tz = str2taddr (taddr)) == NULLTA) + adios (NULLCP, "Unknown transport address '%s'", taddr); +} + +static void envinit () { + int i, + sd; + + nbits = getdtablesize (); + + if (!(debug = isatty (2))) { + for (i = 0; i < 5; i++) { + switch (fork ()) { + case NOTOK: + sleep (5); + continue; + + case OK: + break; + + default: + _exit (0); + } + break; + } + + (void) chdir ("/"); + + if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) + adios ("/dev/null", "unable to read"); + if (sd != 0) + (void) dup2 (sd, 0), (void) close (sd); + (void) dup2 (0, 1); + (void) dup2 (0, 2); + +#ifdef TIOCNOTTY + if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) { + (void) ioctl (sd, TIOCNOTTY, NULLCP); + (void) close (sd); + } +#else +#ifdef SYS5 + (void) setpgrp (); + (void) signal (SIGINT, SIG_IGN); + (void) signal (SIGQUIT, SIG_IGN); +#endif +#endif + } + else + pp_log_norm -> ll_stat |= LLOGTTY; + +#ifndef sun /* damn YP... */ + for (sd = 3; sd < nbits; sd++) + (void) close (sd); +#endif + + (void) signal (SIGPIPE, SIG_IGN); + + ll_hdinit (pp_log_norm, myname); + advise (LLOG_NOTICE, NULLCP, "starting"); +} + +/* ERRORS */ + +#ifndef lint +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS */ + +static void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif diff --git a/Src/qmgr/Makefile b/Src/qmgr/Makefile new file mode 100644 index 0000000..7f65d58 --- /dev/null +++ b/Src/qmgr/Makefile @@ -0,0 +1,307 @@ +# Makefile for qmgr - ros version +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/Makefile,v 6.0 1991/12/18 20:27:38 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:27:38 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = assoc.c chans.c misc.c qmgr.c ryresponder.c structs.c tables.c +OBJS = assoc.o chans.o misc.o qmgr.o ryresponder.o structs.o tables.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + + +HEADERS = ../../h +INCLUDE = -I$(HEADERS) +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) $(PROF) +LDFLAGS = $(LDOPTIONS) $(LLF) $(PROF) + +LLFLAGS = -bhuz -u $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln +PROGS = xqmgr + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# Queue manager +# +############################################################ + +inst-qmgr: $(CMDDIR)/qmgr + +$(CMDDIR)/qmgr: xqmgr + -$(BACKUP) $@ zxqmgr + rm -f $@ + $(INSTALL) xqmgr $@ + -$(CHOWN) $(PPUSER) $@ + -$(CHMOD) $(PGMPROT) $@ + -@ls -ls $@ + -@echo "Queue Manager installed normally"; echo "" + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +qmgr: xqmgr + +xqmgr: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +qmgr.o: ryresponder.h + +############################################################ +# +# Misc stuff +# +############################################################ + +install: inst-dir inst-qmgr + +tags: TAGS +TAGS: $(SRCS) + etags -t $(SRCS) + +inst-dir: $(CMDDIR) + + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old *.BAK $(PROGS) zx* + + +lint: l-qmgr + +l-qmgr: $(SRCS) true + $(LINT) $(LLFLAGS) -DPERFORMER -DINVOKER $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +assoc.o: assoc.c +assoc.o: ../../h/util.h +assoc.o: ../../h/config.h +assoc.o: ../../h/ll_log.h +assoc.o: ./types.h +assoc.o: ../../h/Qmgr-types.h +assoc.o: ../../h/table.h +assoc.o: ../../h/chan.h +assoc.o: ../../h/table.h +assoc.o: ../../h/list_bpt.h +assoc.o: ../../h/list_bpt.h +assoc.o: ../../h/list_rchan.h +assoc.o: ../../h/chan.h +assoc.o: ../../h/auth.h +assoc.o: ../../h/list_bpt.h +assoc.o: ../../h/mta.h +assoc.o: ../../h/adr.h +assoc.o: ../../h/list_rchan.h +assoc.o: ../../h/extension.h +assoc.o: ../../h/mta.h +assoc.o: ../../h/aparse.h +assoc.o: ../../h/ap.h +assoc.o: ../../h/util.h +assoc.o: ../../h/or.h +assoc.o: ../../h/chan.h +assoc.o: ../../h/auth.h +assoc.o: ../../h/list_rchan.h +assoc.o: ../../h/list_bpt.h +assoc.o: ../../h/qmgr.h +assoc.o: ../../h/Qmgr-types.h +assoc.o: ../../h/Qmgr-ops.h +chans.o: chans.c +chans.o: ./types.h +chans.o: ../../h/Qmgr-types.h +chans.o: ../../h/table.h +chans.o: ../../h/chan.h +chans.o: ../../h/table.h +chans.o: ../../h/list_bpt.h +chans.o: ../../h/list_bpt.h +chans.o: ../../h/list_rchan.h +chans.o: ../../h/chan.h +chans.o: ../../h/auth.h +chans.o: ../../h/list_bpt.h +chans.o: ../../h/mta.h +chans.o: ../../h/adr.h +chans.o: ../../h/list_rchan.h +chans.o: ../../h/extension.h +chans.o: ../../h/mta.h +chans.o: ../../h/aparse.h +chans.o: ../../h/ap.h +chans.o: ../../h/util.h +chans.o: ../../h/config.h +chans.o: ../../h/ll_log.h +chans.o: ../../h/or.h +chans.o: ../../h/chan.h +chans.o: ../../h/auth.h +chans.o: ../../h/list_rchan.h +chans.o: ../../h/list_bpt.h +chans.o: ../../h/Qmgr-ops.h +chans.o: ../../h/util.h +misc.o: misc.c +misc.o: ./types.h +misc.o: ../../h/Qmgr-types.h +misc.o: ../../h/table.h +misc.o: ../../h/chan.h +misc.o: ../../h/table.h +misc.o: ../../h/list_bpt.h +misc.o: ../../h/list_bpt.h +misc.o: ../../h/list_rchan.h +misc.o: ../../h/chan.h +misc.o: ../../h/auth.h +misc.o: ../../h/list_bpt.h +misc.o: ../../h/mta.h +misc.o: ../../h/adr.h +misc.o: ../../h/list_rchan.h +misc.o: ../../h/extension.h +misc.o: ../../h/mta.h +misc.o: ../../h/aparse.h +misc.o: ../../h/ap.h +misc.o: ../../h/util.h +misc.o: ../../h/config.h +misc.o: ../../h/ll_log.h +misc.o: ../../h/or.h +misc.o: ../../h/chan.h +misc.o: ../../h/auth.h +misc.o: ../../h/list_rchan.h +misc.o: ../../h/list_bpt.h +qmgr.o: qmgr.c +qmgr.o: ../../h/util.h +qmgr.o: ../../h/config.h +qmgr.o: ../../h/ll_log.h +qmgr.o: ./ryresponder.h +qmgr.o: ../../h/qmgr.h +qmgr.o: ../../h/Qmgr-types.h +qmgr.o: ../../h/Qmgr-ops.h +qmgr.o: ./types.h +qmgr.o: ../../h/Qmgr-types.h +qmgr.o: ../../h/table.h +qmgr.o: ../../h/chan.h +qmgr.o: ../../h/table.h +qmgr.o: ../../h/list_bpt.h +qmgr.o: ../../h/list_bpt.h +qmgr.o: ../../h/list_rchan.h +qmgr.o: ../../h/chan.h +qmgr.o: ../../h/auth.h +qmgr.o: ../../h/list_bpt.h +qmgr.o: ../../h/mta.h +qmgr.o: ../../h/adr.h +qmgr.o: ../../h/list_rchan.h +qmgr.o: ../../h/extension.h +qmgr.o: ../../h/mta.h +qmgr.o: ../../h/aparse.h +qmgr.o: ../../h/ap.h +qmgr.o: ../../h/util.h +qmgr.o: ../../h/or.h +qmgr.o: ../../h/chan.h +qmgr.o: ../../h/auth.h +qmgr.o: ../../h/list_rchan.h +qmgr.o: ../../h/list_bpt.h +ryresponder.o: ryresponder.c +ryresponder.o: ../../h/util.h +ryresponder.o: ../../h/config.h +ryresponder.o: ../../h/ll_log.h +ryresponder.o: ../../h/qmgr.h +ryresponder.o: ../../h/Qmgr-types.h +ryresponder.o: ../../h/Qmgr-ops.h +ryresponder.o: ./ryresponder.h +structs.o: structs.c +structs.o: ../../h/util.h +structs.o: ../../h/config.h +structs.o: ../../h/ll_log.h +structs.o: ./types.h +structs.o: ../../h/Qmgr-types.h +structs.o: ../../h/table.h +structs.o: ../../h/chan.h +structs.o: ../../h/table.h +structs.o: ../../h/list_bpt.h +structs.o: ../../h/list_bpt.h +structs.o: ../../h/list_rchan.h +structs.o: ../../h/chan.h +structs.o: ../../h/auth.h +structs.o: ../../h/list_bpt.h +structs.o: ../../h/mta.h +structs.o: ../../h/adr.h +structs.o: ../../h/list_rchan.h +structs.o: ../../h/extension.h +structs.o: ../../h/mta.h +structs.o: ../../h/aparse.h +structs.o: ../../h/ap.h +structs.o: ../../h/util.h +structs.o: ../../h/or.h +structs.o: ../../h/chan.h +structs.o: ../../h/auth.h +structs.o: ../../h/list_rchan.h +structs.o: ../../h/list_bpt.h +structs.o: ../../h/Qmgr-ops.h +tables.o: tables.c +tables.o: ../../h/util.h +tables.o: ../../h/config.h +tables.o: ../../h/ll_log.h +tables.o: ./types.h +tables.o: ../../h/Qmgr-types.h +tables.o: ../../h/table.h +tables.o: ../../h/chan.h +tables.o: ../../h/table.h +tables.o: ../../h/list_bpt.h +tables.o: ../../h/list_bpt.h +tables.o: ../../h/list_rchan.h +tables.o: ../../h/chan.h +tables.o: ../../h/auth.h +tables.o: ../../h/list_bpt.h +tables.o: ../../h/mta.h +tables.o: ../../h/adr.h +tables.o: ../../h/list_rchan.h +tables.o: ../../h/extension.h +tables.o: ../../h/mta.h +tables.o: ../../h/aparse.h +tables.o: ../../h/ap.h +tables.o: ../../h/util.h +tables.o: ../../h/or.h +tables.o: ../../h/chan.h +tables.o: ../../h/auth.h +tables.o: ../../h/list_rchan.h +tables.o: ../../h/list_bpt.h +tables.o: ../../h/qmgr.h +tables.o: ../../h/Qmgr-types.h +tables.o: ../../h/Qmgr-ops.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/qmgr/assoc.c b/Src/qmgr/assoc.c new file mode 100644 index 0000000..a3df273 --- /dev/null +++ b/Src/qmgr/assoc.c @@ -0,0 +1,178 @@ +/* assoc.c: association functions for clients */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/assoc.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/assoc.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: assoc.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "types.h" +#include "qmgr.h" + +int assoc_start (myservice, fd) +char *myservice; +int *fd; +{ + extern char *pptsapd_addr; + static struct PSAPctxlist pcs; + struct SSAPref sfs; + register struct SSAPref *sf; + struct TSAPaddr *ta; + static struct PSAPaddr pas, *pa; + static OID ctx, + pci; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + if (pa == NULLPA) { + if ((pa = str2paddr (pptsapd_addr)) == NULLPA) { + PP_LOG (LLOG_EXCEPTIONS, + ("Can't translate %s", + pptsapd_addr)); + return NOTOK; + } + pas = *pa; + pa = &pas; + } + ta = &pa -> pa_addr.sa_addr; + ta -> ta_selectlen = str2sel (myservice, 1, ta -> ta_selector, TSSIZE); + + if (ctx == NULLOID && (ctx = oid_cpy (CHANNEL_AC)) == NULLOID) { + PP_LOG (LLOG_EXCEPTIONS, ("out of memory")); + return NOTOK; + } + if (pci == NULLOID) { + if ((pci = oid_cpy (CHANNEL_PCI)) == NULLOID) { + PP_LOG (LLOG_EXCEPTIONS, ("out of memory")); + return NOTOK; + } + } + pcs.pc_nctx = 1; + pcs.pc_ctx[0].pc_id = 1; + pcs.pc_ctx[0].pc_asn = pci; + pcs.pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (PLocalHostName ())) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + switch (result = AcAsynAssocRequest (ctx, NULLAEI, NULLAEI, NULLPA, + pa, &pcs, NULLOID, 0, + ROS_MYREQUIRE, + SERIAL_NONE, 0, sf, NULLPEP, 0, + NULLQOS, acc, aci, 1)) { + case NOTOK: + acs_advise (aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; + case CONNECTING_1: + case CONNECTING_2: + *fd = acc -> acc_sd; + ACCFREE (acc); + PP_TRACE (("Association initiated")); + return result; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, + ("Association rejected: [%s]", + AcErrString (acc -> acc_result))); + return NOTOK; + } + *fd = acc -> acc_sd; + ACCFREE (acc); + PP_TRACE (("Association established")); + if (RoSetService (*fd, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + return NOTOK; + } + PP_TRACE (("Service set")); + return DONE; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Bad response from AcAsynAssocRequest")); + return NOTOK; + } +} + +int acsap_retry (fd) +int fd; +{ + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int result; + + PP_TRACE (("acsap_retry(%d)", fd)); + switch (result = AcAsynRetryRequest (fd, acc, aci)) { + case CONNECTING_1: + case CONNECTING_2: + ACCFREE (acc); + return result; + case NOTOK: + acs_advise (aca, "A-ASSOCIATE.REQUEST"); + return NOTOK; + case DONE: + if (acc -> acc_result != ACS_ACCEPT) { + PP_LOG (LLOG_EXCEPTIONS, + ("Association Rejected: [%s]", + AcErrString (acc -> acc_result))); + return NOTOK; + } + ACCFREE (acc); + if (RoSetService (fd, RoPService, roi) == NOTOK) { + ros_advise (rop, "set RO/PS fails"); + return NOTOK; + } + return DONE; + default: + adios (NULLCP, "Bad response from AcAsynRetryRequest"); + return NOTOK; + } +} + +int assoc_release (sd) +int sd; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) { + acs_advise (aca, "A-RELEASE.REQUEST"); + return DONE; + } + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + PP_NOTICE (("Release rejected by peer: %d", + acr -> acr_reason)); + } + + ACRFREE (acr); + PP_TRACE (("Association released")); + + return DONE; +} diff --git a/Src/qmgr/chans.c b/Src/qmgr/chans.c new file mode 100644 index 0000000..ffcce9a --- /dev/null +++ b/Src/qmgr/chans.c @@ -0,0 +1,2365 @@ +/* chans.c: channel specific stuff for the qmgr */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/chans.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/chans.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: chans.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include +#include "types.h" +#include "Qmgr-ops.h" +#include "util.h" + +extern struct Mtalist *findmtalist (); +extern MsgStruct *newmsgstruct (); +extern MsgStruct *find_msg (); +extern Chanlist *findchanlist (); +extern Mlist *findmtamsg (); + +extern int warn_number; + +static int cb_once_only = 0; +static Connblk cbqueue; +static Connblk *CHead = &cbqueue; +static char *cb2name (); +static char *cb_print (); +static int cb_count = 0; +static int nspecials = 0; +static int demand_chan = 0; + +Chanlist _runq, *runq; +void addtorunq (), delfromrunq (); + +struct eventqueue { + struct eventqueue *ev_forw; + struct eventqueue *ev_back; + + time_t ev_time; + Connblk *ev_conn; + enum cb_type ev_type; + Chanlist *ev_clp; +}; + +struct stats stats; + +static struct eventqueue evqueue; +static struct eventqueue *EHead = &evqueue; +static int ev_count = 0; +static struct eventqueue *newevblk (); +static void freevblk (), init_events (); +static void do_event (); +static void channel_event (); +static void special_event (); +static void restart (); +#define NULLEV ((struct eventqueue *)0) + +static int runnable (); +static int invoke (); +static int timeout_proc (); +static int channel_ttl (); +static int expiremsg (), warnmsg (); +/* static void setfds (); */ +static void getresponse (); +static void start_timer (); +extern void kill_msg (); + +extern Mlist *nextmsg (); + +extern fd_set perf_rfds, perf_wfds; +extern int perf_nfds; +extern int delaytime; +extern int nodisablemsgclean; + +void review_channels (); +void investigate_chan (); +void investigate_mta (); +void delay_channel (); +void cleanup_conn (); +void cache_clear (), clear_msgcache (); +void cache_inc (), msgcache_inc (); +void freems (); +void insertinchan (); +void insertindelchan (); +void insertindrchan (); +void sort_chans(); +void zapmsg (); + +time_t msgmincache (); +int nchansrunning = 0; +static int timer_running = 0; +static int high_wtmk, low_wtmk; + +static int do_processmessage (), processmessage_result (), + processmessage_error (), do_quit (); +static int do_initchannel (), channelinit_result (); +static int do_readqueue (), readqueue_result (); +static int general_error (); +static time_t nextchantime; +static int rqueue; +static int noperations; + +struct client_dispatch { + char *ds_name; + int ds_operation; + + IFP ds_argument; + modtyp *ds_fr_mod; + int ds_fr_index; + IFP ds_result; + IFP ds_error; + + char *ds_help; +}; + +static struct client_dispatch dis[] = { +#define DIS_PROC 0 +{ + "processmessage", operation_Qmgr_processmessage, + do_processmessage, &_ZQmgr_mod, _ZProcMsgQmgr, + processmessage_result, processmessage_error, + "Process some messages" +}, +#define DIS_INIT 1 +{ + "channelInitialise", operation_Qmgr_channelInitialise, + do_initchannel, &_ZQmgr_mod, _ZChannelQmgr, + channelinit_result, general_error, + "Initialise a channel" +}, +#define DIS_QUIT 2 +{ + "quit", 0, do_quit, NULL, 0, NULLIFP, NULLIFP, + "terminate the association" +}, +#define DIS_READQ 3 +{ + "readqueue", operation_Qmgr_readqueue, + do_readqueue, &_ZQmgr_mod, _ZPseudo_readqueueQmgr, + readqueue_result, general_error, + "Load up the queue" +}, + NULL +}; + +static void create_chan (chan) +CHAN *chan; +{ + Chanlist *clp; + extern int chan_state; + + PP_TRACE (("create_chan (%s)", chan -> ch_name)); + + if (nchanlist == 0) + chan_list = (Chanlist **) malloc (sizeof (Chanlist *)); + else + chan_list = (Chanlist **) realloc ((char *)chan_list, + (unsigned)(nchanlist + 1) + * sizeof (Chanlist *)); + chan_list[nchanlist] = clp = (Chanlist *) calloc (1, sizeof (Chanlist)); + clp -> channame = chan -> ch_name; + clp -> chan = chan; + clp -> mtas = (struct Mtalist *) calloc (1, sizeof (Mtalist)); + clp -> mtas -> mta_back = clp -> mtas -> mta_forw = clp -> mtas; + clp -> chan_enabled = chan_state; + clp -> mta_hash = NULL; + switch (chan -> ch_chan_type) { + case CH_DELETE: + delete_chan = clp; + break; + + case CH_QMGR_LOAD: + clp -> chan_special = 1; + loader_chan = clp; + break; + + case CH_DEBRIS: + clp -> chan_special = 1; + trash_chan = clp; + break; + + case CH_TIMEOUT: + timeout_chan = clp; + break; + case CH_WARNING: + warn_chan = clp; + break; + + case CH_OUT: + case CH_BOTH: + if (chan -> ch_sort[0] == 0) + chan -> ch_sort[0] = CH_SORT_MTA; + break; + } + if (chan -> ch_sort[0] == 0) + chan -> ch_sort[0] = CH_SORT_NONE; + if (chan -> ch_sort[0] != CH_SORT_NONE) + clp -> mta_hash = (Mtalist **) + calloc (MTA_HASHSIZE, sizeof (*clp->mta_hash)); + if (clp -> chan_special) + addtorunq (clp); + nchanlist ++; +} + +void init_chans () +{ + int i; + + PP_TRACE (("init_chans ()")); + + runq = &_runq; + runq -> cl_forw = runq -> cl_back = runq; + + for (i = 0; ch_all[i]; i++) + create_chan (ch_all[i]); + init_events (); + stats.boottime = current_time; +} + +/* ARGSUSED */ +int chan_lose (fd, acf) +int fd; +struct AcSAPfinish *acf; +{ + Connblk *cb; + + PP_TRACE (("chan_lose (%d)", fd)); + if ((cb = findcblk (fd)) == NULLCB) + return ACS_ACCEPT; + /* restore the state */ + delay_channel (cb); + if (fd != NOTOK) { + FD_CLR (fd, &perf_rfds); + FD_CLR (fd, &perf_wfds); + } + cb -> cb_fd = NOTOK; + cleanup_conn (cb); + + return ACS_ACCEPT; +} + +void start_specials () +{ + Connblk *cb; + + PP_TRACE (("start_specials ()")); + + if (loader_chan == NULLCHANLIST) + PP_LOG (LLOG_EXCEPTIONS, + ("No loading channel specified")); + else { + loader_chan -> chan_update = 1; + } + + if (trash_chan == NULLCHANLIST) + PP_LOG (LLOG_EXCEPTIONS, + ("No debris channel specified")); + else { + cache_inc (&trash_chan -> cache, + random() % debris_time); + trash_chan -> chan_update = 1; + } + if (timeout_chan == NULLCHANLIST) + PP_LOG (LLOG_EXCEPTIONS, + ("No timeout channel specified")); + else { + if (warn_chan == NULLCHANLIST) + PP_LOG (LLOG_EXCEPTIONS, + ("No warning channel specified")); + cb = newcblk (cb_timer); + cb -> cb_proc = timeout_proc; + cb -> cb_reload = timeout_time; + (void) newevblk (NULLCHANLIST, cb, cb_timer, + random () % timeout_time); + } +} + +#define LOAD_UPDATE_INTERVAL 15 +#define L1_DECAY (0.9) +#define L2_DECAY (0.92) + +static void do_load_avg () +{ + static time_t lastload; + static int last_msg_out, last_msg_in; + int mo, mi; + static int count = 0; + + if (lastload == 0) + lastload = current_time; + if (current_time - lastload < LOAD_UPDATE_INTERVAL) { + stats.runnable_chans = L1_DECAY * stats.runnable_chans + + (1.0 - L1_DECAY) * rqueue; + return; + } + mo = stats.n_messages_out - last_msg_out; + mi = stats.n_messages_in - last_msg_in; + if (mi < 0 || mo < 0) + PP_LOG (LLOG_EXCEPTIONS, ("Negative stats %d & %d", + mi, mo)); + + while (lastload < current_time) { + stats.runnable_chans = L1_DECAY * stats.runnable_chans + + (1.0 - L1_DECAY) * rqueue; + stats.ops_sec = L2_DECAY * stats.ops_sec + + (1.0 - L2_DECAY) * + ((double)noperations / + (double)LOAD_UPDATE_INTERVAL); + lastload += LOAD_UPDATE_INTERVAL; + stats.msg_sec_in = L2_DECAY * stats.msg_sec_in + + (1.0 - L2_DECAY) * ((double)mi/ + (double)LOAD_UPDATE_INTERVAL); + stats.msg_sec_out = L2_DECAY * stats.msg_sec_out + + (1.0 - L2_DECAY) * ((double)mo/ + (double)LOAD_UPDATE_INTERVAL); + } + last_msg_in = stats.n_messages_in; + last_msg_out = stats.n_messages_out; + + noperations = 0; + PP_TRACE (("Load averages rq %g, ops %g mi %g mo %g", + stats.runnable_chans, stats.ops_sec, + stats.msg_sec_in, stats.msg_sec_out)); + lastload = current_time; + if (count++ > 100) { + count = 0; + PP_NOTICE (("STATS: m-in=%d m-out=%d, a-in=%d a-out=%d os=%g rc=%g mis=%g mos=%g %.22s", + stats.n_messages_in, stats.n_messages_out, + stats.n_addr_in, stats.n_addr_out, + stats.ops_sec, stats.runnable_chans, + stats.msg_sec_in, stats.msg_sec_out, + ctime (&stats.boottime))); + } + ll_close (pp_log_norm); +} + +void schedule () +{ + struct eventqueue *ev; + static time_t lasttime; + time_t delta; + + PP_TRACE (("schedule ()")); + + if (opmode && nchansrunning == 0) { + if (opmode == OP_SHUTDOWN) + exit (0); + if (opmode == OP_RESTART) + restart (); + } +#ifdef notdef + if (countdown -- < 0) { + countdown = 50; + sort_chans (); + } +#endif + + if (lasttime == 0) + lasttime = current_time; + delta = current_time - lasttime; + + review_channels (current_time); + do_load_avg (); + + if (EHead -> ev_forw != EHead) + EHead -> ev_forw -> ev_time -= delta; + + + for (ev = EHead -> ev_forw; ev != EHead;) { + struct eventqueue *ev2 = ev -> ev_forw; + + if (ev -> ev_time <= 0) { + do_event (ev); + freevblk (ev); + } + else + break; + ev = ev2; + } + review_channels (current_time); + + if (EHead -> ev_forw == EHead ) + delaytime = nextchantime; + else { + PP_DBG (("event head time = %d delta = %d", + EHead -> ev_forw -> ev_time, delta)); + delaytime = max(0, EHead -> ev_forw -> ev_time); + } + if (nextchantime < delaytime) + delaytime = nextchantime; + + PP_TRACE (("delaytime == %d", delaytime)); + lasttime = current_time; + if (opmode && nchansrunning == 0) { + if (opmode == OP_SHUTDOWN) + exit (0); + if (opmode == OP_RESTART) + restart (); + } +} + +void addtorunq (clp) +Chanlist *clp; +{ + Chanlist *clp2; + + PP_TRACE (("adding channel %s to runq", clp -> channame)); + for (clp2 = runq -> cl_forw; clp2 != runq; clp2 = clp2 -> cl_forw) + if (clp2 == clp) { + PP_LOG (LLOG_EXCEPTIONS, + ("channel %s already on runq", + clp -> channame)); + return; + } + insque (clp, runq -> cl_forw); +} + +static void prunq () +{ + Chanlist *clp; + + for (clp = runq -> cl_forw; clp != runq; clp = clp -> cl_forw) + PP_TRACE (("runq: %s", clp -> channame)); +} + + +void delfromrunq (clp) +Chanlist *clp; +{ + PP_TRACE (("removeing channel %s from runq", clp -> channame)); + + if (clp -> cl_forw == NULLCHANLIST || + clp -> cl_back == NULLCHANLIST) { + PP_LOG(LLOG_EXCEPTIONS, + ("chan %s not on runq", clp -> channame)); + return; + } + if (clp -> nmtas != 0) { + PP_LOG (LLOG_EXCEPTIONS, ("nmtas not zero for %s", + clp -> channame)); + return; + } + if (clp -> mtas -> mta_back != clp -> mtas) { + PP_LOG (LLOG_EXCEPTIONS, ("Still mtas on channel")); + clp -> chan_update = 1; + return; + } + if (clp -> chan_special) { + PP_LOG (LLOG_EXCEPTIONS, + ("Trying to remove special chan %s from runq", + clp -> channame)); + return; + } + remque (clp); + clp -> cl_forw = clp -> cl_back = NULLCHANLIST; +} + + +static void restart () +{ + int n, i; + extern char *cmddfldir, *dupfpath (); + char *path; + char *argv[20]; + int argc; + char nbuf[20]; + extern int chan_state; + + PP_TRACE (("restart ()")); + + while (CHead -> cb_forw != CHead) + freecblk (CHead -> cb_forw); /* shut down connecitons */ + + n = getdtablesize (); + + i = (isatty(2) ? 3 : 0); + for (; i <= n; i++) + (void) close (i); +#ifdef notdef + for (i = 0; i < NSIG; i++) + (void) signal (i, SIG_DFL); +#endif + argc = 0; + argv[argc++] = myname; + if (maxchansrunning != MAXCHANSRUNNING) { + argv[argc++] = "-m"; + (void) sprintf (nbuf, "%d", maxchansrunning); + argv[argc++] = strdup (nbuf); + } + if (load_time != LOAD_RETRY_INTERVAL) { + argv[argc++] = "-l"; + (void) sprintf (nbuf, "%d", load_time/60/60); + argv[argc++] = strdup (nbuf); + } + if (debris_time != TRASH_RETRY_INTERVAL) { + argv[argc++] = "-d"; + (void) sprintf (nbuf, "%d", debris_time/60/60); + argv[argc++] = strdup (nbuf); + } + if (cache_time != CACHE_TIME) { + argv[argc++] = "-c"; + (void) sprintf (nbuf, "%d", cache_time); + argv[argc++] = strdup (nbuf); + } + if (timeout_time != TIMEOUT_RETRY_INTERVAL) { + argv[argc++] = "-t"; + (void) sprintf (nbuf, "%d", timeout_time / 60 / 60); + argv[argc++] = strdup (nbuf); + } + if (chan_state == 0) + argv[argc++] = "-D"; + argv[argc] = NULLCP; + path = dupfpath (cmddfldir, myname); + (void) execv (path, argv); + (void) execv (myname, argv); + _exit(1); +} + +void review_channels (now) +time_t now; +{ + Chanlist *clp; + int ndiffchans = 0; + time_t tdiff; + + PP_TRACE (("review_channels")); + nextchantime = MAX_SLEEP; + rqueue = nchansrunning; + demand_chan = 0; + + /* first find how many different channels are running */ + for (clp = runq -> cl_forw; clp != runq; clp = clp -> cl_forw) + if (clp -> nactive > 0) + ndiffchans ++; + + /* high watermark is the share of the channels allowed each */ + high_wtmk = max(1, (maxchansrunning-1)/(ndiffchans ? ndiffchans : 1)); + /* low water mark - each channel allowed at least this */ + low_wtmk = max(1, high_wtmk/2); + + for (clp = runq -> cl_forw; clp != runq; clp = clp -> cl_forw) { + switch (runnable (clp, now)) { + case OK: + (void) newevblk (clp, NULLCB, + clp-> chan_special ? + cb_special : cb_channel, + (time_t)0); + rqueue ++; + break; + case DONE: + /* + * If it is allowed more - but can't get one + * it can demand its fair share. + * In this case we have to reasses the high + * water mark. + */ + if (clp -> nactive < low_wtmk) { + if (clp -> nactive == 0) + ndiffchans ++; + demand_chan = 1; + PP_TRACE(("%s demands a channel", + clp -> channame)); + } + rqueue ++; + break; + case NOTOK: + tdiff = clp -> nextevent - current_time; + if (tdiff > 0 && tdiff < nextchantime) + nextchantime = tdiff; + break; + } + } + + high_wtmk = max(1, maxchansrunning/(ndiffchans ? ndiffchans : 1)); + PP_TRACE (("review channels lw=%d hw=%d nd=%d", + low_wtmk, high_wtmk, ndiffchans)); +} + + +static int runnable (clp, now) +Chanlist *clp; +time_t now; +{ + PP_TRACE (("runnable %s?", clp -> channame)); + if (opmode) + return NOTOK; + if (clp -> chan_update && clp -> nactive == 0) { + investigate_chan (clp, now); + clp -> chan_update = 0; + } + if (clp -> chan_special == 0 && clp -> num_msgs <= 0 + && clp -> num_drs <= 0) /* special channel with things to do */ + return NOTOK; + if (clp -> chan_enabled == 0) /* channel switched off */ + return NOTOK; + if (clp -> cache.cachetime > now || + clp -> nextevent > now ) /* not time yet */ + return NOTOK; + if (clp -> chan_special && nspecials > 0) + return NOTOK; + if (clp -> chan -> ch_maxproc > 0 && + clp -> nactive >= clp -> chan -> ch_maxproc) + return NOTOK; + if (clp -> nactive <= 0) { + if (nchansrunning >= maxchansrunning) /* too many running already */ + return DONE; + + return OK; /* None running - start one */ + } +/* + * So there is a channel already running: + * OK - should we start more - to do this we need the following + * o More mtas ready than chans currently running + * o We started the last channel more than a 15 secs ago + * + * o We aren't consuming all the channels allowed + * o More messages than channels * 5 OR last time we started was ages ago + */ + if (clp -> nmtas <= clp -> nactive + || clp -> laststart + 15 > current_time) + return NOTOK; + + + /* ok - we ought to start a new channel - but should we? */ + + if (clp -> nactive >= max(1,maxchansrunning-1)) + return DONE; /* Would like to - but out of resources */ + + if ((clp -> num_msgs + clp -> num_drs) > clp -> nactive * 5 + || clp -> laststart + 60*5 < current_time) { + Mtalist *mlp = NULLMTALIST; + + if (nextmsg (clp, &mlp, 0, 0) == NULL) + return NOTOK; /* nope all locked */ + PP_TRACE (("Can start a new chan on %s", mlp -> mtaname)); + if (nchansrunning >= maxchansrunning) /* too many running already */ + return DONE; + return OK; + } + /* No - this channel is just not ready to start another one */ + return NOTOK; +} + +static void do_event (ev) +struct eventqueue *ev; +{ + Connblk *cb; + + PP_TRACE (("do_event ()")); + + if ((cb = ev -> ev_conn) == NULLCB) { + ev -> ev_conn = cb = newcblk (ev -> ev_type); + cb -> cb_clp = ev -> ev_clp; + } + + switch (cb -> cb_type) { + case cb_channel: + channel_event (ev); + break; + + case cb_special: + special_event (ev); + break; + + case cb_timer: + PP_TRACE (("Timeout event")); + if (cb -> cb_proc) + (*cb -> cb_proc)(); + if (cb -> cb_reload) + (void) newevblk (NULLCHANLIST, cb, cb_timer, + cb -> cb_reload); + else freecblk (cb); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown type %d", cb -> cb_type)); + break; + } +} + +static int chan_still_ready (cb) +Connblk *cb; +{ + /* should we continue to process? */ + + /* don't process if: + * - channel disabled + * - we are in some global shutdown + * - we are being greedy & others are suffering + */ + if (cb -> cb_clp -> chan_enabled == 0 || opmode || + (demand_chan && cb -> cb_nops > MIN_OPS && + cb -> cb_clp -> nactive > high_wtmk)) { + if (demand_chan) { + PP_TRACE (("Closing down %s due to demand h=%d l=%d", + cb_print (cb), high_wtmk, low_wtmk)); + if (cb -> cb_clp -> cache.cachetime < + current_time) + cb -> cb_clp -> cache.cachetime = + current_time + 15; + /* we are going to satisfy request */ + demand_chan = 0; + } + return NOTOK; + } + /* + * hmm - this channel is not going so well - perhaps we should + * not try so hard. E.g. close down this channel if there is more + * than one running anyway. + */ + if (cb -> cb_clp -> error_count > 5) { + cb -> cb_clp -> error_count = 0; + if (cb -> cb_clp -> cache.cachetime < current_time) + cache_inc (&cb -> cb_clp -> cache, cache_time); + if (cb -> cb_clp -> nactive > 1) { + PP_NOTICE (("Closing channel %s as things aren't going very well", + cb_print(cb))); + return NOTOK; + } + } + /* + * OK - grab the next message and GO. + */ + if (cb -> cb_ml == NULL && + (cb -> cb_ml = nextmsg (cb -> cb_clp, + &cb -> cb_mlp, 1, 0)) == NULL) { + + if (cb -> cb_clp -> cache.cachetime < current_time) + /* stop it thrashing... */ + cb -> cb_clp -> cache.cachetime = + current_time + 15; + return NOTOK; + } + return OK; +} + +static void channel_event (ev) +struct eventqueue *ev; +{ + Connblk *cb = ev -> ev_conn; + Mlist *ml; + Chanlist *clp; + + PP_TRACE (("channel_event ()")); + + if ((clp = ev -> ev_clp) == NULLCHANLIST) + PP_TRACE (("No chanlist of event queue")); + + switch (cb -> cb_state) { + case cb_idle: + if (runnable (clp, current_time) != OK) { + freecblk (cb); + return; + } + if ((ml = nextmsg (cb -> cb_clp, &cb -> cb_mlp, 1, 0)) == NULL) { + clp -> chan_update = 1; + freecblk (cb); + return; + } + cb -> cb_ml = ml; + cb -> cb_clp -> lastattempt = current_time; + cb -> cb_clp -> laststart = current_time; + switch (start_async (cb, clp -> channame)) { + case NOTOK: + cache_inc (&clp -> cache, cache_time); + clp -> nextevent = clp -> cache.cachetime; + cleanup_conn (cb); + break; + + case DONE: + (void) newevblk (cb -> cb_clp, cb, + cb -> cb_type, (time_t)0); + /* and fall */ + case OK: + clp -> nactive ++; + nchansrunning ++; + break; + } + break; + + case cb_conn_established: + (void) chan_invoke (cb, DIS_INIT, + (caddr_t *) &clp -> channame); + break; + + case cb_conn_request1: + case cb_conn_request2: + case cb_init_sent: + case cb_proc_sent: + case cb_close_sent: + PP_TRACE (("Shouldn't be in this state - %d", + cb -> cb_state)); + break; + + case cb_active: + if (chan_still_ready(cb) == NOTOK) { + (void) chan_invoke (cb, DIS_QUIT, + (caddr_t *)0); + } + else { + (void) chan_invoke (cb, DIS_PROC, (caddr_t *)0); + } + break; + } +} + +static void special_event (ev) +struct eventqueue *ev; +{ + Connblk *cb = ev -> ev_conn; + Chanlist *clp = ev -> ev_clp; + + PP_TRACE (("special_event (%s)", cb_print (cb))); + switch (cb -> cb_state) { + case cb_idle: + if (runnable (clp, current_time) != OK) { + freecblk (cb); + return; + } + clp -> lastattempt = current_time; + clp -> laststart = current_time; + + switch (start_async (cb, clp -> channame)) { + case NOTOK: + PP_LOG (LLOG_EXCEPTIONS, + ("Can't start special channel %s", + clp -> channame)); + cache_inc (&clp -> cache, (time_t)60); + (void) newevblk (NULLCHANLIST, NULLCB, cb_timer, + (time_t) 60); + clp -> chan_update = 1; + freecblk (cb); + break; + + case DONE: + (void) newevblk (clp, cb, cb -> cb_type, + (time_t)0); + case OK: + nspecials ++; + clp -> nactive ++; + nchansrunning ++; + if (clp -> chan -> ch_chan_type == CH_QMGR_LOAD && + nodisablemsgclean == 0 && + delete_chan -> chan_enabled) { + delete_chan -> chan_enabled = 0; + delete_chan -> chan_syssusp = 1; + } + break; + } + break; + + case cb_active: + switch (clp -> chan -> ch_chan_type) { + case CH_QMGR_LOAD: + if (cb -> cb_clp -> chan_enabled == 0 || opmode) { + (void) chan_invoke (cb, DIS_QUIT, (caddr_t*)0); + clp -> cache.cachetime = + current_time + 60; + } + else + (void) chan_invoke (cb, DIS_READQ, + (caddr_t *)0); + break; + case CH_DEBRIS: + (void) chan_invoke (cb, DIS_QUIT, (caddr_t *)0); + clp -> lastsuccess = current_time; + clp -> cache.cachetime = current_time + debris_time; + break; + case CH_TIMEOUT: + (void) chan_invoke (cb, DIS_QUIT, (caddr_t *)0); + break; + } + clp -> chan_update = 1; + break; + + case cb_conn_established: + switch (clp -> chan -> ch_chan_type) { + case CH_QMGR_LOAD: + PP_TRACE (("start loading")); + (void) chan_invoke (cb, DIS_READQ, (caddr_t *)0); + break; + case CH_DEBRIS: + PP_TRACE (("start debris collection")); + (void) chan_invoke (cb, DIS_INIT, + (caddr_t *)&clp -> channame); + break; + case CH_TIMEOUT: + break; + } + break; + case cb_finished: + switch (clp -> chan -> ch_chan_type) { + case CH_QMGR_LOAD: + (void) chan_invoke (cb, DIS_QUIT, (caddr_t *)0); + clp -> cache.cachetime = current_time + load_time; + if (delete_chan -> chan_enabled == 0 && + delete_chan -> chan_syssusp == 1) { + delete_chan -> chan_enabled = 1; + delete_chan -> chan_syssusp = 0; + delete_chan -> chan_update = 1; + } + clp -> chan_update = 1; + break; + default: + PP_LOG (LLOG_EXCEPTIONS, ("Bad state in special %d", + cb -> cb_state)); + break; + } + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Bad state in special %d", + cb -> cb_state)); + break; + } +} + +int start_async (cb, title) +Connblk *cb; +char *title; +{ + int sd; + int result; + + PP_NOTICE (("Starting channel %s %s", title, cb_print(cb))); + switch(result = assoc_start (title, &sd)) { + case NOTOK: + PP_LOG (LLOG_EXCEPTIONS, ("Can't start channel %s", + title)); + return NOTOK; + + case CONNECTING_1: + cb -> cb_state = cb_conn_request1; + cb -> cb_fd = sd; + FD_CLR (sd, &perf_rfds); + FD_SET (sd, &perf_wfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + break; + + case CONNECTING_2: + cb -> cb_state = cb_conn_request2; + cb -> cb_fd = sd; + FD_CLR (sd, &perf_wfds); + FD_SET (sd, &perf_rfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + break; + + case DONE: + cb -> cb_state = cb_conn_established; + cb -> cb_fd = sd; + FD_CLR (sd, &perf_wfds); + FD_SET (sd, &perf_rfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("Unknown return code from assoc_start")); + return NOTOK; + } + start_timer (); + cb -> cb_ttl = current_time + 60; + remque (cb -> cb_clp); + insque (cb -> cb_clp, runq -> cl_back); + PP_DBG (("Association descriptor=%d", sd)); + return result; +} + +int chan_invoke (cb, type, arg) +Connblk *cb; +int type; +caddr_t *arg; +{ + struct client_dispatch *ds; + int result; + + noperations ++; + cb -> cb_nops ++; + ds = &dis[type]; + switch (type) { + default: + PP_TRACE (("%s %s", ds -> ds_name, cb_print (cb))); + break; + case DIS_PROC: + PP_NOTICE (("%s %s", ds -> ds_name, cb_print(cb))); + break; + } + switch (result = invoke (cb, table_Qmgr_Operations, + ds, arg)) { + case OK: + break; + + case NOTOK: + cb -> cb_state = cb_active; + break; + + case DONE: + cleanup_conn (cb); + break; + } + return result; +} + +/* */ + +static int invoke (cb, ops, ds, args) +Connblk *cb; +struct RyOperation ops[]; +register struct client_dispatch *ds; +char **args; +{ + int result; + caddr_t in; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + int sd; + + PP_TRACE (("invoke (%s)", cb_print (cb))); + + sd = cb -> cb_fd; + in = NULL; + if (ds -> ds_argument && + (result = (*ds -> ds_argument) (sd, ds, args, &in)) != OK) + return result; + + switch (result = RyStub (sd, ops, ds -> ds_operation, + cb -> cb_id = RyGenID (sd), + NULLIP, in, ds -> ds_result, ds -> ds_error, + ROS_ASYNC, roi)) { + case NOTOK: /* failure */ + ros_advise (rop, "STUB"); + if (ROS_FATAL (rop -> rop_reason)) + return DONE; + return NOTOK; + + case OK: /* got a result/error response */ + break; + + case DONE: /* got RO-END? */ + adios (NULLCP, "got RO-END.INDICATION"); + return NOTOK; + + default: + adios (NULLCP, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + } + + if (ds -> ds_fr_mod && in) + fre_obj (in, ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod, 1); + return OK; +} + +void chan_manage (fd) +int fd; +{ + register Connblk *cb; + int sd; + + if ((cb = findcblk (fd)) == NULLCB) { + PP_LOG (LLOG_EXCEPTIONS, ("fd %d is not registered!", fd)); + FD_CLR (fd, &perf_rfds); + FD_CLR (fd, &perf_wfds); + return; + } + + PP_TRACE (("chan_manage (%s)", cb_print (cb) )); + + switch (cb -> cb_state) { + case cb_conn_request1: + case cb_conn_request2: + PP_TRACE (("Awaiting async connection (state %d)", + cb -> cb_state == cb_conn_request1 ? 1 : 2)); + switch (acsap_retry (sd = cb -> cb_fd)) { + case NOTOK: + PP_TRACE (("Connection error on %s", cb_print (cb))); + delay_channel (cb); + cleanup_conn (cb); + return; + + case CONNECTING_1: + cb -> cb_state = cb_conn_request1; + PP_TRACE (("State 1 on %s", cb_print (cb))); + FD_CLR (sd, &perf_rfds); + FD_SET (sd, &perf_wfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + break; + + case CONNECTING_2: + cb -> cb_state = cb_conn_request2; + PP_TRACE (("State 2 on %s", cb_print (cb))); + FD_CLR (sd, &perf_wfds); + FD_SET (sd, &perf_rfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + break; + case DONE: + cb -> cb_state = cb_conn_established; + PP_TRACE (("connection now established on %s", + cb_print (cb))); + FD_CLR (sd, &perf_wfds); + FD_SET (sd, &perf_rfds); + if (sd >= perf_nfds) + perf_nfds = sd + 1; + (void) newevblk (cb -> cb_clp, cb, + cb -> cb_type, (time_t)0); + break; + } + break; + case cb_idle: + freecblk (cb); + break; + case cb_proc_sent: + PP_TRACE (("Awaiting proc response ...")); + getresponse (cb, OK); + break; + case cb_init_sent: + PP_TRACE (("Awaiting init response")); + getresponse (cb, OK); + break; + default: + PP_TRACE (("Funny state!")); + break; + } +} + +static void getresponse (cb, type) +Connblk *cb; +int type; +{ + caddr_t out; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + PP_TRACE (("getresponse (%s)", cb_print (cb))); + + switch (RyWait (cb -> cb_fd, &cb -> cb_id, &out, type, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + PP_TRACE (("RyWait returned NOTOK")); + ros_advise (rop, "STUB"); + delay_channel (cb); + cleanup_conn (cb); + break; + + case OK: + PP_TRACE (("RyWait returned OK")); + switch (cb -> cb_state) { + default: + cb -> cb_state = cb_active; + /* and fall */ + case cb_finished: + (void) newevblk (cb -> cb_clp, cb, + cb -> cb_type, (time_t)0); + break; + case cb_proc_sent: + break; + case cb_error: + cleanup_conn (cb); + break; + } + break; + + case DONE: + cb -> cb_ml = NULL; + cleanup_conn (cb); + break; + } +} + +#ifdef notdef +static void setfds () +{ + register Connblk *cb; + struct PSAPindication pi; + + PP_TRACE (("setfds ()")); + + FD_ZERO (&perf_wfds); + FD_ZERO (&perf_rfds); + perf_nfds = 0; + + for (cb = CHead -> cb_forw; cb != CHead; cb = cb -> cb_forw) + switch (cb -> cb_state) { + case cb_conn_request1: + if (PSelectMask (cb -> cb_fd, &perf_wfds, + &perf_nfds, &pi) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, + ("PSelectMask failed")); + break; + case cb_conn_request2: + case cb_proc_sent: + case cb_init_sent: + case cb_conn_established: + if (PSelectMask (cb -> cb_fd, &perf_rfds, + &perf_nfds, &pi) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, + ("PSelectMask failed")); + break; + default: + break; + } + PP_TRACE (("nrfds=%d rfds=0x%x wfds=0x%x", perf_nfds, + perf_rfds.fds_bits[0], perf_wfds.fds_bits[0])); +} +#endif + +/* ARGSUSED */ +static int do_quit (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +caddr_t *arg; +{ + Connblk *cb; + + PP_TRACE (("do_quit(%d)", sd)); + + (void) assoc_release (sd); + if (sd != NOTOK) { + FD_CLR (sd, &perf_wfds); + FD_CLR (sd, &perf_rfds); + } + if ((cb = findcblk (sd)) != NULLCB) + cb -> cb_fd = NOTOK; + else + return DONE; + + PP_TRACE (("do_quit (%s)", cb_print (cb) )); + if (cb -> cb_type == cb_channel) + cb -> cb_clp -> chan_update = 1; + + PP_NOTICE (("Closing channel %s", cb_print (cb))); + + return DONE; +} + +/* connection block functions */ + +Connblk *newcblk (type) +enum cb_type type; +{ + Connblk *cb; + + PP_TRACE (("newcblk () cnt=%d", cb_count)); + + cb = (Connblk *) calloc (1, sizeof *cb); + if (cb == NULLCB) + return cb; + + cb -> cb_fd = NOTOK; + cb -> cb_type = type; + + if (cb_once_only == 0) { + CHead -> cb_forw = CHead -> cb_back = CHead; + cb_once_only ++; + } + insque (cb, CHead -> cb_back); + cb_count ++; + return cb; +} + +void freecblk (cb) +Connblk *cb; +{ + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + + if (cb == NULLCB) + return; + + PP_DBG (("freecblk (%s) cnt=%d", + cb_print(cb), cb_count)); + + if (cb -> cb_fd != NOTOK) { + PP_NOTICE (("Killing channel %s", + cb_print (cb))); + (void) AcUAbortRequest (cb -> cb_fd, NULLPEP, 0, &acis); + (void) RyLose (cb -> cb_fd, roi); + FD_CLR (cb -> cb_fd, &perf_wfds); + FD_CLR (cb -> cb_fd, &perf_rfds); + } + remque (cb); + + cb_count --; + if (cb_count < 0) + PP_LOG (LLOG_EXCEPTIONS, ("Internal error cb_count = %d", + cb_count)); + free ((char *) cb); +} + +Connblk *findcblk (fd) +int fd; +{ + Connblk *cb; + + PP_DBG (("findcblk (%d) cnt=%d", fd, cb_count)); + + if (cb_once_only == 0) + return NULLCB; + + for (cb = CHead -> cb_forw; cb != CHead; cb = cb -> cb_forw) + if (cb -> cb_fd == fd) + return cb; + + PP_TRACE (("Can't locate block with %d (%d alloc'd)", + fd, cb_count)); + return NULLCB; +} + +static char *cb2name (cb) +Connblk *cb; +{ + switch (cb -> cb_type) { + case cb_channel: + case cb_special: + if (cb -> cb_clp && cb -> cb_clp -> channame) + return cb -> cb_clp -> channame; + else return "unknown channel"; + + case cb_timer: + return "timer"; + + case cb_responder: + return "responder"; + + default: + break; + } + return "something"; +} + +static char *cb_print (cb) +Connblk *cb; +{ + static char buf[1024]; + + switch (cb -> cb_type) { + case cb_channel: + case cb_special: + (void) sprintf (buf, "", + cb -> cb_fd, + cb2name(cb), + cb -> cb_mlp ? cb -> cb_mlp -> mtaname: "none", + (cb -> cb_ml && cb -> cb_ml -> ms ) ? + cb -> cb_ml -> ms -> queid : "none"); + break; + case cb_timer: + (void) sprintf (buf, "", + cb -> cb_proc, cb -> cb_reload); + break; + + case cb_responder: + (void) sprintf (buf, "", + cb -> cb_fd, cb -> cb_authenticated); + break; + } + + return buf; +} + +static void pcblock_error (cb) +Connblk *cb; +{ + PP_OPER (NULLCP, + ("Channel %s in state %d taking too long - aborting rfd=%s wfd=%s nfds=%d", + cb_print (cb), cb -> cb_state, + FD_ISSET (cb->cb_fd, &perf_rfds) ? "set" : "unset", + FD_ISSET (cb->cb_fd, &perf_wfds) ? "set" : "unset", + perf_nfds + )); +} + +static struct eventqueue *newevblk (clp, cb, type, when) +Chanlist *clp; +Connblk *cb; +time_t when; +enum cb_type type; +{ + struct eventqueue *ev, *pev; + + PP_TRACE (("newevblk (clp, cb, %d, %d) cnt=%d", + type, when, ev_count)); + + ev = (struct eventqueue *) calloc (1, sizeof *ev); + if (ev == NULLEV) + return ev; + + ev_count ++; + ev -> ev_clp = clp; + ev -> ev_conn = cb; + ev -> ev_type = type; + + for (pev = EHead -> ev_forw; pev != EHead; pev = pev -> ev_forw) { + if (pev -> ev_time > when) { + insque (ev, pev -> ev_back); + break; + } + else + when -= pev -> ev_time; + } + if (pev == EHead) + insque (ev, EHead -> ev_back); + for (; pev != EHead; pev = pev -> ev_forw) + pev -> ev_time -= when; + + ev -> ev_time = when; + + return ev; +} + +static void freevblk (ev) +struct eventqueue *ev; +{ + PP_DBG (("freevblk () cnt=%d", ev_count)); + + if (ev == NULLEV) + return; + + if (ev -> ev_forw != EHead) + ev -> ev_forw -> ev_time += ev -> ev_time; + + remque (ev); + + free ((char *) ev); + ev_count --; + if (ev_count < 0) + PP_LOG (LLOG_EXCEPTIONS, ("Internal error - ev_count = %d", + ev_count)); +} + +#ifdef notdef +static time_t evtimebyclp (clp) +Chanlist *clp; +{ + struct eventqueue *ev; + time_t now = current_time; + + for (ev = EHead -> ev_forw; ev != EHead; ev = ev -> ev_forw) + if (ev -> ev_clp == clp) + return now + ev -> ev_time; + else now += ev -> ev_time; + return now + MAX_SLEEP + 2; +} + +static struct eventqueue *findevbyclp (clp) +Chanlist *clp; +{ + struct eventqueue *ev; + + for (ev = EHead -> ev_forw; ev != EHead; ev = ev -> ev_forw) + if (ev -> ev_clp == clp) + return ev; + return NULLEV; +} +#endif + +static void init_events () +{ + PP_TRACE (("init_events ()")); + + EHead -> ev_forw = EHead -> ev_back = EHead; +} + +sched_delete (rlp, ms, zapped) +Reciplist *rlp; +MsgStruct *ms; +int zapped; +{ + rlp -> status = ST_DELETE; + if (ms -> count == 0) + insertindelchan (ms); + stats.n_addr_out ++; + if (zapped) + stats.n_messages_out ++; +} + +void inc_channel (cb, number) /* successful delivery */ +Connblk *cb; +int number; +{ + MsgStruct *ms; + Reciplist *rlp, *rl0; + LIST_RCHAN *lcp; + int deleted; + + PP_TRACE (("inc_channel (%s, %d)", + cb_print (cb), number)); + + cb -> cb_clp -> lastsuccess = current_time; + cb -> cb_clp -> error_count = 0; + ms = cb -> cb_ml -> ms; + clear_msgcache (cb -> cb_ml); + + if (number == 0) /* set real recip number */ + number = cb -> cb_ml -> recips[0] -> id; + deleted = delfromchan (cb -> cb_clp, cb -> cb_mlp, + cb -> cb_ml, number); + + if (deleted & ZAP_MTA) + cb -> cb_mlp = NULLMTALIST; + + cache_clear (&cb -> cb_clp -> cache); + + if (cb -> cb_mlp) { + cache_clear (&cb -> cb_mlp -> cache); + cb -> cb_mlp -> lastsuccess = current_time; + cb -> cb_mlp -> error_count = 0; + } + + if (ms == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message!")); + return; + } + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) + if (rlp -> id == number) + break; + if (rlp == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipient %d in list!", + number)); + return; + } + + switch (rlp -> status) { + case ST_WARNING: + ms -> numberwarns ++; + lcp = rlp -> cchan; + rlp -> status = ST_NORMAL; + if (lcp) { + insertinchan (lcp -> li_chan, ms, rlp, + chan2mta (lcp -> li_chan, rlp)); + return; + } + break; + case ST_NORMAL: + lcp = rlp -> cchan = rlp -> cchan -> li_next; + if (lcp) { + insertinchan (lcp -> li_chan, ms, rlp, + chan2mta (lcp -> li_chan, rlp)); + return; + } + sched_delete (rlp, ms, deleted & ZAP_MSG); + break; + + case ST_DR: + for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next) + if (rl0 -> id == 0) + break; + if ((lcp = rl0 -> cchan) == NULLIST_RCHAN) { + PP_LOG (LLOG_EXCEPTIONS, ("no channels left for DR")); + break; + } + if (lcp -> li_next == NULLIST_RCHAN) /* end of list */ + sched_delete (rlp, ms, deleted & ZAP_MSG); + else { + lcp = rl0 -> cchan = lcp -> li_next; + insertinchan (lcp -> li_chan, ms, rlp, + chan2mta (lcp -> li_chan, rl0)); + } + break; + case ST_DELETE: + cb -> cb_ml = NULL; + if (ms -> count == 0) + zapmsg (ms); + break; + } +} + +void delay_host (cb, rno, str, first) +Connblk *cb; +int rno; +char *str; +int first; +{ + struct Mtalist *mlp; + + PP_TRACE (("delay_host (%s, %d)", cb_print (cb), rno)); + + if (cb -> cb_ml) + msg_unlock (cb -> cb_ml -> ms); + + if ((mlp = cb -> cb_mlp) == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate mta in queue")); + return; + } + if (mlp -> info) { + free (mlp -> info); + mlp -> info = NULLCP; + } + if (str) + mlp -> info = strdup (str); + cache_inc (&mlp -> cache, cache_time*3/2); + mlp -> nextevent = mlp -> cache.cachetime; + if (cb -> cb_clp) { + remque (mlp); + insque (mlp, cb -> cb_clp -> mtas -> mta_back); + if (first) + cb -> cb_clp -> error_count ++; + } +} + +void delay_message (cb, str, first) +Connblk *cb; +char *str; +int first; +{ + Mtalist *mlp; + + PP_TRACE (("delay_message (%s)", cb_print (cb))); + + if (cb -> cb_ml == NULL) + return; + if ((mlp = cb -> cb_mlp) == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate mta in queue")); + return; + } + if (cb -> cb_ml -> info) { + free (cb -> cb_ml -> info); + cb -> cb_ml -> info = NULLCP; + } + if (str) + cb -> cb_ml -> info = strdup (str); + if (first) + cb -> cb_ml -> ms -> nerrors ++; + msg_unlock (cb -> cb_ml -> ms); + msgcache_inc (cb -> cb_ml, cache_time*2); + mlp -> mta_changed = 1; + if (first) + mlp -> error_count ++; + cb -> cb_clp -> chan_update = 1; +} + +static void bad_recip (cb, rno) +Connblk *cb; +int rno; +{ + Reciplist *rlp; + MsgStruct *ms; + LIST_RCHAN *lcp; + int del; + + PP_TRACE (("bad_recip (%s, %d)", cb_print (cb), rno)); + + if (rno == 0) /* set real recip number */ + rno = cb -> cb_ml -> recips[0] -> id; + + ms = cb -> cb_ml -> ms; + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) + if (rlp -> id == rno) + break; + if (rlp == NULLRL) + return; + + if (rlp -> status == ST_DR) { /* DR being DR'd */ + Reciplist *rl0; + + for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next) + if (rl0 -> id == 0) + break; + + if ((lcp = rl0 -> cchan) && lcp -> li_next == NULLIST_RCHAN) { + PP_OPER (NULLCP, + ("A DR giving status DR on chan %s - Help!", + lcp -> li_chan ? lcp -> li_chan -> ch_name : + "")); + msgcache_inc (cb -> cb_ml, cache_time*2); + cb -> cb_mlp -> mta_changed = 1; + cb -> cb_mlp -> error_count ++; + cb -> cb_clp -> chan_update = 1; + return; + } + + cb -> cb_clp -> lastsuccess = current_time; + cb -> cb_clp -> error_count = 0; + if (cb -> cb_mlp) { + cb -> cb_mlp -> lastsuccess = current_time; + cb -> cb_mlp -> error_count = 0; + } + del = delfromchan (cb -> cb_clp, cb -> cb_mlp, cb -> cb_ml, rno); + if (del & ZAP_MTA) + cb -> cb_mlp = NULLMTALIST; + + PP_NOTICE (("Skipping over DR refromatting channels")); + /* skip over all the bad reformatters */ + while (lcp -> li_next != NULLIST_RCHAN) + lcp = lcp -> li_next; + rl0 -> cchan = lcp; + insertinchan (lcp -> li_chan, ms, + rlp, chan2mta (lcp -> li_chan, rl0)); + } + else { + cb -> cb_clp -> lastsuccess = current_time; + cb -> cb_clp -> error_count = 0; + if (cb -> cb_mlp) { + cb -> cb_mlp -> lastsuccess = current_time; + cb -> cb_mlp -> error_count = 0; + } + del = delfromchan (cb -> cb_clp, cb -> cb_mlp, cb -> cb_ml, rno); + if (del & ZAP_MTA) + cb -> cb_mlp = NULLMTALIST; + insertindrchan (cb -> cb_ml -> ms, rlp); + } +} + +static void sharedDR (cb, rno) +Connblk *cb; +int rno; +{ + int del; + + PP_TRACE (("sharedDR (%s, %d)", cb_print (cb), rno)); + + if (rno == 0) /* set real recip number */ + rno = cb -> cb_ml -> recips[0] -> id; + + cb -> cb_clp -> lastsuccess = current_time; + if (cb -> cb_mlp) + cb -> cb_mlp -> lastsuccess = current_time; + del = delfromchan (cb -> cb_clp, cb -> cb_mlp, cb -> cb_ml, rno); + if (del & ZAP_MTA) + cb -> cb_mlp = NULLMTALIST; +} + +/* ARGSUSED */ + +static int do_processmessage (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_ProcMsg **arg; +{ + Reciplist *rl0; + Connblk *cb; + Mlist *ml; + register struct type_Qmgr_ProcMsg *pm; + struct type_Qmgr_UserList *lusers (); + char *p; + + PP_TRACE (("do_processmessage (%d)", sd)); + + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + if (cb -> cb_state != cb_active) + return NOTOK; + ml = cb -> cb_ml; + if (ml == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("Missing ml structure")); + return NOTOK; + } + *arg = pm = (struct type_Qmgr_ProcMsg *) malloc (sizeof (**arg)); + + pm -> channel = str2qb (cb -> cb_clp -> channame, + strlen (cb -> cb_clp -> channame), 1); + + p = ml -> ms -> queid; + pm -> qid = str2qb (p, strlen (p), 1); + for (rl0 = ml -> ms -> recips; rl0; rl0 = rl0 -> rp_next) + if (rl0 -> id == 0) + break; + if (ml -> recips[0] -> status == ST_DR && + rl0 && rl0 -> cchan && rl0 -> cchan -> li_next != NULL) { + pm -> users = (struct type_Qmgr_UserList *) + smalloc (sizeof *pm -> users); + pm -> users -> next = NULL; + pm -> users -> RecipientId = (struct type_Qmgr_RecipientId *) + smalloc (sizeof *pm -> users -> RecipientId); + pm -> users -> RecipientId -> parm = 0; + } + else + pm -> users = lusers (ml, 0); + if (pm -> users == NULL) + PP_LOG (LLOG_EXCEPTIONS, ("Empty user list!")); + cb -> cb_ttl = current_time + CHAN_TIMEOUT + (ml -> ms -> size /20); + cb -> cb_state = cb_proc_sent; + if (cb -> cb_mlp) + cb -> cb_mlp -> lastattempt = current_time; + return OK; +} + +/* ARGSUSED */ +static int do_readqueue (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_Pseudo__readqueue **arg; +{ + Connblk *cb; + + PP_TRACE (("do_readqueue (%d)", sd)); + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + cb -> cb_state = cb_proc_sent; + return OK; +} + + + +/* ARGSUSED */ +static int do_initchannel (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +struct type_Qmgr_Channel **arg; +{ + Connblk *cb; + + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + + PP_TRACE (("do_initchannel (%s)", cb_print (cb) )); + + *arg = str2qb (*args, strlen (*args), 1); + cb -> cb_state = cb_init_sent; + if (cb -> cb_clp -> chan_special) + cb -> cb_ttl = current_time + CHAN_TIMEOUT; + else cb -> cb_ttl = current_time + 60; + return OK; +} + +/* ARGSUSED */ +static int processmessage_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +register struct type_Qmgr_DeliveryStatus *result; +struct RoSAPindication *roi; +{ + Connblk *cb; + struct type_Qmgr_DeliveryStatus *ds; + int rno; + char buf[LINESIZE]; + char *info; + int first_mta = 1, first_msg = 1; + + PP_TRACE (("processmessage_result (%d)", sd)); + + if ((cb = findcblk (sd)) == NULLCB) { + PP_LOG (LLOG_EXCEPTIONS, ("No connection block for %d", + sd)); + return NOTOK; + } + PP_TRACE (("processmessage_result (%s)", cb_print (cb))); + for (ds = result; ds; ds = ds -> next) { + rno = ds -> IndividualDeliveryStatus -> recipient -> parm; + (void) sprintf (buf, "Recipient ID %d %s:", rno, + cb_print (cb)); + if (ds -> IndividualDeliveryStatus -> info) + info = qb2str(ds -> IndividualDeliveryStatus -> info); + else info = NULLCP; + switch (ds -> IndividualDeliveryStatus -> status) { + case int_Qmgr_status_success: + PP_NOTICE (("%s success", buf)); + inc_channel (cb, rno); + break; + + case int_Qmgr_status_negativeDR: + case int_Qmgr_status_positiveDR: + PP_NOTICE (("%s %s", buf, + ds -> IndividualDeliveryStatus -> status + == int_Qmgr_status_positiveDR ? + "positiveDR" : "negativeDR")); + bad_recip (cb, rno); + break; + + case int_Qmgr_status_successSharedDR: + case int_Qmgr_status_failureSharedDR: + PP_NOTICE (("%s %s", buf, + ds -> IndividualDeliveryStatus -> status + == int_Qmgr_status_failureSharedDR ? + "failureSharedDR" : "sucessSharedDR")); + sharedDR(cb, rno); + break; + + case int_Qmgr_status_messageFailure: + PP_NOTICE (("%s messageFailure (%s)", buf, + info ? info : "")); + delay_message (cb, info, first_msg); + first_msg = 0; + break; + + case int_Qmgr_status_mtaFailure: + PP_NOTICE (("%s mtaFailure (%s)", buf, + info ? info : "")); + delay_host (cb, rno, info, first_mta); + first_mta = 9; + break; + + case int_Qmgr_status_mtaAndMessageFailure: + PP_NOTICE (("%s mtaAndMessageFailure (%s)", buf, + info ? info : "")); + delay_message (cb, info, first_msg); + delay_host (cb, rno, info, first_mta); + first_mta = first_msg = 0; + break; + + default: + PP_NOTICE (("%s Unknown response", buf)); + break; + } + if (info) + free (info); + } + cb -> cb_state = cb_active; + /* quick attempt to fire something off now - if its easy + * otherwise - do it in the main loop and do more clever scheduling. + */ + if (cb -> cb_clp -> chan_enabled == 0 || opmode || + (cb -> cb_ml = nextmsg (cb -> cb_clp, &cb -> cb_mlp, 1, 1))== NULL ) + cb -> cb_ml = NULL; + else + (void) chan_invoke (cb, DIS_PROC, (caddr_t *)0); + + return OK; +} + +/* RPC procedures... */ + +/* ARGSUSED */ +static int readqueue_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +register struct type_Qmgr_MsgList *result; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgStructList *ml; + MsgStruct *ms, *oldms; + char *p; + int count; + Connblk *cb; + struct type_Qmgr_QidList *ql; + + PP_TRACE (("readqueue_result (%d, %d)", sd, id)); + + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + cb -> cb_state = cb_active; + for (count = 0,ml = result -> msgs; ml; ml = ml -> next) { + ms = newmsgstruct (ml -> MsgStruct); + if ((oldms = find_msg (ms -> queid)) != NULLMS) { + (void) updatemessage (oldms, ms); + freems (ms); + } + else + (void) insertmessage (ms); + count ++; + } + for (ql = result -> deleted; ql; ql = ql -> next) { + p = qb2str (ql -> QID); + if ((ms = find_msg (p)) != NULLMS) + kill_msg (ms); + free (p); + } + if (count == 0) + cb -> cb_state = cb_finished; + cb -> cb_ttl = current_time + CHAN_TIMEOUT; + cb -> cb_clp -> lastsuccess = current_time; + return OK; +} + +/* ARGSUSED */ +static int channelinit_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +struct type_Qmgr_Pseudo__channelInitialise *result; +struct RoSAPindication *roi; +{ + PP_TRACE (("channelinit_result (%d, %d)", sd, id)); + + return OK; +} + +/* ARGSUSED */ +static int general_error (sd, id, error, parameter, roi) +int sd, + id, + error; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + Connblk *cb; + + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + PP_TRACE (("general_error (%s)", cb_print(cb))); + if (cb -> cb_type != cb_channel) { + PP_LOG (LLOG_EXCEPTIONS, ("Not a channel!!!")); + return NOTOK; + } + + cb -> cb_state = cb_error; + if (error == RY_REJECT) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s", RoErrString ((int) parameter))); + delay_channel (cb); + return NOTOK; + } + + if ((rye = finderrbyerr (table_Qmgr_Errors, error)) != NULL) + PP_LOG (LLOG_EXCEPTIONS, ("%s", rye -> rye_name)); + else + PP_LOG (LLOG_EXCEPTIONS, ("Error %d", error)); + + delay_channel (cb); + return NOTOK; +} + +/* ARGSUSED */ +static int processmessage_error (sd, id, error, parameter, roi) +int sd, + id, + error; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + Connblk *cb; + char tbuf[128]; + + if ((cb = findcblk (sd)) == NULLCB) + return NOTOK; + PP_TRACE (("processmessage_error (%s)", cb_print(cb))); + + if (cb -> cb_type != cb_channel) { + PP_LOG (LLOG_EXCEPTIONS, ("Not a channel!!!")); + return NOTOK; + } + + if (error == RY_REJECT) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s", RoErrString ((int) parameter))); + delay_message (cb, RoErrString ((int) parameter), 1); + return OK; + } + + if ((rye = finderrbyerr (table_Qmgr_Errors, error)) != NULL) + (void) sprintf (tbuf, "process message error %s", + rye -> rye_name); + else + (void) sprintf (tbuf, "process message error %d", error); + PP_LOG (LLOG_EXCEPTIONS, ("%s", tbuf)); + + delay_message (cb, tbuf, 1); + return OK; +} + +void delay_channel (cb) +Connblk *cb; +{ + PP_TRACE (("delay_channel (%s)", cb_print (cb) )); + + if (cb -> cb_type == cb_responder || cb -> cb_type == cb_timer) + return; + if (cb -> cb_clp == NULL) + return; + cache_inc (&(cb -> cb_clp -> cache), cache_time); + cb -> cb_clp -> nextevent = cb -> cb_clp -> cache.cachetime; +} + +void investigate_chan (clp, now) +Chanlist *clp; +time_t now; +{ + Mtalist *mlp; + int nmtas = clp -> nmtas; + + PP_TRACE (("investigate_chan (%s)", clp -> channame)); + + clp -> nextevent = now + MAX_SLEEP; + clp -> oldest = now; + clp -> nmtas = 0; + + for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas; + mlp = mlp -> mta_forw) { + if (mlp -> mta_changed || mlp -> nextevent < current_time) { + investigate_mta (mlp, now); + mlp -> mta_changed = 0; + } + if (mlp -> oldest < clp -> oldest) + clp -> oldest = mlp -> oldest; + clp -> nmtas ++; + if (!mtaready (mlp)) + continue; + if (mlp -> nextevent < clp -> nextevent) + clp -> nextevent = mlp -> nextevent; + } + if (clp -> chan_special) + clp -> nextevent = now; + if (clp -> cache.cachetime > now) + clp -> nextevent = clp -> cache.cachetime; + if (clp -> chan_enabled == 0) + clp -> nextevent = now + MAX_SLEEP; + if (nmtas != clp -> nmtas) + PP_LOG(LLOG_EXCEPTIONS, ("mta count mismatch on %s (%d != %d)", + clp -> channame, + clp -> nmtas, nmtas)); +} + +void investigate_mta (mlp, now) +Mtalist *mlp; +time_t now; +{ + Mlist *ml; + time_t cachet; + + PP_TRACE (("investigate_mta (%s)", mlp -> mtaname)); + + mlp -> nextevent = now + MAX_SLEEP + 1; + mlp -> oldest = now; + + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) { + /* this calc has to be done - or we could optimise */ + if (ml -> ms -> age < mlp -> oldest) + mlp -> oldest = ml -> ms -> age; + + if (!msgready (ml)) + continue; + + if ((cachet = msgmincache (ml)) > now) { + if (cachet < mlp -> nextevent) + mlp -> nextevent = cachet; + } + else if (ml -> ms -> defferedtime && + ml -> ms -> defferedtime < mlp -> nextevent) + mlp -> nextevent = ml -> ms -> defferedtime; + else mlp -> nextevent = now; + } + if (mlp -> cache.cachetime > now) /* oops - cached */ + mlp -> nextevent = mlp -> cache.cachetime; + if (mlp -> mta_enabled == 0) + mlp -> nextevent = now + MAX_SLEEP + 1; +} + +void cleanup_conn (cb) +Connblk *cb; +{ + PP_TRACE (("cleanup_conn(%s)", cb_print (cb))); + + switch (cb -> cb_type) { + case cb_responder: + case cb_timer: + break; + default: + if (cb -> cb_clp) { + if (cb -> cb_mlp) { + cb -> cb_mlp -> nactive --; + if (cb -> cb_state == cb_idle || + cb -> cb_state == cb_proc_sent) + delay_message (cb, "Connection broke", 1); + } + if (cb -> cb_state != cb_idle) { + cb -> cb_clp -> nactive --; + nchansrunning --; + } + if (cb -> cb_clp -> chan_special) { + nspecials --; + if (cb -> cb_clp -> chan -> ch_chan_type == + CH_QMGR_LOAD) + if (delete_chan -> chan_enabled == 0 && + delete_chan -> chan_syssusp == 1) { + delete_chan -> chan_enabled = 1; + delete_chan -> chan_syssusp = 0; + delete_chan -> chan_update = 1; + } + + } + } + if (cb -> cb_ml) + msg_unlock (cb -> cb_ml -> ms); + + break; + } + freecblk (cb); +} + +static int timeout_proc () +{ + MsgStruct **msp, *ms; + time_t warn_t; + + PP_TRACE (("timeout_proc")); + for (msp = msg_hash; msp < &msg_hash[QUE_HASHSIZE]; ) { + for (ms = *msp; ms; ms = ms -> ms_forw) { + if (ms -> m_locked) + continue; + if (ms -> expirytime < current_time && + expiremsg (ms) != NOTOK) + continue; + + if (ms -> numberwarns >= warn_number) + continue; + + warn_t = ms -> age + (ms -> warninterval * + (ms -> numberwarns+1)); + if (warn_t < current_time) + (void) warnmsg (ms); + } + if (!ms) + msp ++; + } +} + +static int expiremsg (ms) +MsgStruct *ms; +{ + int first = 1; + Reciplist *rlp; + Chanlist *clp; + Mtalist *mlp; + Mlist *ml; + + PP_TRACE (("expiremsg (%s)", ms -> queid)); + if (timeout_chan == NULLCHANLIST || timeout_chan -> chan_enabled == 0) + return NOTOK; + + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) { + if (rlp -> id == 0) + continue; + switch (rlp -> status) { + case ST_DR: + case ST_DELETE: + case ST_TIMEOUT: + case ST_WARNING: + continue; /* leave these alone! */ + + case ST_NORMAL: + if ((ml = rlp -> ml) == NULLMLIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("Recipient not on msg q")); + continue; + } + if ((mlp = ml -> mlp) == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("msg q not on mta")); + continue; + } + if ((clp = mlp -> clp) == NULLCHANLIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("mta not on chan")); + continue; + } + (void) delfromchan (clp, mlp, ml, rlp -> id); + rlp -> status = ST_TIMEOUT; + if (first) { + insertinchan (timeout_chan -> chan, ms, rlp, + chan2mta(timeout_chan -> chan, + rlp)); + first = 0; + } + } + } + return first == 1 ? OK : DONE; +} + +static int warnmsg (ms) +MsgStruct *ms; +{ + int first = 1; + Reciplist *rlp; + Chanlist *clp; + Mtalist *mlp; + Mlist *ml; + + PP_TRACE (("warnmsg (%s)", ms -> queid)); + + if (warn_chan == NULLCHANLIST || warn_chan -> chan_enabled == 0) + return NOTOK; + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) { + if (rlp -> id == 0) + continue; + switch (rlp -> status) { + case ST_DR: + case ST_DELETE: + case ST_TIMEOUT: + case ST_WARNING: + continue; /* leave these alone! */ + + case ST_NORMAL: + if ((ml = rlp -> ml) == NULLMLIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("Recipient not on msg q")); + continue; + } + if ((mlp = ml -> mlp) == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("msg q not on mta")); + continue; + } + if ((clp = mlp -> clp) == NULLCHANLIST) { + PP_LOG (LLOG_EXCEPTIONS, + ("mta not on chan")); + continue; + } + (void) delfromchan (clp, mlp, ml, rlp -> id); + rlp -> status = ST_WARNING; + insertinchan (warn_chan -> chan, ms, rlp, + chan2mta(warn_chan -> chan, + rlp)); + first = 1; + } + } + return first == 1 ? OK : DONE; +} + +static int channel_ttl () +{ + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + Connblk *cb; + + PP_TRACE (("channel_ttl ()")); + + if (cb_once_only == 0) + return OK; + + for (cb = CHead -> cb_forw; cb != CHead; cb = cb -> cb_forw) { + if (cb -> cb_type == cb_channel && cb -> cb_ttl && + cb -> cb_ttl < current_time) { + pcblock_error (cb); + (void) AcUAbortRequest (cb -> cb_fd, NULLPEP, + 0, &acis); + (void) RyLose (cb -> cb_fd, roi); + (void) chan_lose (cb -> cb_fd, + (struct AcSAPfinish *)0); + } + } + timer_running = 0; + if (nchansrunning > 0) + start_timer (); + return OK; +} + +static void start_timer () +{ + Connblk *cb; + + if (timer_running) + return; + + cb = newcblk (cb_timer); + cb -> cb_proc = channel_ttl; + cb -> cb_reload = 0; + (void) newevblk (NULLCHANLIST, cb, cb_timer, CHAN_TIMEOUT); + timer_running = 1; +} diff --git a/Src/qmgr/make b/Src/qmgr/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/qmgr/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/qmgr/misc.c b/Src/qmgr/misc.c new file mode 100644 index 0000000..bd82e82 --- /dev/null +++ b/Src/qmgr/misc.c @@ -0,0 +1,78 @@ +/* misc.c: misc routines required by qmgr */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/misc.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/misc.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: misc.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "types.h" + +int hash (str, n) /* case independant hash function */ +char *str; +int n; +{ + extern char chrcnv[]; + int res = 0; + char *cp; + + for (cp = str; *cp; cp++) { + res = 3 * res + chrcnv[*cp]; + res %= n; + } + return res; +} + +void cache_set (cp, utct) +Cache *cp; +struct type_UNIV_UTCTime *utct; +{ + cp -> cachetime = utcqb2time_t (utct); + cp -> cacheplus = 0; +} + +void cache_clear (cp) +Cache *cp; +{ + cp -> cachetime = cp -> cacheplus = 0; +} + +void cache_inc (cp, factor) +Cache *cp; +time_t factor; +{ + int rfact; + + if (cp -> cacheplus < CACHE_MAX) + cp -> cacheplus ++; + cp -> cachetime = current_time + factor * cp -> cacheplus; + + /* round up the cache time - helps cluster mta's etc. */ + rfact = (factor/10) * cp -> cacheplus; + if (rfact <= 0) + rfact = 1; + cp -> cachetime += rfact - cp -> cachetime % rfact; +} + +time_t utcqb2time_t (qb) +struct qbuf *qb; +{ + char *p = qb2str (qb); + UTC ut; + time_t t; + + ut = str2utct(p, strlen (p)); + t = utc2time_t (ut); + free (p); + return t; +} + diff --git a/Src/qmgr/qmgr.c b/Src/qmgr/qmgr.c new file mode 100644 index 0000000..0ac868d --- /dev/null +++ b/Src/qmgr/qmgr.c @@ -0,0 +1,465 @@ +/* qmgr.c: Queue manager main routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/qmgr.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/qmgr.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: qmgr.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "ryresponder.h" /* for generic idempotent responders */ +#include "qmgr.h" /* operation definitions */ +#include "types.h" + +static char *myservice = "pp qmgr"; +extern char *quedfldir; +static SFD debug_on (), debug_off (), shutdown (), spurious (); +int ureject (); + +/* OPERATIONS */ +static int + op_newmessage (), op_readmsginfo (), + op_channelbegin (), op_channelread (), + op_channelcontrol (), op_mtaread (), op_mtacontrol (), + op_messagecontrol (), op_qmgrcontrol (), + op_readchannelmtamessage (), op_qmgrstatus (); + + +static struct server_dispatch dispatches[] = { + "newmessage", operation_Qmgr_newmessage, op_newmessage, + "readmsginfo", operation_Qmgr_readmsginfo, op_readmsginfo, + "channelbegin", operation_Qmgr_channelbegin, op_channelbegin, + "channelread", operation_Qmgr_channelread, op_channelread, + "channelcontrol", operation_Qmgr_channelcontrol, op_channelcontrol, + "mtaread", operation_Qmgr_mtaread, op_mtaread, + "mtacontrol", operation_Qmgr_mtacontrol, op_mtacontrol, + "msgcontrol", operation_Qmgr_msgcontrol, op_messagecontrol, + "qmgrcontrol", operation_Qmgr_qmgrControl, op_qmgrcontrol, + "readchannelmtamessage", + operation_Qmgr_readChannelMtaMessage, + op_readchannelmtamessage, + "qmgrstatus", operation_Qmgr_qmgrStatus, op_qmgrstatus, + NULL + }; + +extern int chan_lose (); +extern int start_routine (); +extern char *qmgr_hostname; + +time_t current_time; +time_t debris_time = TRASH_RETRY_INTERVAL, load_time = LOAD_RETRY_INTERVAL; +time_t cache_time = CACHE_TIME, timeout_time = TIMEOUT_RETRY_INTERVAL; +int chan_state = 1; +int maxchansrunning = MAXCHANSRUNNING; +int submission_disabled = 0; +int nobackground = 0; +int opmode = 0; +int nocdir = 0; +int nodisablemsgclean = 0; + +/* MAIN */ + +main (argc, argv) +int argc; +char **argv; +{ + int opt; + extern char *optarg; + extern char *pptailor; + + myname = argv[0]; + (void) time (¤t_time); + while ((opt = getopt (argc, argv, "bDd:l:c:Ct:m:MsT:X")) != EOF) { + switch (opt) { + case 'b': + nobackground = 1; + break; + case 'C': + nocdir = 1; + break; + case 'D': + chan_state = 0; + break; + + case 's': + submission_disabled = 1; + break; + + case 'l': + if ((load_time = atoi(optarg)) < 0) + load_time = LOAD_RETRY_INTERVAL; + else load_time *= 60 * 60; + break; + + case 'd': + if ((debris_time = atoi(optarg)) < 0) + debris_time = TRASH_RETRY_INTERVAL; + else debris_time *= 60 * 60; + break; + + case 'c': + if ((cache_time = atoi (optarg)) < 0) + cache_time = CACHE_TIME; + break; + + case 't': + if ((timeout_time = atoi (optarg)) < 0) + timeout_time = TIMEOUT_RETRY_INTERVAL; + else timeout_time *= 60 * 60; + break; + + case 'm': + if ((maxchansrunning = atoi (optarg)) < 1) + maxchansrunning = MAXCHANSRUNNING; + break; + + case 'M': + nodisablemsgclean = 1; + break; + + case 'T': + pptailor = optarg; + break; + + case 'X': + debug_on (); + break; + default: + adios (NULLCP, +"Usage: %s [-bCDNMsX] [-d hours] [-l hours] [-t hours]\n\t\ +[-c secs] [-m nchans] [-T tailorfile]", + myname); + break; + } + } + sys_init (myname); + srandom(getpid()); + +#if defined(SIGUSR1) && defined(SIGUSR2) + (void) signal (SIGUSR1, debug_on); + (void) signal (SIGUSR2, debug_off); +#endif + (void) signal (SIGTERM, shutdown); + (void) signal (SIGPIPE, spurious); + (void) signal (SIGALRM, spurious); + + if (nocdir == 0 && chdir (quedfldir) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("can't cd to %s", quedfldir)); + + (void) ryresponder (argc, argv, qmgr_hostname, myservice, dispatches, + table_Qmgr_Operations, start_routine, chan_lose); + + exit (0); /* NOTREACHED */ +} + +/* OPERATIONS */ + +static int op_newmessage (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + register struct type_Qmgr_MsgStruct *arg = + (struct type_Qmgr_MsgStruct *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_TRACE(("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return add_msg (sd, arg, rox, roi); +} + +static int op_readmsginfo (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + register struct type_Qmgr_ReadMessageArgument *arg = + (struct type_Qmgr_ReadMessageArgument *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return read_msg (sd, arg, rox, roi); +} + +static int op_channelbegin (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_FilterList *arg = (struct type_Qmgr_FilterList *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return chan_begin (sd, arg, rox, roi); +} + +/* ARGSUSED */ +static int op_channelread (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_UNIV_UTCTime *arg = (struct type_UNIV_UTCTime *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return channel_list (sd, arg, rox, roi); +} + +static int op_mtacontrol (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MtaControl *arg = + (struct type_Qmgr_MtaControl *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return mta_control (sd, arg, rox, roi); +} + +static int op_channelcontrol (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_ChannelControl *arg = + (struct type_Qmgr_ChannelControl *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return chan_control (sd, arg, rox, roi); +} + +static int op_mtaread (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MtaRead *arg = (struct type_Qmgr_MtaRead *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return mta_read (sd, arg, rox, roi); +} + +static int op_messagecontrol (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgControl *arg = (struct type_Qmgr_MsgControl *)in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return msg_control (sd, arg, rox, roi); + +} + +static int op_qmgrcontrol (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_QMGROp *op = (struct type_Qmgr_QMGROp *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return qmgrcontrol (sd, (int)op -> parm, rox, roi); +} + +static int op_readchannelmtamessage (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgRead *mr = (struct type_Qmgr_MsgRead *) in; + + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return msgread (sd, mr, rox, roi); +} + +/* ARGSUSED */ +static int op_qmgrstatus (sd, ryo, rox, in, roi) +int sd; +struct RyOperation *ryo; +struct RoSAPinvoke *rox; +caddr_t in; +struct RoSAPindication *roi; +{ + if (rox -> rox_nolinked == 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d", + sd, ryo -> ryo_name, rox -> rox_linkid)); + return ureject (sd, ROS_IP_LINKED, rox, roi); + } + PP_NOTICE (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name)); + + return qmgrstatus (sd, rox, roi); +} + + +/* ERROR */ + +int error (sd, err, param, rox, roi) +int sd, + err; +caddr_t param; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if (RyDsError (sd, rox -> rox_id, err, param, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "ERROR"); + + return OK; +} + +int ureject (sd, reason, rox, roi) +int sd, reason; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + if ( RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) + ros_adios (&roi -> roi_preject, "U-REJECT"); + return OK; +} + +/* debug control */ + +static int debugging = -1; + +/* ARGSUSED */ +static SFD debug_on (sig) +int sig; +{ + if (debugging == -1) + debugging = pp_log_norm -> ll_events; + if ((pp_log_norm -> ll_events & LLOG_NOTICE) == 0) + pp_log_norm -> ll_events |= LLOG_NOTICE; + else if ((pp_log_norm -> ll_events & LLOG_TRACE) == 0) + pp_log_norm -> ll_events |= LLOG_TRACE; + else + pp_log_norm -> ll_events |= LLOG_DEBUG; + ll_close (pp_log_norm); +} + +/* ARGSUSED */ +static SFD debug_off (sig) +int sig; +{ + if (debugging == -1) + debugging = pp_log_norm -> ll_events; + if (debugging != -1) { + if (pp_log_norm -> ll_events != debugging) + pp_log_norm -> ll_events = debugging; + else + pp_log_norm -> ll_events &= ~LLOG_NOTICE; + ll_close (pp_log_norm); + } +} + +/* ARGSUSED */ +static SFD shutdown (sig) +int sig; +{ + opmode = OP_SHUTDOWN; +} + +static SFD spurious (sig) +int sig; +{ + PP_LOG (LLOG_EXCEPTIONS, ("Spurious signal %d", sig)); +} diff --git a/Src/qmgr/ryresponder.c b/Src/qmgr/ryresponder.c new file mode 100644 index 0000000..b21f522 --- /dev/null +++ b/Src/qmgr/ryresponder.c @@ -0,0 +1,599 @@ +/* ryresponder.c - responder stuff - mackled out of ryresponder.c */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/ryresponder.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/ryresponder.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: ryresponder.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "qmgr.h" +#include "ryresponder.h" +#include /* for listening */ +#include +#include +#include + +/* DATA */ + +char *myname = "qmgr"; +static jmp_buf toplevel; +static IFP startfnx; +static IFP stopfnx; +static int ros_init (), + ros_work (), + ros_lose (); +static void ros_indication (); +extern void chan_manage (), + isodeexport (), + init_chans (); +extern int errno; +extern int nobackground; +extern time_t time (); +fd_set perf_rfds, + perf_wfds; +int perf_nfds; +int delaytime = NOTOK; +extern time_t current_time; + +void start_specials (), schedule (); + +static int TMagic (vecp, vec, td) +int *vecp; +char **vec; +struct TSAPdisconnect *td; +{ + int sd; + struct TSAPstart tss; + register struct TSAPstart *ts = &tss; + + if (TInit (*vecp, vec, ts, td) == NOTOK) + return NOTOK; + sd = ts -> ts_sd; + + if (TConnResponse (sd, &ts -> ts_called, ts -> ts_expedited, NULLCP, 0, + NULLQOS, td) == NOTOK) + return NOTOK; + + if (TSaveState (sd, vec + 1, td) == NOTOK) + return NOTOK; + vec[*vecp = 2] = NULL; + + return OK; +} + +background () +{ + int i; + + for (i = 0; i < 5; i++) { + switch (fork ()) { + case NOTOK: + sleep (5); + continue; + + case OK: + break; + + default: + _exit (0); + } + break; + } + + if ((i = open ("/dev/null", O_RDWR)) != NOTOK) { + if (i != 0) + (void) dup2 (i, 0), (void) close (i); + (void) dup2 (0, 1); + (void) dup2 (0, 2); + } + +#ifdef SETSID + (void) setsid (); +#endif +#ifdef TIOCNOTTY + if ((i = open ("/dev/tty", O_RDWR)) != NOTOK) { + (void) ioctl (i, TIOCNOTTY, NULLCP); + (void) close (i); + } +#else +#ifdef SYS5 + (void) setpgrp (); + (void) signal (SIGINT, SIG_IGN); + (void) signal (SIGQUIT, SIG_IGN); +#endif +#endif + isodexport (NULLCP); /* re-initialize logfiles */ +} + +/* RESPONDER */ + +int ryresponder (argc, argv, host, myservice, dispatches, ops, start, stop) +int argc; +char **argv, + *host, + *myservice; +struct server_dispatch *dispatches; +struct RyOperation *ops; +IFP start, + stop; +{ + register struct server_dispatch *ds; + AEI aei; + struct TSAPdisconnect tds; + struct TSAPdisconnect *td = &tds; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + fd_set rfds; + fd_set wfds; + int n; + int fd; + + PP_TRACE (("ryresponder (%d, argv, %s, %s...)", + argc, host, myservice)); + FD_ZERO (&perf_rfds); + FD_ZERO (&rfds); + FD_ZERO (&perf_wfds); + FD_ZERO (&wfds); + + if ((myname = rindex (argv[0], '/')) != NULLCP) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + isodetailor (myname, 0); + ll_hdinit (pp_log_norm, myname); + + if (isatty (fileno (stderr))) + pp_log_norm -> ll_stat |= LLOGTTY; + else { + if (nobackground == 0) + background (); + + } + + PP_TRACE (("starting")); + init_chans (); + + for (ds = dispatches; ds -> ds_name; ds++) + if (RyDispatch (NOTOK, ops, ds -> ds_operation, + ds -> ds_vector, roi) == NOTOK) + ros_adios (rop, ds -> ds_name); + + startfnx = start; + stopfnx = stop; + + for (n = 1;; n++) { + if ((aei = _str2aei (host,myservice, QMGR_CTX_OID, 0, + dap_user, dap_passwd)) == NULLAEI) + adios (NULLCP, "%s %s (%s): unknown service", + host, QMGR_CTX_OID, myservice); + + if (iserver_init_aux (0, argv, aei, ros_init, TMagic, 1, td) == NOTOK) { + if (n > 15) { + if (td -> td_cc > 0) + adios (NULLCP, + "iserver_init: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, + td -> td_data); + else + adios (NULLCP, "iserver_init: [%s]", + TErrString (td -> td_reason)); + } + if (td -> td_cc > 0) + PP_LOG (LLOG_EXCEPTIONS, + ("iserver_init: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, + td -> td_data)); + else + PP_LOG (LLOG_EXCEPTIONS, + ("iserver_init: [%s]", + TErrString (td -> td_reason))); + sleep ((unsigned) 5 * n); + continue; + } + break; + } +#ifdef MALLCHK + _mal_trace_restart (); +#endif + start_specials (); + + PP_TRACE(("Listening")); + + for (;;) { + schedule (); + rfds = perf_rfds; + wfds = perf_wfds; + PP_TRACE (("Main loop...")); + switch (iserver_wait (ros_init, ros_work, ros_lose, perf_nfds, + &rfds, &wfds, NULLFD, delaytime, td)) { + case DONE: + return 0; + + case NOTOK: + if (td -> td_cc > 0) + adios (NULLCP, "iserver_wait: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, + td -> td_data); + else + adios (NULLCP, "iserver_wait: [%s]", + TErrString (td -> td_reason)); + break; + case OK: + (void) time (¤t_time); + + for (fd = 0; fd < perf_nfds; fd++) + if (FD_ISSET (fd, &rfds) || + FD_ISSET (fd, &wfds)) + chan_manage (fd); + break; + default: + adios (NULLCP, "Illegal return from iserver_wait"); + } + } +} + +/* */ + +static int ros_init (vecp, vec) +int vecp; +char **vec; +{ + int reply, + result, + sd; + PE pep[1]; + int npe = 0; + struct AcSAPstart acss; + register struct AcSAPstart *acs = &acss; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + register struct PSAPstart *ps = &acs -> acs_start; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + struct TSAPdisconnect tds; + struct TSAPdisconnect *td = &tds; + + PP_TRACE (("ros_init (%d, vec)", vecp)); + + if (AcInit (vecp, vec, acs, aci) == NOTOK) { + acs_advise (aca, "initialization fails"); + return NOTOK; + } + PP_NOTICE (("A-ASSOCIATE.INDICATION/%d", acs -> acs_sd)); + sd = acs -> acs_sd; + + for (vec++; *vec; vec++) + if (**vec) + PP_LOG (LLOG_EXCEPTIONS, + ("unknown argument \"%s\"", *vec)); + + pep[0] = NULLPE; + reply = startfnx ? (*startfnx) (sd, acs, pep, &npe) : ACS_ACCEPT; + + result = AcAssocResponse (sd, reply, + reply != ACS_ACCEPT ? + ACS_USER_NOREASON : ACS_USER_NULL, + NULLOID, NULLAEI, NULLPA, NULLPC, + ps -> ps_defctxresult, + ps -> ps_prequirements, + ps -> ps_srequirements, SERIAL_NONE, + ps -> ps_settings, &ps -> ps_connect, + pep, npe, aci); + + if (pep[0]) + pe_free (pep[0]); + ACSFREE (acs); + + if (result == NOTOK) { + acs_advise (aca, "A-ASSOCIATE.RESPONSE"); + return NOTOK; + } + if (reply != ACS_ACCEPT) + return NOTOK; + + if (RoSetService (sd, RoPService, roi) == NOTOK) + ros_adios (rop, "set RO/PS fails"); + + if (TSetQueuesOK (sd, 1, td) == NOTOK) { + if (td -> td_cc > 0) + PP_LOG (LLOG_EXCEPTIONS, + ("iserver_init: [%s] %*.*s", + TErrString (td -> td_reason), + td -> td_cc, td -> td_cc, + td -> td_data)); + else + PP_LOG (LLOG_EXCEPTIONS, + ("iserver_init: [%s]", + TErrString (td -> td_reason))); + + } + return sd; +} + +/* */ + +static int ros_work (fd) +int fd; +{ + int result; + caddr_t out; + struct AcSAPindication acis; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + extern time_t time (); + + PP_TRACE (("ros_work (%d)", fd)); + + (void) time (¤t_time); + switch (setjmp (toplevel)) { + case OK: + break; + + default: + if (stopfnx) + (void) (*stopfnx) (fd, (struct AcSAPfinish *) 0); + case DONE: + (void) AcUAbortRequest (fd, NULLPEP, 0, &acis); + (void) RyLose (fd, roi); + return NOTOK; + } + + switch (result = RyWait (fd, NULLIP, &out, OK, roi)) { + case NOTOK: + if (rop -> rop_reason == ROS_TIMER) + break; + case OK: + case DONE: + ros_indication (fd, roi); + break; + + default: + adios (NULLCP, "unknown return from RoWaitRequest=%d", result); + } + + return OK; +} + +/* */ + +static void ros_indication (sd, roi) +int sd; +register struct RoSAPindication *roi; +{ + int reply, + result; + + PP_TRACE (("ros_indication (%d)", sd)); + + switch (roi -> roi_type) { + case ROI_INVOKE: + case ROI_RESULT: + case ROI_ERROR: + adios (NULLCP, "unexpected indication type=%d", + roi -> roi_type); + break; + + case ROI_UREJECT: + { + register struct RoSAPureject *rou = + &roi -> roi_ureject; + + if (rou -> rou_noid) + PP_LOG (LLOG_EXCEPTIONS, + ("RO-REJECT-U.INDICATION/%d: %s", + sd, RoErrString (rou -> rou_reason))); + else + PP_LOG (LLOG_EXCEPTIONS, + ("RO-REJECT-U.INDICATION/%d: %s (id=%d)", + sd, RoErrString (rou -> rou_reason), + rou -> rou_id)); + } + break; + + case ROI_PREJECT: + { + char tbuf[BUFSIZ]; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + (void) sprintf (tbuf, "RO-REJECT-P.INDICATION/%d", + sd); + if (ROS_FATAL (rop -> rop_reason)) + ros_adios (rop, tbuf); + ros_advise (rop, tbuf); + } + break; + + case ROI_FINISH: + { + register struct AcSAPfinish *acf = &roi -> roi_finish; + struct AcSAPindication acis; + register struct AcSAPabort *aca = &acis.aci_abort; + + PP_NOTICE (("A-RELEASE.INDICATION/%d: %d", + sd, acf -> acf_reason)); + + reply = stopfnx ? (*stopfnx) (sd, acf) : ACS_ACCEPT; + + result = AcRelResponse (sd, reply, ACR_NORMAL, + NULLPEP, 0, NOTOK, &acis); + ACFFREE (acf); + + if (result == NOTOK) + acs_advise (aca, "A-RELEASE.RESPONSE"); + else + if (reply != ACS_ACCEPT) + break; + longjmp (toplevel, DONE); + } + /* NOTREACHED */ + + default: + adios (NULLCP, "unknown indication type=%d", roi -> roi_type); + } +} + +/* */ + +static int ros_lose (td) +struct TSAPdisconnect *td; +{ + PP_TRACE (("ros_lose ()")); + + if (td -> td_cc > 0) + PP_LOG (LLOG_EXCEPTIONS, + ("TNetAccept: [%s] %*.*s", + TErrString(td -> td_reason), td -> td_cc, td -> td_cc, + td -> td_data)); + else + PP_LOG (LLOG_EXCEPTIONS, + ("TNetAccept: [%s]", + TErrString (td -> td_reason))); + return OK; +} + +/* ERRORS */ + +void ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + longjmp (toplevel, NOTOK); +} + + +void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", + RoErrString (rop -> rop_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s", event, buffer)); +} + +/* */ + +void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", + AcErrString (aca -> aca_reason)); + + PP_LOG (LLOG_EXCEPTIONS, ("%s: %s (source %d)", event, buffer, + aca -> aca_source)); +} + +/* */ + +#ifndef lint +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +/* VARARGS */ +void advise (va_alist) +va_dcl +{ + int code; + va_list ap; + + va_start (ap); + + code = va_arg (ap, int); + + _ll_log (pp_log_norm, code, ap); + + va_end (ap); +} +#else +/* VARARGS3 */ + +void advise (code, what, fmt) +char *what, + *fmt; +int code; +{ + advise (code, what, fmt); +} +#endif + + +#ifndef lint +void ryr_advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_NOTICE, ap); + + va_end (ap); +} +#else +/* VARARGS2 */ + +void ryr_advise (what, fmt) +char *what, + *fmt; +{ + ryr_advise (what, fmt); +} +#endif diff --git a/Src/qmgr/ryresponder.h b/Src/qmgr/ryresponder.h new file mode 100644 index 0000000..d5950f7 --- /dev/null +++ b/Src/qmgr/ryresponder.h @@ -0,0 +1,37 @@ +/* ryresponder.h - include file for the generic idempotent responder */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/ryresponder.h,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: ryresponder.h,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGRLOAD_RYRESPONDER +#define _H_QMGRLOAD_RYRESPONDER + + +#include + + +struct server_dispatch { + char *ds_name; + int ds_operation; + IFP ds_vector; +}; + + +extern int debug; + +void adios(), advise(); +void acs_advise(); +void ros_adios(), ros_advise(); +void ryr_advise(); +int ryresponder(); + +#endif diff --git a/Src/qmgr/structs.c b/Src/qmgr/structs.c new file mode 100644 index 0000000..2079075 --- /dev/null +++ b/Src/qmgr/structs.c @@ -0,0 +1,788 @@ +/* structs.c: structure building routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/structs.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/structs.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: structs.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "types.h" +#include "Qmgr-ops.h" +#include + +#define STR2QB(str) str2qb (str, strlen(str), 1) +#define OOM() PP_LOG(LLOG_EXCEPTIONS, ("out of memory")) +struct type_Qmgr_PrioritisedChannel *lpchan (); +struct type_Qmgr_ChannelInfo *lchani (); +struct type_Qmgr_PrioritisedMta *lpmta (); +struct type_Qmgr_MtaInfo *lmta (); +struct type_Qmgr_ProcStatus *lstatus (); +struct type_UNIV_UTCTime *ltime (); +struct type_Qmgr_MsgStruct *lmessage (); +struct type_Qmgr_PerMessageInfo *lmsginfo (); +struct type_Qmgr_MPDUIdentifier *lmpduiden (); +struct type_Qmgr_EncodedInformationTypes*leit (); +struct type_Qmgr_RecipientList *lreciplist (); +struct type_Qmgr_RecipientInfo *lrecip (); +struct type_Qmgr_ChannelList *lchanlist (); + +MsgStruct *newmsgstruct (); +static Reciplist *newrecips (); +static LIST_BPT *neweit (); +static MPDUid *newmpduid (); + +void freerecips (); +void freempdu (); + +struct type_Qmgr_ChannelInfo *lchani (clp) +Chanlist *clp; +{ + struct type_Qmgr_ChannelInfo *ci; + + PP_DBG (("lchani ()")); + + ci = (struct type_Qmgr_ChannelInfo *) + calloc (1, sizeof (*ci)); + if (ci == NULL) { + OOM (); + return NULL; + } + + ci -> channel = STR2QB (clp -> channame); + if (clp -> chan -> ch_show) + ci -> channelDescription = STR2QB (clp -> chan -> ch_show); + else + ci -> channelDescription = STR2QB (clp -> channame); + + ci -> oldestMessage = ltime (clp -> oldest); + ci -> numberMessages = clp -> num_msgs; + ci -> numberReports = clp -> num_drs; + ci -> volumeMessages = clp -> volume; + ci -> numberActiveProcesses = clp -> nactive; + ci -> status = lstatus (clp); + ci -> direction = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_BITS); + switch (clp -> chan -> ch_chan_type) { + case CH_IN: + bit_on (ci -> direction, bit_Qmgr_direction_inbound); + break; + + case CH_BOTH: + bit_on (ci -> direction, bit_Qmgr_direction_inbound); + /* fall */ + case CH_OUT: + bit_on (ci -> direction, bit_Qmgr_direction_outbound); + break; + } + if (clp -> chan -> ch_access == CH_MTS) + ci -> chantype = int_Qmgr_chantype_mts; + else + switch (clp -> chan -> ch_chan_type) { + case CH_SHAPER: + case CH_WARNING: + case CH_DELETE: + case CH_QMGR_LOAD: + case CH_DEBRIS: + case CH_TIMEOUT: + ci -> chantype = int_Qmgr_chantype_internal; + break; + + default: + ci -> chantype = int_Qmgr_chantype_mta; + break; + } + ci -> maxprocs = clp -> chan -> ch_maxproc; + ci -> numberMtas = clp -> nmtas; + return ci; +} + +struct type_Qmgr_ProcStatus *lstatus (clp) +Chanlist *clp; +{ + struct type_Qmgr_ProcStatus *ps; + + ps = (struct type_Qmgr_ProcStatus *) calloc (1, sizeof *ps); + if (ps == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, "memory", ("out of")); + return NULL; + } + + ps -> enabled = clp -> chan_enabled; + if (clp -> lastattempt) { + if((ps -> lastAttempt = ltime (clp -> lastattempt)) == NULL) { + free_Qmgr_ProcStatus (ps); + return NULL; + } + } + if (clp -> lastsuccess) + ps -> lastSuccess = ltime (clp -> lastsuccess); + if (clp -> cache.cachetime > current_time) { + if ((ps -> cachedUntil = ltime (clp -> cache.cachetime)) + == NULL) { + free_Qmgr_ProcStatus (ps); + return NULL; + } + } + + return ps; +} + +struct type_Qmgr_PrioritisedMta *lpmta (mlp, clp) +Mtalist *mlp; +Chanlist *clp; +{ + struct type_Qmgr_PrioritisedMta *pmta; + + PP_DBG (("lpmta ()")); + + pmta = (struct type_Qmgr_PrioritisedMta *) calloc (1, sizeof (*pmta)); + if (pmta == NULL) { + OOM (); + return NULL; + } + + pmta -> priority = (struct type_Qmgr_Priority *) + calloc (1, sizeof *pmta -> priority); + if (pmta -> priority == NULL) { + OOM (); + free_Qmgr_PrioritisedMta (pmta); + return NULL; + } + + pmta -> priority -> parm = 1; + + pmta -> mta = lmta (mlp, clp); + if (pmta -> mta == NULL) { + free_Qmgr_PrioritisedMta (pmta); + return NULL; + } + + return pmta; +} + +struct type_Qmgr_MtaInfo *lmta (mlp, clp) +Mtalist *mlp; +Chanlist *clp; +{ + struct type_Qmgr_MtaInfo *mta; + + mta = (struct type_Qmgr_MtaInfo *) calloc (1, sizeof *mta); + if (mta == NULL) { + OOM (); + return NULL; + } + + mta -> channel = STR2QB (clp -> channame); + mta -> mta = STR2QB (mlp -> mtaname); + + mta -> oldestMessage = ltime (mlp -> oldest); + mta -> numberMessage = mlp -> num_msgs; + mta -> numberDRs = mlp -> num_drs; + mta -> volumeMessages = mlp -> volume; + + mta -> status = (struct type_Qmgr_ProcStatus *) + calloc (1, sizeof *mta -> status); + if (mta -> status == NULL) { + OOM (); + free_Qmgr_MtaInfo (mta); + return NULL; + } + + mta -> status -> enabled = mlp -> mta_enabled; + if (mlp -> lastattempt) + mta -> status -> lastAttempt = ltime (mlp -> lastattempt); + if (mlp -> lastsuccess) + mta -> status -> lastSuccess = ltime (mlp -> lastsuccess); + + if (mlp -> cache.cachetime > current_time) + mta -> status -> cachedUntil = ltime (mlp -> cache.cachetime); + mta -> active = mlp -> nactive > 0; + if (mlp -> info) + mta -> info = STR2QB (mlp -> info); + else + mta -> info = NULL; + return mta; +} + + struct type_UNIV_UTCTime *ltime (when) +time_t when; +{ + UTC ut; + char *str; + struct qbuf *qb; + + ut = time_t2utc (when); + str = utct2str (ut); + + qb = STR2QB (str); + free ((char *)ut); + + return qb; +} + + +struct type_Qmgr_PrioritisedChannel *lpchan (clp) +Chanlist *clp; +{ + struct type_Qmgr_PrioritisedChannel *pc; + + PP_DBG (("lpchan ()")); + + pc = (struct type_Qmgr_PrioritisedChannel *) + calloc (1, sizeof *pc); + if (pc == NULL) { + OOM (); + return NULL; + } + + pc -> channel = lchani (clp); + pc -> priority = (struct type_Qmgr_Priority *) + calloc (1, sizeof *pc -> priority); + if (pc -> priority == NULL) { + OOM (); + free_Qmgr_PrioritisedChannel (pc); + return NULL; + } + + pc -> priority -> parm = int_Qmgr_Priority_normal; + + return pc; +} + +struct type_Qmgr_UserList *lusers (ml, check) +Mlist *ml; +int check; +{ + int i; + struct type_Qmgr_UserList **upp, *upbase, *up; + Reciplist *rl; + + PP_TRACE (("lusers (ml, %d) %d", check, ml -> rcount)); + upbase = NULL; + upp = &upbase; + + for (i = 0; i < ml -> rcount; i++) { + rl = ml -> recips[i]; + if (check) { + if (rl -> msg_enabled == 0) + continue; + if (rl -> cache.cachetime > current_time) + continue; + } + *upp = (struct type_Qmgr_UserList *) calloc (1, sizeof *up); + up = *upp; + upp = &(*upp) -> next; + up -> RecipientId = (struct type_Qmgr_RecipientId *) + calloc (1, sizeof *up -> RecipientId); + up -> RecipientId -> parm = rl->id; + PP_DBG (("Adding user %d to list", rl->id)); + } + return upbase; +} + +MsgStruct *newmsgstruct (msg) +struct type_Qmgr_MsgStruct *msg; +{ + MsgStruct *ms; + struct type_Qmgr_PerMessageInfo *pmi; + + if ((ms = (MsgStruct *) malloc (sizeof *ms)) == NULLMS) + return ms; + bzero ((char *)ms, sizeof *ms); + + ms -> ms_forw = NULLMS; + ms -> count = 0; + pmi = msg -> messageinfo; + + ms -> queid = qb2str (pmi -> queueid); + ms -> mpduid = newmpduid (pmi -> mpduiden); + ms -> originator = qb2str (pmi -> originator); + if (pmi -> contenttype) + ms -> contenttype = qb2str (pmi -> contenttype); + else ms -> contenttype = NULLCP; + if (pmi -> eit) + ms -> eit = neweit (pmi -> eit); + else ms -> eit = NULL; + ms -> priority = pmi -> priority -> parm; + ms -> size = pmi -> size; + ms -> age = utcqb2time_t (pmi -> age); + ms -> warninterval = pmi -> warnInterval; + if (ms -> warninterval == 0) + ms -> warninterval = 24 * 60 * 60; /* default it */ + else ms -> warninterval *= 3600; + ms -> numberwarns = pmi -> numberWarningsSent; + ms -> expirytime = utcqb2time_t (pmi -> expiryTime); + if (pmi -> deferredTime) + ms -> defferedtime = utcqb2time_t (pmi -> deferredTime); + else ms -> defferedtime = 0; + if ( pmi -> uaContentId) + ms -> uacontent = qb2str (pmi -> uaContentId); + else ms -> uacontent = NULLCP; + if (pmi -> inChannel) { + char *p = qb2str (pmi -> inChannel); + ms -> inchan = ch_nm2struct (p); + free (p); + } + ms -> recips = newrecips (msg -> recipientlist); + ms -> m_locked = 0; + return ms; +} + +static Reciplist *newrecips (rlist) +struct type_Qmgr_RecipientList *rlist; +{ + Reciplist *nr; + struct type_Qmgr_RecipientInfo *ri; + struct type_Qmgr_ChannelList *qclp; + LIST_RCHAN *chan; + char *p; + int i; + + if (rlist == NULL) + return NULLRL; + + nr = (Reciplist *) smalloc (sizeof *nr); + bzero ((char *)nr, sizeof *nr); + + ri = rlist -> RecipientInfo; + nr -> status = ST_NORMAL; + nr -> id = ri -> id -> parm; + nr -> user = qb2str (ri -> user); + nr -> mta = qb2str (ri -> mta); + nr -> chans = NULL; + for (qclp = ri -> channelList; qclp; qclp = qclp -> next) { + chan = list_rchan_new (NULLCP, p = qb2str(qclp -> Channel)); + free (p); + if (chan) + list_rchan_add (&nr -> chans, chan); + } + nr -> cchan = nr -> chans; + for (i = ri->channelsDone; i > 0; i--) { + if (nr -> cchan == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("Run out of channels")); + break; + } + nr -> cchan = nr -> cchan -> li_next; + } + nr -> msg_enabled = 1; + + nr -> rp_next = newrecips (rlist -> next); + + return nr; +} + +static LIST_BPT *neweit (eit) +struct type_Qmgr_EncodedInformationTypes *eit; +{ + LIST_BPT *bpt = NULLIST_BPT, *bp; + char *p; + + for (; eit; eit = eit -> next) { + bp = list_bpt_new (p = qb2str (eit -> PrintableString)); + if (bp) + list_bpt_add (&bpt, bp); + free (p); + } + + return bpt; +} + + +static MPDUid *newmpduid (mpduiden) +struct type_Qmgr_MPDUIdentifier *mpduiden; +{ + MPDUid *mi; + struct type_Qmgr_GlobalDomainIdentifier *gdi = + mpduiden -> global; + struct type_Qmgr_CountryName *co = gdi -> country; + struct type_Qmgr_AdministrationDomainName *admd = + gdi -> admd; + struct type_Qmgr_PrivateDomainIdentifier *prmd = + gdi -> prmd; + GlobalDomId *gd; + + mi = (MPDUid *) malloc (sizeof *mi); + + mi -> mpduid_string = qb2str (mpduiden -> local); + gd = &mi -> mpduid_DomId; + + gd -> global_Country = + qb2str (co -> offset == + type_Qmgr_CountryName_numeric ? + co -> un.numeric : + co -> un.printable); + + gd -> global_Admin = + qb2str (admd -> offset == + type_Qmgr_AdministrationDomainName_numeric ? + admd -> un.numeric : + admd -> un.printable); + + if (prmd) + gd -> global_Private = + qb2str (prmd -> offset == + type_Qmgr_PrivateDomainIdentifier_numeric ? + prmd -> un.numeric : + prmd -> un.printable); + else gd -> global_Private = NULLCP; + return mi; +} + +Filter *newfilter (flp) +struct type_Qmgr_FilterList *flp; +{ + Filter *f; + struct type_Qmgr_Filter *fl; + + if (flp == NULL || flp -> Filter == NULL) + return NULL; + + f = (Filter *) calloc (1, sizeof *f); + + fl = flp -> Filter; + + if (fl -> contenttype) + f -> cont = qb2str (fl -> contenttype); + if (fl -> eit) + f -> eit = neweit (fl -> eit); + if (fl -> priority) + f -> priority = fl -> priority -> parm; + else f -> priority = -1; + + if (fl -> moreRecentThan) + f -> morerecent = utcqb2time_t (fl -> moreRecentThan); + if (fl -> earlierThan) + f -> earlier = utcqb2time_t (fl -> earlierThan); + f -> maxsize = fl -> maxSize; + if (fl -> originator) + f -> orig = qb2str (fl -> originator); + if (fl -> recipient) + f -> recip = qb2str (fl -> recipient); + if (fl -> channel) { + char *p; + + f -> channel = ch_nm2struct(p = qb2str (fl -> channel)); + free (p); + } + if (fl -> mta) + f -> mta = qb2str (fl -> mta); + if (fl -> queueid) + f -> queid = qb2str (fl -> queueid); + if (fl -> mpduiden) + f -> mpduid = newmpduid (fl -> mpduiden); + if (fl -> uaContentId) + f -> uacontent = qb2str (fl -> uaContentId); + if (flp -> next) + f -> next = newfilter (flp -> next); + return f; +} + + +struct type_Qmgr_MsgStruct *lmessage (ms) +MsgStruct *ms; +{ + struct type_Qmgr_MsgStruct *qms; + + qms = (struct type_Qmgr_MsgStruct *) calloc (1, sizeof *qms); + + qms -> messageinfo = lmsginfo (ms); + qms -> recipientlist = lreciplist (ms -> recips, NULLCP); + return qms; +} + +struct type_Qmgr_MsgStruct *l_cm_message (ml) +Mlist *ml; +{ + struct type_Qmgr_MsgStruct *qms; + struct type_Qmgr_RecipientList **rl; + int i; + + qms = (struct type_Qmgr_MsgStruct *) calloc (1, sizeof *qms); + + qms -> messageinfo = lmsginfo (ml -> ms); + rl = &qms -> recipientlist; + *rl = (struct type_Qmgr_RecipientList *) smalloc (sizeof **rl); + (*rl) -> RecipientInfo = lrecip (ml -> ms -> recips, + ml -> ms -> recips, + NULLCP); + (*rl) -> next = NULL; + rl = &(*rl) -> next; + for ( i = 0; i < ml -> rcount; i++) { + *rl = (struct type_Qmgr_RecipientList *) + smalloc (sizeof **rl); + (*rl) -> RecipientInfo = lrecip (ml -> recips[i], + ml -> ms -> recips, + ml -> info); + (*rl) -> next = NULL; + rl = &(*rl) -> next; + } + return qms; +} + +struct type_Qmgr_PerMessageInfo *lmsginfo (ms) +MsgStruct *ms; +{ + struct type_Qmgr_PerMessageInfo *pmi; + + pmi = (struct type_Qmgr_PerMessageInfo *) calloc (1, sizeof *pmi); + + pmi -> queueid = STR2QB (ms -> queid); + pmi -> mpduiden = lmpduiden (ms->mpduid); + pmi -> originator = STR2QB (ms -> originator); + if (ms -> contenttype) + pmi -> contenttype = STR2QB (ms -> contenttype); + if (ms -> eit) + pmi -> eit = leit (ms -> eit); + pmi -> priority = (struct type_Qmgr_Priority *) + calloc (1, sizeof *(pmi -> priority)); + pmi -> priority -> parm = ms -> priority; + pmi -> size = ms -> size; + pmi -> age = ltime (ms->age); + pmi -> warnInterval = ms -> warninterval; + pmi -> numberWarningsSent = ms -> numberwarns; + pmi -> expiryTime = ltime (ms->expirytime); + if (ms -> defferedtime) + pmi -> deferredTime = ltime (ms -> defferedtime); + else pmi -> deferredTime = NULL; + if (ms -> uacontent) + pmi -> uaContentId = STR2QB (ms -> uacontent); + else pmi -> uaContentId = NULL; + pmi -> errorCount = ms -> nerrors; + pmi -> optionals |= opt_Qmgr_PerMessageInfo_errorCount; + + if (ms -> inchan) + pmi -> inChannel = STR2QB (ms -> inchan -> ch_name); + return pmi; +} + +struct type_Qmgr_MPDUIdentifier *lmpduiden (mpduid) +MPDUid *mpduid; +{ + struct type_Qmgr_MPDUIdentifier *mp; + struct type_Qmgr_GlobalDomainIdentifier *gdi; + struct type_Qmgr_CountryName *co; + struct type_Qmgr_AdministrationDomainName *admd; + struct type_Qmgr_PrivateDomainIdentifier *prmd; + + mp = (struct type_Qmgr_MPDUIdentifier *) calloc (1, sizeof *mp); + + mp -> local = STR2QB (mpduid -> mpduid_string); + + gdi = mp -> global = + (struct type_Qmgr_GlobalDomainIdentifier *) + calloc (1, sizeof *gdi); + + co = gdi -> country = + (struct type_Qmgr_CountryName *) calloc (1, sizeof *co); + co -> offset = type_Qmgr_CountryName_printable; + co -> un.printable = + STR2QB (mpduid -> mpduid_DomId.global_Country); + + admd = gdi -> admd = + (struct type_Qmgr_AdministrationDomainName *) + calloc (1, sizeof *admd); + admd -> offset = type_Qmgr_AdministrationDomainName_printable; + admd -> un.printable = + STR2QB (mpduid -> mpduid_DomId.global_Admin); + + if (mpduid -> mpduid_DomId.global_Private) { + prmd = gdi -> prmd = + (struct type_Qmgr_PrivateDomainIdentifier *) + calloc (1, sizeof *prmd); + prmd -> offset = type_Qmgr_PrivateDomainIdentifier_printable; + prmd -> un.printable = + STR2QB (mpduid -> mpduid_DomId.global_Private); + } + else + gdi -> prmd = NULL; + + return mp;; +} + +struct type_Qmgr_EncodedInformationTypes *leit (eit) +LIST_BPT *eit; +{ + struct type_Qmgr_EncodedInformationTypes *et = NULL, *ep; + LIST_BPT *bp; + + for (bp = eit; bp; bp = bp -> li_next) { + ep = (struct type_Qmgr_EncodedInformationTypes *) + calloc (1, sizeof *eit); + if (et == NULL) + et = ep; + ep -> PrintableString = STR2QB (bp -> li_name); + ep = ep -> next; + } + return et; +} + +struct type_Qmgr_RecipientList *lreciplist (recips, info) +Reciplist *recips; +char *info; +{ + struct type_Qmgr_RecipientList *rlbase = NULL, *rl = NULL; + Reciplist *rlp; + + for (rlp = recips; rlp != NULLRL; rlp = rlp -> rp_next) { + if (rlbase == NULL) + rlbase = rl = (struct type_Qmgr_RecipientList *) + calloc (1, sizeof *rl); + else { + rl -> next = (struct type_Qmgr_RecipientList *) + calloc (1, sizeof *rl); + rl = rl -> next; + } + rl -> RecipientInfo = lrecip (rlp, recips, info); + } + return rlbase; +} + +struct type_Qmgr_RecipientInfo *lrecip (rlp, rl0, info) +Reciplist *rlp; +Reciplist *rl0; +char *info; +{ + struct type_Qmgr_RecipientInfo *ri; + + ri = (struct type_Qmgr_RecipientInfo *) calloc (1, sizeof *ri); + + ri -> user = STR2QB (rlp -> user); + ri -> id = (struct type_Qmgr_RecipientId *) + calloc (1, sizeof *ri -> id); + ri -> id -> parm = rlp -> id; + ri -> mta = STR2QB (rlp -> mta); + + switch (rlp -> status) { + case ST_NORMAL: + { + LIST_RCHAN *lcp; + + ri -> channelsDone = 0; + ri -> channelList = lchanlist (rlp -> chans); + for (lcp = rlp -> chans; lcp && lcp != rlp -> cchan; + lcp = lcp -> li_next) + ri -> channelsDone ++; + } + break; + + case ST_DR: + ri -> channelsDone = 0; + ri -> channelList = lchanlist (rl0 -> chans); + break; + + case ST_DELETE: + ri -> channelsDone = 0; + ri -> channelList = (struct type_Qmgr_ChannelList *) + smalloc (sizeof *ri -> channelList); + ri -> channelList -> Channel = + STR2QB (delete_chan -> channame); + ri -> channelList -> next = NULL; + break; + + case ST_TIMEOUT: + ri -> channelsDone = 0; + ri -> channelList = (struct type_Qmgr_ChannelList *) + smalloc (sizeof *ri -> channelList); + ri -> channelList -> Channel = + STR2QB (timeout_chan -> channame); + ri -> channelList -> next = NULL; + break; + } + + ri -> procStatus = (struct type_Qmgr_ProcStatus *) + calloc (1, sizeof *ri -> procStatus); + ri -> procStatus -> enabled = rlp -> msg_enabled; + if (rlp -> cache.cachetime > current_time) + ri -> procStatus -> cachedUntil = + ltime (rlp -> cache.cachetime); + if (info) + ri -> info = STR2QB (info); + else ri -> info = NULL; + return ri; +} + +struct type_Qmgr_ChannelList *lchanlist (chans) +LIST_RCHAN *chans; +{ + struct type_Qmgr_ChannelList *clp; + + if (chans == NULL) + return NULL; + + clp = (struct type_Qmgr_ChannelList *) calloc (1, sizeof *clp); + + clp -> Channel = STR2QB (chans -> li_chan -> ch_name); + clp -> next = lchanlist (chans -> li_next); + return clp; +} + + +void freems (ms) +MsgStruct *ms; +{ + freerecips (ms->recips); + if (ms -> uacontent) + free (ms -> uacontent); + list_bpt_free (ms -> eit); + if (ms -> contenttype) + free (ms -> contenttype); + if (ms -> originator) + free (ms -> originator); + freempdu (ms -> mpduid); + if (ms -> queid) + free (ms -> queid); + free ((char *)ms); +} + +void freerecips (rlist) +Reciplist *rlist; +{ + if (rlist == NULLRL) + return; + freerecips (rlist -> rp_next); + list_rchan_free (rlist -> chans); + free (rlist -> mta); + free (rlist -> user); + + free ((char *)rlist); +} + +void freempdu (mp) +MPDUid *mp; +{ + MPDUid_free (mp); + free ((char *)mp); +} + +void freefilter (f) +Filter *f; +{ + if (f -> cont) + free (f -> cont); + if (f -> eit) + list_bpt_free (f -> eit); + if (f -> orig) + free (f -> orig); + if (f -> recip) + free (f -> recip); + if (f -> mta) + free (f -> mta); + if (f -> queid) + free (f -> queid); + if (f -> mpduid) + freempdu (f -> mpduid); + if (f -> uacontent) + free (f -> uacontent); + if (f -> next) + freefilter (f -> next); + free ((char *)f); +} diff --git a/Src/qmgr/tables.c b/Src/qmgr/tables.c new file mode 100644 index 0000000..93830a5 --- /dev/null +++ b/Src/qmgr/tables.c @@ -0,0 +1,2083 @@ +/* tables.c: table handling routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/qmgr/RCS/tables.c,v 6.0 1991/12/18 20:27:38 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/tables.c,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: tables.c,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "types.h" +#include "qmgr.h" + +/* Variables */ + +MsgStruct *msg_hash[QUE_HASHSIZE]; +Chanlist **chan_list; +int nchanlist = 0; + +/* Procedures & functions */ + +extern char *strdup (); +int hash (); +void addtochan (); +void create_chan (); +Mtalist *findmtalist (); +MsgStruct *find_msg (); +Mlist *findmtamsg (); +Chanlist *delete_chan = NULLCHANLIST; +Chanlist *loader_chan = NULLCHANLIST; +Chanlist *trash_chan = NULLCHANLIST; +Chanlist *timeout_chan = NULLCHANLIST; +Chanlist *warn_chan = NULLCHANLIST; +Chanlist *findchanlist (); +static void mcontrol (); +static int chaninsert (); +static int insertinmta (); +static int addmtaid (); +static int filtermatch (); +static int compmpduid (); +static int nullstrcmp (); +static int bind_result (); +static int bind_error (); +static void setchannels (); + +void insertinchan (); +void insertindelchan (); +void insertindrchan (); +void cache_clear (); +void cache_set (); +void cache_inc (); +void freems (); +void freefilter (); + +int zapmtamsg (); + +/* External functions */ +extern struct type_Qmgr_PrioritisedChannel *lpchan (); +extern struct type_Qmgr_ChannelInfo *lchani (); +extern struct type_Qmgr_PrioritisedMta *lpmta (); +extern struct type_Qmgr_MtaInfo *lmta (); +extern struct type_Qmgr_ProcStatus *lstatus (); +extern struct type_Qmgr_MsgStruct *lmessage (); +extern struct type_Qmgr_MsgStruct *l_cm_message (); +extern struct type_UNIV_UTCTime *ltime (); +extern void addtorunq (), delfromrunq (); +extern void investigate_mta (); +extern MsgStruct *newmsgstruct (); +extern Filter *newfilter (); + +extern int maxchansrunning, nchansrunning; + +#define STR2QB(s) str2qb ((s), strlen((s)), 1) + +static int check_credentails (cb, name, passwd) +Connblk *cb; +char *name, *passwd; +{ + extern char *crypt (); + char result[BUFSIZ]; + static Table *auth= NULLTBL; + char *av[30]; + int ac; + char *tbl_passwd = NULLCP; + char *tbl_rights = NULLCP; + char *tbl_name; + extern char *qmgr_auth_tbl; + + cb -> cb_authenticated = 0; + if (auth == NULLTBL) { + if ((auth = tb_nm2struct(qmgr_auth_tbl)) == NULLTBL) { + PP_NOTICE (("Accepted Limited Access for %s", + name)); + return int_Qmgr_result_acceptedLimitedAccess; + } + } + if (name == NULLCP) + tbl_name = "anon"; + else tbl_name = name; + + if (tb_k2val (auth, tbl_name, result, TRUE) == NOTOK) { + if (name == NULLCP) { + PP_NOTICE (("Accepted Limited Access for %s", + tbl_name)); + return int_Qmgr_result_acceptedLimitedAccess; + } + else { + PP_NOTICE (("Refused connection for %s", tbl_name)); + return NOTOK; + } + } + + ac = sstr2arg (result, 30, av, ", \t"); + for (ac --; ac >= 0; ac --) { + char *cp; + + if ((cp = index (av[ac], '=')) == NULLCP) + tbl_passwd = av[ac]; + else { + *cp ++ = '\0'; + if (lexequ (av[ac], "passwd") == 0) + tbl_passwd = cp; + else if (lexequ (av[ac], "rights") == 0) + tbl_rights = cp; + } + } + + if (tbl_passwd) { + if (passwd == NULLCP) { + PP_LOG (LLOG_EXCEPTIONS, + ("Password required, none given for %s", + tbl_name)); + return NOTOK; + } + if (strcmp (tbl_passwd, crypt (passwd, tbl_passwd)) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("Password mismatch for %s", tbl_name)); + return NOTOK; + } + } + /* now authenticated, if required */ + + if (tbl_rights == NULLCP) { + PP_NOTICE (("Limited Access granted for %s (no default rights)", + tbl_name)); + cb -> cb_authenticated = 0; + return int_Qmgr_result_acceptedLimitedAccess; + } + if (lexequ (tbl_rights, "none") == 0) { + PP_NOTICE (("%s explicitly refused", tbl_name)); + return NOTOK; + } + if (lexequ (tbl_rights, "limited") == 0) { + PP_NOTICE (("Limited access granted for %s", tbl_name)); + return int_Qmgr_result_acceptedLimitedAccess; + } + if (lexequ (tbl_rights, "full") == 0) { + PP_NOTICE (("Full Access granted for %s", tbl_name)); + cb -> cb_authenticated = 1; + return int_Qmgr_result_acceptedFullAccess; + } + PP_LOG (LLOG_EXCEPTIONS, ("Unknown rights '%s'", tbl_rights)); + return NOTOK; +} + +int start_routine (sd, acs, pep, npe) +int sd; +struct AcSAPstart *acs; +PE *pep; +int *npe; +{ + struct type_Qmgr_BindArgument *ba; + Connblk *cb; + + PP_TRACE (("start_routine (%d)", sd)); + *pep = NULLPE; + cb = newcblk (cb_responder); + cb -> cb_fd = sd; + + *npe = 0; + if (acs -> acs_ninfo == 0) { + cb -> cb_authenticated = 0; + return bind_result (pep, npe, cb, + int_Qmgr_result_acceptedLimitedAccess); + } + + if (decode_Qmgr_BindArgument (acs -> acs_info[0], 1, + NULLVP, NULLIP, &ba) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("failed to parse connect data [%s]", + PY_pepy)); + cb -> cb_authenticated = 0; + return bind_result (pep, npe, cb, + int_Qmgr_result_acceptedLimitedAccess); + } + if (ba -> offset == type_Qmgr_BindArgument_noAuthentication) { + cb -> cb_authenticated = 0; + free_Qmgr_BindArgument (ba); + if (check_credentails (cb, NULLCP, NULLCP) == NOTOK) + return bind_error (pep, npe, cb, + int_Qmgr_reason_badCredentials); + return bind_result (pep, npe, cb, + int_Qmgr_result_acceptedLimitedAccess); + } + + if (ba -> offset == type_Qmgr_BindArgument_weakAuthentication) { + char *username; + char *pass; + int result; + + username = qb2str (ba -> un.weakAuthentication -> username); + if (ba -> un.weakAuthentication -> passwd) + pass = qb2str (ba -> un.weakAuthentication -> passwd); + else pass = NULLCP; + + result = check_credentails (cb, username, pass); + + if (username) free (username); + if (pass) free (pass); + free_Qmgr_BindArgument (ba); + if (result == NOTOK) + return bind_error (pep, npe, cb, + int_Qmgr_reason_badCredentials); + else + return bind_result (pep, npe, cb, result); + } + free_Qmgr_BindArgument (ba); + return bind_error (pep, npe, cb, int_Qmgr_reason_congested); +} + + +static int bind_result (pep, npe, cb, type) +PE *pep; +int *npe; +Connblk *cb; +int type; +{ + struct type_Qmgr_BindResult *br; + extern char *qmgr_hostname, *ppversion; + + PP_TRACE (("bind_result")); + + br = (struct type_Qmgr_BindResult *) smalloc (sizeof *br); + br -> result = type; + br -> information = STR2QB (qmgr_hostname); + br -> version = STR2QB (ppversion); + + if (encode_Qmgr_BindResult (pep, 1, NULLCP, 0, br) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("failed to encode BindResult [%s]", + PY_pepy)); + free_Qmgr_BindResult (br); + return bind_error (pep, npe, cb, + int_Qmgr_reason_congested); + } + (*pep) -> pe_context = 3; + free_Qmgr_BindResult (br); + *npe = 1; + return ACS_ACCEPT; +} + +static int bind_error (pep, npe, cb, type) +PE *pep; +int *npe; +Connblk *cb; +int type; +{ + struct type_Qmgr_BindError *be; + + PP_TRACE (("bind_error")); + + be = (struct type_Qmgr_BindError *) smalloc (sizeof *be); + be -> reason = type; + be -> information = NULL; + + cb -> cb_fd = NOTOK; + freecblk (cb); + if (encode_Qmgr_BindError (pep, 1, NULLCP, 0, be) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Failed to build BindError [%s]", PY_pepy)); + *pep = NULLPE; + *npe = 0; + free_Qmgr_BindError (be); + return ACS_PERMANENT; + } + (*pep) -> pe_context = 3; + *npe = 1; + free_Qmgr_BindError (be); + return ACS_PERMANENT; +} + +int add_msg (sd, msg, rox, roi) +int sd; +struct type_Qmgr_MsgStruct *msg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + MsgStruct *ms, *oldms; + int result; + + PP_TRACE (("add_msg (%d, msg, rox, roi)", sd)); + + if (submission_disabled == 1) /* not submitting right now */ + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + if ((ms = newmsgstruct (msg)) == NULLMS) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + if (ms -> inchan && ms -> inchan -> ch_chan_type == CH_IN) { + Chanlist *clp; + + if ((clp = findchanlist (ms -> inchan)) && + clp -> lastsuccess < ms -> age) + clp -> lastsuccess = ms -> age; + } + + if ((oldms = find_msg (ms -> queid)) != NULLMS) { + result = updatemessage (oldms, ms); + freems (ms); + } + else + result = insertmessage (ms); + + if (result == OK) + return RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, + ROS_NOPRIO, roi); + else + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); +} + +/* ARGSUSED */ +int updatemessage (old, new) +MsgStruct *old, *new; +{ + PP_TRACE (("updatemessage ()")); + /* to be written !! */ + PP_NOTICE (("update on message %s - ignored", new -> queid)); + + return OK; +} + +int insertmessage (ms) +MsgStruct *ms; +{ + MsgStruct **msp; + + + PP_TRACE (("insertmessage ()")); + + for (msp = &msg_hash[hash(ms -> queid, QUE_HASHSIZE)]; *msp; + msp = &(*msp) -> ms_forw) + continue; + + (*msp) = ms; + + switch (chaninsert (ms)) { + case NOTOK: /* back out change */ + freems (ms); + (*msp) = NULLMS; + return NOTOK; + case OK: /* normal */ + stats.n_messages_in ++; + break; + case DONE: /* deletion */ + break; + } + return OK; +} + +/* ARGSUSED */ +int read_msg (sd, rma, rox, roi) +int sd; +struct type_Qmgr_ReadMessageArgument *rma; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + MsgStruct **msp, *ms; + struct type_Qmgr_MsgStructList **mlp; + struct type_Qmgr_MsgList *base; + Filter *filter; + + PP_TRACE (("read_msg (%d)", sd)); + + if ((base = (struct type_Qmgr_MsgList *) calloc (1, sizeof *base)) + == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + mlp = &base -> msgs; + + filter = newfilter (rma -> filters); + + for (msp = msg_hash; msp < &msg_hash[QUE_HASHSIZE]; msp++) { + for (ms = *msp; ms; ms = ms -> ms_forw) { + if (filtermatch (filter, ms)) { + *mlp = (struct type_Qmgr_MsgStructList *) + calloc (1, sizeof (**mlp)); + + (*mlp) -> MsgStruct = lmessage (ms); + mlp = &(*mlp) -> next; + } + } + } + freefilter (filter); + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) base, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_MsgList (base); + + return OK; +} + +/* ARGSUSED */ +int channel_list (sd, arg, rox, roi) +int sd; +struct type_UNIV_UTCTime *arg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + struct type_Qmgr_ChannelReadResult *crr; + struct type_Qmgr_PrioritisedChannelList **list; + Chanlist **clp; + + PP_TRACE (("channel_list (%d)", sd)); + + crr = (struct type_Qmgr_ChannelReadResult *) smalloc (sizeof *crr); + list = &crr -> channels; + crr -> channels = NULL; + crr -> load1 = 100 * stats.runnable_chans; + crr -> load2 = 100 * stats.ops_sec; + crr -> currchans = nchansrunning; + crr -> maxchans = maxchansrunning; + + for (clp = chan_list; clp < &chan_list[nchanlist]; clp ++) { + *list = (struct type_Qmgr_PrioritisedChannelList *) + calloc (1, sizeof (**list)); + + if (*list == NULL || + ((*list) -> PrioritisedChannel = lpchan (*clp)) == NULL) { + free_Qmgr_ChannelReadResult (crr); + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + } + + list = &((*list) -> next); + } + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) crr, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + + free_Qmgr_ChannelReadResult (crr); + return OK; +} + +int chan_control (sd, in, rox, roi) +int sd; +struct type_Qmgr_ChannelControl *in; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + Chanlist *clp; + struct type_Qmgr_PrioritisedChannelList *pcl; + struct type_Qmgr_PrioritisedChannel *pc; + Connblk *cb; + char *p; + + PP_TRACE (("chan_control (%d)", sd)); + + if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + if (cb -> cb_authenticated == 0) + return error (sd, error_Qmgr_authenticationFailure, + (caddr_t) NULL, rox, roi); + + p = qb2str (in -> channel); + clp = findchanlist (ch_nm2struct (p)); + free (p); + if (clp == NULLCHANLIST) + return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL, + rox, roi); + + switch (in -> control -> offset) { + case type_Qmgr_Control_stop: + clp -> chan_enabled = 0; + clp -> chan_syssusp = 0; + break; + + case type_Qmgr_Control_start: + if (clp -> chan_enabled == 0) + clp -> chan_update = 1; + clp -> chan_enabled = 1; + clp -> chan_syssusp = 0; + break; + + case type_Qmgr_Control_cacheClear: + cache_clear (&clp -> cache); + clp -> chan_update = 1; + break; + + case type_Qmgr_Control_cacheAdd: + cache_set (&clp -> cache, in -> control -> un.cacheAdd); + clp -> nextevent = clp -> cache.cachetime; + break; + + default: + return error (sd, error_Qmgr_illegalOperation, (caddr_t) NULL, + rox, roi); + } + + pcl = (struct type_Qmgr_PrioritisedChannelList *) malloc (sizeof *pcl); + + if ((pc = lpchan (clp)) == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + pcl -> PrioritisedChannel = pc; + pcl -> next = NULL; + if (RyDsResult (sd, rox -> rox_id, (caddr_t) pcl, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_PrioritisedChannelList (pcl); + return OK; +} + +/*ARGSUSED */ +int chan_begin (sd, arg, rox, roi) +int sd; +struct type_Qmgr_FilterList *arg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + struct type_Qmgr_FilterList *out; + + PP_TRACE (("chan_begin (%d)", sd)); + + out = (struct type_Qmgr_FilterList *) calloc (1, sizeof(*out)); + if (out == NULL || (out -> Filter = (struct type_Qmgr_Filter *) + calloc (1, sizeof (struct type_Qmgr_Filter))) + == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) out, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_FilterList (out); + return OK; +} + +int mta_control (sd, arg, rox, roi) +int sd; +struct type_Qmgr_MtaControl *arg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + Chanlist *clp = NULLCHANLIST; + Mtalist *mlp; + struct type_Qmgr_MtaInfo *mta; + CHAN *chan; + Connblk *cb; + char *p; + + PP_TRACE (("mta_control (%d)", sd)); + + if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + if (cb -> cb_authenticated == 0) + return error (sd, error_Qmgr_authenticationFailure, + (caddr_t) NULL, rox, roi); + + p = qb2str (arg -> channel); + if ((chan = ch_nm2struct (p)) != NULLCHAN) + clp = findchanlist (chan); + free (p); + + if (clp == NULLCHANLIST) + return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL, + rox, roi); + p = qb2str (arg -> mta); + mlp = findmtalist (clp, p); + free(p); + + if (mlp == NULLMTALIST) + return error (sd, error_Qmgr_mtaNotInQueue, (caddr_t) NULL, + rox, roi); + + switch (arg -> control -> offset) { + case type_Qmgr_Control_stop: + mlp -> mta_enabled = 0; + break; + case type_Qmgr_Control_start: + if (mlp -> mta_enabled == 0) { + mlp -> mta_changed = 1; + clp -> chan_update = 1; + } + mlp -> mta_enabled = 1; + break; + case type_Qmgr_Control_cacheClear: + cache_clear (&mlp -> cache); + mlp -> mta_changed = 1; + clp -> chan_update = 1; + remque (mlp); + insque (mlp, clp -> mtas -> mta_forw); + break; + case type_Qmgr_Control_cacheAdd: + cache_set (&mlp -> cache, arg -> control -> un.cacheAdd); + mlp -> mta_changed = 1; + clp -> chan_update = 1; + remque (mlp); + insque (mlp, clp -> mtas -> mta_back); + break; + default: + return error (sd, error_Qmgr_illegalOperation, (caddr_t) NULL, + rox, roi); + } + + if ((mta = lmta (mlp, clp)) == NULL) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + if (RyDsResult (sd, rox -> rox_id, (caddr_t) mta, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_MtaInfo (mta); + return OK; +} + +int mta_read (sd, arg, rox, roi) +int sd; +struct type_Qmgr_MtaRead *arg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + Chanlist *clp; + struct type_Qmgr_PrioritisedMtaList **qmlpp, *qmlp; + char *p; + Mtalist *mlp; + + PP_TRACE (("mta_read (%d)", sd)); + + qmlp = 0; + qmlpp = &qmlp; + + p = qb2str (arg -> channel); + clp = findchanlist (ch_nm2struct (p)); + free (p); + if (clp == NULLCHANLIST) + return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL, + rox, roi); + + for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas; + mlp = mlp -> mta_forw) { + *qmlpp = (struct type_Qmgr_PrioritisedMtaList *) + calloc (1, sizeof(**qmlpp)); + + if (*qmlpp == NULL || + ((*qmlpp) -> PrioritisedMta = lpmta (mlp, clp)) == NULL) { + free_Qmgr_PrioritisedMtaList (qmlp); + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + } + + qmlpp = &((*qmlpp) -> next); + } + + if (RyDsResult (sd, rox -> rox_id, (caddr_t) qmlp, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_PrioritisedMtaList (qmlp); + return OK; +} + +int msg_control (sd, arg, rox, roi) +int sd; +struct type_Qmgr_MsgControl *arg; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + char *q; + Reciplist *rl; + struct type_Qmgr_UserList *ul; + Connblk *cb; + MsgStruct *ms; + + PP_TRACE (("msg_control (%d)", sd)); + if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + if (cb -> cb_authenticated == 0) + return error (sd, error_Qmgr_authenticationFailure, + (caddr_t) NULL, rox, roi); + + q = qb2str (arg -> qid); + if ((ms = find_msg (q)) == NULLMS) + return error (sd, error_Qmgr_noSuchChannel, (caddr_t)NULL, + rox, roi); + for (rl = ms -> recips; rl; rl = rl -> rp_next) { + for (ul = arg -> users; ul; ul = ul -> next) { + if (ul -> RecipientId -> parm == rl -> id) + mcontrol (ms, rl, arg -> control); + } + } + if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + return OK; +} + +static void mcontrol (ms, rl, ctrl) +MsgStruct *ms; +Reciplist *rl; +struct type_Qmgr_Control *ctrl; +{ + LIST_RCHAN *cl; + char *p; + Chanlist *clp = NULL; + Mlist *ml; + Mtalist *mlp; + + PP_TRACE (("mcontrol (%s, %d)", ms -> queid, rl -> id)); + + switch (rl -> status) { + case ST_NORMAL: + + if ((cl = rl -> cchan) == NULL) + return; + clp = findchanlist (cl -> li_chan); + p = chan2mta (cl -> li_chan, rl); + break; + + case ST_DR: + { + Reciplist *rlp2; + + for (rlp2 = ms -> recips; rlp2; rlp2 = rlp2 -> rp_next) + if (rlp2 -> id == 0) + break; + if (rlp2 == NULL) + return; + clp = findchanlist(rlp2 -> chans->li_chan); + + p = chan2mta (clp -> chan, rlp2); + break; + } + + case ST_DELETE: + clp = delete_chan; + p = chan2mta (delete_chan -> chan, rl); + break; + + case ST_TIMEOUT: + clp = timeout_chan; + p = chan2mta (timeout_chan -> chan, rl); + break; + + case ST_WARNING: + clp = warn_chan; + p = chan2mta (warn_chan -> chan, rl); + break; + + default: + return; + + } + if (clp == NULLCHANLIST) + return; + + if ((mlp = findmtalist (clp, p)) == NULLMTALIST) + return; + + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) { + if (ml -> ms == ms) + break; + } + if (ml == mlp -> msgs) + return; + + switch (ctrl -> offset) { + case type_Qmgr_Control_stop: + rl -> msg_enabled = 0; + break; + case type_Qmgr_Control_start: + rl -> msg_enabled = 1; + break; + case type_Qmgr_Control_cacheClear: + cache_clear (&rl -> cache); + break; + case type_Qmgr_Control_cacheAdd: + cache_set (&rl -> cache, ctrl -> un.cacheAdd); + break; + } + mlp -> mta_changed = 1; + clp -> chan_update = 1; +} + +int qmgrcontrol (sd, op, rox, roi) +int sd; +int op; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + Connblk *cb; + + PP_TRACE (("qmgrcontrol (%d)", sd)); + + if ((cb = findcblk (sd)) == NULLCB || cb -> cb_type != cb_responder) + return error (sd, error_Qmgr_congested, (caddr_t) NULL, + rox, roi); + if (cb -> cb_authenticated == 0) + return error (sd, error_Qmgr_authenticationFailure, + (caddr_t) NULL, rox, roi); + switch (op) { + case int_Qmgr_QMGROp_abort: + exit (0); + break; + + case int_Qmgr_QMGROp_gracefulTerminate: + setchannels (1); + opmode = OP_SHUTDOWN; + break; + + case int_Qmgr_QMGROp_restart: + setchannels (0); + opmode = OP_RESTART; + break; + + case int_Qmgr_QMGROp_rereadQueue: + if (loader_chan) { + cache_clear (&loader_chan -> cache); + loader_chan -> nextevent = current_time; + } + break; + + case int_Qmgr_QMGROp_disableSubmission: + submission_disabled = 1; + break; + + case int_Qmgr_QMGROp_enableSubmission: + submission_disabled = 0; + if (loader_chan) { + cache_clear (&loader_chan -> cache); + loader_chan -> nextevent = current_time; + } + break; + + case int_Qmgr_QMGROp_disableAll: + case int_Qmgr_QMGROp_enableAll: + setchannels (op == int_Qmgr_QMGROp_enableAll ? 1 : 0); + break; + + case int_Qmgr_QMGROp_increasemaxchans: + maxchansrunning ++; + break; + + case int_Qmgr_QMGROp_decreasemaxchans: + maxchansrunning --; + maxchansrunning = max (1, maxchansrunning); + break; + + default: + PP_LOG (LLOG_EXCEPTIONS, ("Unknown operation %d", op)); + break; + } + if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + return OK; +} + +int msgread (sd, mr, rox, roi) +int sd; +struct type_Qmgr_MsgRead *mr; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgStructList **qmlpp; + struct type_Qmgr_MsgList *base; + Mtalist *mlp; + Chanlist *clp; + Mlist *ml; + char *p; + + PP_TRACE (("msgread (%d)", sd)); + + p = qb2str (mr -> channel); + clp = findchanlist (ch_nm2struct (p)); + free (p); + if (clp == NULLCHANLIST) + return error (sd, error_Qmgr_noSuchChannel, (caddr_t) NULL, + rox, roi); + + p = qb2str (mr -> mta); + mlp = findmtalist (clp, p); + free (p); + + if (mlp == NULLMTALIST) + return error (sd, error_Qmgr_mtaNotInQueue, (caddr_t) NULL, + rox, roi); + + base = (struct type_Qmgr_MsgList *) calloc (1, sizeof *base); + qmlpp = &base -> msgs; + + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) { + *qmlpp = (struct type_Qmgr_MsgStructList *) + calloc (1, sizeof **qmlpp); + (*qmlpp) -> MsgStruct = l_cm_message (ml); + qmlpp = &(*qmlpp) -> next; + } + + if (RyDsResult (sd, rox -> rox_id, (caddr_t)base, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_MsgList (base); + + return OK; +} + +int qmgrstatus (sd, rox, roi) +int sd; +struct RoSAPinvoke *rox; +struct RoSAPindication *roi; +{ + struct type_Qmgr_QmgrStatus *qs; + int i; + + PP_TRACE (("qmgrstatus (%d)", sd)); + + if ((qs = (struct type_Qmgr_QmgrStatus *)malloc (sizeof *qs)) == NULL) + return error (sd, error_Qmgr_congested, (caddr_t)NULL, + rox, roi); + + qs -> boottime = ltime(stats.boottime); + qs -> messagesIn = stats.n_messages_in; + qs -> messagesOut = stats.n_messages_out; + qs -> addrIn = stats.n_addr_in; + qs -> addrOut = stats.n_addr_out; + qs -> opsPerSec = stats.ops_sec * 100.0; + qs -> runnableChans = stats.runnable_chans * 100.0; + qs -> msgsInPerSec = stats.msg_sec_in * 100.0;; + qs -> msgsOutPerSec = stats.msg_sec_out * 100.0; + qs -> maxChans = maxchansrunning; + qs -> currChans = nchansrunning; + qs -> totalMsgs = qs -> totalVolume = qs -> totalDrs = 0; + for (i = 0; i < nchanlist; i++) { + qs -> totalMsgs += chan_list[i] -> num_msgs; + qs -> totalVolume += chan_list[i] -> volume; + qs -> totalDrs += chan_list[i] -> num_drs; + } + + if (RyDsResult (sd, rox -> rox_id, (caddr_t)qs, ROS_NOPRIO, roi) + == NOTOK) + ros_adios (&roi -> roi_preject, "RESULT"); + free_Qmgr_QmgrStatus (qs); + + return OK; +} + +/* private functions */ + +/* Channel functions */ + +static int chaninsert (ms) +MsgStruct *ms; +{ + LIST_RCHAN *clp; + Reciplist *rlp; + int num = 0; + + PP_TRACE (("chaninsert ()")); + + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) { + + if ( rlp -> id == 0) + continue; + num ++; + rlp -> status = ST_NORMAL; + if ((clp = rlp -> cchan) == NULL) { + insertindrchan (ms, rlp); + PP_NOTICE (("Message %s to %s added - DR", + ms -> queid, rlp -> user)); + continue; + } + + insertinchan (clp -> li_chan, ms, rlp, + chan2mta (clp -> li_chan, rlp)); + PP_NOTICE (("Message %s to %s added", + ms -> queid, rlp -> user)); + } + if (num == 0) { + ms -> recips -> cchan = NULL; + insertindelchan (ms); + PP_NOTICE (("Message %s added - for deletion", ms -> queid)); + return DONE; + } + else + stats.n_addr_in += num; + return OK; +} + +static void add_mta_hash (clp, mlp) +Chanlist *clp; +Mtalist *mlp; +{ + int idx; + + idx = hash(mlp -> mtaname,MTA_HASHSIZE); + mlp -> hash_next = clp -> mta_hash[idx]; + clp -> mta_hash[idx] = mlp; +} + + +void insertinchan (chan, ms, ri, mta) +CHAN *chan; +MsgStruct *ms; +Reciplist *ri; +char *mta; +{ + Mtalist *mlp; + Chanlist *clp; + + PP_TRACE (("insertinchan (%s, %s, id=%d, mta=%s)", chan -> ch_name, + ms -> queid, ri -> id, mta)); + + clp = findchanlist (chan); + if (clp == NULLCHANLIST) { + PP_LOG (LLOG_EXCEPTIONS, ("No channel for %s", + chan -> ch_name)); + return; + } + if ((mlp = findmtalist(clp, mta)) == NULLMTALIST) { + mlp = (Mtalist *) calloc (1, sizeof *mlp); + mlp -> msgs = (Mlist *) calloc (1, sizeof *mlp -> msgs); + mlp -> msgs -> ml_back = mlp -> msgs -> ml_forw = mlp -> msgs; + insque (mlp, clp -> mtas -> mta_back); + mlp -> mtaname = strdup (mta); + mlp -> mta_enabled = 1; + mlp -> nextevent = current_time; + mlp -> clp = clp; + clp -> nmtas ++; + if (clp -> mta_hash) + add_mta_hash (clp, mlp); + + if (clp -> nmtas == 1) + addtorunq (clp); + } + if (insertinmta (mlp, ms, ri, clp) == OK ) { + if (ri -> status == ST_DR) + clp -> num_drs ++; + else + clp -> num_msgs ++; + clp -> volume += ms -> size; + if (mlp -> nextevent < clp -> nextevent && + clp -> cache.cachetime < current_time) + clp -> nextevent = mlp -> nextevent; + if (clp -> oldest == 0 || ms -> age < clp -> oldest) + clp -> oldest = ms -> age; + if (mlp -> oldest == 0 || ms -> age < mlp -> oldest) + mlp -> oldest = ms -> age; + + } +} + +void insertindelchan (ms) +MsgStruct *ms; +{ + Reciplist *ri, *ri2; + + PP_TRACE (("insertindelchan ()")); + + if (delete_chan == NULLCHANLIST) { + PP_LOG(LLOG_EXCEPTIONS, ("No delete channel!")); + return; + } + + ri = ms -> recips; + ri -> status = ST_DELETE; + ri2 = ri -> rp_next ? ri -> rp_next : ri; + insertinchan (delete_chan -> chan, ms, ri, + chan2mta(delete_chan -> chan, ri2)); +} + +void insertindrchan (ms, rlp) +MsgStruct *ms; +Reciplist *rlp; +{ + Reciplist *r; + LIST_RCHAN *cp; + + PP_TRACE (("insertindrchan ()")); + + rlp -> status = ST_DR; + for (r = ms -> recips; r; r = r -> rp_next) + if (r -> id == 0) + break; + if (r == NULLRL) + return; + if ((cp = r -> cchan) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("DR chan appears to have finished")); + return; + } + insertinchan (cp -> li_chan, ms, rlp, chan2mta (cp -> li_chan, r)); +} + +Chanlist *findchanlist (chan) +CHAN *chan; +{ + Chanlist **clpp; + + if (chan == NULLCHAN) + return NULLCHANLIST; + + for (clpp = chan_list; clpp < &chan_list[nchanlist]; clpp++) + if ((*clpp) -> chan == chan) + return *clpp; + + return NULLCHANLIST; +} + +static void setchannels (state) +int state; +{ + Chanlist **cpp; + + for (cpp = chan_list; cpp < &chan_list[nchanlist]; cpp++) { + (*cpp) -> chan_enabled = state; + (*cpp) -> chan_update = 1; + } +} + + + +static int chan_sort (clp1, clp2) +Chanlist **clp1, **clp2; +{ + switch ((*clp1) -> chan -> ch_chan_type) { + case CH_WARNING: + case CH_DELETE: + case CH_QMGR_LOAD: + case CH_DEBRIS: + case CH_TIMEOUT: + case CH_SHAPER: + switch ((*clp2) -> chan -> ch_chan_type) { + case CH_BOTH: + case CH_OUT: + case CH_IN: + return -1; + + default: + break; + } + return 0; + + case CH_IN: + switch ((*clp2) -> chan -> ch_chan_type) { + case CH_IN: + return 0; + + default: + break; + } + return 1; + + case CH_BOTH: + case CH_OUT: + switch ((*clp2) -> chan -> ch_chan_type) { + case CH_IN: + return -1; + case CH_OUT: + case CH_BOTH: + return ((*clp1) -> averaget - + (*clp2) -> averaget) * 100.0; + default: + break; + } + return 1; + } + return 0; +} + +void sort_chans () +{ + int i; + + if (nchanlist) + qsort ((char *)chan_list, nchanlist, + sizeof (Chanlist *), (IFP)chan_sort); + PP_TRACE (("Channels resorted")); + for (i = 0; i < nchanlist; i++) + PP_TRACE (("Channel %d - %s (%g)", i, + chan_list[i] -> channame, + chan_list[i] -> averaget)); +} + + +int delfromchan (clp, mlp, ml, rno) +Chanlist *clp; +Mtalist *mlp; +Mlist *ml; +int rno; +{ + int i; + int st = ST_NORMAL; + + PP_TRACE (("delfromchan (chan=%s, id=%d)", + clp -> channame, rno)); + + msg_unlock (ml -> ms); + + for (i = 0; i < ml -> rcount; i++) + if (rno == ml -> recips[i] -> id) + break; + if (i < ml -> rcount) { + st = ml -> recips[i] -> status; + ml -> recips[i] -> ml = NULLMLIST; + for (i++; i < ml -> rcount; i++) + ml -> recips[i-1] = ml -> recips[i]; + } + else + PP_LOG (LLOG_EXCEPTIONS, ("can't locate correct recipient")); + ml -> rcount --; + if (ml -> rcount == 0) { + ml -> recips = NULL; + return zapmtamsg (ml, mlp, clp, st); + } + return 0; +} + +/* Host functions */ + +static int csort_prio (ml1, ml2) +Mlist *ml1, *ml2; +{ + if (ml1 -> ms -> priority == ml2 -> ms -> priority) + return 0; + if (ml1 -> ms -> priority == int_Qmgr_Priority_high) + return 1; + if (ml2 -> ms -> priority == int_Qmgr_Priority_high) + return -1; + if (ml1 -> ms -> priority == int_Qmgr_Priority_normal) + return 1; + if (ml1 -> ms -> priority == int_Qmgr_Priority_normal) + return -1; + return 0; +} + +static int csort_time (ml1, ml2) +Mlist *ml1, *ml2; +{ + if (ml1 -> ms -> age < ml2 -> ms -> age) + return 1; + if (ml2 -> ms -> age < ml1 -> ms -> age) + return -1; + return 0; +} + +static int csort_size (ml1, ml2) +Mlist *ml1, *ml2; +{ + if (ml1 -> ms -> size < ml2 -> ms -> size) + return 1; + if (ml2 -> ms -> size > ml1 -> ms -> size) + return -1; + return 0; +} + +static mtaenqueue (ml, mlp, clp) +Mlist *ml; +Mtalist *mlp; +Chanlist *clp; +{ + int i, msort; + Mlist *m; + IFP sfnx[CH_MAX_SORT - 1]; + + if (clp -> chan -> ch_sort[1] == 0) { + insque (ml, mlp -> msgs -> ml_back); + return; + } + + msort = 0; + for (i = 1; i < CH_MAX_SORT && clp -> chan -> ch_sort[i]; i++) { + switch (clp -> chan -> ch_sort[i]) { + case CH_SORT_USR: + case CH_SORT_MTA: + PP_LOG (LLOG_EXCEPTIONS, ("Bad sort criteria for %s", + clp -> channame)); + insque (ml, mlp -> msgs -> ml_back); + return; + + case CH_SORT_NONE: + break; + + case CH_SORT_PRIORITY: + sfnx[msort++] = csort_prio; + continue; + case CH_SORT_TIME: + sfnx[msort++] = csort_time; + continue; + case CH_SORT_SIZE: + sfnx[msort++] = csort_size; + continue; + + default: + break; + } + break; + } + for (m = mlp -> msgs -> ml_forw; m != mlp -> msgs; m = m -> ml_forw) { + + for (i = 0; i < msort; i++) { + switch ((*sfnx[i])(m, ml)) { + case 0: + continue; + case -1: + insque (ml, m -> ml_back); + return; + + case 1: + break; + } + break; + } + } + insque (ml, mlp -> msgs -> ml_back); +} + + +static int insertinmta (mlp, ms, rlp, clp) +Mtalist *mlp; +MsgStruct *ms; +Reciplist *rlp; +Chanlist *clp; +{ + Mlist *ml; + int result; + + PP_TRACE (("insertinmta (%s, id=%d)", + mlp -> mtaname, rlp -> id)); + + if (mlp -> lastone && mlp -> lastone -> ms == ms) { + PP_TRACE (("Lastone hit")); + (void) addmtaid (mlp -> lastone, rlp); + return DONE; + } + if (rlp -> status != ST_DR) { + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) { + if (ml -> ms -> m_locked) + continue; + if (ml -> ms == ms) { + (void) addmtaid (ml, rlp); + mlp -> lastone = ml; + return DONE; + } + } + } + ml = (Mlist *) calloc (1, sizeof *ml); + ml -> ms = ms; + ml -> mlp = mlp; + + ms -> count ++; + PP_TRACE (("Message reference count = %d", ms -> count)); + + mtaenqueue (ml, mlp, clp); + + if ((result = addmtaid (ml, rlp)) == OK) { + if (rlp -> status == ST_DR) + mlp -> num_drs ++; + else + mlp -> num_msgs ++; + mlp -> volume += ms -> size; + if (mtaready(mlp)) + mlp -> nextevent = current_time; + } + mlp -> lastone = ml; + return result; +} + +static int addmtaid (ml, rlp) +Mlist *ml; +Reciplist *rlp; +{ + Reciplist **ri; + + PP_TRACE (("addmtaid (%d)", rlp -> id)); + + for (ri = ml -> recips; ri && ri < &ml->recips[ml->rcount]; + ri ++) + if (*ri == rlp) + return DONE; + + if (ml -> rcount == 0) { + ml -> recips = (Reciplist **) malloc (sizeof (ri)); + ml -> recips[0] = rlp; + rlp -> ml = ml; + ml -> rcount = 1; + return OK; + } + + ml -> rcount ++; + ml -> recips = (Reciplist **) realloc ((char *)ml -> recips, + (unsigned) ml -> rcount * sizeof (ri)); + ml -> recips[ml -> rcount - 1] = rlp; + rlp -> ml = ml; + return DONE; +} + +Mtalist *findmtalist (clp, mta) +Chanlist *clp; +char *mta; +{ + Mtalist *mlp; + + PP_TRACE (("findmtalist (%s)", mta)); + + if (clp -> mta_hash) { + mlp = clp->mta_hash[hash(mta, MTA_HASHSIZE)]; + while (mlp) { + if (lexequ (mta, mlp -> mtaname) == 0) + return mlp; + mlp = mlp -> hash_next; + } + return NULLMTALIST; + } + + for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas; + mlp = mlp -> mta_forw) + if (lexequ (mta, mlp -> mtaname) == 0) + return mlp; + return NULLMTALIST; +} + +int zapmta (mlp) +Mtalist *mlp; +{ + Chanlist *clp; + PP_TRACE (("zapmta (%s)", mlp -> mtaname)); + + if (mlp -> num_msgs != 0 || mlp -> num_drs != 0) { + PP_LOG (LLOG_EXCEPTIONS, ("zapmta called but msg not dead")); + return ZAP_NONE; + } + if ((clp = mlp -> clp) != NULLCHANLIST) + clp -> nmtas --; + else { + PP_LOG (LLOG_EXCEPTIONS, ("mta does not have chan")); + return ZAP_NONE; + } + if (clp -> nmtas < 0) { + PP_LOG (LLOG_EXCEPTIONS, ("mtas gone negative on %s (%d)", + clp -> channame, clp -> nmtas)); + clp -> chan_update = 1; + } + if (clp -> mta_hash) { /* remove from hash list */ + Mtalist **mlpp; + + for (mlpp = &clp -> mta_hash[hash(mlp->mtaname, MTA_HASHSIZE)]; + *mlpp; mlpp = &(*mlpp) -> hash_next) { + if (*mlpp == mlp) { + *mlpp = mlp -> hash_next; + break; + } + } + } + remque (mlp); + + if (mlp -> msgs) + free ((char *) mlp -> msgs); + if (mlp -> info) + free (mlp -> info); + if (mlp -> mtaname) + free (mlp -> mtaname); + free ((char *) mlp); + if (clp && clp -> nmtas == 0) { + delfromrunq (clp); + clp -> oldest = 0; + } + return ZAP_MTA; +} + +int zapmtamsg (ml, mlp, clp, st) +Mlist *ml; +Mtalist *mlp; +Chanlist *clp; +int st; +{ + int result = ZAP_MSG; + + if (mlp == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, ("Null mtalist param")); + return ZAP_NONE; + } + + PP_TRACE (("zapmtamsg (mta=%s, chan=%s)", + mlp -> mtaname, clp -> channame)); + + if (st == ST_DR) + clp -> num_drs --; + else + clp -> num_msgs --; + clp -> volume -= ml -> ms -> size; + if (ml -> ms -> age <= clp -> oldest) + clp -> chan_update = 1; + if (st == ST_DR) + mlp -> num_drs --; + else + mlp -> num_msgs --; + mlp -> volume -= ml -> ms -> size; + if (ml -> ms -> age <= mlp -> oldest) + mlp -> mta_changed = 1; + + remque (ml); + ml -> ms -> count --; + PP_TRACE (("Message reference count = %d", + ml -> ms -> count)); + + if (ml -> info) + free (ml -> info); + if (ml -> recips) + free ((char *)ml -> recips); + if (mlp -> lastone == ml) + mlp -> lastone = NULL; + free ((char *)ml); + + if (mlp -> num_msgs == 0 && mlp -> num_drs == 0) + result |= zapmta (mlp); + return result; +} + +static Mlist *findnextml (); + +/* Msg functions */ + +Mlist *nextmsg (clp, mlpp, lock, samemta) +Chanlist *clp; +Mtalist **mlpp; +int lock; +int samemta; +{ + Mlist *ml; + Mtalist *mlp; + + PP_TRACE (("nextmsg (clp, mlp)")); + + if ((mlp = *mlpp) != NULLMTALIST) { + if (mlp -> mta_changed) { + investigate_mta (mlp, current_time); + mlp -> mta_changed = 0; + } + if (mlp -> error_count > 5 && + clp -> chan -> ch_sort[0] == CH_SORT_MTA) { + mlp -> error_count = 0; + if (mlp -> cache.cachetime < current_time) + cache_inc (&mlp -> cache, cache_time * 3 / 2); + PP_NOTICE (("Avoiding MTA %s - too many errors", + mlp -> mtaname)); + } + else if (mlp -> mta_enabled && + mlp -> cache.cachetime <= current_time && + (ml = findnextml (mlp, current_time, lock)) != NULL) + return ml; + mlp -> nactive --; + } + + if (samemta) { + *mlpp = NULL; + return (Mlist *)0; + } + + if (*mlpp) { + PP_TRACE (("nothing on current MTA list - trying others")); + *mlpp = NULLMTALIST; + } + + for (mlp = clp -> mtas -> mta_forw; mlp != clp -> mtas; + mlp = mlp -> mta_forw) { + if (mlp -> mta_changed) { + investigate_mta (mlp, current_time); + mlp -> mta_changed = 0; + } + if (! mtaready (mlp)) { + PP_TRACE (("mta %s not ready", mlp -> mtaname)); + continue; + } + + if (mlp -> cache.cachetime > current_time) { + PP_TRACE (("Mta %s cached for %d seconds", + mlp -> mtaname, + mlp -> cache.cachetime - current_time)); + continue; + } + + if ((ml = findnextml (mlp, current_time, lock)) != NULL) { + if (lock) + mlp -> nactive ++; + *mlpp = mlp; + remque (mlp); + insque (mlp, clp -> mtas); + PP_TRACE (("Found a ml")); + return ml; + } + PP_TRACE (("Mta %s no messages ready", mlp -> mtaname)); + } + return (Mlist *)0; +} + +static Mlist *findnextml (mlp, now, lock) +Mtalist *mlp; +time_t now; +int lock; +{ + Mlist *ml; + + PP_TRACE (("findnextml (mta=%s)", mlp -> mtaname)); + + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) { + if (!msgready (ml)) { + PP_TRACE (("Message %s not ready", ml -> ms -> queid)); + continue; + } + + if (msgiscached (ml, now)) { + PP_TRACE (("Message %s cached", ml -> ms -> queid)); + continue; + } + + if (ml -> ms -> defferedtime && + ml -> ms -> defferedtime > now) { + PP_TRACE (("Message defered")); + continue; + } + + if (lock) + ml -> ms -> m_locked = 1; + return ml; + } + return (Mlist *)0; +} + +void zapmsg (ms) +MsgStruct *ms; +{ + MsgStruct **mspp; + + PP_TRACE (("zapmsg (%s)", ms -> queid)); + + mspp = &msg_hash[hash(ms -> queid, QUE_HASHSIZE)]; + + for (; *mspp; mspp = &(*mspp) -> ms_forw) + if (*mspp == ms) { + *mspp = (*mspp) -> ms_forw; + freems (ms); + PP_TRACE (("Message zapped")); + return; + } + PP_LOG (LLOG_EXCEPTIONS, ("Can't locate message")); +} + + +Mlist *findmtamsg (mlp, qid) +Mtalist *mlp; +char *qid; +{ + MsgStruct *ms; + Mlist *ml; + + ms = find_msg (qid); + + for (ml = mlp -> msgs -> ml_forw; ml != mlp -> msgs; + ml = ml -> ml_forw) + if (ml -> ms == ms) + return ml; + return NULL; +} + +MsgStruct *find_msg (qid) +char *qid; +{ + MsgStruct *ms; + + PP_TRACE (("find_msg (%s)", qid)); + for (ms = msg_hash[hash (qid, QUE_HASHSIZE)]; ms; ms = ms -> ms_forw) + if ( strcmp (ms -> queid, qid) == 0) + return ms; + return NULLMS; +} + +/* ARGSUSED */ +void kill_msg (ms) +MsgStruct *ms; +{ + PP_TRACE (("kill_msg")); +} + +static int filtermatch (f, ms) +Filter *f; +MsgStruct *ms; +{ + PP_TRACE (("filtermatch ()")); + + if (f == NULLFL) + return 0; + + if (f -> cont) { + if (lexequ (f -> cont, ms -> contenttype) != 0) + return filtermatch (f -> next, ms); + } + + if (f -> eit) { + LIST_BPT *bp, *bp2; + + for (bp = ms -> eit; bp; bp = bp -> li_next) { + for (bp2 = f -> eit; bp2; bp2 = bp2 -> li_next) { + if (lexequ (bp -> li_name, + bp2 -> li_name) != 0) + return filtermatch (f -> next, ms); + } + } + } + + if (f -> orig) { + if (lexequ (f -> orig, ms -> originator) != 0) + return filtermatch (f -> next, ms); + } + + if (f -> recip) { + Reciplist *rl, *rl0; + + for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next) + if (rl0 -> id == 0) + break; + + for (rl = ms -> recips; rl; rl = rl -> rp_next) { + switch (rl -> status) { + case ST_DELETE: + continue; /* we ignore recips that dead */ + + case ST_TIMEOUT: + case ST_WARNING: + case ST_NORMAL: + if (rl -> id == 0) + continue; + if (lexequ (rl -> user, f -> recip) == 0) + break; + continue; + + case ST_DR: + if (rl0 && + lexequ (rl0 -> user, f -> recip) == 0) + break; + continue; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("filtermatch - Unknown state %d", + rl -> status)); + continue; + } + break; + } + if (rl == NULLRL) + return filtermatch (f -> next, ms); + } + if (f -> channel) { + Reciplist *rl, *rl0; + + for (rl0 = ms -> recips; rl0; rl0 = rl0 -> rp_next) + if (rl0 -> id == 0) + break; + if (rl0 == NULLRL) + return filtermatch (f -> next, ms); + + for (rl = ms -> recips; rl; rl = rl -> rp_next) { + switch (rl -> status) { + case ST_DR: + if (f -> channel == rl0 -> chans -> li_chan) + break; + continue; + + case ST_DELETE: + if (f -> channel == delete_chan -> chan) + break; + continue; + + case ST_TIMEOUT: + if (f -> channel == timeout_chan -> chan) + break; + continue; + + case ST_WARNING: + if (warn_chan && + f -> channel == warn_chan -> chan) + break; + continue; + + case ST_NORMAL: + if (rl -> cchan && + f -> channel == rl -> cchan -> li_chan) + break; + continue; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("filtermatch - unknown state %d", + rl -> status)); + break; + } + } + if (rl == NULLRL) + return filtermatch (f -> next, ms); + } + + if (f -> mta) { + Reciplist *rl; + + for (rl = ms -> recips; rl; rl = rl -> rp_next) { + switch (rl -> status) { + case ST_DR: + case ST_NORMAL: + if (lexequ (rl -> mta, f -> mta) == 0) + break; + if (rl -> ml && rl -> ml -> mlp && + lexequ (rl -> ml -> mlp -> mtaname, + f -> mta) == 0) + break; + continue; + + case ST_DELETE: + if (delete_chan && + lexequ (f -> mta, + delete_chan -> channame) == 0) + break; + continue; + case ST_TIMEOUT: + if (timeout_chan && + lexequ (f -> mta, + timeout_chan -> channame) == 0) + break; + continue; + case ST_WARNING: + if (warn_chan && + lexequ (f -> mta, + warn_chan -> channame) == 0) + break; + continue; + default: + PP_LOG (LLOG_EXCEPTIONS, + ("filtermatch - Bad state %d", rl -> status)); + continue; + } + break; + } + if (rl == NULLRL) + return filtermatch (f -> next, ms); + } + + if (f -> queid) { + if (lexequ (f -> queid, ms -> queid) != 0) + return filtermatch (f -> next, ms); + } + + if (f -> mpduid) { + if (!compmpduid (f -> mpduid, ms -> mpduid)) + return filtermatch (f -> next, ms); + } + if (f -> uacontent) { + if (lexequ (f -> uacontent, ms -> uacontent) != 0) + return filtermatch (f -> next, ms); + } + if (f ->morerecent) { + if (ms -> age <= f -> morerecent) + return filtermatch (f -> next, ms); + } + if (f -> earlier) { + if (ms -> age >= f -> earlier) + return filtermatch (f -> next, ms); + } + if (f -> priority != -1) { + if (ms -> priority != f -> priority) + return filtermatch (f -> next, ms); + } + if (f -> maxsize) { + if (ms -> size > f -> maxsize) + return filtermatch (f -> next, ms); + + } + return 1; +} + +static int compmpduid (m1, m2) +MPDUid *m1, *m2; +{ + PP_TRACE (("compmpduid ()")); + + if (!nullstrcmp (m1 -> mpduid_string, m2 -> mpduid_string)) + return 0; + + if (!nullstrcmp (m1 -> mpduid_DomId.global_Country, + m2 -> mpduid_DomId.global_Country)) + return 0; + if (!nullstrcmp (m1 -> mpduid_DomId.global_Admin, + m2 -> mpduid_DomId.global_Admin)) + return 0; + if (!nullstrcmp (m1 -> mpduid_DomId.global_Private, + m2 -> mpduid_DomId.global_Private)) + return 0; + return 1; +} + +static int nullstrcmp (s1, s2) +char *s1, *s2; +{ + if (s1 && s2) + return lexequ (s1, s2) == 0; + if (s1 == NULLCP && s2 == NULLCP) + return 1; + return 0; +} + +int mtaready (mlp) +Mtalist *mlp; +{ + if (mlp -> nactive > 0) { + PP_TRACE (("mta %s started already", + mlp -> mtaname)); + return FALSE; + } + if (mlp -> mta_enabled == 0) { + PP_TRACE (("Mta %s not enabled", + mlp -> mtaname)); + return FALSE; + } + return TRUE; +} + +msgready (ml) +Mlist *ml; +{ + Reciplist **rl; + + if (ml -> ms -> m_locked) { + PP_TRACE (("Message locked")); + return FALSE; + } + for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) { + if ((*rl) -> msg_enabled == 0) { + PP_TRACE (("Message disabled")); + return FALSE; + } + } + + return TRUE; +} + +msgiscached (ml, now) +Mlist *ml; +time_t now; +{ + Reciplist **rl; + + for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) { + if ((*rl) -> cache.cachetime <= now) + return FALSE; + } + return TRUE; +} + +void clear_msgcache (ml) +Mlist *ml; +{ + Reciplist **rl; + + for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) { + cache_clear (&(*rl) -> cache); + } +} + +void msgcache_inc (ml, plus) +Mlist *ml; +time_t plus; +{ + Reciplist **rl; + + for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) { + cache_inc (&(*rl) -> cache, plus); + } +} + +time_t msgmincache (ml) +Mlist *ml; +{ + time_t minc = 0; + int flag = 0; + Reciplist **rl; + + for (rl = ml -> recips; rl < &ml -> recips[ml->rcount]; rl ++) { + if (!flag) { + flag = 1; + minc = (*rl) -> cache.cachetime; + } + else + minc = minc < (*rl) -> cache.cachetime ? minc : + (*rl) -> cache.cachetime; + } + return minc; +} + +msg_unlock (ms) +MsgStruct *ms; +{ + Reciplist *rlp; + Chanlist *clp; + Mtalist *mlp; + Mlist *ml; + + PP_TRACE (("msg_unlock")); + ms -> m_locked = 0; + + for (rlp = ms -> recips; rlp; rlp = rlp -> rp_next) { + + if (rlp -> id == 0 || + rlp -> msg_enabled == 0) + continue; + + if ((ml = rlp -> ml) == NULLMLIST) { + PP_TRACE (("recipient not on mlist!")); + continue; + } + + if ((mlp = ml -> mlp) == NULLMTALIST) { + PP_LOG (LLOG_EXCEPTIONS, ("message not on MTA")); + continue; + } + + + if (current_time > rlp -> cache.cachetime) + rlp -> cache.cachetime = current_time; + if (ml -> ms -> defferedtime > rlp -> cache.cachetime) + rlp -> cache.cachetime = ml -> ms -> defferedtime; + + if (rlp -> cache.cachetime < mlp -> nextevent && + mlp -> cache.cachetime < current_time) + mlp -> nextevent = rlp -> cache.cachetime; + + if ((clp = mlp -> clp) == NULLCHANLIST) { + PP_LOG (LLOG_EXCEPTIONS, ("mta not on channel!")); + continue; + } + if (clp -> chan_enabled == 0) + continue; + if (rlp -> cache.cachetime < clp -> nextevent && + clp -> cache.cachetime < current_time) + clp -> nextevent = rlp -> cache.cachetime; + } +} + +char *chan2mta (chan, rlp) +CHAN *chan; +Reciplist *rlp; +{ + if (chan -> ch_sort[0] == CH_SORT_NONE) + return chan -> ch_name; + else if (chan -> ch_sort[0] == CH_SORT_USR) + return rlp -> user; +/* removed for JA@UCL + else if (chan -> ch_mta) + return chan -> ch_mta; +*/ + else + return rlp -> mta; +} diff --git a/Src/qmgr/types.h b/Src/qmgr/types.h new file mode 100644 index 0000000..1d9631b --- /dev/null +++ b/Src/qmgr/types.h @@ -0,0 +1,313 @@ +/* types.h: queue manager general purpose type definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Src/qmgr/RCS/types.h,v 6.0 1991/12/18 20:27:38 jpo Rel $ + * + * $Log: types.h,v $ + * Revision 6.0 1991/12/18 20:27:38 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGR_TYPES +#define _H_QMGR_TYPES + + +#include +#include "Qmgr-types.h" +#include "table.h" +#include "chan.h" +#include "list_bpt.h" +#include "list_rchan.h" +#include "mta.h" + + +#define MTA_HASHSIZE 503 +#define QUE_HASHSIZE 1009 +#define DISP_INDENT 2 + + +/* how often to reload from disk */ +#define LOAD_RETRY_INTERVAL ((time_t)(6 * 60 * 60)) /* every hour or so */ +/* how often to rerun trash channel */ +#define TRASH_RETRY_INTERVAL ((time_t)(3 * 60 * 60)) /* every 3 hours */ +/* first timeout sweep of queues */ +#define TIMEOUT_RETRY_INTERVAL ((time_t)(12 * 60 * 60)) /* every 12 hours */ +/* A constant - no channel allowed to sleep longer than this */ +#define MAX_SLEEP ((time_t)(1 * 24 * 60 * 60)) /* 1 day */ +/* kill a channel after this time if it doesn't appear to be working */ +#define CHAN_TIMEOUT ((time_t)(60 * 15)) /* 15 mins */ +/* default number of simultaneous channels */ +#define MAXCHANSRUNNING 3 + + + +/* --- Cache structure - general purpose. --- */ +typedef struct cache { + time_t cachetime; + int cacheplus; +#define CACHE_TIME (5*60) /* 5 minutes retry time */ +#define CACHE_MAX (10) /* 50 mins max */ +} Cache; + + + +/* --- Recipient list - internal form --- */ +typedef struct Reciplist { + struct Reciplist *rp_next; + + int id; + char *user; + char *mta; + LIST_RCHAN *chans; + LIST_RCHAN *cchan; + + /* --- non protocol stuff --- */ + unsigned int status:4, +#define ST_NORMAL 0 +#define ST_DR 1 +#define ST_DELETE 2 +#define ST_TIMEOUT 3 +#define ST_WARNING 4 + msg_enabled:1, + msg_locked:1; + Cache cache; + struct Mlist *ml; /* back pointer */ +} Reciplist; +#define NULLRL ((Reciplist *)0) + + + +/* --- Msg information - internal form --- */ +typedef struct MsgStruct { + struct MsgStruct *ms_forw; + + char *queid; + MPDUid *mpduid; + char *originator; + char *contenttype; + LIST_BPT *eit; + int size; + time_t age; + int warninterval; + int numberwarns; + time_t expirytime; + time_t defferedtime; + char *uacontent; + unsigned int m_locked:1, + m_timeout:1, + priority:4, + count:10; + unsigned short nerrors; + CHAN *inchan; + Reciplist *recips; +} MsgStruct; +#define NULLMS ((MsgStruct *)0) + + + + +/* --- Msg list - as associated with an MTA --- */ +typedef struct Mlist { + struct Mlist *ml_forw; + struct Mlist *ml_back; + + MsgStruct *ms; + char *info; + Reciplist **recips; + int rcount; + struct Mtalist *mlp; +} Mlist; +#define NULLMLIST ((Mlist *)0) + + + +/* --- List of MTA's associated with channel --- */ +typedef struct Mtalist { + struct Mtalist *mta_forw; + struct Mtalist *mta_back; + + struct Mtalist *hash_next; + char *mtaname; + Cache cache; + time_t oldest; + time_t lastattempt; + time_t lastsuccess; + time_t nextevent; + int num_msgs; + int num_drs; + long volume; + char *info; + int error_count; + unsigned int mta_enabled:1, + mta_changed:1, + mta_waiting:1, + nactive:12; + struct chanlist *clp; + Mlist *lastone; + Mlist *msgs; +} Mtalist; +#define NULLMTALIST ((Mtalist *)0) + + + +/* --- Channel list --- */ +typedef struct chanlist { + struct chanlist *cl_forw; + struct chanlist *cl_back; + + Mtalist *mtas; + Mtalist **mta_hash; + + CHAN *chan; + char *channame; + Cache cache; + time_t lastattempt; + time_t lastsuccess; + time_t laststart; + time_t oldest; + time_t nextevent; + float averaget; + int num_msgs; + int num_drs; + int volume; + int nactive; + int nmtas; + int error_count; + unsigned int + chan_special:1, /* special system channel */ + chan_enabled:1, /* enabled? */ + chan_syssusp:1, /* system disabled this channel */ + chan_update:1; /* channel needs looking at */ +} Chanlist; +#define NULLCHANLIST ((Chanlist *)0) + + + + +/* --- Internal 'compiled' filter type --- */ +typedef struct Filter { + char *cont; + LIST_BPT *eit; + int priority; + time_t morerecent; + time_t earlier; + int maxsize; + char *orig; + char *recip; + CHAN *channel; + char *mta; + char *queid; + MPDUid *mpduid; + char *uacontent; + struct Filter *next; +} Filter; +#define NULLFL ((Filter *)0) + +#define ZAP_MSG 01 +#define ZAP_MTA 02 +#define ZAP_NONE 00 + +enum cb_type { + cb_channel, + cb_special, + cb_responder, + cb_timer +} cb_type; + + + +struct connblk { + struct connblk *cb_forw; + struct connblk *cb_back; + + int cb_fd; + int cb_id; + int cb_nops; + enum cb_type cb_type; + + union { + struct { + Chanlist *cb_un_clp; + Mtalist *cb_un_mlp; + Mlist *cb_un_ml; + time_t cb_un_ttl; + enum { + cb_idle = 0, + cb_conn_request1, + cb_conn_request2, + cb_conn_established, + cb_init_sent, + cb_active, + cb_proc_sent, + cb_close_sent, + cb_finished, + cb_error + } cb_un_state; + } cb_chan; +#define cb_state un.cb_chan.cb_un_state +#define cb_mlp un.cb_chan.cb_un_mlp +#define cb_ml un.cb_chan.cb_un_ml +#define cb_clp un.cb_chan.cb_un_clp +#define cb_ttl un.cb_chan.cb_un_ttl + struct { + IFP cb_un_proc; + time_t cb_un_reload; + } cb_timer; +#define cb_proc un.cb_timer.cb_un_proc +#define cb_reload un.cb_timer.cb_un_reload + struct { + int cb_un_authenticated; + } cb_responder; +#define cb_authenticated un.cb_responder.cb_un_authenticated + } un; +}; +#define MIN_OPS 20 +typedef struct connblk Connblk; +#define NULLCB ((Connblk *)0) + + +void freecblk(); +Connblk *findcblk(), *newcblk(); + +struct stats { + time_t boottime; /* when we started */ + int n_messages_in; /* total messages in */ + int n_messages_out; /* total messages out */ + int n_addr_in; /* total addresses in */ + int n_addr_out; /* total addresses out */ + double ops_sec; /* qmgr ops/sec */ + double runnable_chans; /* runnable qmgr chans */ + double msg_sec_in; /* msg/sec inbound */ + double msg_sec_out; /* msg/sec outbound */ +}; + +/* --- misc external things --- */ +extern char *myname; +extern MsgStruct *msg_hash[]; +extern Chanlist **chan_list; +extern int nchanlist; +extern Chanlist *delete_chan, *loader_chan, *trash_chan, + *timeout_chan, *warn_chan; +extern time_t current_time; +extern time_t debris_time, load_time, cache_time, timeout_time; +extern int maxchansrunning, submission_disabled, opmode; +extern struct stats stats; + +#define OP_SHUTDOWN 1 +#define OP_RESTART 2 + +extern void advise(), adios(), acs_advise(), + ros_advise(), ros_adios(); +extern time_t time(), utc2time_t(), utcqb2time_t(); +extern char *chan2mta(); + +#ifdef SYS5 +#define srandom(x) srand((x)) +#define random() rand() +#endif + +#endif diff --git a/Src/submit/Makefile b/Src/submit/Makefile new file mode 100644 index 0000000..f2e7360 --- /dev/null +++ b/Src/submit/Makefile @@ -0,0 +1,589 @@ +# Submit - the pp submission agent +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Src/submit/RCS/Makefile,v 6.0 1991/12/18 20:28:02 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:02 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ad_mgt.c auth.c auth_logs.c auth_tb.c auth_ut.c ch_bind.c \ + gen_io2dr.c gen_ndr.c gen_probedr.c gen_warn.c \ + rd_rfchdr.c submit.c submit_srvr.c\ + submit_chk.c submit_mgt.c submit_prm.c submit_que.c submit_txt.c + +OBJS = ad_mgt.o auth.o auth_logs.o auth_tb.o auth_ut.o ch_bind.o \ + gen_io2dr.o gen_ndr.o gen_probedr.o gen_warn.o \ + rd_rfchdr.o submit.o submit_srvr.o \ + submit_chk.o submit_mgt.o submit_prm.o submit_que.o submit_txt.o + +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I. -I$(HEADERS) +# CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +# CFLAGS = $(CCOPTIONS) $(LCF) -I./h -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) + +############################################################ +# +# Building rules +# +############################################################ + +PROGS = xsubmit + +default: $(PROGS) + +xtrdrfc: t-rd_rfchdr.o rd_rfchdr.o $(LIBPP) + $(CC) $(LDFLAGS) t-rd_rfchdr.o rd_rfchdr.o \ + $(LIBPP) $(LIBSYS) -o $@ + +xt-trace: t-tracecheck.o $(LIBPP) + $(CC) $(LDFLAGS) t-tracecheck.o $(LIBPP) \ + $(LIBSYS) -o $@ + +AUTHOBJS = t-auth.o auth.o auth_logs.o auth_tb.o auth_ut.o ch_bind.o +xt-auth: $(AUTHOBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(AUTHOBJS) $(LIBPP) $(LIBSYS) + +xsubmit: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) $(OBJS) $(LIBPP) $(LIBSYS) -o xsubmit + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lint: l-submit +l-submit: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) *.o + +tidy: + rm -f zxsubmit xsubmit core a.out *.old *.BAK + rm -f xtdrfc xt-trace t-rd_rfchdr.o t-tracecheck.o + + +install: inst-dir inst-submit +inst-submit: $(CMDDIR)/submit +$(CMDDIR)/submit: xsubmit + -$(BACKUP) $@ zxsubmit + rm -f $@ + $(INSTALL) xsubmit $@ + -$(CHOWN) $(PPUSER) $@ + -$(CHMOD) 4755 $@ + -@ls -ls $@ + -@echo "submit installed normally"; echo "" + +inst-dir: $(CMDDIR) + + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ad_mgt.o: ad_mgt.c +ad_mgt.o: ../../h/util.h +ad_mgt.o: ../../h/config.h +ad_mgt.o: ../../h/ll_log.h +ad_mgt.o: ../../h/retcode.h +ad_mgt.o: ../../h/q.h +ad_mgt.o: ../../h/adr.h +ad_mgt.o: ../../h/list_rchan.h +ad_mgt.o: ../../h/chan.h +ad_mgt.o: ../../h/table.h +ad_mgt.o: ../../h/list_bpt.h +ad_mgt.o: ../../h/auth.h +ad_mgt.o: ../../h/list_bpt.h +ad_mgt.o: ../../h/extension.h +ad_mgt.o: ../../h/mta.h +ad_mgt.o: ../../h/adr.h +ad_mgt.o: ../../h/list_bpt.h +ad_mgt.o: ../../h/aparse.h +ad_mgt.o: ../../h/ap.h +ad_mgt.o: ../../h/util.h +ad_mgt.o: ../../h/or.h +ad_mgt.o: ../../h/chan.h +ad_mgt.o: ../../h/auth.h +ad_mgt.o: ../../h/list_rchan.h +ad_mgt.o: ../../h/mta.h +ad_mgt.o: ../../h/dr.h +ad_mgt.o: ../../h/extension.h +ad_mgt.o: ../../h/mta.h +ad_mgt.o: ../../h/ap.h +auth.o: auth.c +auth.o: ../../h/head.h +auth.o: ../../h/util.h +auth.o: ../../h/config.h +auth.o: ../../h/ll_log.h +auth.o: ../../h/retcode.h +auth.o: ../../h/q.h +auth.o: ../../h/adr.h +auth.o: ../../h/list_rchan.h +auth.o: ../../h/chan.h +auth.o: ../../h/table.h +auth.o: ../../h/list_bpt.h +auth.o: ../../h/auth.h +auth.o: ../../h/list_bpt.h +auth.o: ../../h/extension.h +auth.o: ../../h/mta.h +auth.o: ../../h/adr.h +auth.o: ../../h/list_bpt.h +auth.o: ../../h/aparse.h +auth.o: ../../h/ap.h +auth.o: ../../h/util.h +auth.o: ../../h/or.h +auth.o: ../../h/chan.h +auth.o: ../../h/auth.h +auth.o: ../../h/list_rchan.h +auth.o: ../../h/mta.h +auth.o: ../../h/dr.h +auth.o: ../../h/extension.h +auth.o: ../../h/mta.h +auth.o: ../../h/tb_auth.h +auth_logs.o: auth_logs.c +auth_logs.o: ../../h/util.h +auth_logs.o: ../../h/config.h +auth_logs.o: ../../h/ll_log.h +auth_logs.o: ../../h/q.h +auth_logs.o: ../../h/adr.h +auth_logs.o: ../../h/list_rchan.h +auth_logs.o: ../../h/chan.h +auth_logs.o: ../../h/table.h +auth_logs.o: ../../h/list_bpt.h +auth_logs.o: ../../h/auth.h +auth_logs.o: ../../h/list_bpt.h +auth_logs.o: ../../h/extension.h +auth_logs.o: ../../h/mta.h +auth_logs.o: ../../h/adr.h +auth_logs.o: ../../h/list_bpt.h +auth_logs.o: ../../h/aparse.h +auth_logs.o: ../../h/ap.h +auth_logs.o: ../../h/util.h +auth_logs.o: ../../h/or.h +auth_logs.o: ../../h/chan.h +auth_logs.o: ../../h/auth.h +auth_logs.o: ../../h/list_rchan.h +auth_logs.o: ../../h/mta.h +auth_tb.o: auth_tb.c +auth_tb.o: ../../h/util.h +auth_tb.o: ../../h/config.h +auth_tb.o: ../../h/ll_log.h +auth_tb.o: ../../h/q.h +auth_tb.o: ../../h/adr.h +auth_tb.o: ../../h/list_rchan.h +auth_tb.o: ../../h/chan.h +auth_tb.o: ../../h/table.h +auth_tb.o: ../../h/list_bpt.h +auth_tb.o: ../../h/auth.h +auth_tb.o: ../../h/list_bpt.h +auth_tb.o: ../../h/extension.h +auth_tb.o: ../../h/mta.h +auth_tb.o: ../../h/adr.h +auth_tb.o: ../../h/list_bpt.h +auth_tb.o: ../../h/aparse.h +auth_tb.o: ../../h/ap.h +auth_tb.o: ../../h/util.h +auth_tb.o: ../../h/or.h +auth_tb.o: ../../h/chan.h +auth_tb.o: ../../h/auth.h +auth_tb.o: ../../h/list_rchan.h +auth_tb.o: ../../h/mta.h +auth_tb.o: ../../h/tb_auth.h +auth_ut.o: auth_ut.c +auth_ut.o: ../../h/util.h +auth_ut.o: ../../h/config.h +auth_ut.o: ../../h/ll_log.h +auth_ut.o: ../../h/q.h +auth_ut.o: ../../h/adr.h +auth_ut.o: ../../h/list_rchan.h +auth_ut.o: ../../h/chan.h +auth_ut.o: ../../h/table.h +auth_ut.o: ../../h/list_bpt.h +auth_ut.o: ../../h/auth.h +auth_ut.o: ../../h/list_bpt.h +auth_ut.o: ../../h/extension.h +auth_ut.o: ../../h/mta.h +auth_ut.o: ../../h/adr.h +auth_ut.o: ../../h/list_bpt.h +auth_ut.o: ../../h/aparse.h +auth_ut.o: ../../h/ap.h +auth_ut.o: ../../h/util.h +auth_ut.o: ../../h/or.h +auth_ut.o: ../../h/chan.h +auth_ut.o: ../../h/auth.h +auth_ut.o: ../../h/list_rchan.h +auth_ut.o: ../../h/mta.h +ch_bind.o: ch_bind.c +ch_bind.o: ../../h/head.h +ch_bind.o: ../../h/util.h +ch_bind.o: ../../h/config.h +ch_bind.o: ../../h/ll_log.h +ch_bind.o: ../../h/retcode.h +ch_bind.o: ../../h/q.h +ch_bind.o: ../../h/adr.h +ch_bind.o: ../../h/list_rchan.h +ch_bind.o: ../../h/chan.h +ch_bind.o: ../../h/table.h +ch_bind.o: ../../h/list_bpt.h +ch_bind.o: ../../h/auth.h +ch_bind.o: ../../h/list_bpt.h +ch_bind.o: ../../h/extension.h +ch_bind.o: ../../h/mta.h +ch_bind.o: ../../h/adr.h +ch_bind.o: ../../h/list_bpt.h +ch_bind.o: ../../h/aparse.h +ch_bind.o: ../../h/ap.h +ch_bind.o: ../../h/util.h +ch_bind.o: ../../h/or.h +ch_bind.o: ../../h/chan.h +ch_bind.o: ../../h/auth.h +ch_bind.o: ../../h/list_rchan.h +ch_bind.o: ../../h/mta.h +ch_bind.o: ../../h/ch_bind.h +gen_io2dr.o: gen_io2dr.c +gen_io2dr.o: ../../h/head.h +gen_io2dr.o: ../../h/util.h +gen_io2dr.o: ../../h/config.h +gen_io2dr.o: ../../h/ll_log.h +gen_io2dr.o: ../../h/retcode.h +gen_io2dr.o: ../../h/q.h +gen_io2dr.o: ../../h/adr.h +gen_io2dr.o: ../../h/list_rchan.h +gen_io2dr.o: ../../h/chan.h +gen_io2dr.o: ../../h/table.h +gen_io2dr.o: ../../h/list_bpt.h +gen_io2dr.o: ../../h/auth.h +gen_io2dr.o: ../../h/list_bpt.h +gen_io2dr.o: ../../h/extension.h +gen_io2dr.o: ../../h/mta.h +gen_io2dr.o: ../../h/adr.h +gen_io2dr.o: ../../h/list_bpt.h +gen_io2dr.o: ../../h/aparse.h +gen_io2dr.o: ../../h/ap.h +gen_io2dr.o: ../../h/util.h +gen_io2dr.o: ../../h/or.h +gen_io2dr.o: ../../h/chan.h +gen_io2dr.o: ../../h/auth.h +gen_io2dr.o: ../../h/list_rchan.h +gen_io2dr.o: ../../h/mta.h +gen_io2dr.o: ../../h/dr.h +gen_io2dr.o: ../../h/extension.h +gen_io2dr.o: ../../h/mta.h +gen_ndr.o: gen_ndr.c +gen_ndr.o: ../../h/head.h +gen_ndr.o: ../../h/util.h +gen_ndr.o: ../../h/config.h +gen_ndr.o: ../../h/ll_log.h +gen_ndr.o: ../../h/retcode.h +gen_ndr.o: ../../h/q.h +gen_ndr.o: ../../h/adr.h +gen_ndr.o: ../../h/list_rchan.h +gen_ndr.o: ../../h/chan.h +gen_ndr.o: ../../h/table.h +gen_ndr.o: ../../h/list_bpt.h +gen_ndr.o: ../../h/auth.h +gen_ndr.o: ../../h/list_bpt.h +gen_ndr.o: ../../h/extension.h +gen_ndr.o: ../../h/mta.h +gen_ndr.o: ../../h/adr.h +gen_ndr.o: ../../h/list_bpt.h +gen_ndr.o: ../../h/aparse.h +gen_ndr.o: ../../h/ap.h +gen_ndr.o: ../../h/util.h +gen_ndr.o: ../../h/or.h +gen_ndr.o: ../../h/chan.h +gen_ndr.o: ../../h/auth.h +gen_ndr.o: ../../h/list_rchan.h +gen_ndr.o: ../../h/mta.h +gen_ndr.o: ../../h/dr.h +gen_ndr.o: ../../h/extension.h +gen_ndr.o: ../../h/mta.h +gen_probedr.o: gen_probedr.c +gen_probedr.o: ../../h/head.h +gen_probedr.o: ../../h/util.h +gen_probedr.o: ../../h/config.h +gen_probedr.o: ../../h/ll_log.h +gen_probedr.o: ../../h/retcode.h +gen_probedr.o: ../../h/q.h +gen_probedr.o: ../../h/adr.h +gen_probedr.o: ../../h/list_rchan.h +gen_probedr.o: ../../h/chan.h +gen_probedr.o: ../../h/table.h +gen_probedr.o: ../../h/list_bpt.h +gen_probedr.o: ../../h/auth.h +gen_probedr.o: ../../h/list_bpt.h +gen_probedr.o: ../../h/extension.h +gen_probedr.o: ../../h/mta.h +gen_probedr.o: ../../h/adr.h +gen_probedr.o: ../../h/list_bpt.h +gen_probedr.o: ../../h/aparse.h +gen_probedr.o: ../../h/ap.h +gen_probedr.o: ../../h/util.h +gen_probedr.o: ../../h/or.h +gen_probedr.o: ../../h/chan.h +gen_probedr.o: ../../h/auth.h +gen_probedr.o: ../../h/list_rchan.h +gen_probedr.o: ../../h/mta.h +gen_probedr.o: ../../h/dr.h +gen_probedr.o: ../../h/extension.h +gen_probedr.o: ../../h/mta.h +gen_warn.o: gen_warn.c +gen_warn.o: ../../h/util.h +gen_warn.o: ../../h/config.h +gen_warn.o: ../../h/ll_log.h +gen_warn.o: ../../h/q.h +gen_warn.o: ../../h/adr.h +gen_warn.o: ../../h/list_rchan.h +gen_warn.o: ../../h/chan.h +gen_warn.o: ../../h/table.h +gen_warn.o: ../../h/list_bpt.h +gen_warn.o: ../../h/auth.h +gen_warn.o: ../../h/list_bpt.h +gen_warn.o: ../../h/extension.h +gen_warn.o: ../../h/mta.h +gen_warn.o: ../../h/adr.h +gen_warn.o: ../../h/list_bpt.h +gen_warn.o: ../../h/aparse.h +gen_warn.o: ../../h/ap.h +gen_warn.o: ../../h/util.h +gen_warn.o: ../../h/or.h +gen_warn.o: ../../h/chan.h +gen_warn.o: ../../h/auth.h +gen_warn.o: ../../h/list_rchan.h +gen_warn.o: ../../h/mta.h +gen_warn.o: ../../h/auth.h +gen_warn.o: ../../h/prm.h +gen_warn.o: ../../h/retcode.h +rd_rfchdr.o: rd_rfchdr.c +rd_rfchdr.o: ../../h/head.h +rd_rfchdr.o: ../../h/util.h +rd_rfchdr.o: ../../h/config.h +rd_rfchdr.o: ../../h/ll_log.h +rd_rfchdr.o: ../../h/retcode.h +rd_rfchdr.o: ../../h/q.h +rd_rfchdr.o: ../../h/adr.h +rd_rfchdr.o: ../../h/list_rchan.h +rd_rfchdr.o: ../../h/chan.h +rd_rfchdr.o: ../../h/table.h +rd_rfchdr.o: ../../h/list_bpt.h +rd_rfchdr.o: ../../h/auth.h +rd_rfchdr.o: ../../h/list_bpt.h +rd_rfchdr.o: ../../h/extension.h +rd_rfchdr.o: ../../h/mta.h +rd_rfchdr.o: ../../h/adr.h +rd_rfchdr.o: ../../h/list_bpt.h +rd_rfchdr.o: ../../h/aparse.h +rd_rfchdr.o: ../../h/ap.h +rd_rfchdr.o: ../../h/util.h +rd_rfchdr.o: ../../h/or.h +rd_rfchdr.o: ../../h/chan.h +rd_rfchdr.o: ../../h/auth.h +rd_rfchdr.o: ../../h/list_rchan.h +rd_rfchdr.o: ../../h/mta.h +rd_rfchdr.o: ../../h/tb_q.h +rd_rfchdr.o: ../../h/or.h +rd_rfchdr.o: ../../h/ap.h +submit.o: submit.c +submit.o: ../../h/head.h +submit.o: ../../h/util.h +submit.o: ../../h/config.h +submit.o: ../../h/ll_log.h +submit.o: ../../h/retcode.h +submit.o: ../../h/prm.h +submit.o: ../../h/q.h +submit.o: ../../h/adr.h +submit.o: ../../h/list_rchan.h +submit.o: ../../h/chan.h +submit.o: ../../h/table.h +submit.o: ../../h/list_bpt.h +submit.o: ../../h/auth.h +submit.o: ../../h/list_bpt.h +submit.o: ../../h/extension.h +submit.o: ../../h/mta.h +submit.o: ../../h/adr.h +submit.o: ../../h/list_bpt.h +submit.o: ../../h/aparse.h +submit.o: ../../h/ap.h +submit.o: ../../h/util.h +submit.o: ../../h/or.h +submit.o: ../../h/chan.h +submit.o: ../../h/auth.h +submit.o: ../../h/list_rchan.h +submit.o: ../../h/mta.h +submit.o: ../../h/or.h +submit_chk.o: submit_chk.c +submit_chk.o: ../../h/head.h +submit_chk.o: ../../h/util.h +submit_chk.o: ../../h/config.h +submit_chk.o: ../../h/ll_log.h +submit_chk.o: ../../h/retcode.h +submit_chk.o: ../../h/q.h +submit_chk.o: ../../h/adr.h +submit_chk.o: ../../h/list_rchan.h +submit_chk.o: ../../h/chan.h +submit_chk.o: ../../h/table.h +submit_chk.o: ../../h/list_bpt.h +submit_chk.o: ../../h/auth.h +submit_chk.o: ../../h/list_bpt.h +submit_chk.o: ../../h/extension.h +submit_chk.o: ../../h/mta.h +submit_chk.o: ../../h/adr.h +submit_chk.o: ../../h/list_bpt.h +submit_chk.o: ../../h/aparse.h +submit_chk.o: ../../h/ap.h +submit_chk.o: ../../h/util.h +submit_chk.o: ../../h/or.h +submit_chk.o: ../../h/chan.h +submit_chk.o: ../../h/auth.h +submit_chk.o: ../../h/list_rchan.h +submit_chk.o: ../../h/mta.h +submit_chk.o: ../../h/dr.h +submit_chk.o: ../../h/extension.h +submit_chk.o: ../../h/mta.h +submit_mgt.o: submit_mgt.c +submit_mgt.o: ../../h/head.h +submit_mgt.o: ../../h/util.h +submit_mgt.o: ../../h/config.h +submit_mgt.o: ../../h/ll_log.h +submit_mgt.o: ../../h/retcode.h +submit_mgt.o: ../../h/prm.h +submit_mgt.o: ../../h/q.h +submit_mgt.o: ../../h/adr.h +submit_mgt.o: ../../h/list_rchan.h +submit_mgt.o: ../../h/chan.h +submit_mgt.o: ../../h/table.h +submit_mgt.o: ../../h/list_bpt.h +submit_mgt.o: ../../h/auth.h +submit_mgt.o: ../../h/list_bpt.h +submit_mgt.o: ../../h/extension.h +submit_mgt.o: ../../h/mta.h +submit_mgt.o: ../../h/adr.h +submit_mgt.o: ../../h/list_bpt.h +submit_mgt.o: ../../h/aparse.h +submit_mgt.o: ../../h/ap.h +submit_mgt.o: ../../h/util.h +submit_mgt.o: ../../h/or.h +submit_mgt.o: ../../h/chan.h +submit_mgt.o: ../../h/auth.h +submit_mgt.o: ../../h/list_rchan.h +submit_mgt.o: ../../h/mta.h +submit_mgt.o: ../../h/dr.h +submit_mgt.o: ../../h/extension.h +submit_mgt.o: ../../h/mta.h +submit_mgt.o: ../../h/ap.h +submit_prm.o: submit_prm.c +submit_prm.o: ../../h/head.h +submit_prm.o: ../../h/util.h +submit_prm.o: ../../h/config.h +submit_prm.o: ../../h/ll_log.h +submit_prm.o: ../../h/retcode.h +submit_prm.o: ../../h/prm.h +submit_prm.o: ../../h/q.h +submit_prm.o: ../../h/adr.h +submit_prm.o: ../../h/list_rchan.h +submit_prm.o: ../../h/chan.h +submit_prm.o: ../../h/table.h +submit_prm.o: ../../h/list_bpt.h +submit_prm.o: ../../h/auth.h +submit_prm.o: ../../h/list_bpt.h +submit_prm.o: ../../h/extension.h +submit_prm.o: ../../h/mta.h +submit_prm.o: ../../h/adr.h +submit_prm.o: ../../h/list_bpt.h +submit_prm.o: ../../h/aparse.h +submit_prm.o: ../../h/ap.h +submit_prm.o: ../../h/util.h +submit_prm.o: ../../h/or.h +submit_prm.o: ../../h/chan.h +submit_prm.o: ../../h/auth.h +submit_prm.o: ../../h/list_rchan.h +submit_prm.o: ../../h/mta.h +submit_que.o: submit_que.c +submit_que.o: ../../h/head.h +submit_que.o: ../../h/util.h +submit_que.o: ../../h/config.h +submit_que.o: ../../h/ll_log.h +submit_que.o: ../../h/retcode.h +submit_que.o: ../../h/prm.h +submit_que.o: ../../h/q.h +submit_que.o: ../../h/adr.h +submit_que.o: ../../h/list_rchan.h +submit_que.o: ../../h/chan.h +submit_que.o: ../../h/table.h +submit_que.o: ../../h/list_bpt.h +submit_que.o: ../../h/auth.h +submit_que.o: ../../h/list_bpt.h +submit_que.o: ../../h/extension.h +submit_que.o: ../../h/mta.h +submit_que.o: ../../h/adr.h +submit_que.o: ../../h/list_bpt.h +submit_que.o: ../../h/aparse.h +submit_que.o: ../../h/ap.h +submit_que.o: ../../h/util.h +submit_que.o: ../../h/or.h +submit_que.o: ../../h/chan.h +submit_que.o: ../../h/auth.h +submit_que.o: ../../h/list_rchan.h +submit_que.o: ../../h/mta.h +submit_que.o: ../../h/adr.h +submit_txt.o: submit_txt.c +submit_txt.o: ../../h/head.h +submit_txt.o: ../../h/util.h +submit_txt.o: ../../h/config.h +submit_txt.o: ../../h/ll_log.h +submit_txt.o: ../../h/retcode.h +submit_txt.o: ../../h/list_bpt.h +submit_txt.o: ../../h/q.h +submit_txt.o: ../../h/adr.h +submit_txt.o: ../../h/list_rchan.h +submit_txt.o: ../../h/chan.h +submit_txt.o: ../../h/table.h +submit_txt.o: ../../h/list_bpt.h +submit_txt.o: ../../h/auth.h +submit_txt.o: ../../h/list_bpt.h +submit_txt.o: ../../h/extension.h +submit_txt.o: ../../h/mta.h +submit_txt.o: ../../h/adr.h +submit_txt.o: ../../h/list_bpt.h +submit_txt.o: ../../h/aparse.h +submit_txt.o: ../../h/ap.h +submit_txt.o: ../../h/util.h +submit_txt.o: ../../h/or.h +submit_txt.o: ../../h/chan.h +submit_txt.o: ../../h/auth.h +submit_txt.o: ../../h/list_rchan.h +submit_txt.o: ../../h/mta.h +submit_txt.o: ../../h/chan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Src/submit/ad_mgt.c b/Src/submit/ad_mgt.c new file mode 100644 index 0000000..34fa078 --- /dev/null +++ b/Src/submit/ad_mgt.c @@ -0,0 +1,824 @@ +/* ad_mgt.c: address management routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/ad_mgt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/ad_mgt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: ad_mgt.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "retcode.h" +#include +#include "q.h" +#include "dr.h" +#include "ap.h" + +extern int accept_all; + +extern void x400_add(), rfc822_add(), err_abrt(), pro_reply(); +extern void redirect_free (); +extern char *getpostmaster(); + +/* -- globals -- */ +static int ad_extend; + + +/* -- local routines -- */ +int rplose (); +int validate_sender (); +void ad_init (); +int validate_recip (); +void ad_log_print (); + +static int bad_address(); +static int recip_parse(); +static int do_sender_dr_outchan(); +static void set_return_chan(); + +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) + + +/* --------------------- Begin Routines -------------------------------- */ + + +ADDR *read_sender (qp) +Q_struct *qp; +{ + RP_Buf rpbuf, + *rp = &rpbuf; + ADDR *ad = NULLADDR; + int retval; + int type = qp -> inbound -> li_chan -> ch_in_ad_type; + + PP_TRACE (("submit/read_sender (%d)", type)); + rp -> rp_val = RP_OK; + + if ((retval = rd_adr (stdin, TRUE, &ad)) == RP_DONE) + err_abrt (retval, "Error reading sender"); + + + if (rp_isbad (retval) || ad -> ad_value == NULLCP) { + if (ad == NULLADDR) + err_abrt (RP_EOF, "No sender given"); + + err_abrt (retval, "Invalid sender '%s'", + isstr (ad -> ad_value) ? ad -> ad_value : "(none)"); + } + + + ad -> ad_resp = FALSE; + if (qp -> msgtype == MT_DMPDU) + ad -> ad_status = AD_STAT_PEND; + else + ad -> ad_status = AD_STAT_DONE; + ad -> ad_extension = 0; + ad -> ad_no = 0; + ad -> ad_type = type; + + + + if (qp -> msgtype == MT_DMPDU) + ad -> ad_resp = TRUE; + + return ad; +} + +static void copy_drstuff(ad, newad, isPostie) +ADDR *ad, *newad; +int isPostie; +{ + LIST_RCHAN *tmpchan; + char *tmpchar; + + tmpchan = ad->ad_fmtchan; + ad->ad_fmtchan = newad->ad_fmtchan; + newad->ad_fmtchan = tmpchan; + + tmpchan = ad->ad_outchan; + ad->ad_outchan = newad->ad_outchan; + newad->ad_outchan = tmpchan; + + if (isPostie == TRUE) { + tmpchar = ad->ad_r400DR; + ad->ad_r400DR = newad->ad_r400adr; + newad->ad_r400adr = tmpchar; + + tmpchar = ad->ad_r822DR; + ad->ad_r822DR = newad->ad_r822adr; + newad->ad_r822adr = tmpchar; + } +} + +static int x400routeback (ad, inbound, mta) +ADDR *ad; +CHAN *inbound; +char *mta; +{ + LIST_RCHAN *outchans = NULLIST_RCHAN, *ix; + int found; + char buf[BUFSIZ]; + /* attempt to route back x400 message to inbound mta */ + + if (tb_getchan (mta, &outchans) != OK) + /* can't find inbound mta in routing tables */ + return NOTOK; + ix = outchans; + found = FALSE; + while (ix != NULLIST_RCHAN && found == FALSE) { + if (ix -> li_chan != NULLCHAN + && ix -> li_chan == inbound) { + /* found routing via inbound */ + /* now check that can route to inbound mta that way */ + if ((ix -> li_mta == NULLCP + || lexequ(ix -> li_mta, mta) == 0) + && (ix -> li_chan -> ch_table == NULLTBL + || tb_k2val(ix -> li_chan -> ch_table, + mta, buf, 1) == OK)) + found = TRUE; + } + if (found == FALSE) + ix = ix -> li_next; + } + + if (found == TRUE) { + /* can routeback via x400 */ + if (ad->ad_outchan != NULLIST_RCHAN) + list_rchan_free(ad->ad_outchan); + ad->ad_outchan = ix; + /* remove all but ad->ad_outchan */ + if (ad -> ad_outchan -> li_next != NULLIST_RCHAN) { + list_rchan_free (ad->ad_outchan->li_next); + ad->ad_outchan->li_next = NULLIST_RCHAN; + } + if (outchans != ad->ad_outchan) { + for (ix = outchans; + ix != NULLIST_RCHAN && + ix -> li_next != ad->ad_outchan; + ix = ix -> li_next) + continue; + if (ix != NULLIST_RCHAN) + ix -> li_next = NULLIST_RCHAN; + list_rchan_free(outchans); + } + PP_NOTICE (("Will route DRs for unrouteable sender '%s' via inbound mta '%s'", + ad->ad_value, + mta)); + return OK; + } + PP_LOG (LLOG_EXCEPTIONS, + ("unable to route DRs to inbound mta '%s' via channel '%s' for unrouteable sender '%s'", + mta, inbound->ch_name, ad->ad_value)); + return NOTOK; +} + +static void removeNon822chans (plist) +LIST_RCHAN **plist; +{ + LIST_RCHAN *ix, *tmp; + /* remove all non 822 channels */ + + /* remove ones at front of queue */ + while (*plist != NULLIST_RCHAN + && (*plist) -> li_chan -> ch_out_ad_type != AD_822_TYPE) { + tmp = *plist; + *plist = tmp -> li_next; + tmp -> li_next = NULLIST_RCHAN; + list_rchan_free(tmp); + } + + if (*plist != NULLIST_RCHAN) { + ix = *plist; + while (ix -> li_next != NULLIST_RCHAN) { + if (ix -> li_next -> li_chan -> ch_out_ad_type != AD_822_TYPE) { + tmp = ix -> li_next; + ix -> li_next = tmp -> li_next; + tmp -> li_next = NULLIST_RCHAN; + list_rchan_free (tmp); + } else + ix = ix -> li_next; + } + } +} + +static int r822routeback (ad, inbound, mta) +ADDR *ad; +CHAN *inbound; +char *mta; +{ + AP_ptr tree, group, name, local, domain, route; + RP_Buf rpbuf; + ADDR *newad; + char buf[BUFSIZ]; + + /* attempt to source route DRs back via inbound mta */ + + if (ap_s2p(ad->ad_value, &tree, &group, &name, &local, + &domain, &route) != (char *) NOTOK) { + char *str; + AP_ptr newap = ap_new (AP_DOMAIN, + mta); + if (domain == NULLAP) + str = ap_p2s (group, name, local, + newap, NULLAP); + else if (route == NULLAP) + str = ap_p2s (group, name, local, + domain, newap); + else { + newap->ap_next = route; + newap->ap_ptrtype = AP_PTR_MORE; + str = ap_p2s (group, name, local, + domain, newap); + newap->ap_next = NULLAP; + } + ap_sqdelete(tree, NULLAP); + ap_free(tree); + ap_free(newap); + strcpy(buf, str); + free(str); + } else { + PP_LOG (LLOG_EXCEPTIONS, + ("unable to parse sender '%s' so unwilling to route DRs via inbound mta", + ad->ad_value)); + return NOTOK; + } + + newad = adr_new (buf, + inbound->ch_in_ad_type, + 0); + newad->ad_resp = FALSE; + + if (rp_isbad (ad_parse (newad, &rpbuf, + inbound->ch_ad_order))) { + PP_LOG (LLOG_EXCEPTIONS, + ("unable to route DRs to inbound mta '%s' for bad sender '%s' [%s]", + mta, + ad -> ad_value, + rpbuf.rp_line)); + adr_free (newad); + return NOTOK; + } + + removeNon822chans(&(newad->ad_outchan)); + if (newad->ad_outchan == NULLIST_RCHAN) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to route DRs to inbound mta '%s' via an rfc 822 channel for unrouteable sender '%s'", + mta, ad->ad_value)); + adr_free(newad); + return NOTOK; + } + + /* copy various things across */ + copy_drstuff(ad, newad, FALSE); + adr_free (newad); + PP_NOTICE(("Will source route DRs for unrouteable sender '%s' via inbound mta '%s'", + ad->ad_value, mta)); + return OK; +} + +static int postmasterrouteback (ad, inbound, mta) +ADDR *ad; +CHAN *inbound; +char *mta; +{ + RP_Buf rpbuf; + ADDR *newad; + + /* attempt to route DRs to 822 postmaster */ + PP_NOTICE(("Failed to route DRs for unrouteable sender '%s' back to inbound mta '%s', now attepmting sloppy mode routing to postmaster", + ad->ad_value, mta)); + + newad = adr_new(getpostmaster(inbound->ch_in_ad_type), + inbound->ch_in_ad_type, + 0); + newad->ad_resp = FALSE; + if (rp_isbad (ad_parse (newad, &rpbuf, + inbound->ch_ad_order))) { + PP_LOG (LLOG_EXCEPTIONS, + ("parsing of postmaster address '%s' fails [%s]", + newad->ad_value, + rpbuf.rp_line)); + adr_free (newad); + return NOTOK; + } + + removeNon822chans(&(newad->ad_outchan)); + if (newad->ad_outchan == NULLIST_RCHAN) { + PP_LOG (LLOG_EXCEPTIONS, + ("Unable to route DRs to postmaster '%s' via an rfc 822 channel for unrouteable sender '%s'", + newad->ad_value, ad->ad_value)); + adr_free(newad); + return NOTOK; + } + + /* copy various things across */ + PP_NOTICE(("Will route DRs for bad sender '%s' to postmaster '%s'", + ad->ad_value, newad->ad_value)); + copy_drstuff(ad, newad, TRUE); + adr_free (newad); + return OK; +} + +int validate_sender(qp, ad, user, rp) /* -- read in sender and validate -- */ +ADDR *ad; +Q_struct *qp; +char *user; +RP_Buf *rp; +{ + CHAN *ch_in = qp -> inbound -> li_chan; + int oldresp; + /* --- *** --- + Reject bad senders unless we can figure out some hack to + return them. + --- *** --- */ + + ad_extend = 1; /* -- reset -- */ + + oldresp = ad -> ad_resp; + ad->ad_resp = FALSE; + if (rp_isbad (ad_parse (ad, rp, ch_in -> ch_ad_order))) { + if (ch_in->ch_badSenderPolicy == CH_BADSENDER_SLOPPY + && ((ch_in->ch_in_ad_type == AD_X400_TYPE + && x400routeback(ad, ch_in, qp -> inbound -> li_mta) == OK) + /* managed to route back via x400 to inbound mta */ + || (ch_in->ch_in_ad_type == AD_822_TYPE + && r822routeback (ad, ch_in, qp->inbound->li_mta) == OK) + /* managed to route back via 822 to inbound mta */ + || postmasterrouteback (ad, ch_in, qp->inbound->li_mta) == OK + /* managed to route back to 822 local postmaster */)) + /* managed to route DRs somehow */ + rp -> rp_val = RP_OK; + else { + /* bad sender bounce */ + PP_LOG(LLOG_EXCEPTIONS, + ("Bounced message due to unrouteable sender")); + return rp -> rp_val; + } + + } + ad->ad_resp = oldresp; + + PP_NOTICE (("Sender '%s'", ad -> ad_value)); + + if (ch_in -> ch_access == CH_MTS && user != NULLCP && + tb_checkauth (gval(ad), ch_in, + user, NULLCP) == NOTOK) + return rplose (rp, RP_USER, + "User %s not allowed to submit as %s", + gval(ad), user); + + ad -> ad_resp = FALSE; + return do_sender_dr_outchan (ad, qp, rp); +} + +ADDR *read_recipient (qp) +Q_struct *qp; +{ + int retval; + RP_Buf rps, *rp = &rps; + ADDR *ad; + int type = qp -> inbound -> li_chan -> ch_in_ad_type; + + PP_TRACE (("submit/read_recip()")); + + ad = NULLADDR; + + retval = rd_adr (stdin, TRUE, &ad); + + switch (retval) { + case RP_OK: + if (ad -> ad_value == NULLCP) + break; + ad -> ad_type = type; + if (ad -> ad_resp == NO) + ad -> ad_status = AD_STAT_DONE; + return ad; + + case RP_DONE: + return NULL; + + } + PP_TRACE (("submit/read_recipient(def=%s)", + rp_valstr (retval))); + rp -> rp_val = retval; + (void) strcpy(rp -> rp_line, "Empty address ?"); + if (ad == NULLADDR) + ad = adr_new(" ", NULL, NULL); + else + ad -> ad_value = strdup(" "); + ad->ad_r822adr = strdup(" "); + x400_add(ad); + ad->ad_type = type; + ad -> ad_no = ad_extend++; + if (ad -> ad_extension == 0) + ad -> ad_extension = ad -> ad_no; + if (ad -> ad_resp) + ad->ad_status = AD_STAT_PEND; + else + ad->ad_status = AD_STAT_DONE; + return ad; +} + + + + +static void set_return_chan (ad, chan, host) +ADDR *ad; +CHAN *chan; +char *host; +{ + LIST_RCHAN *ch; + + if (chan == NULLCHAN || ad == NULLADDR || host == NULLCP) + err_abrt (RP_BAD, "set_return_chan called with NULL fields"); + + PP_TRACE (("set_return_chan (chan='%s', host='%s', drchan='%s')", + chan -> ch_name ? chan -> ch_name : "", + host ? host : "", + chan -> ch_drchan ? chan -> ch_drchan : "")); + + if (isstr (chan -> ch_drchan)) + ch = list_rchan_new (host, chan -> ch_drchan); + else + ch = list_rchan_new (host, chan -> ch_name); + + if (ad -> ad_outchan) + list_rchan_free (ad -> ad_outchan); + ad -> ad_outchan = ch; +} + + +static int do_sender_dr_outchan (ad, qp, rp) +ADDR *ad; +Q_struct *qp; +RP_Buf *rp; +{ + PP_TRACE (("do_sender_dr_outchan (%s)", ad -> ad_value)); + + if (ad -> ad_outchan == NULLIST_RCHAN || + ad -> ad_outchan -> li_chan == NULLCHAN) + return rplose (rp, RP_BAD, "DR has no channel"); + + if (fillin_orig_outchan (qp, ad) == NOTOK) + return rplose (rp, RP_BAD, "Can't find channel for DR"); + + set_return_chan (ad, ad -> ad_outchan -> li_chan, + ad -> ad_outchan -> li_mta); + return RP_OK; +} + + +/* -- read recip, & validate before adding to list. -- */ +int validate_recip(ad, qp, rp) +ADDR *ad; +Q_struct *qp; +RP_Buf *rp; +{ + int retval; + + PP_TRACE (("submit/validate_recip()")); + + ad -> ad_no = ad_extend++; + if (ad -> ad_extension == 0) + ad -> ad_extension = ad -> ad_no; + + switch (ad -> ad_status) { + case AD_STAT_DRWRITTEN: + if (ad -> ad_resp == FALSE) { + (void) rplose (rp, RP_AOK, "DR '%s'", ad -> ad_value); + break; + } + else if (ad -> ad_no != DR_FILENO_DEFAULT) + ad -> ad_status = AD_STAT_DONE; + /* fall */ + + case AD_STAT_PEND: + retval = recip_parse (ad, qp, rp); + if (rp_isbad (retval)) { + if (rp_isbad (bad_address (ad, qp, rp))) + return rp -> rp_val; + break; + } + + (void) rplose (rp, RP_AOK, "Nice address %s", ad -> ad_value); + break; + + default: + (void) rplose (rp, RP_AOK, "Skip '%s'", ad -> ad_value); + break; + + } + return rp -> rp_val; +} + +static int bad_address (ad, qp, rp) +ADDR *ad; +Q_struct *qp; +RP_Buf *rp; +{ + int retval = rp -> rp_val; + + if (rp_gbval (retval) == RP_BTNO && + retval != RP_BHST && + retval != RP_DHST) + return retval; /* temp failure */ + + if (accept_all && qp -> msgtype != MT_DMPDU) { + ad -> ad_parse_stat = retval; + ad -> ad_status = AD_STAT_DRREQUIRED; + ad -> ad_reason = DRR_UNABLE_TO_TRANSFER; + ad -> ad_diagnostic = DRD_UNRECOGNISED_OR; + ad -> ad_add_info = strdup (rp -> rp_line); + (void) rplose (rp, RP_AOK, + "Recipient %s failed to parse: DR to be generated", + ad -> ad_value); + } + else if (accept_all && qp -> msgtype == MT_DMPDU) + return rp -> rp_val; + else { + ad -> ad_resp = FALSE; + ad -> ad_status = AD_STAT_DONE; + } + + return rp -> rp_val; +} + +extern Redirection *redirect_new(); +extern void redirect_add(), redirect_rewind(); +extern char *adminstration_req_alt; + +static int recip_parse (ad, qp, rp) +ADDR *ad; +Q_struct *qp; +RP_Buf *rp; +{ + int retval; + char *orig; + Redirection *rewind; + PP_TRACE (("submit/recip_parse()")); + + retval = ad_parse (ad, rp, qp -> inbound -> li_chan -> ch_ad_order); + + if (rp_isbad (retval) + && qp->alternate_recip_allowed == TRUE + && qp->recip_reassign_prohibited != TRUE + && isstr(ad -> ad_orig_req_alt)) { + char buf[BUFSIZ]; + + PP_TRACE(("attempting ad_orig_req_alt '%s'", + ad -> ad_orig_req_alt)); + if (ad->ad_type == AD_X400_TYPE) { + if (isstr(ad->ad_r400adr)) + strcat(buf, ad->ad_r400adr); + else + strcat(buf, ad->ad_value); + } else { + OR_ptr or = NULLOR; + + if (isstr(ad->ad_r822adr)) + or_rfc2or_aux(ad->ad_r822adr, &or, ad->ad_no); + else + or_rfc2or_aux(ad->ad_value, &or, ad->ad_no); + if (or != NULLOR) { + or_or2std(or, buf, FALSE); + or_free(or); + } else + buf[0] = '\0'; + } + rewind = redirect_new(buf, + (isstr(ad->ad_dn)) ? + ad->ad_dn : "", + NULLUTC, + RDR_ORIG_ASSIGNED); + if (redirect_before(ad->ad_redirection_history, + rewind) == TRUE) { + PP_NOTICE(("redirection loop detected for '%s'", + buf)); + redirect_free(rewind); + } else { + redirect_add(&(ad->ad_redirection_history), + rewind); + orig = ad->ad_value; + + ad -> ad_value = strdup (ad -> ad_orig_req_alt); + if (ad -> ad_r400adr != NULLCP) { + free(ad -> ad_r400adr); + ad -> ad_r400adr = NULLCP; + } + if (ad -> ad_r822adr != NULLCP) { + free(ad -> ad_r822adr); + ad -> ad_r822adr = NULLCP; + } + + aparse_rewindx400(ad -> aparse); + aparse_rewindr822(ad -> aparse); + if (ad->ad_parse_message) { + free(ad->ad_parse_message); + ad->ad_parse_message = NULLCP; + } + if (rp_isbad(retval = ad_parse (ad, rp, + qp -> inbound -> li_chan -> ch_ad_order))) { + redirect_rewind(&(ad->ad_redirection_history), + rewind); + if (ad->ad_value) free(ad->ad_value); + ad->ad_value = orig; + if (ad -> ad_r400adr != NULLCP) { + free(ad -> ad_r400adr); + ad -> ad_r400adr = NULLCP; + } + if (ad -> ad_r822adr != NULLCP) { + free(ad -> ad_r822adr); + ad -> ad_r822adr = NULLCP; + } + } else { + if (orig) free(orig); + } + } + } + + if (rp_isbad(retval) && isstr(adminstration_req_alt)) { + char buf[BUFSIZ]; + char *saveerror = NULLCP; + + PP_TRACE(("attempting adminstration_req_alt '%s'", + adminstration_req_alt)); + + if (ad->ad_type == AD_X400_TYPE) { + if (isstr(ad->ad_r400adr)) + strcat(buf, ad->ad_r400adr); + else + strcat(buf, ad->ad_value); + } else { + OR_ptr or = NULLOR; + + if (isstr(ad->ad_r822adr)) + or_rfc2or_aux(ad->ad_r822adr, &or, ad->ad_no); + else + or_rfc2or_aux(ad->ad_value, &or, ad->ad_no); + if (or != NULLOR) { + or_or2std(or, buf, FALSE); + or_free(or); + } else + buf[0] = '\0'; + } + + rewind = redirect_new(buf, + (isstr(ad->ad_dn)) ? + ad->ad_dn : "", + NULLUTC, + RDR_MD_ASSIGNED); + if (redirect_before(ad->ad_redirection_history, + rewind) == TRUE) { + PP_NOTICE(("redirection loop detected for '%s'", + buf)); + redirect_free(rewind); + } else { + redirect_add(&(ad->ad_redirection_history), + rewind); + orig = ad->ad_value; + ad -> ad_value = strdup (adminstration_req_alt); + if (ad -> ad_r400adr != NULLCP) { + free(ad -> ad_r400adr); + ad -> ad_r400adr = NULLCP; + } + if (ad -> ad_r822adr != NULLCP) { + free(ad -> ad_r822adr); + ad -> ad_r822adr = NULLCP; + } + + aparse_rewindx400(ad -> aparse); + aparse_rewindr822(ad -> aparse); + saveerror = ad->ad_parse_message; + ad->ad_parse_message = NULLCP; + + if (rp_isbad(retval = ad_parse (ad, rp, + qp -> inbound -> li_chan -> ch_ad_order))) { + redirect_rewind(&(ad->ad_redirection_history), + rewind); + if (ad -> ad_r400adr != NULLCP) { + free(ad -> ad_r400adr); + ad -> ad_r400adr = NULLCP; + } + if (ad -> ad_r822adr != NULLCP) { + free(ad -> ad_r822adr); + ad -> ad_r822adr = NULLCP; + } + if (ad->ad_parse_message) + free(ad->ad_parse_message); + ad->ad_parse_message = saveerror; + } else { + if (saveerror) + free(saveerror); + } + /* maintain previous ad_value for */ + /* adminstration_req_alt redirects */ + if (ad->ad_value) free(ad->ad_value); + ad->ad_value = orig; + } + } + + if (!accept_all && rp_isbad (retval)) { + PP_TRACE (("recip_parse failed (%s %s)", + rp_valstr((int)rp -> rp_val), + rp -> rp_line)); + return retval; + } + + + /* -- Patch up the local x400adr -- */ + + if (!rp_isbad (retval)) { + if (ad -> ad_r400adr == NULLCP && ad -> ad_type == AD_822_TYPE) + x400_add (ad); + + if (ad -> ad_r822adr == NULLCP && ad -> ad_type == AD_X400_TYPE) + rfc822_add (ad); + } + else { + if (ad -> ad_r400adr == NULLCP) + ad -> ad_r400adr = strdup (ad -> ad_value); + if (ad -> ad_r822adr == NULLCP) + ad -> ad_r822adr = strdup (ad -> ad_value); + } + return (retval); +} + + + + +void ad_log_print (ad) +ADDR *ad; +{ + char *recip; + if (ad == NULLADDR) + return; + + + switch (ad -> ad_type) { + case AD_X400_TYPE: + recip = (ad -> ad_r400adr) ? ad -> ad_r400adr : ad -> ad_value; + break; + case AD_822_TYPE: + recip = (ad -> ad_r822adr) ? ad -> ad_r822adr : ad -> ad_value; + break; + default: + recip = ad->ad_value; + break; + } + PP_NOTICE (("Recipient '%s' mta '%s'", + recip, + (ad -> ad_outchan && ad -> ad_outchan -> li_mta) ? + ad -> ad_outchan -> li_mta : "")); + + ad_log_print (ad -> ad_next); +} + + + +#ifdef lint +/* VARARGS3 */ +int rplose (rp, val, str) +RP_Buf *rp; +int val; +char *str; +{ + return rplose (rp, val, str); +} +#else +int rplose (va_alist) +va_dcl +{ + va_list ap; + RP_Buf *rp; + int val; + char buf[BUFSIZ]; + + va_start (ap); + + rp = va_arg (ap, RP_Buf *); + val = va_arg (ap, int); + + _asprintf (buf, NULLCP, ap); + + if (rp_isbad (val)) + PP_LOG (LLOG_EXCEPTIONS, ("rplose (%s, '%s')", + rp_valstr (val), buf)); + + rp -> rp_val = val; + (void) strncpy (rp -> rp_line, buf, sizeof (rp -> rp_line) - 1); + + va_end (ap); + + return val; +} +#endif diff --git a/Src/submit/auth.c b/Src/submit/auth.c new file mode 100644 index 0000000..3f7c1f0 --- /dev/null +++ b/Src/submit/auth.c @@ -0,0 +1,1281 @@ +/* auth.c: authorisation procedures used by submit */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/auth.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/auth.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: auth.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" +#include "tb_auth.h" +#include + + + +#define ORED FALSE +#define freason(i) (rcmd_srch (i, authtbl_reasons)) +#define rrights(i) (rcmd_srch (i, authtbl_rights)) +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) + + +extern CMD_TABLE authtbl_rights[]; +extern CMD_TABLE authtbl_loglevel[]; +extern LIST_AUTH_CHAN *authchan_new(); +extern LIST_AUTH_MTA *authmta_new (); +extern AUTH_USER *authusr_new(); +extern AUTH *auth_new(); +extern char *re_comp(); +extern CMD_TABLE authtbl_reasons[]; +extern char *authchannel; +extern char *authloglevel; +extern char *loc_dom_site; +extern void do_reason(), err_abrt(); +extern void tb_parse_authchan(); +extern void authchan_add(), authmta_add(); +/* -- static variables -- */ +static AUTH *sender_auth = NULL_AUTH; +static LIST_AUTH_CHAN *def_authchan = NULLIST_AUTHCHAN; +static LIST_AUTH_CHAN *authchan_start = NULLIST_AUTHCHAN; +static LIST_AUTH_MTA *authmta_start = NULLIST_AUTHMTA; + + +/* -- globals -- */ +char auth2submit_msg[BUFSIZ]; +int auth_loglev; + + +/* -- local routines -- */ +int auth_finish(); +int fillin_orig_outchan(); +void auth_start(); + +static Bindings *bindings_new(); +static Bindings *do_ch_binds(); +static char *ltoa(); +static int test_pair(); +static int bindings_free(); +static int chk_mtarights(); +static int chk_usrights(); +static int do_stage_1(); +static int do_stage_2(); +static int test_flags(); +static int test_recip_finish(); +static int test_recip_start(); +static int test_regex(); +static void auth_chan(); +static void auth_err2adr(); +static void auth_init(); +static void auth_init_recip(); +static void auth_mta(); +static void auth_remdup(); +static void auth_usr(); +static void auth_usr_chks(); +static void bindings_add(); +static void pr_rights(); +static void rem_excess_outchans(); +static void rem_pair(); +static void set_fmt_and_content(); + + + + +/* ------------------------ Begin Routines ------------------------------- */ + + + + +void auth_start(que, sender, recip) +Q_struct *que; +ADDR *sender, *recip; +{ + ADDR *ad; + + PP_TRACE (("auth_start()")); + + auth_init(que, recip); + auth_usr(sender, recip); + + for (ad = recip; ad; ad = ad -> ad_next) + if (ad -> ad_status == AD_STAT_PEND) + test_recip_start (que, sender, ad); +} + + + + + +int auth_finish(qp, sender, recip) +Q_struct *qp; +ADDR *sender, *recip; +{ + ADDR *ad; + int retval = RP_OK; + + for (ad = recip; ad; ad = ad -> ad_next) { + + PP_TRACE (("auth_finish ('%s', '%d')", + ad -> ad_value, ad -> ad_status)); + + switch (ad -> ad_status) { + case AD_STAT_PEND: + if (test_recip_finish (qp, sender, ad) == NOTOK) + retval = RP_NAUTH; + continue; + default: + continue; + } + } + + PP_TRACE (("auth_finish returns ('%s')", rp_valstr (retval))); + return retval; +} + + + + +int fillin_orig_outchan (qp, ad) +Q_struct *qp; +ADDR *ad; +{ + Bindings *binds, *ix; + int unknownBP; + if ((binds = do_ch_binds (qp, ad, &unknownBP)) == (Bindings *) NULL) { + PP_LOG(LLOG_EXCEPTIONS, + ("Unable to reformat return of contents")); + /* take first channel */ + rem_excess_outchans(ad, ad->ad_outchan); + ad->ad_type = ad->ad_outchan->li_chan->ch_out_ad_type; + return OK; + } + + /* try for one without reformatting ? */ + /* should also check unknownBP */ + for (ix = binds;ix && ix -> fmtchans;ix = ix->next) + continue; + if (!ix) { + /* revert to first choice */ + ix = binds; +#ifdef NOTDEF + if (unknownBP == TRUE) { + /* oh oh unknown bodypart and reformatting */ + /* just have to forget about return of contents */ + list_rchan_free(ix -> fmtchans); + ix -> fmtchans = NULLIST_RCHAN; + } +#endif + } + + set_fmt_and_content(qp, ad, ix); + + rem_excess_outchans (ad, ix -> outchan); + ad -> ad_type = ix -> outchan -> li_chan -> ch_out_ad_type; + bindings_free (binds); + return OK; +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static int bindings_free (ix) +Bindings *ix; +{ + if (ix == NULL) return; + if (ix -> next != (Bindings *) NULL) bindings_free (ix -> next); + list_rchan_free (ix -> fmtchans); + list_bpt_free (ix -> bpts); + free ((char *) ix); +} + + + +static Bindings *bindings_new (out, fmts, bpts, cost) +LIST_RCHAN *out, + *fmts; +LIST_BPT *bpts; +int cost; +{ + Bindings *ret = (Bindings *) malloc(sizeof(Bindings)); + ret -> outchan = out; + ret -> fmtchans = fmts; + ret -> bpts = bpts; + ret -> cost = cost; + ret -> next = (Bindings *) NULL; + return ret; +} + + + +static void bindings_add (plist, new) +Bindings **plist, + *new; +{ + Bindings *ix; + + PP_TRACE (("bindings_add ('%s')", + new -> outchan -> li_chan -> ch_name)); + + if (*plist == (Bindings *) NULL + || new -> cost < (*plist) -> cost) { + /* easy */ + new -> next = *plist; + *plist = new; + return; + } + + ix = *plist; + + while (ix -> next != (Bindings *) NULL + && ix -> next -> cost <= new -> cost) + ix = ix -> next; + new -> next = ix -> next; + ix -> next = new; +} + + + +static Bindings *do_ch_binds (qp, ad, punknown) +Q_struct *qp; +ADDR *ad; +int *punknown; +{ + Bindings *ret = (Bindings *) NULL; + LIST_RCHAN *ix = ad -> ad_outchan, *fmts; + LIST_BPT *bpts; + int cost, unknown; + + *punknown = FALSE; + + while (ix != NULLIST_RCHAN) { + PP_TRACE (("do_ch_binds ('%s')", ix -> li_chan -> ch_name)); + if (ch_bind (qp, ad, ix, &fmts, &bpts, &cost, &unknown) == OK) { + bindings_add(&ret, bindings_new(ix, fmts, bpts, cost)); + if (unknown == TRUE) + *punknown = TRUE; + } + ix = ix -> li_next; + } + return ret; +} + + + + +static int test_recip_finish (qp, orig, ad) +Q_struct *qp; +ADDR *orig, *ad; +{ + Bindings *binds, *ix; + int retval = OK, unknownBP; + int test = ad -> ad_outchan -> li_auth -> chan -> test; + + PP_TRACE (("test_recip_finish : %s", gval(ad))); + + if ((binds = do_ch_binds (qp, ad, &unknownBP)) == (Bindings *) NULL) + return NOTOK; + + for (ix = binds; ix != (Bindings *) NULL; ix = ix -> next) { + + if (unknownBP == TRUE + && ix -> fmtchans) + continue; + + switch (ix -> outchan -> li_auth -> status) { + case AUTH_OK: + case AUTH_DR_OK: + ad -> ad_type = ix -> outchan -> li_chan -> ch_out_ad_type; + retval = test_pair (qp, ad, ix -> outchan, orig); + + if (retval == NOTOK) { + rem_pair (qp, ad, ix -> outchan); + if (test != AUTH_CHAN_TEST) + continue; + } + + /* --- otherwise fall through --- */ + + case AUTH_FAILED_TEST: /* --- failed at do_stage_1 --- */ + set_fmt_and_content (qp, ad, ix); + rem_excess_outchans (ad, ix -> outchan); + bindings_free (binds); + return OK; + + default: + continue; + } + } + + if (unknownBP == TRUE && ad -> ad_status != AD_STAT_DRREQUIRED) { + /* failed because of unknown bodypart */ + ad -> ad_status = AD_STAT_DRREQUIRED; + ad -> ad_reason = DRR_CONVERSION_NOT_PERFORMED; + ad -> ad_diagnostic = DRD_CONVERSION_IMPRACTICAL; + ad -> ad_add_info = strdup("Unrecognised bodypart in message"); + } + bindings_free (binds); + return NOTOK; +} + + + + +static void set_fmt_and_content (qp, ad, ix) +Q_struct *qp; +ADDR *ad; +Bindings *ix; +{ + char *content_out = ix -> outchan -> li_chan -> ch_content_out; + + PP_TRACE (("submit/Give message to '%s'", + ix -> outchan -> li_chan -> ch_name)); + + ad -> ad_fmtchan = ix -> fmtchans; + + /* -- stop them being freed -- */ + ix -> fmtchans = NULLIST_RCHAN; + ad -> ad_eit = ix -> bpts; + + /* -- stop them being freed -- */ + ix -> bpts = NULLIST_BPT; + if (ad -> ad_content != NULLCP) { + free (ad -> ad_content); + ad -> ad_content = NULLCP; + } + + if (isstr (qp -> cont_type) && + isstr (content_out) && + strcmp (qp -> cont_type, content_out) != 0) + ad -> ad_content = strdup (content_out); + else if (isstr (content_out)) + ad -> ad_content = strdup (content_out); + + return; +} + + + + +static int test_recip_start (qp, orig, ad) +Q_struct *qp; +ADDR *orig, *ad; +{ + LIST_RCHAN *lp = ad -> ad_outchan; + int retval = FALSE; + + PP_TRACE (("test_recip_start : %s", gval(ad))); + + for (; lp != NULLIST_RCHAN; lp = lp -> li_next) { + + ad -> ad_type = lp -> li_chan -> ch_out_ad_type; + + switch (lp -> li_auth -> status) { + case AUTH_OK: + case AUTH_DR_OK: + retval = test_pair (qp, ad, lp, orig); + if (retval == OK) return OK; + rem_pair (qp, ad, lp); + continue; + default: + continue; + } + } + + return retval; +} + + + +static int test_pair (qp, ad, lp, orig) /* Test chan/mta/usr per recip */ +Q_struct *qp; +ADDR *ad; +LIST_RCHAN *lp; +ADDR *orig; +{ + char *val = gval(ad); + AUTH *au = lp -> li_auth; + int retval; + + PP_TRACE (("test_pair : '%s' '%s' '%s'", val, + au -> chan -> li_chan -> ch_name, au -> mta -> li_mta)); + + + + switch (au -> stage) { + + case AUTH_STAGE_1: + if (au -> chan -> li_found == FALSE) + auth_chan (au -> chan); + retval = do_stage_1 (qp, ad, au, orig); + return retval; + + + case AUTH_STAGE_2: + retval = do_stage_2 (qp, val, au); + return retval; + } + + + PP_LOG (LLOG_EXCEPTIONS, + ("auth/Internal error unknown test stage %d", au -> stage)); + return NOTOK; +} + + +static void auth_user (au, ad) +AUTH *au; +ADDR *ad; +{ + if (au -> user -> found == TRUE) + return; + + if (tb_getauthusr (au -> user, ad) == NOTOK) + err_abrt (RP_NAUTH, "Cannot look up authorisation for '%s'", + gval(ad)); + if (au -> user -> found == FALSE) + PP_TRACE (("auth_usr_chks/recipient '%s' missing", + gval (ad))); +} + +static int do_stage_1 (qp, ad, au, orig) +Q_struct *qp; +ADDR *ad; +AUTH *au; +ADDR *orig; +{ + + int t[4]; + int i = 0; + int retval = NOTOK; + char buf[LINESIZE]; + LIST_REGEX *lr; + + + PP_TRACE (("do_stage_1: %s", gval(ad))); + + switch (au -> chan -> policy) { + + default: + PP_LOG (LLOG_EXCEPTIONS, + ("auth/do_stage_1 unknown channel policy %d", + au -> chan -> policy)); + break; + + case AUTH_CHAN_FREE: + do_reason (au, freason(AUR_CH_FREE)); + retval = OK; + break; + + + case AUTH_CHAN_NONE: + do_reason (au, freason(AUR_CH_NONE)); + break; + + + case AUTH_CHAN_NEGATIVE: + auth_mta (au); + auth_mta (sender_auth); + auth_user (sender_auth, orig); + auth_user (au, ad); + + t [i++] = chk_mtarights (qp, sender_auth, + au -> chan -> li_chan); + t [i++] = chk_usrights (qp, sender_auth, + au -> chan -> li_chan); + t [i++] = chk_mtarights (qp, au, au -> chan -> li_chan); + t [i++] = chk_usrights (qp, au, au -> chan -> li_chan); + + /* with negative, OK means one of the values is true, + * which in turn means there is an explicit block on this + * which means its failed authorisation */ + if (test_flags (t, NOTOK, ORED) != OK) + retval = OK; + pr_rights (au, AUTH_CHAN_NEGATIVE, retval); + break; + + + case AUTH_CHAN_BLOCK: + auth_mta (au); + auth_mta (sender_auth); + auth_user (sender_auth, orig); + auth_user (au, ad); + t [i++] = chk_mtarights (qp, sender_auth, + au -> chan -> li_chan); + t [i++] = chk_usrights (qp, sender_auth, + au -> chan -> li_chan); + t [i++] = chk_mtarights (qp, au, au -> chan -> li_chan); + t [i++] = chk_usrights (qp, au, au -> chan -> li_chan); + retval = test_flags (t, OK, ORED); + pr_rights (au, AUTH_CHAN_BLOCK, retval); + break; + } + + + + if (retval == NOTOK) + return NOTOK; + + + /* -- regex testing -- */ + + bzero (buf, LINESIZE); + + lr = sender_auth -> mta -> requires; + if (lr && (!test_regex (gval (orig), lr, buf))) { + do_reason (au, freason(AUR_IMTA_MISSING_SNDR), buf); + return NOTOK; + } + + lr = sender_auth -> mta -> excludes; + if (lr && (test_regex (gval (orig), lr, buf))) { + do_reason (au, freason(AUR_IMTA_EXCLUDES_SNDR), buf); + return NOTOK; + } + + lr = au -> mta -> requires; + if (lr && (!test_regex (gval(ad), lr, buf))) { + do_reason (au, freason(AUR_OMTA_MISSING_RECIP), buf); + return NOTOK; + } + + lr = au -> mta -> excludes; + if (lr && (test_regex (gval(ad), lr, buf))) { + do_reason (au, freason(AUR_OMTA_EXCLUDES_RECIP), buf); + return NOTOK; + } + + au -> stage = AUTH_STAGE_2; + return OK; +} + + + + +static int do_stage_2 (qp, adval, au) +Q_struct *qp; +char *adval; +AUTH *au; +{ + LIST_BPT *le, *lb; + long size; + + + PP_TRACE (("do_stage_2: %s", adval)); + + /* -- content tests -- */ + + size = au -> chan -> sizelimit; + if (size && (qp -> msgsize > size)) { + do_reason (au, freason(AUR_MSGSIZE_FOR_CHAN), + ltoa(qp -> msgsize), ltoa(size)); + return NOTOK; + } + + size = au -> mta -> sizelimit; + if (size && (qp -> msgsize > size)) { + do_reason (au, freason(AUR_MSGSIZE_FOR_MTA), + ltoa(qp -> msgsize), ltoa(size)); + return NOTOK; + } + + size = au -> user -> sizelimit; + if (size && (qp -> msgsize > size)) { + do_reason (au, freason(AUR_MSGSIZE_FOR_USR), + ltoa(qp -> msgsize), ltoa(size)); + return NOTOK; + } + + + /* -- body part tests -- */ + + + for (le = au -> mta -> content_excludes; le; le = le -> li_next) { + for (lb = qp->encodedinfo.eit_types; lb; lb = lb -> li_next) { + + PP_TRACE (("do_stage_2 exclude mta body parts %s : %s", + le -> li_name, lb -> li_name)); + + if (strcmp (le -> li_name, lb -> li_name) == 0) { + do_reason (au, freason(AUR_MTA_BPT), + le -> li_name); + return NOTOK; + } + } + } + + + for (le = au -> user -> content_excludes; le; le = le -> li_next) { + for (lb = qp->encodedinfo.eit_types; lb; lb=lb -> li_next) { + + PP_TRACE (("do_stage_2 exclude user body parts %s : %s", + le -> li_name, lb -> li_name)); + + if (strcmp (le -> li_name, lb -> li_name) == 0) { + do_reason (au, freason(AUR_USR_BPT), + le -> li_name); + return NOTOK; + } + } + } + + + au -> stage ++; + PP_TRACE (("do_stage_2: successful & returns '%s'", au -> reason)); + return OK; +} + + + + +static int test_regex (val, list, ptr) +char *val; +LIST_REGEX *list; +char *ptr; +{ + LIST_REGEX *lr; + char *cp; + int test; + + PP_TRACE (("test_regex: %s", val)); + + for (lr = list; lr != NULLIST_REGEX; lr = lr -> li_next) { + + PP_TRACE (("auth/test_regex: '%s'", lr -> li_regex)); + + cp = re_comp (lr -> li_regex); + + if (cp) { + PP_LOG (LLOG_EXCEPTIONS, + ("auth/test_regex: invalid expression <%s> %s", + lr -> li_regex, cp)); + continue; + } + + test = re_exec (val); + + if (test == 1) { + (void) sprintf (ptr, "%s", lr -> li_regex); + PP_TRACE (("auth/test_regex : %s matches %s", + val, lr -> li_regex)); + return TRUE; + } + + + if (test == -1) { + PP_LOG (LLOG_EXCEPTIONS, + ("auth/test_regex : internal error <%s>", + lr -> li_regex)); + continue; + } + + + if (strlen (ptr)) { + (void) strcat (ptr, " | "); + (void) strcat (ptr, lr -> li_regex); + } + else + (void) sprintf (ptr, "%s", lr -> li_regex); + + PP_TRACE (("auth/test_regex: no match: %s : %s", + lr -> li_regex, ptr)); + + continue; + } + + return FALSE; +} + + + + +static int chk_mtarights (qp, au, ch) +Q_struct *qp; +AUTH *au; +CHAN *ch; +{ + int infound = FALSE, + outfound = FALSE; + LIST_CHAN_RIGHTS *lr; + + + PP_TRACE (("chk_mtarights()")); + + if (au -> mta -> li_found == FALSE) return MAYBE; + + if (au -> mta -> rights != AUTH_RIGHTS_UNSET) { + au -> mta_inrights = au -> mta -> rights; + au -> mta_outrights = au -> mta -> rights; + } + + + for (lr = au -> mta -> li_cr; lr; lr = lr -> li_next) { + if (lr -> li_chan == qp -> inbound -> li_chan) { + infound = TRUE; + au -> mta_inrights = lr -> li_rights; + } + + if (lr -> li_chan == ch) { + outfound = TRUE; + au -> mta_outrights = lr -> li_rights; + } + + if (infound && outfound) + break; + } + + + /* -- returns OK if (inbound = in|both && outbound = out|both -- */ + + if (au -> mta_inrights == AUTH_RIGHTS_NONE || + au -> mta_inrights == AUTH_RIGHTS_OUT || + au -> mta_inrights == AUTH_RIGHTS_UNSET) + return NOTOK; + + if (au -> mta_outrights == AUTH_RIGHTS_NONE || + au -> mta_outrights == AUTH_RIGHTS_IN || + au -> mta_outrights == AUTH_RIGHTS_UNSET) + return NOTOK; + + PP_TRACE (("chk_mtarights : successful: in = %s out = %s", + rrights (au -> mta_inrights), + rrights (au -> mta_outrights))); + + return OK; +} + +static int chk_usrights (qp, au, ch) +Q_struct *qp; +AUTH *au; +CHAN *ch; +{ + int infound = FALSE, + outfound = FALSE; + LIST_CHAN_RIGHTS *lr; + + + PP_TRACE (("chk_usrights()")); + + if (au -> user -> found == FALSE) + return MAYBE; + + if (au -> user -> rights != AUTH_RIGHTS_UNSET) { + au -> user_inrights = au -> user -> rights; + au -> user_outrights = au -> user -> rights; + } + + for (lr = au -> user -> li_cr; lr; lr = lr -> li_next) { + if (lr -> li_chan == qp -> inbound -> li_chan) { + infound = TRUE; + au -> user_inrights = lr -> li_rights; + } + + if (lr -> li_chan == ch) { + outfound = TRUE; + au -> user_outrights = lr -> li_rights; + } + + if (infound && outfound) + break; + } + + + /* -- returns OK if (inbound = in|both && outbound = out|both -- */ + + if (au -> user_inrights == AUTH_RIGHTS_NONE || + au -> user_inrights == AUTH_RIGHTS_OUT || + au -> user_inrights == AUTH_RIGHTS_UNSET) + return NOTOK; + + if (au -> user_outrights == AUTH_RIGHTS_NONE || + au -> user_outrights == AUTH_RIGHTS_IN || + au -> user_outrights == AUTH_RIGHTS_UNSET) + return NOTOK; + + PP_TRACE (("chk_usrights : successful : in = %s out = %s", + rrights (au -> user_inrights), + rrights (au -> user_outrights))); + + return OK; +} + +static void rem_excess_outchans (ad, outchan) +ADDR *ad; +LIST_RCHAN *outchan; +{ + LIST_RCHAN *ix, *tmp; + + /* remove excess ad_outchans */ + + ix = ad -> ad_outchan; + + if (ix != outchan) { + while (ix -> li_next != NULLIST_RCHAN + && ix -> li_next != outchan) + ix = ix -> li_next; + if (ix -> li_next != NULLIST_RCHAN) { + tmp = ad -> ad_outchan; + ad -> ad_outchan = ix -> li_next; + ix -> li_next = NULLIST_RCHAN; + list_rchan_free (tmp); + } + } + + if (ad -> ad_outchan -> li_next != NULLIST_RCHAN) { + list_rchan_free (ad -> ad_outchan -> li_next); + ad -> ad_outchan -> li_next = NULLIST_RCHAN; + } +} + + + + +static void rem_pair (qp, ad, remch) +Q_struct *qp; +ADDR *ad; +LIST_RCHAN *remch; +{ + LIST_RCHAN *lp; + AUTH *au = remch -> li_auth; + int allgone = TRUE; + + + if (remch == NULLIST_RCHAN) return; + + + PP_TRACE (("rem_pair : '%s' '%s' '%s' '%d'", + gval (ad), remch -> li_chan -> ch_name, + remch -> li_mta, au -> chan -> test)); + + + switch (au -> chan -> test) { + case AUTH_CHAN_TEST: + au -> status = AUTH_FAILED_TEST; + return; + default: + au -> status = AUTH_FAILED; + break; + } + + + for (lp = ad -> ad_outchan; lp; lp = lp -> li_next) { + switch (lp -> li_auth -> status) { + case AUTH_OK: + case AUTH_DR_OK: + case AUTH_FAILED_TEST: + allgone = FALSE; + break; + + case AUTH_DR_FAILED: + case AUTH_FAILED: + continue; + } + break; + } + + if (allgone) + auth_err2adr (qp, ad); +} + + + + +static void auth_err2adr (qp, ad) +Q_struct *qp; +ADDR *ad; +{ + char buf [BUFSIZ * 2]; + int oldType; + if (ad == NULLADDR) return; + + ad -> ad_status = AD_STAT_DRREQUIRED; + ad -> ad_reason = DRR_UNABLE_TO_TRANSFER; + ad -> ad_diagnostic = DRD_NO_BILATERAL_AGREEMENT; + + oldType = ad->ad_type; + if (qp && qp -> inbound && qp -> inbound -> li_chan) + ad->ad_type = qp -> inbound -> li_chan -> ch_in_ad_type; + (void) sprintf (buf, + "Authorisation failure at site '%s' for recip '%s' Reason: '%s'", + loc_dom_site, gval(ad), auth2submit_msg); + ad->ad_type = oldType; + + ad -> ad_add_info = strdup (buf); + + PP_TRACE (("auth_err2adr: '%s'", buf)); +} + + + + +static void auth_chan (ch) +LIST_AUTH_CHAN *ch; +{ + if (tb_getauthchan (ch) == NOTOK) + err_abrt (RP_NAUTH, + "Cannot look up channel authorisation table '%s'", + ch -> li_chan -> ch_name); + + if (ch -> li_found == FALSE) + PP_TRACE (("auth_chan/Chan '%s' missing", + ch -> li_chan -> ch_name)); +} + + + + +static void auth_mta (au) +AUTH *au; +{ + if (au -> mta -> li_found == TRUE) + return; + if (tb_getauthmta (au -> mta) == NOTOK) + err_abrt (RP_NAUTH, + "Cannot look up mta authorisation table '%s'", + au -> mta -> li_mta); + + if (au -> mta -> li_found == FALSE) + PP_TRACE (("auth_mta/Mta '%s' missing", + au -> mta -> li_mta)); +} + + + + +static void auth_usr(orig, recip) +ADDR *orig, *recip; +{ + ADDR *ad; + int ac; + + PP_TRACE (("auth_usr()")); + + if (sender_auth -> user == NULL_AUTHUSR) + err_abrt (RP_NAUTH, "No sender user authorisation table"); + + if (orig == NULLADDR) + err_abrt (RP_NAUTH, "No sender address found"); + +#ifdef notdef + if (tb_getauthusr (sender_auth -> user, orig) == NOTOK) + err_abrt (RP_NAUTH, + "Authorisation lookup failed for sender '%s'", + gval (orig)); + + if (sender_auth -> user -> found == FALSE) + PP_TRACE (("auth_usr/sender user '%s' missing", + gval (orig))); +#endif + + for (ad = recip, ac = 0; ad; ac ++,ad = ad -> ad_next) + auth_usr_chks (ad); + + + if (ac > 1000) + return; + /* -- eliminate duplicates -- */ + + for (ad = recip; ad; ad = ad -> ad_next) { + + PP_TRACE (("auth_usr/dup loop '%s' stat='%d', resp='%d')", + ad -> ad_value, ad -> ad_status, ad -> ad_resp)); + + if (ad -> ad_resp == FALSE) + continue; + + switch (ad -> ad_status) { + case AD_STAT_DRREQUIRED: + case AD_STAT_DONE: + continue; + } + + auth_remdup (ad, ad -> ad_next); + } +} + + + + +static void auth_usr_chks (ad) +ADDR *ad; +{ + char *value = ad -> ad_value; + + PP_TRACE (("auth_usr_chks (%s)", gval (ad))); + + if (ad -> ad_status == AD_STAT_DRREQUIRED || + ad -> ad_status == AD_STAT_DRWRITTEN || + ad -> ad_resp == FALSE) { + PP_TRACE (("auth_usr/recip='%s' stat=%d resp=%d", + value, ad -> ad_status, ad -> ad_resp)); + return; + } + + if (ad -> ad_outchan == NULL) + err_abrt (RP_NAUTH, "ad_outchan unset for '%s'", + value); + + if (ad -> ad_outchan -> li_auth == NULL_AUTH) + err_abrt (RP_NAUTH, "chan auth unset for '%s'", + value); +#ifdef notdef + if (tb_getauthusr (ad -> ad_outchan -> li_auth -> user, ad) == NOTOK) + err_abrt (RP_NAUTH, "Cannot look up authorisation for '%s'", + value); + + if (ad -> ad_outchan -> li_auth -> user -> found == FALSE) + PP_TRACE (("auth_usr_chks/recipient '%s' missing", gval (ad))); +#endif +} + + + + +static void auth_remdup (ad, list) /* -- removes duplicates -- */ +ADDR *ad; +ADDR *list; +{ + AUTH *au; + + PP_TRACE (("auth_remdup (%s)", gval (ad))); + + for (list = ad -> ad_next; list; list = list -> ad_next) { + + PP_TRACE (("auth_remdup/'%s' stat='%d', resp='%d')", + list -> ad_value, list -> ad_status, list -> ad_resp)); + + if (list -> ad_resp == FALSE) + continue; + + switch (list -> ad_status) { + case AD_STAT_DRREQUIRED: + case AD_STAT_DONE: + continue; + } + + + if (strcmp (gval(ad), gval(list)) == 0) { + + PP_TRACE (("auth_remdup/removed: '%s' (%d)", + gval (list), list -> ad_no)); + + list -> ad_status = AD_STAT_DONE; + list -> ad_outchan -> li_next = NULLIST_RCHAN; + + au = list -> ad_outchan -> li_auth; + au -> status = AUTH_OK; + do_reason (au, freason (AUR_DUPLICATE_REMOVED)); + } + } +} + + + + +static void auth_init(qp, recip) +Q_struct *qp; +ADDR *recip; +{ + char *argv[MAX_AUTH_ARGS], + *cp; + int argc; + ADDR *ad; + + + PP_TRACE (("auth_init: authloglevel='%s' authchannel='%s'", + authloglevel, authchannel)); + + bzero (auth2submit_msg, BUFSIZ); + + + switch (auth_loglev = cmd_srch (authloglevel, authtbl_loglevel)) { + case AUTH_LOGLEVEL_LOW: + case AUTH_LOGLEVEL_MEDIUM: + case AUTH_LOGLEVEL_HIGH: + break; + default: + auth_loglev = AUTH_LOGLEVEL_LOW; + PP_LOG (LLOG_EXCEPTIONS, + ("auth_init/authloglevel invalid : '%s' (low assumed)", + authloglevel)); + break; + } + + + cp = strdup (authchannel); + + if ((argc = sstr2arg (cp, MAX_AUTH_ARGS, argv, " \t,")) == NOTOK) + err_abrt (RP_NAUTH, "auth_init/authchannel invalid '%s'", + authchannel); + + def_authchan = authchan_new (NULLCHAN, NULLIST_AUTHCHAN); + tb_parse_authchan (def_authchan, argc, argv); + + sender_auth = auth_new(qp -> msgtype == MT_DMPDU); + + authmta_start = authmta_new (qp -> inbound -> li_mta); + sender_auth -> mta = authmta_start; + +#ifdef notdef + auth_mta (sender_auth -> mta); +#endif + + sender_auth -> user = authusr_new(); + + for (ad = recip; ad; ad = ad -> ad_next) + auth_init_recip (qp, ad); + + free (cp); +} + + + + +static void auth_init_recip (qp, ad) +Q_struct *qp; +ADDR *ad; +{ + AUTH_USER *up; + LIST_RCHAN *lr; + LIST_AUTH_CHAN *lc; + LIST_AUTH_MTA *lm; + int found = FALSE; + char *val; + + + PP_TRACE (("auth_init_recip (%s)", gval (ad))); + + up = authusr_new(); + + for (lr = ad -> ad_outchan; lr; lr = lr -> li_next) { + + lr -> li_auth = auth_new(qp -> msgtype == MT_DMPDU); + lr -> li_auth -> user = up; + val = lr -> li_chan -> ch_name; + found = FALSE; + + for (lc = authchan_start; lc; lc = lc -> li_next) + if (strcmp (val, lc -> li_chan -> ch_name) == 0) { + found = TRUE; + break; + } + + if (!found && lr -> li_chan) { + lc = authchan_new (lr -> li_chan, def_authchan); + authchan_add (&authchan_start, lc); + } + + lr -> li_auth -> chan = lc; + found = FALSE; + + for (lm = authmta_start; lm; lm = lm -> li_next) + if (strcmp (lm -> li_mta, lr -> li_mta) == 0) { + found = TRUE; + break; + } + + if (!found && lr -> li_mta) { + lm = authmta_new (lr -> li_mta); + authmta_add (&authmta_start, lm); + } + + lr -> li_auth -> mta = lm; + } +} + + + + +static void pr_rights (au, ch_policy, val) +AUTH *au; +int ch_policy, val; +{ + char buf[BUFSIZ*2]; + char *msg, *policy; + + PP_TRACE (("pr_rights ('%d')", ch_policy)); + + switch (ch_policy) { + case AUTH_CHAN_BLOCK: + policy = "block"; + break; + case AUTH_CHAN_NEGATIVE: + policy = "negative"; + break; + default: + policy = "Unknown"; + break; + } + if (val == OK) + msg = "Authorisation approved"; + else + switch (ch_policy) { + case AUTH_CHAN_BLOCK: + msg = "You are not authorised for this route"; + break; + case AUTH_CHAN_NEGATIVE: + msg = "You are prohibited from using this route"; + break; + default: + msg = "UnknownPolicy"; + break; + } + (void) sprintf (buf, +"%s: (policy %s, imta (%s %s) sender (%s %s) omta (%s %s) recip (%s %s))", + msg, policy, + rrights (sender_auth -> mta_inrights), + rrights (sender_auth -> mta_outrights), + rrights (sender_auth -> user_inrights), + rrights (sender_auth -> user_outrights), + rrights (au -> mta_inrights), + rrights (au -> mta_outrights), + rrights (au -> user_inrights), + rrights (au -> user_outrights)); + + do_reason (au, "%s", buf); + return; +} + + + + +static char *ltoa (l) +long l; +{ + char buf[LINESIZE]; + + (void) sprintf (buf, "%ld", l); + return (strdup (buf)); +} + + + + +static int test_flags (f, val, type) +int f[]; +int val; +int type; +{ + switch (type) { + case ORED: + if (f[0] == val || f[1] == val || f[2] == val || f[3] == val) + return OK; + break; + } + + return NOTOK; +} diff --git a/Src/submit/auth_logs.c b/Src/submit/auth_logs.c new file mode 100644 index 0000000..c7389c0 --- /dev/null +++ b/Src/submit/auth_logs.c @@ -0,0 +1,306 @@ +/* auth_logs.c: Prints out the authorisation logging info */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_logs.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_logs.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: auth_logs.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "dr.h" +#include + + +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) + +/* -- externals -- */ +extern CMD_TABLE authtbl_statmsgs[]; +extern int auth_loglev; +extern UTC utclocalise (); + +/* -- local routines -- */ +void auth_log(); +static int auth_isdr(); +static int auth_isgood(); +static void gen_auth_logs(); +static void gen_auth_notok(); +static void gen_auth_ok(); +static void gen_auth_stats(); +static void wr2statfile(); +static void wrdr2statfile(); +static void wrmsg2statfile(); +static void logfailure (); + + + +/* ------------------- Begin Routines ------------------------------------ */ + + + + +void auth_log(qp, sender, recip, msgname) +Q_struct *qp; +ADDR *sender; +ADDR *recip; +char *msgname; +{ + ADDR *ad; + + PP_TRACE (("auth_log()")); + + for (ad = recip; ad; ad = ad->ad_next) + gen_auth_logs (qp, sender, ad, msgname); +} + + + + +/* ----------------------------- Logging ------------------------------------ */ + + + + + +static void gen_auth_logs (qp, sender, ad, msgname) +Q_struct *qp; +ADDR *sender, *ad; +char *msgname; +{ + LIST_RCHAN *lp; + int retval = NOTOK; + + PP_TRACE (("gen_auth_logs(%s)", gval(ad))); + + for (lp = ad -> ad_outchan; lp != NULLIST_RCHAN; lp = lp -> li_next) + if ((retval = auth_isgood (lp)) == OK) + break; + + gen_auth_stats (qp, sender, ad, retval, msgname); +} + + + + +static void gen_auth_stats (qp, sender, ad, result, msgname) +Q_struct *qp; +ADDR *sender, *ad; +int result; +char *msgname; +{ + + PP_TRACE (("gen_auth_stats '%d' '%s'", result, gval (ad))); + + switch (result) { + case OK: + gen_auth_ok (qp, sender, ad, msgname); + break; + default: + gen_auth_notok (sender, ad); + break; + } +} + + + + +static void gen_auth_ok (qp, sender, ad, msgname) +Q_struct *qp; +ADDR *sender; +ADDR *ad; +char *msgname; +{ + LIST_RCHAN *lp = ad -> ad_outchan; + + PP_TRACE (("gen_auth_ok '%s'", gval (ad))); + + wr2statfile (qp, sender, ad, lp, msgname); +} + +static void gen_auth_notok (sender, ad) +ADDR *sender; +ADDR *ad; +{ + LIST_RCHAN *lp = ad -> ad_outchan; + + PP_TRACE (("gen_auth_notok '%s'", gval (ad))); + + switch (auth_loglev) { + default: + case AUTH_LOGLEVEL_LOW: + if (lp != NULLIST_RCHAN) + logfailure (sender, ad, lp); + return; + + case AUTH_LOGLEVEL_MEDIUM: + case AUTH_LOGLEVEL_HIGH: + for (; lp != NULLIST_RCHAN; lp = lp -> li_next) + logfailure (sender, ad, lp); + return; + } +} + +static int auth_isgood (lp) +LIST_RCHAN *lp; +{ + if (lp == NULLIST_RCHAN) + return FALSE; + + switch (lp -> li_auth -> status) { + case AUTH_OK: + case AUTH_DR_OK: + case AUTH_FAILED_TEST: + return OK; + default: + return NOTOK; + } +} + +static int auth_isdr (lp) +LIST_RCHAN *lp; +{ + if (lp == NULLIST_RCHAN) + return FALSE; + + switch (lp -> li_auth -> status) { + case AUTH_DR_OK: + case AUTH_DR_FAILED: + return OK; + } + return NOTOK; +} + +static void wr2statfile (qp, sender, ad, lp, msgname) +Q_struct *qp; +ADDR *sender; +ADDR *ad; +LIST_RCHAN *lp; +char *msgname; +{ + int oldType; + + oldType = sender->ad_type; + if (qp && qp -> inbound && qp -> inbound -> li_chan) + sender->ad_type = qp -> inbound -> li_chan -> ch_in_ad_type; + + if (auth_isdr (lp) == OK) + wrdr2statfile (qp, sender, ad, lp, msgname); + else + wrmsg2statfile (qp, sender, ad, lp, msgname); + sender->ad_type=oldType; +} + +static void wrmsg2statfile (qp, sender, ad, lp, msgname) +Q_struct *qp; +ADDR *sender; +ADDR *ad; +LIST_RCHAN *lp; +char *msgname; +{ + AUTH *au = lp -> li_auth; + char *cp; + char *argv[100]; + int argc; + char midbuf[BUFSIZ]; + char buffer[BUFSIZ]; + char tbuf[BUFSIZ]; + char sizebuf[30]; + static char eq[] = "="; + PP_TRACE (("submit/wrmsg2statfile ('%s')", au -> reason)); + + + cp = rcmd_srch (au -> status, authtbl_statmsgs); + + if (cp == NULLCP) + cp = rcmd_srch (AUTH_FAILED, authtbl_statmsgs); + + argc = 0; + argv[argc++] = cp; + argv[argc++] = msgname; + + argv[argc++] = qp -> inbound -> li_chan -> ch_name; + argv[argc++] = "->"; + argv[argc++] = au -> chan -> li_chan -> ch_name; + + argv[argc++] = eq; + argv[argc++] = "p1msgid"; + (void) msgid2rfc_aux (&qp->msgid, midbuf, FALSE); + argv[argc++] = midbuf; + + argv[argc++] = eq; + argv[argc++] = "size"; + (void) sprintf (sizebuf, "%d", qp -> msgsize); + argv[argc++] = sizebuf; + + argv[argc++] = eq; + argv[argc++] = "sender"; + argv[argc++] = gval (sender); + argv[argc++] = qp -> inbound -> li_mta; + + argv[argc++] = eq; + argv[argc++] = "recip"; + argv[argc++] = gval (ad); + argv[argc++] = au -> mta -> li_mta; + argv[argc++] = au -> reason; + + argv[argc++] = eq; + argv[argc++] = "submit-time"; + (void) strcpy (tbuf, "unknown"); + if (qp -> trace != NULL && + qp -> trace -> trace_DomSinfo.dsi_time) { + UTC ut = utclocalise (qp -> trace -> trace_DomSinfo.dsi_time); + if (ut) { + (void) sprintf (tbuf, "%d:%d:%d:%02d:%02d", + ut -> ut_mon, ut -> ut_mday, + ut -> ut_hour, ut -> ut_min, + ut -> ut_sec); + free ((char *) ut); + } + + } + argv[argc++] = tbuf; + + argv[argc] = NULLCP; + + arg2vstr (0, sizeof buffer, buffer, argv); + PP_STAT (("%s", buffer)); +} + +static void wrdr2statfile (qp, sender, ad, lp, msgname) +Q_struct *qp; +ADDR *sender; +ADDR *ad; +LIST_RCHAN *lp; +char *msgname; +{ + int sreason; + + PP_TRACE (("submit/wrdr2statfile ('%s')", lp -> li_auth -> reason)); + + sreason = ad -> ad_reason; + ad -> ad_reason = DRR_NO_REASON; + (void) wr_dr_stat_log (qp, sender, ad, msgname, "transit"); + ad -> ad_reason = sreason; +} + +static void logfailure (sender, ad, lp) +ADDR *sender; +ADDR *ad; +LIST_RCHAN *lp; +{ + PP_LOG (LLOG_EXCEPTIONS, + ("Message failed to %s (%s) from %s to %s: %s", lp -> li_mta, + lp -> li_chan -> ch_name, gval(sender), gval(ad), + lp -> li_auth -> reason)); +} + diff --git a/Src/submit/auth_tb.c b/Src/submit/auth_tb.c new file mode 100644 index 0000000..0393009 --- /dev/null +++ b/Src/submit/auth_tb.c @@ -0,0 +1,63 @@ +/* auth_tb.c: authorisation tables */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_tb.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_tb.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: auth_tb.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "tb_auth.h" +#include + + + + +CMD_TABLE authtbl_reasons[] = { + "unknown error", AUR_UNKNOWN, + "This route is prohibited: (policy none)", AUR_CH_NONE, + "Authorisation approved: (policy free)", AUR_CH_FREE, + "in MTA regex : %s does not include sender", AUR_IMTA_MISSING_SNDR, + "in MTA regex : %s excludes sender", AUR_IMTA_EXCLUDES_SNDR, + "out MTA regex : %s does not include recip", AUR_OMTA_MISSING_RECIP, + "out MTA regex : %s excludes recip", AUR_OMTA_EXCLUDES_RECIP, + "msg size %s exceeds channel limit of %s", AUR_MSGSIZE_FOR_CHAN, + "msg size %s exceeds mta limit of %s", AUR_MSGSIZE_FOR_MTA, + "msg size %s exceeds user limit of %s", AUR_MSGSIZE_FOR_USR, + "bad body part : %s (mta restriction)", AUR_MTA_BPT, + "bad body part : %s (user restriction)", AUR_USR_BPT, + "channel bind failed", AUR_CHBIND, + "duplicate recip removed", AUR_DUPLICATE_REMOVED, + 0, -1 + }; + + + + +CMD_TABLE authtbl_loglevel[] = { + "low", AUTH_LOGLEVEL_LOW, + "medium", AUTH_LOGLEVEL_MEDIUM, + "high", AUTH_LOGLEVEL_HIGH, + 0, -1 + }; + + + +CMD_TABLE authtbl_statmsgs [] = { + "ok", AUTH_OK, + "failed", AUTH_FAILED, + "ok-testfailed", AUTH_FAILED_TEST, + "dr_ok", AUTH_DR_OK, + "dr_failed", AUTH_DR_FAILED, + 0, -1 + }; diff --git a/Src/submit/auth_ut.c b/Src/submit/auth_ut.c new file mode 100644 index 0000000..686bd74 --- /dev/null +++ b/Src/submit/auth_ut.c @@ -0,0 +1,232 @@ +/* auth_ut.c: authorisation utilities */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_ut.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/auth_ut.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: auth_ut.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include + +extern char auth2submit_msg[]; + + +/* -- local routines -- */ +void authchan_add(); +void authmta_add(); +void do_reason(); +AUTH *auth_new(); +AUTH_USER *authusr_new(); +LIST_AUTH_CHAN *authchan_new(); +LIST_AUTH_MTA *authmta_new(); +static LIST_AUTH_CHAN *authchan_malloc(); +static LIST_AUTH_MTA *authmta_malloc(); + + + + +/* ------------------------ Begin Routines ------------------------------- */ + + + + +#ifdef lint +/*VARARGS2*/ +void do_reason (au, str) +AUTH *au; +char *str; +{ + do_reason (au, str); +} + +#else +void do_reason (va_alist) +va_dcl +{ + va_list ap; + AUTH *au; + + va_start (ap); + + au = va_arg (ap, AUTH *); + + _asprintf (auth2submit_msg, NULLCP, ap); + + au -> reason = strdup (auth2submit_msg); + va_end (ap); +} +#endif + + + + +LIST_AUTH_CHAN *authchan_new (value, def) +CHAN *value; +LIST_AUTH_CHAN *def; +{ + LIST_AUTH_CHAN *list; + + + PP_TRACE (("authchan_new (%x)", value)); + + list = authchan_malloc(); + + if (def) + *list = *def; /* --- structure copy --- */ + if (value) + list -> li_chan = value; + + return (list); +} + + + + +void authchan_add (list, item) +LIST_AUTH_CHAN **list; +LIST_AUTH_CHAN *item; +{ + LIST_AUTH_CHAN *lp = *list; + + PP_TRACE (("authchan_add()")); + + if (lp == NULLIST_AUTHCHAN) { + *list = item; + return; + } + + while (lp -> li_next != NULLIST_AUTHCHAN) + lp = lp -> li_next; + lp -> li_next = item; +} + + + + +void authmta_add (list, item) +LIST_AUTH_MTA **list; +LIST_AUTH_MTA *item; +{ + LIST_AUTH_MTA *lp = *list; + + PP_TRACE (("authmta_add()")); + + if (lp == NULLIST_AUTHMTA) { + *list = item; + return; + } + + while (lp -> li_next != NULLIST_AUTHMTA) + lp = lp -> li_next; + lp -> li_next = item; +} + + + + +LIST_AUTH_MTA *authmta_new (value) +char *value; +{ + LIST_AUTH_MTA *list; + + if (value == NULLCP) + return (NULLIST_AUTHMTA); + + PP_TRACE (("authmta_new ('%s')", value)); + + list = authmta_malloc(); + list -> li_mta = value; + return (list); +} + + + + +AUTH_USER *authusr_new() +{ + AUTH_USER *new; + + PP_TRACE (("authusr_new()")); + new = (AUTH_USER *) malloc (sizeof *new); + bzero ((char *)new, sizeof *new); + + new -> found = FALSE; + new -> rights = AUTH_RIGHTS_UNSET; + return (new); +} + + + + +AUTH *auth_new(isdr) +int isdr; +{ + AUTH *new; + + PP_TRACE (("auth_new()")); + + new = (AUTH *) malloc (sizeof *new); + bzero ((char *)new, sizeof *new); + + if (isdr) + new -> status = AUTH_DR_OK; + else + new -> status = AUTH_OK; + + new -> stage = AUTH_STAGE_1; + new -> warnings = AUTH_NOTWARNED; + new -> mta_inrights = AUTH_RIGHTS_UNSET; + new -> mta_outrights = AUTH_RIGHTS_UNSET; + new -> user_inrights = AUTH_RIGHTS_UNSET; + new -> user_outrights = AUTH_RIGHTS_UNSET; + return (new); +} + + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + +static LIST_AUTH_CHAN *authchan_malloc() +{ + LIST_AUTH_CHAN *new; + + PP_TRACE (("authchan_malloc()")); + new = (LIST_AUTH_CHAN *) malloc (sizeof *new); + bzero ((char *)new, sizeof *new); + + new -> li_found = FALSE; + new -> policy = AUTH_CHAN_FREE; + return (new); +} + + + + +static LIST_AUTH_MTA *authmta_malloc() +{ + LIST_AUTH_MTA *new; + + PP_TRACE (("authmta_malloc()")); + + new = (LIST_AUTH_MTA *) malloc (sizeof *new); + bzero ((char *)new, sizeof *new); + + new -> li_found = FALSE; + new -> rights = AUTH_RIGHTS_UNSET; + return (new); +} diff --git a/Src/submit/ch_bind.c b/Src/submit/ch_bind.c new file mode 100644 index 0000000..9cb3985 --- /dev/null +++ b/Src/submit/ch_bind.c @@ -0,0 +1,803 @@ +/* ch_bind.c - binds reformatting channels to a recipient address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/ch_bind.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/ch_bind.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: ch_bind.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "ch_bind.h" + + +extern void err_abrt(); +extern LIST_BPT *bodies_all, *headers_all; + + +/* -- static variables -- */ +static FILTER *filterlist = NULL; +static TYPES *typelist; +static MAT *mainmatrix; +static int matsize; +static FLAT *flattenlist = NULL, *unflatlist = NULL; + + +/* -- local routines -- */ +int ch_bind(); +void fmt_init(); + +static FILTER *getfilter(); +static FILTER *name2filter(); +static FLAT *add2flatlist(); +static FLAT *flttype2ptr(); +static LIST *additem(); +static LIST *copylist(); +static LIST *getitem(); +static LIST *inslist(); +static MAT *initmat(); +static TYPES *addchantypes(); +static TYPES *name2type(); +static int isinlist(); +static void addmat(); +static void do_calc(); +static void flatten(); +static void format(); +static void freelist(); +static void get_formatters(); +static void initform(); +static void unflat(); + + + + +/* --------------------- Begin Routines --------------------------------- */ + + +/* --- *** Start Description *** --- + + ch_bind (ad, p, pfmts, pcost, punknown) + ADDR *ad; + LIST_RCHAN *p; + LIST_RCHAN **pfmts; + int *pcost, *punknown; + + Parameters required: + - The channel calling submit + - The flatness of the channel + - The channel/mta pair used to get to the Next Hop hostname ( p ) + - The list of Encoded Information Types within the message + (Qstruct.encodedinfo.eit_types) + - A pointer to a list of Reformatting channels (ad->ad_fmtchan) + + Example: + ch_inbound = x400in + content_in = "rfc" or "p2" + p = li_mta = ukc.ac.uk li_chan => JANET + ( or li_mta = stl.stc.co.uk li_chan => PSS ) + Qstruct.encodedinfo + .eit_types = ia5Text, voice + ad->ad_fmtchan = unflattenp2, voice2text, flattenrfc + + Routine: + - Calculates the reformatting channels. + - Updates ad_fmtchan. + - Returns OK or NOTOK. + + + fmt_init () + - Initialise reformatting stuff + + --- *** End Description *** --- */ + + + + +/* ------------------------------------------------------------------------ */ + + + + + +void fmt_init () +{ + PP_TRACE (("ch_bind/fmt_init ()")); + + initform (); + get_formatters (); + do_calc (mainmatrix); +} + +static FLAT *add2flatlist (list, name, type) +FLAT *list; +char *name, *type; +{ + FLAT *ptr; + + ptr = (FLAT *) smalloc (sizeof (FLAT)); + ptr->flt_type = strdup (type); + ptr->flt_name = strdup ( name); + ptr->flt_next = list; + return (ptr); +} + +static void unflat (name, type) /* Add an unflattening channel to the list */ +char *name, *type; /* of unflattening channels */ +{ + PP_TRACE (("ch_bind/unflat (%s, %s)", name, type)); + + if (flttype2ptr (unflatlist, type) != NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/UNFLAT type %s is in use already", type)); + return; + } + unflatlist = add2flatlist (unflatlist, name, type); +} + +static void flatten (name, type) /* Add a Flattening channel to the list */ +char *name, *type; /* of flattening channels */ +{ + PP_TRACE (("ch_bind/flatten (%s, %s)", name, type)); + + if (flttype2ptr (flattenlist, type) != NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/FLATTEN type %s is in use already\n", + type)); + return; + } + flattenlist = add2flatlist (flattenlist, name, type); +} + +static FLAT *flttype2ptr (list, type) +char *type; +FLAT *list; +{ + PP_DBG (("ch_bind/flttype2ptr (list, %s)", type)); + + if (type == NULLCP) + return NULL; + for (; list != NULL; list = list->flt_next) + if (strcmp (list->flt_type, type) == 0) + return (list); + PP_TRACE (("ch_bind/flttype2ptr - NO match")); + return (NULL); +} + +static FILTER *name2filter (name) /* Format Channel name to pointer to struct */ +char *name; +{ + FILTER *ptr; + + PP_TRACE (("ch_bind/name2filter (%s)", name)); + + for (ptr = filterlist; ptr != NULL; ptr = ptr->fil_next) + if (strcmp (name, ptr->fil_name) == 0) + return (ptr); + return (NULL); +} + + +static LIST *inslist (list, new) +LIST *list, *new; +{ + + if (new == NULL) + { + PP_TRACE (("ch_bind/inslist (NULL)")); + return (list); + } + + PP_TRACE (("ch_bind/inslist (%s)", new -> li_name )); + list = inslist (list, new->li_next); + /* SEK - should replace with for loop */ + if (!isinlist (list, new)) + { + new->li_next = list; + list = new; + } + return (list); +} + +static int isinlist (list, item) +LIST *list, *item; +{ + + for (; list != NULL; list = list->li_next) + if (strcmp (list->li_name, item->li_name) == 0) + return (1); + return (0); +} + +static TYPES *addchantypes (atypelist, punknown) +LIST_BPT *atypelist; +int *punknown; +{ + register TYPES *list, *all, *storenum; + + PP_TRACE (("ch_bind/addchantypes (atypelist)")); + *punknown = FALSE; + list = NULL; + for (; atypelist != NULL; atypelist = atypelist->li_next) + { + if ((storenum = name2type (atypelist->li_name)) == NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/%s is not a defined type", + atypelist->li_name)); + *punknown = TRUE; + continue; + } + all = (TYPES *) smalloc (sizeof (TYPES)); + all->ty_next = list; + list = all; + all->ty_name = atypelist->li_name; + all->ty_number = storenum->ty_number; + } + return (list); +} + + +static TYPES *name2type (str) +char *str; +{ + TYPES *ptr; + + PP_TRACE (("ch_bind/name2type (%s)", str)); + for (ptr = typelist; ptr != NULL; ptr = ptr->ty_next) + if (strcmp (str, ptr->ty_name) == 0) + return (ptr); + return (NULL); +} + +static void format (fname, fcost, ffrom, fto) +int fcost; +char *fname, *ffrom, *fto; /* Don't use FNAME, pass the CHAN pointer */ +{ + int x, y; + FILTER *ptr; + TYPES *type; + + PP_TRACE (("ch_bind/format (%s, %d, %s, %s)", + fname, fcost, ffrom, fto)); + + if ((type = name2type (ffrom)) == NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/%s is not a defined type", ffrom)); + return; + } + x = type->ty_number; + if ((type = name2type (fto)) == NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/%s is not a defined type", fto)); + return; + } + y = type->ty_number; + addmat (mainmatrix, x, y, fcost, fname); + ptr = getfilter (); + ptr->fil_next = filterlist; + filterlist = ptr; + ptr->fil_name = fname; + ptr->fil_from = ffrom; + ptr->fil_to = fto; +} + +static LIST *copylist (list) +register LIST *list; +{ + register LIST *tmpitem, *ptr; + + PP_DBG (("ch_bind/copylist (list)")); + + for (tmpitem = NULL; list != NULL; list = list->li_next) + { + ptr = getitem (); + ptr->li_name = list->li_name; + tmpitem = additem (tmpitem, ptr); + } + return (tmpitem); +} + + +static LIST *additem (list, item) /* Adds LIST item onto end of LIST list */ +register LIST *list; +LIST *item; +{ + PP_DBG (("ch_bind/additem (list, item)")); + + if (list == NULL) + return (item); + list->li_next = additem (list->li_next, item); + return (list); +} + +static void freelist (list) +register LIST *list; +{ + PP_TRACE (("ch_bind/freelist (list)")); + + if (list == NULL) + return; + freelist (list->li_next); + free ((char *)list); +} + +static void do_calc (mat) +MAT mat []; +{ + register MAT *ptr1, *ptr2, *ptr3; + register int i, j, k; + + PP_TRACE (("ch_bind/do_calc (mat)")); + for (i = 0; i < matsize; i++) + for (j = 0; j < matsize; j++) + { + ptr3 = &mat [j * matsize + i]; + if (ptr3->m_int != 0) + for (k = 0; k < matsize; k++) + { + ptr2 = &mat [i * matsize + k]; + if (ptr2->m_int != 0) + { + ptr1 = &mat [j * matsize + k]; + if (ptr1->m_int == 0) + { + ptr1->m_int = ptr2->m_int + ptr3->m_int; + ptr1->m_list = additem (ptr1->m_list, copylist (ptr3->m_list)); + ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list)); + } + else + { + if (ptr2->m_int + ptr3->m_int < ptr1->m_int) + { + freelist (ptr1->m_list); + ptr1->m_list = copylist (ptr3->m_list); + ptr1->m_list = additem (ptr1->m_list, copylist (ptr2->m_list)); + ptr1->m_int = ptr2->m_int + ptr3->m_int; + } + } + } + } + } +} + +static MAT *initmat (size) +int size; +{ + MAT *mat; + int i, j; + + PP_TRACE (("ch_bind/initmat (%d)", size)); + matsize = size; + mat = (MAT *) smalloc (size * size * sizeof (MAT)); + + for (i = 0; i < size; i++) + for (j = 0; j < size; j++) + { + mat [i * matsize + j].m_int = (i == j) ? 1 : 0; + mat [i * matsize + j].m_list = NULL; + } + return (mat); +} + +static void addmat (mat, x, y, cost, name) +MAT mat []; +int x, y, cost; +char *name; /* Should be Pointer to CHAN struct */ +{ + register MAT *tmp; + register LIST *ptr; + + PP_TRACE (("ch_bind/addmat (mat, %d, %d, %d, %s)", x, y, cost, name)); + ptr = getitem (); + ptr->li_name = name; + tmp = &mat [x * matsize + y]; + if (tmp -> m_list == NULL) { + tmp->m_list = ptr; + tmp->m_int = cost; + } + else { + PP_TRACE(("Duplicate reformatter %s (clashes with %s)",name, + tmp -> m_list -> li_name)); + if (cost < tmp -> m_int) { + free ((char *)tmp->m_list); + tmp -> m_list = ptr; + tmp -> m_int = cost; + } + else + free ((char *)ptr); + } +} + +static FILTER *getfilter () +{ + register FILTER *ptr; + + PP_DBG (("ch_bind/getfilter ()")); + ptr = (FILTER *) smalloc (sizeof (FILTER)); + + ptr->fil_next = NULL; + return (ptr); +} + +static LIST *getitem () +{ + register LIST *ptr; + + PP_DBG (("ch_bind/getitem ()")); + ptr = (LIST *) smalloc (sizeof (LIST)); + ptr->li_name = NULL; + ptr->li_next = NULL; + return (ptr); +} + +/* initform + * This routine goes through the body parts + */ + + +static void initform () +{ + register LIST_BPT *bptptr; + TYPES *all, *list; + int count; + + PP_TRACE (("ch_bind/initform ()")); + + list = NULL; + count = 0; + for (bptptr = headers_all; bptptr != NULLIST_BPT; + bptptr = bptptr -> li_next) + { + PP_TRACE (("ch_bind/doing body part %s", + bptptr -> li_name)); + all = (TYPES *) smalloc (sizeof (TYPES)); + all->ty_next = list; + list = all; + all->ty_name = bptptr->li_name; + all->ty_number = count++; + } + for (bptptr = bodies_all; bptptr != NULLIST_BPT; + bptptr = bptptr -> li_next) + { + PP_TRACE (("ch_bind/doing body part %s", + bptptr -> li_name)); + all = (TYPES *) smalloc (sizeof (TYPES)); + all->ty_next = list; + list = all; + all->ty_name = bptptr->li_name; + all->ty_number = count++; + } + mainmatrix = initmat (count); + typelist = list; +} + +/* get_formatters + * This routine will go through the list of Channels and put the + * formatters, flatteners and un-flatteners into the matrix. + */ + +static void get_formatters () +{ + register CHAN **chanptr; + PP_TRACE (("ch_bind/get_formatters")); + for (chanptr = ch_all; (*chanptr) != NULL; chanptr++) + { + if ((*chanptr)->ch_chan_type != CH_SHAPER) + continue; + if ((*chanptr)->ch_bpt_in == NULL + && (*chanptr)->ch_bpt_out == NULL + && (*chanptr)->ch_hdr_out == NULL + && (*chanptr)->ch_hdr_in == NULL) { + /* Flatten/Unfflatten */ + if ((*chanptr)->ch_content_out == NULL + && (*chanptr)->ch_content_in == NULL) + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/no content definitions for %s", + (*chanptr)-> ch_name)); + } + else if ((*chanptr)->ch_content_in != NULL) + { /* This is Unflattener */ + unflat ((*chanptr)->ch_name, + (*chanptr)->ch_content_in); + } + else + { /* This is a flattener */ + flatten ((*chanptr)->ch_name, + (*chanptr)->ch_content_out); + } + } + + else if ((*chanptr)->ch_bpt_in != NULL + && (*chanptr)->ch_bpt_out != NULL) + + { /* This is Formatter */ + LIST_BPT *ix = (*chanptr)->ch_bpt_in; + for (;ix != NULLIST_BPT; ix = ix -> li_next) + format ((*chanptr)->ch_name, + (*chanptr)->ch_cost + 2, + ix -> li_name, + (*chanptr)->ch_bpt_out->li_name); + if ((*chanptr)->ch_bpt_out->li_next != NULLIST_BPT) + PP_LOG(LLOG_EXCEPTIONS, + ("ch_bind mulitple bptouts specified for shaper channel '%s'", + (*chanptr)->ch_name)); + + } + + else if ((*chanptr)->ch_hdr_in != NULL + && (*chanptr)->ch_hdr_out != NULL) + + { /* This is Formatter */ + LIST_BPT *ix = (*chanptr)->ch_hdr_in; + for (;ix != NULLIST_BPT; ix = ix -> li_next) + format ((*chanptr)->ch_name, + (*chanptr)->ch_cost + 2, + ix->li_name, + (*chanptr)->ch_hdr_out->li_name); + if ((*chanptr)->ch_hdr_out->li_next != NULLIST_BPT) + PP_LOG(LLOG_EXCEPTIONS, + ("ch_bind mulitple hdrouts specified for shaper channel '%s'", + (*chanptr)->ch_name)); + } + + else + { + PP_LOG (LLOG_EXCEPTIONS, + ("ch_bind/ erroneous definitions for %s", + (*chanptr)-> ch_name)); + } + + } +} + +extern int numBps, forwMsg; +extern char *cont_822; + +int ch_bind (qp, ad, p, pfmts, pbpts, pcost, punknown) +Q_struct *qp; +ADDR *ad; +LIST_RCHAN *p; +LIST_RCHAN **pfmts; +LIST_BPT **pbpts; +int *pcost, *punknown; +{ + MAT *mat; + CHAN *out_chan; + TYPES *chan, *messty, *outty, *hdrty, *t2, *ty = NULL; + LIST *list = NULL, *worklist; + LIST_BPT *new_bpt = NULLIST_BPT; + LIST_RCHAN *new_chan; + FILTER *filt; + FLAT *flat; + char *filtername, *in_content; + int cost, ind, unknownOutBP; + + *pfmts = NULLIST_RCHAN; + *pcost = 0; + *pbpts = NULLIST_BPT; + + PP_TRACE (("ch_bind ()")); + + + /* in_content = ch_inbound->ch_content_in; */ + in_content = qp -> cont_type; + if (p == NULLIST_RCHAN) + err_abrt (RP_MECH, "No channel in address for %s", + ad -> ad_value); + out_chan = p->li_chan; + + /* Messty - EITs within the message */ + messty = addchantypes (qp -> encodedinfo.eit_types, + punknown); + +#if PP_DEBUG > 1 + if (pp_log_norm -> ll_events & LLOG_DEBUG) { + /* Testing Blurb */ + if (out_chan->ch_hdr_out) { + chan = addchantypes (out_chan->ch_hdr_out, + &unknownOutBP); + if (unknownOutBP == TRUE) + PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound header(s)", + out_chan->ch_name)); + PP_DBG (("ch_bind/Channel %s supports headers ->", out_chan->ch_name)); + for (; chan != NULL; chan = chan->ty_next) + PP_DBG (("\t`%s'", chan->ty_name)); + PP_DBG (("EOL")); + } + if (out_chan->ch_bpt_out) { + chan = addchantypes (out_chan->ch_bpt_out, + &unknownOutBP); + if (unknownOutBP == TRUE) + PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound bodypart(s)", + out_chan->ch_name)); + + PP_DBG (("ch_bind/Channel %s supports bodyparts ->", out_chan->ch_name)); + for (; chan != NULL; chan = chan->ty_next) + PP_DBG (("\t`%s'", chan->ty_name)); + PP_DBG (("EOL")); + } + /* End of Testing Blurb */ + } +#endif + worklist = NULL; + if (out_chan -> ch_hdr_out != NULLIST_BPT || + out_chan -> ch_bpt_out != NULLIST_BPT) { + if (out_chan -> ch_bpt_out != NULLIST_BPT) { + outty = addchantypes (out_chan->ch_bpt_out, + &unknownOutBP); + if (unknownOutBP == TRUE) + PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound bodypart(s)", + out_chan->ch_name)); + } else + outty = NULL; + if (out_chan -> ch_hdr_out != NULLIST_BPT) { + hdrty = addchantypes (out_chan->ch_hdr_out, + &unknownOutBP); + if (unknownOutBP == TRUE) + PP_NOTICE(("ch_bind/Channel %s has an undeclared outbound header(s)", + out_chan->ch_name)); + + } else + hdrty = NULL; + + for (chan = messty; chan != NULL; chan = chan->ty_next) + { + cost = 0; + + /* SEK addchantypes is called 4 times + once on each channel - this seems excessive */ + + /* SEK this loop initialises for inbound */ + for (t2 = outty; t2 != NULL; t2 = t2->ty_next) + { + ind = chan->ty_number * matsize + t2->ty_number; + mat = &mainmatrix[ind]; + if ((cost == 0 && mat->m_int != 0) || + (cost != 0 && cost > mat->m_int + && mat->m_int != 0)) + { + list = mat->m_list; + cost = mat->m_int; + ty = t2; + } + } + + if (cost == 0) { + for (t2 = hdrty; t2 != NULL; t2 = t2->ty_next) + { + ind = chan->ty_number * matsize + t2->ty_number; + mat = &mainmatrix[ind]; + if ((cost == 0 && mat->m_int != 0) || + (cost != 0 && cost > mat->m_int + && mat->m_int != 0)) + { + list = mat->m_list; + cost = mat->m_int; + ty = t2; + } + } + } + + if (cost == 0) { + PP_LOG (LLOG_NOTICE, + ("ch_bind/Can't convert %s", chan->ty_name)); + if (worklist) freelist(worklist); + return NOTOK; + } + else { + if (list_bpt_find (new_bpt, ty->ty_name) == + NULLIST_BPT) + list_bpt_add (&new_bpt, + list_bpt_new (ty->ty_name)); + if (cost == 1) { + PP_TRACE (("Cost = 1")); + continue; + } + else { + worklist = inslist (worklist, + copylist(list)); + } + } + } + } + + /* if NO EITS, NO unflatten! */ + if (qp -> encodedinfo.eit_types != NULL) { + /* unflatten message if + * submitted with a content and + * either converting EITS or + * there is a change in content type (or to none) + */ + if (isstr(in_content) && + (worklist != NULL || + !isstr(out_chan->ch_content_out) || + strcmp (out_chan->ch_content_out, + in_content) != 0)) { + flat = flttype2ptr (unflatlist, in_content); + if (flat != NULL) { + filtername = flat -> flt_name; + PP_DBG (("ch_bind/UNFLATTEN with %s", + filtername)); + new_chan = list_rchan_new (NULLCP, filtername); + *pcost += new_chan -> li_chan -> ch_cost; + list_rchan_add (pfmts, new_chan); + } + else + PP_LOG (LLOG_EXCEPTIONS, + ("Can't find exploder for %s", + in_content)); + } + } + /* SEK - calculate real work */ + for (list = worklist; list != NULL; list = list->li_next) + { + filt = name2filter (list->li_name); + if (filt == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("No filter defined for %s", + list -> li_name)); + continue; + } + PP_DBG (("ch_bind/%s [%s to %s]\n", filt->fil_name, + filt->fil_from, filt->fil_to)); + new_chan = list_rchan_new (NULLCP, filt -> fil_name); + *pcost += new_chan -> li_chan -> ch_cost; + list_rchan_add (pfmts, new_chan); + } + + /* No EITS, No flatten */ + if (qp -> encodedinfo.eit_types != NULL) { + /* + * flatten message if + * outchan has a content and + * message isn't straight 822 format and + * either converting EITS or + * changing content type (or from none) + */ + if (isstr(out_chan -> ch_content_out) && + (lexequ(out_chan->ch_content_out, cont_822) != 0 + || isstr(in_content) + || numBps > 2 || forwMsg > 0) && + (worklist != NULL || !isstr(in_content) || + strcmp (in_content, out_chan->ch_content_out) != 0)) { + flat = flttype2ptr (flattenlist, + out_chan->ch_content_out); + if (flat != NULL) { + filtername = flat -> flt_name; + PP_DBG (("ch_bind/FLATTEN with %s", + filtername)); + new_chan = list_rchan_new (NULLCP, filtername); + *pcost += new_chan -> li_chan -> ch_cost; + list_rchan_add (pfmts, new_chan); + } + else + PP_LOG (LLOG_EXCEPTIONS, + ("Can't find flattener for %s", + out_chan -> ch_content_out)); + } + } + if (ad -> ad_content == NULLCP + && isstr (in_content) && isstr (out_chan -> ch_content_out) && + strcmp (in_content, out_chan -> ch_content_out) != 0) + ad -> ad_content = strdup (out_chan -> ch_content_out); + else if (ad -> ad_content == NULLCP && + isstr(out_chan -> ch_content_out)) + ad -> ad_content = strdup (out_chan -> ch_content_out); + + *pbpts = new_bpt; + if (worklist) freelist(worklist); + return OK; +} diff --git a/Src/submit/gen_io2dr.c b/Src/submit/gen_io2dr.c new file mode 100644 index 0000000..1c5e070 --- /dev/null +++ b/Src/submit/gen_io2dr.c @@ -0,0 +1,143 @@ +/* gen_io2dr.c: write a DR submitted by an X400 incomming channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_io2dr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_io2dr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: gen_io2dr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "head.h" +#include "q.h" +#include "dr.h" + + +extern char msg_fullpath[]; +extern long msg_size; +extern char *dr_file; +extern int errno, + protocol_mode; + +extern void check_dr_crits (); + +/* -- local routines -- */ +int gen_io2dr(); +static void reset_protocol_mode(); +static void unset_protocol_mode(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int gen_io2dr(qp) +Q_struct *qp; +{ + struct stat st_rec; + FILE *fp; + DRmpdu DeliveryReport, *dr; + char *fname, + buf[MAXPATHLENGTH]; + int retval; + + PP_TRACE (("gen_io2dr (protocol_mode=%d)", protocol_mode)); + + dr_init (dr = &DeliveryReport); + + /* -- read the DR from stdin -- */ + + if (rp_isbad (retval = rd_dr (dr, stdin))) { + switch (retval) { + case RP_EOF: + PP_LOG (LLOG_EXCEPTIONS,("no more input")); + return (RP_EOF); + case RP_PARM: + PP_LOG (LLOG_EXCEPTIONS, ("gen_io2dr Invalid param")); + return (RP_PARM); + default: + PP_LOG (LLOG_EXCEPTIONS, + ("gen_io2dr read error %d", retval)); + return (retval); + } + } + + check_dr_crits (qp, dr); + trace_add (&dr -> dr_trace, trace_new()); + + /* -- write the DR into the PP queue -- */ + + (void) sprintf (buf, "%s/%s%d", msg_fullpath, dr_file, + DR_FILENO_DEFAULT); + fname = strdup (buf); + if ((fp = fopen (fname, "w")) == NULLFILE) { + PP_LOG (LLOG_FATAL, ("gen_io2dr (unable to open %s)", fname)); + return (RP_FIO); + } + + unset_protocol_mode(); + retval = wr_dr (dr, fp); + reset_protocol_mode(); + + if (rp_isbad (retval)) { + PP_LOG(LLOG_EXCEPTIONS, + ("gen_io2dr Unable to write")); + (void) fclose (fp); + return (RP_PARM); + } + + if (check_close (fp) == NOTOK) { + PP_SLOG (LLOG_EXCEPTIONS, "gen_io2dr", + ("gen_io2dr Unable to close")); + return (RP_FIO); + } + + if (stat (fname, &st_rec) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, + ("gen_io2dr: Unable to stat %s %d", fname, errno)); + msg_size = st_rec.st_size; + + dr_free (dr); + + PP_TRACE (("gen_io2dr returns (%d)", retval)); + + return (retval); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static void unset_protocol_mode () +{ + reset_protocol_mode(); + protocol_mode = 0; + return; +} + + +static void reset_protocol_mode () +{ + static int save = -1; + + if (save == -1) + save = protocol_mode; + else { + protocol_mode = save; + save = -1; + } +} diff --git a/Src/submit/gen_ndr.c b/Src/submit/gen_ndr.c new file mode 100644 index 0000000..bd63f95 --- /dev/null +++ b/Src/submit/gen_ndr.c @@ -0,0 +1,172 @@ +/* gen_ndr.c: generate the Non Delivery Notifications from submit */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_ndr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_ndr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: gen_ndr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" +#include + +extern char msg_fullpath[]; +extern char *loc_dom_site; +extern char *msg_unique; +extern CMD_TABLE rr_tcode[], + rr_dcode[], + rr_rcode[]; +extern void err_abrt(); + +/* -- local routines -- */ +void gen_ndr(); +static void gen_ndrFORrecip(); +static void gen_ndrFORsender(); +static void set_DRvalues(); + + + + +/*---------------------- Begin Routines -------------------------------- */ + + +#define isSet(x, str) ((str) ? str : x -> ad_value) +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (isSet(x, x -> ad_r400adr)) : \ + (isSet(x, x -> ad_r822adr))) + +void gen_ndr(qp) +Q_struct *qp; +{ + PP_TRACE (("submit/gen_ndr()")); + + if (qp -> Oaddress -> ad_status == AD_STAT_DRREQUIRED) + gen_ndrFORsender(qp); + else + gen_ndrFORrecip(qp); +} + + + + +static void gen_ndrFORsender(qp) +Q_struct *qp; +{ + register ADDR *ad, + *sender; + char errbuf[LINESIZE]; + + PP_TRACE (("submit/gen_ndrFORsender()")); + + sender = qp -> Oaddress; + sender -> ad_status = AD_STAT_DONE; + (void) sprintf (errbuf, + "Bad sender address '%s' [%s], all recips are rejected", + gval(sender), sender -> ad_parse_message); + + if (qp -> queuetime == NULLUTC) + qp -> queuetime = utcnow(); + + for (ad = qp -> Raddress; ad != NULLADDR; ad = ad -> ad_next) { + if (ad -> ad_status == AD_STAT_DONE) + continue; + + ad -> ad_status = AD_STAT_DRREQUIRED; + ad -> ad_reason = DRR_NO_REASON; + if (ad -> ad_add_info) + free (ad -> ad_add_info); + ad -> ad_add_info = NULLCP; + set_DRvalues (qp, sender, ad, errbuf); + } + + if (wr_q2drfile (qp, msg_fullpath, 0) != RP_OK) + err_abrt(RP_AGN, "Error writing delivery report"); + + return; +} + + + + +static void gen_ndrFORrecip(qp) +Q_struct *qp; +{ + register ADDR *ad, + *sender; + int recip_err = FALSE; + + PP_TRACE (("submit/gen_ndrFORrecip()")); + + sender = qp -> Oaddress; + if (qp -> queuetime == NULLUTC) + qp -> queuetime = utcnow(); + + for (ad = qp -> Raddress; ad != NULLADDR; ad = ad -> ad_next) { + if (ad -> ad_status != AD_STAT_PEND && + ad -> ad_status != AD_STAT_DRREQUIRED) + continue; + + if (rp_isbad (ad -> ad_parse_stat) || + ad -> ad_status == AD_STAT_DRREQUIRED) + { + recip_err = TRUE; + set_DRvalues (qp, sender, ad, NULLCP); + } + } + + + if (recip_err == FALSE) { + PP_TRACE (("submit/gen_ndrFORrecip (not generated)")); + return; + } + + + if (wr_q2drfile (qp, msg_fullpath, 0) != RP_OK) + err_abrt (RP_AGN, "Error writing DR"); + + return; +} + +static void set_DRvalues (qp, sender, recip, errstr) +Q_struct *qp; +ADDR *sender; +ADDR *recip; +char *errstr; +{ + char *str, boundadd[BUFSIZ]; + int freeit = 0; + + recip -> ad_type = sender -> ad_type; + + if (recip -> ad_reason == DRR_NO_REASON) { + recip -> ad_reason = DRR_UNABLE_TO_TRANSFER; + recip -> ad_diagnostic = DRD_UNRECOGNISED_OR; + } + + if ((str = recip -> ad_add_info) == NULLCP) { + if (errstr) + str = errstr; + else + (void) sprintf (str = boundadd, + "Bad recipient address '%s' [%s]", + gval(recip), + rp_valstr (recip -> ad_parse_stat)); + } + else + freeit = 1; + set_1dr (qp, recip -> ad_no, msg_unique, + recip -> ad_reason, + recip -> ad_diagnostic, str); + if (freeit) + free (str); +} diff --git a/Src/submit/gen_probedr.c b/Src/submit/gen_probedr.c new file mode 100644 index 0000000..1958f9e --- /dev/null +++ b/Src/submit/gen_probedr.c @@ -0,0 +1,102 @@ +/* gen_probedr.c: generate DRs or NDRs for probes */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_probedr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_probedr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: gen_probedr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" + +extern char msg_fullpath[]; + +extern void gen_ndr (), err_abrt(); +/* -- local routines -- */ +void gen_probedr(); + + + + +/*---------------------- Begin Routines -------------------------------- */ + + + + +/* -- Generate NDRs or DRs for submitted probe -- */ + + +void gen_probedr(qp) +Q_struct *qp; +{ + register ADDR *ad, + *sender; + int found = FALSE; + + PP_TRACE (("submit/gen_probedr()")); + + /* -- clear reformatting for sender -- */ + + for (ad = qp->Oaddress; ad != NULLADDR; ad = ad->ad_next) { + if (ad -> ad_fmtchan) { + list_rchan_free (ad -> ad_fmtchan); + ad -> ad_fmtchan = NULLIST_RCHAN; + } + } + + /* -- First generate Non Delivery Notifications -- */ + + for (ad = qp->Raddress; ad != NULLADDR; ad = ad->ad_next) { + if (ad->ad_status != AD_STAT_PEND && + ad->ad_status != AD_STAT_DRREQUIRED) + continue; + + if (rp_isbad (ad->ad_parse_stat) || + ad -> ad_status == AD_STAT_DRREQUIRED) + found = TRUE; + + if (ad -> ad_fmtchan) { + list_rchan_free (ad -> ad_fmtchan); + ad -> ad_fmtchan = NULLIST_RCHAN; + } + } + + + if (found ) + gen_ndr(qp); + + + /* -- Secondly Generate Delivery Notifications -- */ + + sender = qp->Oaddress; + if (qp -> queuetime == NULLUTC) + qp -> queuetime = utcnow(); + + for (ad=qp->Raddress, found=FALSE; ad != NULLADDR; ad = ad->ad_next) { + if (ad->ad_status != AD_STAT_PEND) + continue; + if (ad->ad_outchan->li_chan->ch_probe) + continue; + + found = TRUE; + ad->ad_type = sender->ad_type; + ad->ad_status = AD_STAT_DRREQUIRED; + ad -> ad_reason = DRR_NO_REASON; + } + + if (found) + if (wr_q2drfile (qp, msg_fullpath, 0) != RP_OK) + err_abrt (RP_AGN, "Error writing DR"); + + return; +} diff --git a/Src/submit/gen_warn.c b/Src/submit/gen_warn.c new file mode 100644 index 0000000..2543cbd --- /dev/null +++ b/Src/submit/gen_warn.c @@ -0,0 +1,280 @@ +/* gen_warn.c: generate warning messages */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_warn.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/gen_warn.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: gen_warn.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "q.h" +#include "auth.h" +#include "prm.h" +#include "retcode.h" +#include "expand.h" + +extern char *getpostmaster(), *postmaster; +extern char *loc_dom_mta; +extern char *local_822_chan, *loc_dom_site; +extern char *msg_unique; +extern char *ia5_bp, *hdr_822_bp; +extern char *wrndfldir; + +extern void getfpath (), ad_log_print(), + auth_start(), auth_log(), time_mgt(); + +static void gen_auth_warn (), setup_macros (); +static int copy_warn_file(); + +void gen_warnings (qp, sender, recips) +Q_struct *qp; +ADDR *sender; +ADDR *recips; +{ + ADDR *ad; + + for (ad = recips; ad; ad = ad -> ad_next) + gen_auth_warn (qp, sender, ad); +} + +#define gval(x) ((x -> ad_type) == AD_X400_TYPE ? \ + (x -> ad_r400adr) : (x -> ad_r822adr)) + + +static void gen_auth_warn (qp, sender, ad) +Q_struct *qp; +ADDR *sender, *ad; +{ + LIST_RCHAN *lp = ad -> ad_outchan; + + if (lp == NULL || lp -> li_auth == NULL) + return; + + switch (lp -> li_auth -> status) { + case AUTH_OK: + case AUTH_DR_OK: + return; + case AUTH_FAILED_TEST: + case AUTH_DR_FAILED: + case AUTH_FAILED: + if (lp -> li_auth -> chan -> warnsender) { + send_warning (qp, sender, ad, + lp -> li_auth -> chan -> warnsender, + "sender", lp -> li_auth -> reason); + PP_OPER (NULLCP, ("%s '%s' from file '%s'", + "Warning message to sender", + gval (sender), + lp -> li_auth -> chan -> warnsender)); + } + if (lp -> li_auth -> chan -> warnrecipient) { + send_warning (qp, ad, ad, + lp -> li_auth -> chan -> warnrecipient, + "recip", lp -> li_auth -> reason); + PP_OPER (NULLCP, ("%s '%s' from file '%s'", + "Warning message to recipient", + gval (ad), + lp -> li_auth -> chan -> warnsender)); + } + } + +} + +send_warning (qporig, recip, ad, file, direction, reason) +Q_struct *qporig; +ADDR *recip; +ADDR *ad; +char *file; +char *direction; +char *reason; +{ + struct prm_vars prm; + Q_struct que; + ADDR *ap; + ADDR *postie; + RP_Buf rps, *rp = &rps; + char buf[BUFSIZ]; + char datebuf[LINESIZE]; + UTC ut; + + prm_init (&prm); + q_init (&que); + que.inbound = list_rchan_new (loc_dom_mta, local_822_chan); + list_bpt_add (&que.encodedinfo.eit_types, list_bpt_new(hdr_822_bp)); + list_bpt_add (&que.encodedinfo.eit_types, list_bpt_new (ia5_bp)); + ap = adr_new (recip -> ad_r822adr, AD_822_TYPE, 1); + postie = adr_new (getpostmaster(AD_822_TYPE), AD_822_TYPE, 0); + postie -> ad_resp = FALSE; + postie -> ad_status = AD_STAT_DONE; + postie -> ad_no = NULL; + + if (rp_isbad (cntrl_mgt (&prm, &que)) || + rp_isbad (q_mgt (&que))) { + PP_LOG (LLOG_EXCEPTIONS, ("bad paramters")); + goto out; + } + if (rp_isbad (validate_sender (&que, postie, NULLCP, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("bad sender %s, %s", + getpostmaster(AD_822_TYPE), rp -> rp_line)); + goto out; + } + if (rp_isbad (validate_recip (ap, &que, rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("bad recip %s, %s", + ap -> ad_value, rp -> rp_line)); + goto out; + } + + ad_log_print (ap); + auth_start (&que, postie, ap); + que.Oaddress = postie; + que.Raddress = ap; + + time_mgt(&que); + + if (rp_isbad (winit_q (rp))) { + PP_LOG (LLOG_EXCEPTIONS, ("Problem writing into the que: %s", + rp -> rp_line)); + goto out; + } + + if (rp_isbad (txt_init (&que)) || + rp_isbad (txt_psetup (&que, hdr_822_bp, NULLCP))) { + PP_LOG (LLOG_EXCEPTIONS, ("Problem initialising text")); + goto out; + } + if (UTC2rfc (ut = utcnow(), datebuf) == NOTOK) + goto out; + free ((char *)ut); + (void) sprintf (buf, "To: %s\nFrom: %s\nDate: %s\n\ +Subject: Warning message\n", + recip -> ad_r822adr, postmaster, datebuf); + if (rp_isbad (txt_write (buf, strlen (buf)))) { + PP_LOG (LLOG_EXCEPTIONS, ("Problems writing text")); + goto out; + } + if (rp_isbad (txt_pfinish ())) { + PP_LOG (LLOG_EXCEPTIONS, ("Problems finishing hdr")); + goto out; + } + + (void) sprintf (datebuf, "1.%s", ia5_bp); + if (rp_isbad (txt_psetup (&que, datebuf, NULLCP))) { + PP_LOG (LLOG_EXCEPTIONS, ("Problems initialising for text")); + goto out; + } + setup_macros (&que, qporig, ad, direction, reason); + + if (copy_warn_file (file) == NOTOK) + goto out; + if (rp_isbad (txt_pfinish ()) || + rp_isbad (txt_tend())) { + PP_LOG (LLOG_EXCEPTIONS, ("Problems finishing text")); + goto out; + } + + if (rp_isbad (auth_finish (&que, postie, ap))) { + PP_LOG (LLOG_EXCEPTIONS, ("Authorisation problems")); + goto out; + } + + setup_directories (&que); + gen_ndr (&que); + if (rp_isbad (write_q (&que, &prm, rp)) || + rp_isbad (move_q (rp))) { + PP_LOG (LLOG_EXCEPTIONS, + ("Queue problems: %s", rp -> rp_line)); + goto out; + } + + auth_log (&que, postie, ap, msg_unique); + tell_qmgr (msg_unique, &prm, &que, postie, ap, 1); +out:; + que.Oaddress = que.Raddress = NULL; + if (ap) + adr_free (ap); + if (postie) + adr_free (postie); + q_free (&que); + prm_free (&prm); + return; +} + + +static Expand expand_macros[] = { + "sender", NULLCP, /* 0 */ + "822sender", NULLCP, /* 1 */ + "400sender", NULLCP, /* 2 */ + "ua-id", NULLCP, /* 3 */ + "p1-id", NULLCP, /* 4 */ + "recips", NULLCP, /* 5 */ + "822recips", NULLCP, /* 6 */ + "400recips", NULLCP, /* 7 */ + "locmta", NULLCP, /* 8 */ + "locsite", NULLCP, /* 9 */ + "reason", NULLCP, /* 10 */ + "direction", NULLCP, /* 11 */ + NULLCP, NULLCP}; + +static void setup_macros (qp, qporig, recip, direction, reason) +Q_struct *qp; +Q_struct *qporig; +ADDR *recip; +char *direction; +char *reason; +{ + expand_macros[0].expansion = qporig -> Oaddress -> ad_value; + expand_macros[1].expansion = qporig -> Oaddress -> ad_r822adr; + expand_macros[2].expansion = qporig -> Oaddress -> ad_r400adr; + expand_macros[3].expansion = qporig -> ua_id; + expand_macros[4].expansion = qporig -> msgid.mpduid_string; + expand_macros[5].expansion = recip -> ad_value; + expand_macros[6].expansion = recip -> ad_r822adr; + expand_macros[7].expansion = recip -> ad_r400adr; + expand_macros[8].expansion = loc_dom_mta; + expand_macros[9].expansion = loc_dom_site; + expand_macros[10].expansion = reason; + expand_macros[11].expansion = direction; +} + +static int copy_warn_file (file) +char *file; +{ + char filename[MAXPATHLENGTH]; + char buf[BUFSIZ], *cp; + FILE *fp; + int retval = OK; + + getfpath (wrndfldir, file, filename); + + if ((fp = fopen (filename, "r")) == NULL) { + PP_SLOG (LLOG_EXCEPTIONS, filename, ("Can't open")); + return NOTOK; + } + + while (fgets (buf, sizeof buf, fp) != NULLCP) { + if (index (buf, '$')) { + cp = expand_dyn (buf, expand_macros); + if (rp_isbad(txt_write (cp, strlen(cp)))) { + PP_LOG (LLOG_EXCEPTIONS, ("write error")); + retval = NOTOK; + break; + } + free (cp); + } + else { + if (rp_isbad(txt_write (buf, strlen(buf)))) { + PP_LOG (LLOG_EXCEPTIONS, ("write error")); + retval = NOTOK; + break; + } + } + } + (void) fclose (fp); + return retval; +} diff --git a/Src/submit/make b/Src/submit/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Src/submit/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Src/submit/rd_rfchdr.c b/Src/submit/rd_rfchdr.c new file mode 100644 index 0000000..336fc4d --- /dev/null +++ b/Src/submit/rd_rfchdr.c @@ -0,0 +1,1136 @@ +/* rd_rfchdr.c: parse 822 headers */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/rd_rfchdr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/rd_rfchdr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: rd_rfchdr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include +#include "q.h" +#include "tb_q.h" +#include "or.h" +#include "ap.h" +#include "x400_ub.h" + +extern void err_abrt(); +extern char *compress(); +static int hdr_parse (); +static int hdr_type (), fillin_DomId(); +static void hdr_rcv (); +static void hdr_via (); +static void hdr_check (); +static void hdr_subject (); +static void hdr_date (); +static void hdr_msgid (); +static void hdr_remcomm (); +static void do_correlators (); +static int getline (); +static int got_x400_mts_id = FALSE; +static int ua_id_set_by_x400 = FALSE; +static void hdr_x400_content_id(), + hdr_priority(), + hdr_x400_mts_id(), + hdr_dl_history(), + hdr_conversion(), + hdr_convert_with_loss(), + hdr_x400_received(), + hdr_def_deliv(), + hdr_latest_time(), + hdr_orig_eit (), + hdr_prohibition (), + hdr_gen_del_report(), + hdr_prev_non_del_report(); + +static char cor_to[BUFSIZ], *cor_subject = NULLCP, + *cor_date = NULLCP, *cor_mid = NULLCP; +static int cor_to_len; + +#define ub_content_id_length 16 +#define ub_content_correlator_length 512 + +/* -- basic states for the state machine -- */ +#define HDV_EOH 0 +#define HDV_NEW 1 +#define HDV_MORE 2 + +/* -- munge the header lines of the message -- */ +#define HDR_FROM 1 +#define HDR_SENDER 2 +#define HDR_REPLYTO 3 +#define HDR_RECEIVED 4 +#define HDR_VIA 5 +#define HDR_DATE 6 +#define HDR_MESSAGEID 7 +#define HDR_SUBJECT 8 + +/* rfc 1138 fields */ +/* mts */ +#define HDR_X400_MTS_ID 9 +#define HDR_ORIG_EIT 10 +#define HDR_CONTENT_IDENTIFIER 11 +#define HDR_PRIORITY 12 +#define HDR_DL_HISTORY 13 +#define HDR_CONVERSION 18 +#define HDR_CONVERT_WITH_LOSS 14 +/* mta */ +#define HDR_X400_RECEIVED 15 +#define HDR_DEF_DELIV 16 +#define HDR_LAST_DELIV 17 + +/* needed for content correlator */ +#define HDR_TO 19 + +/* appendix H of rfc 1148 bis */ +#define HDR_GEN_DEL_REPORT 20 +#define HDR_PREV_NON_DEL_REPORT 21 +#define HDR_ALT_RECIP 22 +#define HDR_DISCLOSE_RECIPS 23 +#define HDR_CONT_RETURN 24 + +/* appendix B of rfc 1148 bis */ +#define HDR_ACK_TO 25 +/* greybook specific so done in greybook */ + +static CMD_TABLE htbl_rfc [] = { + "from", HDR_FROM, + "sender", HDR_SENDER, + "reply-to", HDR_REPLYTO, + "received", HDR_RECEIVED, + "via", HDR_VIA, + "date", HDR_DATE, + "message-id", HDR_MESSAGEID, + "subject", HDR_SUBJECT, +/* rfc 1138 */ + "x400-mts-identifier", HDR_X400_MTS_ID, + "original-encoded-information-types", HDR_ORIG_EIT, + "content-identifier", HDR_CONTENT_IDENTIFIER, + "priority", HDR_PRIORITY, + "dl-expansion-history", HDR_DL_HISTORY, + "conversion", HDR_CONVERSION, + "conversion-with-loss", HDR_CONVERT_WITH_LOSS, + "x400-received", HDR_X400_RECEIVED, + "deferred-delivery", HDR_DEF_DELIV, + "latest-delivery-time", HDR_LAST_DELIV, + "to", HDR_TO, + "generate-delivery-report", HDR_GEN_DEL_REPORT, + "prevent-nondelivery-report", HDR_PREV_NON_DEL_REPORT, + "alternate-recipient", HDR_ALT_RECIP, + "disclose-recipients", HDR_DISCLOSE_RECIPS, + "content-return", HDR_CONT_RETURN, + 0, 0 + }; + + +/* -- statics -- */ +static FILE *hdr_fp; +static int from_count, + trace_count, + date_count, + hdr_prefix, + redistributed_mail, + sender_count, + x400_receiveds; +static Trace *date_trace; + +/* -- externals -- */ +extern Q_struct Qstruct; +extern CHAN *ch_inbound; +extern char *loc_dom_mta; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void rd_rfchdr (file) /* -- basic processing of incoming header lines -- */ +char *file; +{ + char *bp, + *name = NULLCP, /* hdr content location */ + *contents = NULLCP; + int retval = NOTOK, + type; + + + PP_DBG (("submit/rd_rfchdr (%s)", file)); + + sender_count = 0; + from_count = 0; + trace_count = 0; + date_count = 0; + redistributed_mail = FALSE; + ua_id_set_by_x400 = FALSE; + got_x400_mts_id = FALSE; + x400_receiveds = 0; + date_trace = (Trace *) NULL; + cor_to[0] = '\0'; + cor_to_len = sizeof cor_to; + cor_mid = NULLCP; + cor_date = NULLCP; + cor_subject = NULLCP; + + if ((hdr_fp = fopen (file, "r")) == NULL) + err_abrt (RP_FIO, + "Unable to open '%s'", file); + + + while (getline (&bp, hdr_fp) == OK) { + hdr_prefix = FALSE; + + switch (retval = hdr_parse (bp, &name, &contents)) { + case HDV_MORE: + continue; + case HDV_NEW: + if ((type = hdr_type (name)) > 0) + hdr_check (type, contents); + continue; + case HDV_EOH: + break; + case NOTOK: + err_abrt(RP_USER, "Unable to parse '%s' as key:field", bp); + break; + } + break; + } + + (void) fclose (hdr_fp); + + do_correlators(); + + if (retval != HDV_EOH) + PP_DBG (("submit/rd_rfchdr/retval (%d) != hdr_eoh", retval)); + + if (ch_inbound -> ch_access == CH_MTS && + sender_count == 0 && from_count == 0) + err_abrt (RP_USER, "No sender given"); + if (ch_inbound -> ch_strict_mode == CH_STRICT_CHECK) { + if (date_count == 0) + err_abrt (RP_USER, "No date field given"); + else if (date_count != 1) + err_abrt (RP_USER, "Too many date fields (%d)", + date_count); + } +} + +/* --------------------- Static Routines ------------------------------- */ + +static int hdr_parse (txt, name, contents) /* -- parse one header line -- */ +register char *txt; /* -- a line of header text -- */ +char **name; /* -- location of field's name -- */ +char **contents; /* -- location of field's contents -- */ +{ + char linetype; + + + PP_DBG (("submit/hdr_parse (%s)", txt)); + + + if (isspace (*txt)) { + /* -- continuation text -- */ + if (*txt == '\n' || *txt == '\0') + return (HDV_EOH); + linetype = HDV_MORE; + } + else { + linetype = HDV_NEW; + + *name = txt; + while (*txt && *txt != ':') + txt ++; + if (*txt == '\0' || *txt == '\n') + return NOTOK; + *txt ++ = '\0'; + + (void) compress (*name, *name); + } + + + *contents = txt; + (void) compress (*contents, *contents); + + return (linetype); +} + +static int hdr_type (name) /* -- return the type of the component -- */ +char *name; +{ + PP_DBG (("submit/hdr_type (%s)",name)); + + if (prefix ("Resent-", name)) { + name += 7; + goto doremail; + } + if (prefix ("Remailed-", name)) { + name += 9; + goto doremail; + } + if (prefix ("Redistributed-", name)) { + name += 14; +doremail: + hdr_prefix = TRUE; + if (!redistributed_mail) { + sender_count = from_count = 0; + redistributed_mail = TRUE; + } + } + + return (cmd_srch (name, htbl_rfc)); +} + +static void hdr_check (type, body) +char *body; +int type; +{ + AP_ptr ap; + int hlen; + + PP_DBG (("submit/hdr_check (%d,%s)", type, body)); + + if (type <= 0) + return; /* -- for all unknown types -- */ + + switch (type) { + case HDR_SENDER: + if (redistributed_mail && !hdr_prefix) + break; + if ((ap = ap_s2t (body)) == NULLAP) + err_abrt (RP_USER, "Syntactically invalid address for sender '%s'", body); + else + ap_free(ap); + sender_count++; + break; + case HDR_TO: + if (cor_to[0] != '\0' && cor_to_len > 4) { + (void) strcat (cor_to, ", "); + cor_to_len -= 2; + } + if ((hlen = strlen (body)) > cor_to_len) + cor_to_len = 0; + else { + (void) strncat (cor_to, body, cor_to_len); + cor_to_len -= hlen; + } + break; + case HDR_FROM: + if (redistributed_mail && !hdr_prefix) + break; + if ((ap = ap_s2t (body)) == NULLAP) + err_abrt (RP_USER, "Syntactically invalid address for from field '%s'", body); + else + ap_free(ap); + from_count++; + break; + case HDR_REPLYTO: + if (redistributed_mail && !hdr_prefix) + break; + break; + case HDR_VIA: + hdr_via (body); + break; + case HDR_RECEIVED: + hdr_rcv (body); + break; + case HDR_MESSAGEID: + hdr_msgid (body); + break; + case HDR_DATE: + if (hdr_prefix == FALSE) { + hdr_date (body); + date_count++; + } + break; + case HDR_SUBJECT: + hdr_subject (body); + break; + case HDR_X400_MTS_ID: + hdr_x400_mts_id (body); + break; + case HDR_ORIG_EIT: + hdr_orig_eit (body); + break; + case HDR_CONTENT_IDENTIFIER: + hdr_x400_content_id (body); + break; + case HDR_PRIORITY: + hdr_priority(body); + break; + case HDR_DL_HISTORY: + hdr_dl_history(body); + break; + case HDR_CONVERSION: + hdr_conversion(body); + break; + case HDR_CONVERT_WITH_LOSS: + hdr_convert_with_loss(body); + break; + case HDR_X400_RECEIVED: + hdr_x400_received (body); + break; + case HDR_DEF_DELIV: + hdr_def_deliv (body); + break; + case HDR_LAST_DELIV: + hdr_latest_time (body); + break; + case HDR_GEN_DEL_REPORT: + hdr_gen_del_report (); + break; + case HDR_PREV_NON_DEL_REPORT: + hdr_prev_non_del_report (); + break; + case HDR_ALT_RECIP: + hdr_prohibition(body, &(Qstruct.alternate_recip_allowed)); + break; + case HDR_DISCLOSE_RECIPS: + hdr_prohibition(body, &(Qstruct.disclose_recips)); + break; + case HDR_CONT_RETURN: + hdr_prohibition(body, &(Qstruct.content_return_request)); + break; + default: + break; + } /* -- switch -- */ +} + +static void hdr_subject (str) +char *str; +{ + char buf[BUFSIZ]; + + if (cor_subject == NULLCP) + cor_subject = strdup(str); + + if (ua_id_set_by_x400 == TRUE) + return; + if (Qstruct.ua_id != NULLCP) + return; + bzero (buf, sizeof buf); + if ((int)strlen(str) >= ub_content_id_length) { + (void) strncat (buf, str, (ub_content_id_length-strlen("..."))); + (void) strcat (buf, "..."); + } else + (void) strcat (buf, str); + Qstruct.ua_id = strdup (buf); +} + +static void hdr_x400_content_id (str) +char *str; +{ + char buf[BUFSIZ]; + + if (Qstruct.ua_id != NULLCP) + free(Qstruct.ua_id); + bzero (buf, sizeof buf); + if ((int)strlen(str) >= ub_content_id_length) { + (void) strncat (buf, str, (ub_content_id_length-strlen("..."))); + (void) strcat (buf, "..."); + } else + (void) strncat (buf, str, strlen(str)); + Qstruct.ua_id = strdup (buf); + ua_id_set_by_x400 = TRUE; +} + +static void hdr_priority (str) +char *str; +{ + (void) compress(str, str); + if (lexequ(str, "normal") == 0) + Qstruct.priority = PRIO_NORMAL; + else if (lexequ(str, "urgent") == 0) + Qstruct.priority = PRIO_URGENT; + else if (lexequ(str, "non-urgent") == 0 + || lexequ(str, "nonurgent") == 0) + Qstruct.priority = PRIO_NONURGENT; +} + +static void hdr_dl_history (str) +char *str; +{ + register DLHistory *dlp; + char *cp; + int n; + OR_ptr or; + UTC utc; + char buf[BUFSIZ]; + + if ((cp = index(str, ';')) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("Illegal DLHistory field %s", str)); + return; + } + if ((n = cp - str) >= BUFSIZ) + n = BUFSIZ - 1; + (void) strncpy (buf, str, n); + buf[n] = 0; + if (or_rfc2or_aux (buf, &or, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("Illegal rfc822 address in DLHistory %s", buf)); + return; + } + or_or2std (or, buf, FALSE); + or_free (or); + cp ++; + if (index (cp, ';') == NULL) + PP_LOG (LLOG_EXCEPTIONS, + ("DLhistory Missing trailing ';' in %s", str)); + if (rfc2UTC (cp, &utc) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("DLhistory: bad time in %s", str)); + return; + } + dlp = (DLHistory *)smalloc (sizeof *dlp); + dlp -> dlh_addr = strdup (buf); + dlp -> dlh_time = utc; + dlp -> dlh_dn = NULLCP; + dlp -> dlh_next = Qstruct.dl_expansion_history; + Qstruct.dl_expansion_history = dlp; +} + +static void hdr_conversion (str) +char *str; +{ + (void) compress (str, str); + if (lexequ (str, "prohibited") == 0) + Qstruct.implicit_conversion_prohibited = 1; +} + +static void hdr_convert_with_loss (str) +char *str; +{ + (void) compress (str, str); + if (lexequ (str, "prohibited") == 0) + Qstruct.conversion_with_loss_prohibited = 1; +} + +static void hdr_x400_received (str) +char *str; +{ + Trace *trace; + + PP_DBG (("submit/hdr_x400_received (%s)", str)); + + trace_count++; + + if (ch_inbound -> ch_access == CH_MTS) + err_abrt (RP_MECH, + "No trace information allowed for local submission"); + + x400_receiveds++; + + if (date_trace != (Trace *) NULL) { + /* remove date generated trace */ + /* should never need as trace should be above */ + /* date fields */ + if (Qstruct.trace == date_trace) + Qstruct.trace = Qstruct.trace->trace_next; + else { + for (trace = Qstruct.trace; + trace != (Trace *) NULL + && trace->trace_next != date_trace; + trace = trace->trace_next) + continue; + if (trace->trace_next == date_trace) + trace->trace_next = date_trace->trace_next; + } + date_trace->trace_next = (Trace *) NULL; + trace_free(date_trace); + date_trace = (Trace *) NULL; + } + + trace = (Trace *) smalloc (sizeof(Trace)); + bzero ((char *) trace, sizeof(*trace)); + + if (rfc2x400trace (trace, str) == OK) { + PP_DBG (("rfc2x400trace OK")); + trace -> trace_next = Qstruct.trace; + Qstruct.trace = trace; + } else + free((char *) trace); +} + +static void hdr_def_deliv (str) +char *str; +{ + if (Qstruct.defertime != 0) + /* don't override */ + return; + if (rfc2UTC (str, &Qstruct.defertime) != OK) + /* ignore */ + Qstruct.defertime = 0; +} + +static void hdr_latest_time (str) +char *str; +{ + if (Qstruct.latest_time != 0) + /* don't override */ + return; + if (rfc2UTC (str, &Qstruct.latest_time) != OK) + Qstruct.latest_time = 0; + else + /* assume if present then critical */ + Qstruct.latest_time_crit = Q_LATESTTIME; +} + +static void hdr_date (str) +char *str; +{ + Trace *tp; + char *adr = NULL; + OR_ptr or; + + if (x400_receiveds > 0) + /* have x400-received lines */ + /* so don't need to add date generated trace */ + return; + + if (cor_date != NULLCP) + cor_date = strdup(str); + + tp = (Trace *) smalloc (sizeof (Trace)); + bzero ((char *)tp, sizeof(*tp)); + if (rfc2UTC (str, &(tp -> trace_DomSinfo.dsi_time)) != OK) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/hdr_date unable to convert time to UTC '%s'", + str)); + free((char *) tp); + return; + } + tp->trace_DomSinfo.dsi_action = ACTION_RELAYED; + + if (Qstruct.Oaddress->ad_r400adr != NULL) { + adr = strdup(Qstruct.Oaddress->ad_r400adr); + if ((or = or_std2or(adr)) == NULLOR) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/hdr_date unable to get OR tree for orig '%s'", Qstruct.Oaddress->ad_r400adr)); + free((char *)adr); + } + } + if (or == NULL && Qstruct.Oaddress->ad_r822adr != NULL) { + adr = strdup(Qstruct.Oaddress->ad_r822adr); + if (or_rfc2or_aux (adr, &or, 1) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/hdr_date unable to get OR tree for orig '%s'", Qstruct.Oaddress->ad_r822adr)); + free ((char *) adr); + } + } + + if (or == NULL + || fillin_DomId (&tp -> trace_DomId, or, adr) == NOTOK) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/hdr_date unable to create gld for orig")); + free ((char *) tp); + return; + } + + or_free(or); + if (Qstruct.Oaddress->ad_r822adr != NULLCP) { + AP_ptr tree, group, + name, local, + domain, route; + ap_s2p(Qstruct.Oaddress->ad_r822adr, + &tree, &group, &name, + &local, &domain, &route); + rfc822_norm_dmn (domain, ch_inbound->ch_ad_order); + tp -> trace_mta = strdup(domain -> ap_obvalue); + ap_sqdelete (tree, NULLAP); + ap_free(tree); + } + free(adr); + if (tp -> trace_DomSinfo.dsi_time == NULL) + tp -> trace_DomSinfo.dsi_time = utcnow (); + tp -> trace_next = Qstruct.trace; + date_trace = Qstruct.trace = tp; +} + +/* ARGSUSED */ +static void hdr_x400_mts_id (str) +char *str; +{ + if (Qstruct.msgid.mpduid_string != NULL) + MPDUid_free(&Qstruct.msgid); + /* force random generation to avoid clashes */ + MPDUid_new(&Qstruct.msgid); + got_x400_mts_id = TRUE; +#ifdef KEEPMTSID + rfc2msgid(&Qstruct.msgid, str); +#endif +} + +static void hdr_orig_eit (str) +char *str; +{ + if (Qstruct.orig_encodedinfo.eit_types != NULL) + /* override */ + encodedinfo_free (&Qstruct.orig_encodedinfo); + (void) rfc2encinfo (&Qstruct.orig_encodedinfo, str); +} + +static void hdr_msgid (str) +char *str; +{ + MPDUid *mp; + char *midstring, *cp; + AP_ptr ap, local, domain; + OR_ptr or; + + if (cor_mid == NULLCP) + cor_mid = strdup(str); + + if (got_x400_mts_id == TRUE) + return; + + if (Qstruct.msgid.mpduid_string == NULL) + MPDUid_new (&Qstruct.msgid); + + mp = &Qstruct.msgid; + if (mp -> mpduid_string != NULLCP) + free (mp -> mpduid_string); + (void) compress (str, str); + if ((int) strlen(str) > UB_LOCAL_ID_LENGTH) { + char tbuf[UB_LOCAL_ID_LENGTH+1]; + (void) strncpy (tbuf, str, UB_LOCAL_ID_LENGTH); + tbuf[UB_LOCAL_ID_LENGTH] = 0; + mp -> mpduid_string = strdup (tbuf); + } + else mp -> mpduid_string = strdup (str); + + if ((midstring = index (str, '<')) == NULLCP + || (cp = rindex(str, '>')) == NULLCP) + return; + *cp ='\0'; + midstring++; + + if (ap_s2p(midstring, &ap, NULLAPP, NULLAPP, &local, + &domain, NULLAPP) == (char *) NOTOK) + return; + if (domain != NULLAP) { + rfc822_norm_dmn (domain, + Qstruct.inbound->li_chan->ch_ad_order); + if (or_domain2or(domain->ap_obvalue, &or) != NOTOK) { + OR_ptr c, admd, prmd; + + or_chk_admd(&or); + if ((c = or_find(or, OR_C, NULLCP)) != NULLOR + && (admd = or_find(or, OR_ADMD, NULLCP)) != NULLOR + && (prmd = or_find(or, OR_PRMD, NULLCP)) != NULLOR) { + /* swap generated with found */ + if (mp->mpduid_DomId.global_Country) + free(mp->mpduid_DomId.global_Country); + mp->mpduid_DomId.global_Country = strdup(c->or_value); + if (mp->mpduid_DomId.global_Admin) + free(mp->mpduid_DomId.global_Admin); + mp->mpduid_DomId.global_Admin = strdup(admd->or_value); + if (mp->mpduid_DomId.global_Private) + free(mp->mpduid_DomId.global_Private); + mp->mpduid_DomId.global_Private = strdup(prmd->or_value); + } + if (or) + or_free(or); + } + } + + ap_sqdelete(ap, NULLAP); +} + + +/* -- take comments from 'from' & add to 'to' leaving 'from' without any -- */ + +static void hdr_remcomm (from, to) +char *from; +char *to; +{ + char *start = from, + *r = to, + *s, + *p, + *q; + + + if (start) { + + /* -- in case of NULL start ie missing date -- */ + + PP_DBG (("submit/hdr_remcomm (%s,%s)", from, to)); + + /* -- get to end -- */ + while (*r != '\0') + r++; + + for (p = start ; (p = index (p, '(')) != NULLCP;) { + if ((q = index (p, ')')) == NULLCP) { + *p = '\0'; + break; + } + + if (*to != '\0') + *r++ = ' '; + + for (s = p; s <= q; *r++ = *s++) continue; + + (void) strcpy (p, q+1); + + } /* -- for -- */ + + *r = '\0'; + (void) compress (from, from); + } /* -- if -- */ + else + PP_DBG (("submit/hdr_remcomm (NULL, %s)",to)); +} + +static void hdr_via (contents) +char *contents; +{ + register Trace *tp; + char *datestart = NULLCP, + *argv[25], *domain, extraspace[LINESIZE]; + OR_ptr or; + + PP_DBG (("submit/hdr_via (%s)", contents)); + + trace_count++; + + if (trace_count == 1) + return;/* we've added the first trace! */ + + if (ch_inbound -> ch_access == CH_MTS) + err_abrt (RP_MECH, + "No trace information allowed for local submission"); + + /* -- rip out the comments -- */ + + *extraspace = '\0'; + hdr_remcomm (contents, extraspace); + + if ((datestart = index (contents, ';')) != NULLCP) + *datestart++ = '\0'; + + if (sstr2arg (contents, 25, argv, ",\t ") < 1 + || argv[0] == NULLCP) + return; + + domain = strdup(argv[0]); + or = NULLOR; + if (or_domain2or (domain, &or) == NOTOK) { + PP_TRACE(("unable to parse domain '%s' to OR tree", argv[0])); + return; + } + or_chk_admd (&or); + tp = (Trace *) smalloc (sizeof (Trace)); + bzero ((char *)tp, sizeof(*tp)); + + if (fillin_DomId (&tp -> trace_DomId, or, argv[0]) == NOTOK){ + free ((char *) tp); + return; + } + + or_free(or); + free(domain); + tp -> trace_mta = strdup(argv[0]); + + if (datestart == NULLCP || + rfc2UTC(datestart,&(tp->trace_DomSinfo.dsi_time)) == NOTOK) + tp -> trace_DomSinfo.dsi_time = utcnow(); + + tp->trace_DomSinfo.dsi_action = ACTION_RELAYED; + tp -> trace_next = Qstruct.trace; + Qstruct.trace = tp; +} + + + + +static void hdr_rcv (contents) +char *contents; +{ + register Trace *tp; + char *bystart = NULLCP, *datestart = NULLCP, + *argv[25], *domain, extraspace[LINESIZE]; + int argc, i; + OR_ptr or; + + PP_DBG (("submit/hdr_rcv (%s)", contents)); + + trace_count++; + + if (trace_count == 1) + return;/* we've added the first trace! */ + + if (ch_inbound -> ch_access == CH_MTS) + err_abrt (RP_MECH, + "No trace information allowed for local submission"); + /* -- rip out the comments -- */ + + *extraspace = '\0'; + hdr_remcomm (contents, extraspace); + + if ((datestart = index (contents, ';')) != NULLCP) + *datestart++ = '\0'; + + argc = sstr2arg (contents, 25, argv, ",\t "); + + for (i = 0; i < argc; i++) { + if (lexequ (argv [i], "by") == 0) { + if (bystart == NULLCP && i < argc -1) { + bystart = argv [++i]; + continue; + } + } + } + + if (bystart == NULLCP) + return; + domain = strdup(bystart); + or = NULLOR; + if (or_domain2or (domain, &or) == NOTOK) { + PP_TRACE(("unable to parse domain '%s' to OR tree", bystart)); + return; + } + or_chk_admd (&or); + + tp = (Trace *) smalloc (sizeof (Trace)); + bzero ((char *)tp, sizeof(*tp)); + + if (fillin_DomId (&tp -> trace_DomId, or, bystart) == NOTOK){ + free ((char *) tp); + return; + } + + or_free(or); + free(domain); + tp -> trace_mta = strdup(bystart); + + if (datestart == NULLCP || + rfc2UTC(datestart,&(tp->trace_DomSinfo.dsi_time)) == NOTOK) + tp -> trace_DomSinfo.dsi_time = utcnow(); + + tp->trace_DomSinfo.dsi_action = ACTION_RELAYED; + tp -> trace_next = Qstruct.trace; + Qstruct.trace = tp; +} + + + +static int getline (bp, fp) +char **bp; +FILE *fp; +{ + static char *buf; + static int bufsiz = 0; + int count; + char *cp; + int c; + + if (buf == NULLCP) + buf = smalloc (bufsiz = BUFSIZ); + for (cp = buf, count = 0; ; count ++) { + if (count >= bufsiz - 5) { + int curlen = cp - buf; + buf = realloc (buf, (unsigned) (bufsiz += BUFSIZ)); + if (buf == NULL) + err_abrt (RP_LIO, "Out of memeory"); + cp = buf + curlen; + } + switch (c = getc (fp)) { + case '\n': + *cp ++ = ' '; + if ((c = getc(fp)) == ' ' || c == '\t') + continue; + ungetc (c, fp); + break; + case EOF: + if (cp == buf) + return NOTOK; + break; + default: + *cp ++ = c; + continue; + } + break; + } + *cp = '\0'; + *bp = buf; + return OK; +} + +static int fillin_DomId (domId, or, str) +GlobalDomId *domId; +OR_ptr or; +char *str; +{ + OR_ptr tmp_or; + + if ((tmp_or = or_find (or, OR_C, NULLCP)) == NULLOR) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/fillin_DomId: no country in '%s'", str)); + return NOTOK; + } + domId->global_Country = strdup(tmp_or -> or_value); + + if ((tmp_or = or_find (or, OR_ADMD, NULLCP)) == NULLOR) { + PP_LOG(LLOG_EXCEPTIONS, + ("submit/fillin_DomId: no ADMD in '%s'", str)); + free ((char *) domId -> global_Country); + return NOTOK; + } + domId->global_Admin = strdup(tmp_or -> or_value); + + if ((tmp_or = or_find (or, OR_PRMD, NULLCP)) != NULLOR) + domId->global_Private = strdup(tmp_or -> or_value); + return OK; +} + +static int add_str (buf, s1, s2, len) +char buf[]; +char *s1, *s2; +int len; +{ + int l1, l2; + if (len <= 0) + return len; + l1 = strlen(s1); + l2 = strlen(s2); + if (l1 + 2>= len) return len; + if (buf[0]) { + (void) strcat(buf, ",\n"); + len -= 2; + } + (void) strcat (buf, s1); + len -= l1; + if (len > l2) { + (void) strcat (buf, s2); + len -= l2; + } + else { + (void) strncat (buf, s2, len - 1); + len = 0; + } + return len; +} + +static void do_correlators() +{ + char buf[2*BUFSIZ], realbuf[BUFSIZ+1]; + PS ps; + PE pe; + int len; + char *cp; + + buf[0] = '\0'; + len = 512; + buf[len] = 0; + if (NULLCP != cor_subject) { + len = add_str (buf, "Subject: ", cor_subject, len); + free(cor_subject); + cor_subject = NULLCP; + } + + if (NULLCP != cor_mid) { + len = add_str (buf, "Message-ID: ", cor_mid, len); + free(cor_mid); + cor_mid = NULLCP; + } + + if (NULLCP != cor_date) { + len = add_str (buf, "Date: ", cor_date, len); + free(cor_date); + cor_date = NULLCP; + } + + if ('\0' != cor_to) { + len = add_str (buf, "To: ", cor_to, len); + cor_to[0] = '\0'; + } + + realbuf[0] = '\0'; + if ((int) strlen(buf) >= ub_content_correlator_length) { + (void) strncat (realbuf, buf, + (ub_content_correlator_length-strlen("..."))); + (void) strcat (realbuf, "..."); + } else + (void) strcat (realbuf, buf); + + Qstruct.pp_content_correlator = strdup(realbuf); + + pe = oct2prim(realbuf, strlen(realbuf)); + + if ((ps = ps_alloc (str_open)) == NULLPS) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't allocate PS")); + return; + } + + len = ps_get_abs (pe); + cp = smalloc (len); + + if (str_setup (ps, cp, len, 1) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, ("Can't setup stream [%s]", + ps_error (ps -> ps_errno))); + return; + } + + if (pe2ps (ps, pe) == NOTOK) { + PP_LOG (LLOG_EXCEPTIONS, + ("pe2ps failed [%s]", ps_error (ps -> ps_errno))); + return; + } + + ps_free (ps); + + if ((Qstruct.general_content_correlator = str2qb (cp, len, 1)) == NULL) + return; + + free(cp); + pe_free(pe); +} + +static void hdr_prohibition(str, pchar) +char *str, *pchar; +{ + compress(str, str); + if (lexequ(str, "allowed") == 0) + *pchar = TRUE; + else if (lexequ(str, "prohibited") == 0) + *pchar = FALSE; + else + PP_NOTICE(("Unknown string encoding for prohibition: '%s'", + str)); +} + +static void hdr_gen_del_report () +{ + ADDR *ix; + + for (ix = Qstruct.Raddress; + ix != NULLADDR; + ix = ix -> ad_next) { + if (ix -> ad_resp == TRUE) + /* set for +ve drs */ + ix -> ad_usrreq = AD_USR_CONFIRM; + } +} + +static void hdr_prev_non_del_report () +{ + ADDR *ix; + + for (ix = Qstruct.Raddress; + ix != NULLADDR; + ix = ix -> ad_next) { + if (ix -> ad_resp == TRUE) + /* no drs at all */ + ix -> ad_usrreq = AD_USR_NOREPORT; + } +} diff --git a/Src/submit/submit.c b/Src/submit/submit.c new file mode 100644 index 0000000..f66902d --- /dev/null +++ b/Src/submit/submit.c @@ -0,0 +1,598 @@ +/* submit.c: the mail enqueuer */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "or.h" +#include +#include +#include +#include +#include +#include + + + +/* -- externals -- */ +extern char *msg_unique, /* unique part of msg queue name */ + *mgt_inhost, + *qmgr_hostname, + *rcmd_srch(), + *quedfldir, /* dir w/mail queue directories */ + auth2submit_msg[]; + +extern int mgt_adtype, + protocol_mode; + +ADDR *ad_originator, + *ad_recip; + +extern struct passwd *getpwuid(); +extern long msg_size; +extern CHAN *ch_inbound; +extern CMD_TABLE qtbl_mt_type[]; + + + + +/* -- globals -- */ +char *username; /* login name of usr running me */ +int effecid, /* id providing access priviliges */ + privileged, /* am I a priveledged user ? */ + userid, /* id of user running me */ + accept_all, + submit_debug = 0, + notrace; +Q_struct Qstruct, *qptr; + + + + +/* -- static variables -- */ +static struct prm_vars Prm; +static int qmgr_fd = NOTOK; +static int log_msgtype; +static int adr_count; + +extern void fmt_init (); +extern int validate_recip (); +extern void auth_start (); +extern void gen_warnings (); +extern void gen_probedr (); +extern void gen_ndr (); +extern void auth_log (); +extern void ad_init (); +extern void check_splitter (); +extern void check_conversions (); +extern void check_report_level (); +extern void check_crits (); +extern void check_dr_crits (); +extern void msg_mgt (); +extern void time_mgt (); +extern void clear_q (); +extern int move_q (); +extern int winit_q (); +extern int write_q (); +extern void txt_input (); +extern void ad_log_print (); +extern ADDR *read_sender (); +extern ADDR *read_recipient (); +extern int server_start (); + +/* -- local routines -- */ +void err_abrt(); +void pro_reply(); + +static int priv_user(); +static void _pro_reply(); +static void dir_init(); +static void done(); +static void msg_init(); +static void user_init(); + + + +/* -------------------- Main Routine ---------------------------------- */ + + + +/* ARGSUSED */ +main (argc, argv) +int argc; +char **argv; +{ + int retval; + int qmgr_status; + int server = 0; + ADDR *ad; + ADDR **app; + RP_Buf rps, *rp = &rps; + int opt; + extern char *optarg, *pptailor; + + while ((opt = getopt (argc, argv, "dst:")) != EOF) { + switch (opt) { + case 'd': + submit_debug = 1; + break; + case 's': + server = 1; + break; + case 't': + pptailor = optarg; + break; + } + } + + (void) umask (0); + sys_init (argv[0]); + + qptr = &Qstruct; + q_init (qptr); + + user_init(); + dir_init(); + or_myinit(); + fmt_init(); + + (void) signal (SIGPIPE, done); + if (server) + qmgr_fd = server_start (qmgr_hostname, &qmgr_status); + else + qmgr_fd = qmgr_start (qmgr_hostname, &qmgr_status, 1); + +#define pp_could_go_faster 1 + while (pp_could_go_faster) { /* infinite loop! */ + + /* + Reset various parameters + */ + msg_init(); + + protocol_mode = 1; + + + /* + Read the parameter settings for a Message + */ + if (rp_isbad (retval = rd_prm_info (&Prm))) { + if (retval == RP_EOF) + break; /* we're done */ + err_abrt (retval, "bad parameters"); + } + else + pro_reply (RP_OK, "Got the parameters"); + + if (qmgr_status != DONE && qmgr_fd != NOTOK) + qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status); + /* + Read the queue structure + */ + if (rp_isbad (retval = rd_q_info (qptr))) + err_abrt (retval, "Bad queue read"); + + /* + Perform management functions on parameters + */ + if (rp_isbad (retval = cntrl_mgt (&Prm, qptr))) + err_abrt (retval, "Bad parameter settings"); + + /* + Perform management functions on the queue + */ + if (rp_isbad (retval = q_mgt (qptr))) + err_abrt (retval, "Bad queue parameter settings"); + + pro_reply (RP_OK, "Starting fine, sender please"); + + /* + * read and validate the sender + */ + + ad = read_sender (qptr); + if (validate_sender(qptr, ad, username, rp) != RP_OK) + err_abrt (rp -> rp_val, "%s", rp -> rp_line); + ad_originator = ad; + + pro_reply (RP_AOK, "Continuing fine, addresses please"); + + if (qmgr_status != DONE && qmgr_fd != NOTOK) + qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status); + + /* + * Read and validate the recipients. + */ + + app = &ad_recip; + while ((ad = read_recipient (qptr)) != NULLADDR) { + if (rp_isbad(validate_recip(ad, qptr, rp))) { + if (rp_gbval (rp -> rp_val) == RP_BTNO && + retval != RP_BHST && + retval != RP_DHST) + err_abrt (rp -> rp_val, "%s", + rp -> rp_line); + pro_reply (rp -> rp_val, "%s", rp -> rp_line); + adr_tfree (ad); + continue; + } + else + pro_reply (rp -> rp_val, "%s", rp -> rp_line); + (*app) = ad; /* add to recipient list */ + app = &(*app) -> ad_next; + adr_count ++; + } + if (ad_recip == NULLADDR) + err_abrt (RP_USER, "No valid addresses found"); + ad_log_print (ad_recip); + + /* + Authorisation - main routines + */ + + auth_start(qptr, ad_originator, ad_recip); + + /* + Sets the Qstruct's Originator and Recipient fields + */ + qptr -> Oaddress = ad_originator; + qptr -> Raddress = ad_recip; + time_mgt(qptr); + /* + Initialize to the queue directory for output + */ + + if (rp_isbad(winit_q(rp))) + err_abrt (rp -> rp_val, "%s", rp -> rp_line); + + /* + if (DMPDU) + parse DR from incoming channel + then get body (if any) + else if probe + nothing much + else (normal message) + splat the body into a file + */ + + log_msgtype = qptr -> msgtype; + + switch (qptr -> msgtype) { + case MT_DMPDU: + pro_reply (RP_AOK, "Addresses ok, DR info please"); + if (rp_isbad (retval = gen_io2dr(qptr))) { + err_abrt (retval, "Bad DR struct"); + } + pro_reply (RP_AOK, "DR OK"); + txt_input (qptr, notrace == 0); + break; + + case MT_PMPDU: + msg_size = qptr -> msgsize; + break; + + default: + pro_reply (RP_AOK, "Addresses ok, text please"); + txt_input (qptr, notrace == 0); + break; + } + + if (qmgr_status != DONE && qmgr_fd != NOTOK) + qmgr_fd = qmgr_retry (qmgr_fd, &qmgr_status); + + protocol_mode = 0; /* end of protocol phase */ + + /* + finish authorisation tests on message + size/body parts and perform channel binding + */ + + if (rp_isbad (retval = auth_finish(qptr, ad_originator, + ad_recip))) + if (!accept_all) + err_abrt (retval, "%s : %s", + "At least one recipient fails authorisation", + auth2submit_msg); + + check_splitter(qptr); + check_crits (qptr); + check_conversions (qptr); + check_report_level (qptr); + setup_directories (qptr); + + /* + Generate the appropriate Delivery Notifications + */ + + switch (qptr -> msgtype) { + case MT_PMPDU: + gen_probedr(qptr); + break; + default: + gen_ndr(qptr); + break; + } + + if (rp_isbad (write_q (qptr, &Prm, rp)) || + rp_isbad (move_q(rp))) + err_abrt (rp -> rp_val, "%s", rp -> rp_line); + + + pro_reply (RP_MOK, "Submitted & queued (%s)", msg_unique); + + + /* + generate authorisation statistics logs + now that msg_unique is known + */ + + auth_log(qptr, ad_originator, ad_recip, msg_unique); + + /* Tell qmgr */ + + if (qmgr_fd != NOTOK) + tell_qmgr (msg_unique, &Prm, qptr, ad_originator, + ad_recip, adr_count); + if (ch_inbound != NULL && ch_inbound->ch_access == CH_MTS) + PP_NOTICE (("<<< local %s %s %s %s %s", + rcmd_srch(log_msgtype, qtbl_mt_type), + msg_unique, + ch_inbound -> ch_name, + username, + mgt_inhost)); + else + PP_NOTICE (("<<< remote %s %s %s %s", + rcmd_srch(log_msgtype, qtbl_mt_type), + msg_unique, + ch_inbound -> ch_name, + mgt_inhost == NULLCP ? "" : + mgt_inhost)); + + gen_warnings (qptr, ad_originator, ad_recip); + } + + if (qmgr_fd != NOTOK) + (void) qmgr_end (qmgr_fd); + + PP_TRACE (("Submit normal end")); + exit (0); /* NOTREACHED */ +} + + +tell_qmgr (msg, prm, qp, sndr, recip, cnt) +char *msg; +struct prm_vars *prm; +Q_struct *qp; +ADDR *sndr, *recip; +int cnt; +{ + if (qmgr_fd != NOTOK) + (void) message_send (qmgr_fd, msg, prm, qp, sndr, recip, cnt); +} + + +/* -------------------- Static Routines ------------------------------- */ + + + + +/* +Get information on the incomming channel calling submit +*/ + +static void user_init() +{ + register struct passwd *pw; + + PP_LOG (LLOG_DEBUG, ("submit/user_init()")); + + privileged = FALSE; + userid = getuid(); + effecid = geteuid(); + + if ((pw = getpwuid (userid)) == NULL) + err_abrt (RP_LIO, + "No login for UID %d, call Support.", userid); + endpwent(); + + username = strdup (pw->pw_name); + + if (priv_user (userid, effecid) == TRUE) + privileged = TRUE; + + if (pp_setuserid() == NOTOK) + err_abrt (RP_LIO, "Unable to set user id"); +} + +static int priv_user (id, eid) +int id, eid; +{ + struct passwd *pwd; + extern char *pplogin; + + if (id == 0 || eid == id) + return TRUE; + + if ((pwd = getpwnam (pplogin)) == (struct passwd *)0) + return FALSE; + if (id == pwd -> pw_uid) + return TRUE; + return FALSE; +} + + + +/* +chdir +*/ + +static void dir_init() +{ + /* + cd into the queue directory + */ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory. '%s'", quedfldir); +} + + + + +/* +Initialise a msg +*/ + +static void msg_init() +{ + msg_unique = NULLCP; /* for logging failed messages */ + + /* + address and qstruct + done in two stages in case we filled in recipients but not + assigned to qstruct + */ + adr_count = 0; + if (ad_recip != NULLADDR) + adr_tfree (ad_recip); + if (ad_originator != NULLADDR) + adr_tfree (ad_originator); + ad_originator = NULLADDR; + ad_recip = NULLADDR; + qptr -> Oaddress = NULLADDR; + qptr -> Raddress = NULLADDR; + q_free (qptr); + msg_mgt(); +} + +/* -------------------- Reply Routines -------------------------------- */ + + + + +#ifdef lint +/*VARARGS2*/ +void pro_reply (code, fmt) +int code; +char *fmt; +{ + pro_reply (code, fmt); +} +#else +void pro_reply (va_alist) +va_dcl +{ + va_list ap; + int code; + + va_start(ap); + + code = va_arg (ap, int); + + _pro_reply (code, ap); + + va_end (ap); +} + +static void _pro_reply (code, ap) +int code; +va_list ap; +{ + char buffer[4*BUFSIZ]; + register char *errchar = NULLCP; + + if (rp_isbad (code)) + switch (code) { + case RP_HUH: /* not if it was a user error */ + case RP_PARM: + case RP_USER: + case RP_PARSE: + case RP_BHST: + case RP_NAUTH: + case RP_EOF: + break; + + default: + errchar = " "; + break; + } + + _asprintf (buffer, NULLCP, ap); + + if (rp_isbad (code)) + PP_SLOG (LLOG_EXCEPTIONS, errchar, + ("submit/pro_reply(%s) '%s'", rp_valstr (code), + buffer)); + else + PP_LOG (LLOG_PDUS|LLOG_TRACE, + ("submit/pro_reply(%s) '%s'", rp_valstr (code), + buffer)); + + if (submit_debug) + printf ("%s:", rp_valstr(code)); + else + (void) putc (code, stdout); + + (void) fputs (buffer, stdout); + (void) putc ('\n', stdout); + (void) fflush (stdout); +} +#endif + +/* --------------- (err_) GENERAL ERROR-HANDLING ----------------------- */ + + +#ifdef lint +/*VARARGS2*/ +void err_abrt (code, fmt) +int code; +char *fmt; +{ + clear_q(); + + pro_reply (code, fmt); +} +#else +void err_abrt (va_alist) /* terminate the process */ +va_dcl +{ + va_list ap; + int code; + + va_start (ap); + + code = va_arg (ap, int); + + PP_TRACE (("err_abrt (%d)", code)); + + _pro_reply (code, ap); + + va_end (ap); + + done (-1); /* pass the reply code to caller */ +} +#endif + +static void done (n) +int n; +{ + PP_TRACE (("done (%d)", n)); + clear_q(); + if (qmgr_fd != NOTOK) + qmgr_end (qmgr_fd); + exit (n); +} diff --git a/Src/submit/submit_chk.c b/Src/submit/submit_chk.c new file mode 100644 index 0000000..dc1d3ed --- /dev/null +++ b/Src/submit/submit_chk.c @@ -0,0 +1,478 @@ +/* submit_chk.c: checks done by submit */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_chk.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_chk.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_chk.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "dr.h" + +/* -- externals -- */ +extern char *cont_p22; +extern void message_failure(); + + +/* -- local routines -- */ +void check_conversions(); +void check_crits(); +void check_dr_crits(); +int check_crit(); +static void check_extn_crits(); +static void check_q_crits(); +static void check_rrinfo_crits(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int check_crit (this, mask, qp, adr, str) +char this, + mask; +Q_struct *qp; +ADDR *adr; /* if NULLADDR and fail, fail total message */ +char *str; +{ + char buf[BUFSIZ]; + if (this != 0 && (this & (~mask))) { + /* fail on critical */ + (void) sprintf (buf, "Unsupported criticality of '%s'", + str); + if (adr == NULLADDR) + message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_UNSUPPORTED_CRITICAL_FUNCTION, + buf); + else { + if (adr -> ad_status == AD_STAT_PEND) { + adr -> ad_status = AD_STAT_DRREQUIRED; + adr -> ad_reason = DRR_UNABLE_TO_TRANSFER; + adr -> ad_diagnostic = DRD_UNSUPPORTED_CRITICAL_FUNCTION; + adr -> ad_add_info = strdup(buf); + } + } + return NOTOK; + } + return OK; +} + + + + +void check_crits (qp) +register Q_struct *qp; +{ + ADDR *ix = qp -> Raddress; + + check_extn_crits (qp, qp -> per_message_extensions, + "per_message_extensions"); + while (ix != NULLADDR) { + if (ix -> ad_status == AD_STAT_PEND) + check_q_crits (qp, ix); + ix = ix -> ad_next; + } +} + + + + +void check_dr_crits (qp, dr) +Q_struct *qp; +DRmpdu *dr; +{ + Rrinfo *ix = dr -> dr_recip_list; + + check_extn_crits (qp, dr->dr_per_envelope_extensions, + "per_envelope_extensions"); + check_extn_crits (qp, dr -> dr_per_report_extensions, + "per_report_extensions"); + + while (ix != (Rrinfo *) NULL) { + check_rrinfo_crits (qp, dr, ix); + ix = ix -> rr_next; + } +} + + + + +void check_conversions (qp) +register Q_struct *qp; +{ + ADDR *ix; + LIST_RCHAN *chan; + int cont; + if (qp -> implicit_conversion_prohibited == TRUE) { + ix = qp -> Raddress; + + while (ix != NULLADDR) { + if (ix -> ad_status == AD_STAT_PEND + && ix -> ad_fmtchan != NULLIST_RCHAN) { + chan = ix -> ad_fmtchan; + cont = TRUE; + while (cont == TRUE + && chan != NULLIST_RCHAN) { + switch (chan -> li_chan -> ch_conversion) { + case CH_CONV_CONVERT: + case CH_CONV_WITHLOSS: + /* fail this recipient */ + ix -> ad_status = AD_STAT_DRREQUIRED; + ix -> ad_reason = DRR_UNABLE_TO_TRANSFER; + ix -> ad_diagnostic = DRD_CONVERSION_PROHIBITED; + ix -> ad_add_info = strdup("Conversion of this message was prohibited"); + cont = FALSE; + default: + break; + } + chan = chan -> li_next; + } + } + ix = ix -> ad_next; + } + } + if (qp -> conversion_with_loss_prohibited == TRUE) { + ix = qp -> Raddress; + while (ix != NULLADDR) { + if (ix -> ad_status == AD_STAT_PEND + && ix -> ad_fmtchan != NULLIST_RCHAN) { + chan = ix -> ad_fmtchan; + cont = TRUE; + while (cont == TRUE + && chan != NULLIST_RCHAN) { + if (chan -> li_chan -> ch_conversion == CH_CONV_WITHLOSS) { + /* fail this recipient */ + ix -> ad_status = AD_STAT_DRREQUIRED; + ix -> ad_reason = DRR_UNABLE_TO_TRANSFER; + ix -> ad_diagnostic = DRD_CONVERSION_PROHIBITED; + ix -> ad_add_info = strdup("Conversion of this message would incur loss of information"); + cont = FALSE; + } + chan = chan -> li_next; + } + } + ix = ix -> ad_next; + } + } +} + + + + +/* --------------------- Static Routines -------------------------------- */ + + + + +static void check_rrinfo_crits (qp, dr, rr) +Q_struct *qp; +register DRmpdu *dr; +register Rrinfo *rr; +{ + char mask = CRITICAL_SUBMISSION; + ADDR *adr = qp -> Raddress; + CHAN *outchan; + X400_Extension *ix; + + while (adr != NULLADDR && adr -> ad_no != rr -> rr_recip) + adr = adr -> ad_next; + if (adr == NULLADDR) + return; + + /* --- *** --- + ad_outchan may be missing if msg is a x400 DR & its Recip is invalid + --- *** --- */ + + if (adr -> ad_outchan == NULLIST_RCHAN || + adr -> ad_outchan -> li_chan == NULLCHAN) + return; + + outchan = adr -> ad_outchan -> li_chan; + if (lexequ (outchan -> ch_content_out, cont_p22) == 0) + mask = mask | CRITICAL_TRANSFER | CRITICAL_DELIVERY; + else if (outchan -> ch_access == CH_MTS) + mask = mask | CRITICAL_DELIVERY; + + if (check_crit (dr -> dr_dl_history_crit, mask, qp, + adr, "dr_dl_history_crit") == NOTOK) + return; + if (check_crit (dr -> dr_reporting_dl_name_crit, mask, qp, + adr, "dr_reporting_dl_name_crit") == NOTOK) + return; + if (check_crit (dr -> dr_security_label_crit, mask, qp, + adr, "dr_security_label_crit") == NOTOK) + return; + if (check_crit (dr -> dr_reporting_mta_certificate_crit, mask, + qp, + adr, "dr_reporting_mta_certificate_crit") == NOTOK) + return; + if (check_crit (dr -> dr_report_origin_auth_check_crit, mask, qp, + adr, "dr_report_origin_auth_check_crit") == NOTOK) + return; + if (check_crit (rr -> rr_redirect_history_crit, mask, qp, + adr, "rr_redirect_history_crit") == NOTOK) + return; + if (check_crit (rr -> rr_physical_fwd_addr_crit, mask, qp, + adr, "rr_physical_fwd_addr_crit") == NOTOK) + return; + if (check_crit (rr -> rr_recip_certificate_crit, mask, qp, + adr, "rr_recip_certificate_crit") == NOTOK) + return; + if (check_crit (rr -> rr_report_origin_authentication_check_crit, + mask, qp, + adr, "rr_report_origin_authentication_check_crit") == NOTOK) + return; + + ix = rr -> rr_per_recip_extensions; + while (ix != NULL) { + if (check_crit (ix -> ext_criticality, CRITICAL_SUBMISSION, + qp, + adr, "rr_per_recip_extensions") == NOTOK) + return; + ix = ix -> ext_next; + } +} + + + + +static void check_q_crits (qp, adr) +register Q_struct *qp; +register ADDR *adr; +{ + char mask = CRITICAL_SUBMISSION; + CHAN *outchan = adr -> ad_outchan -> li_chan; + X400_Extension *ix; + + if (lexequ (outchan -> ch_content_out, cont_p22) == 0) + mask = mask | CRITICAL_TRANSFER | CRITICAL_DELIVERY; + else if (outchan -> ch_access == CH_MTS) + mask = mask | CRITICAL_DELIVERY; + + if (check_crit (qp -> latest_time_crit, mask, qp, + adr, "latest_time") == NOTOK) + return; + + if (check_crit(qp -> recip_reassign_crit, mask, qp, adr, + "recipient reassignment") == NOTOK) + return; + + if (check_crit (qp -> dl_expansion_crit, mask, qp, adr, + "dl expansion") == NOTOK) + return; + if (check_crit (qp -> conversion_with_loss_crit, mask, qp, + adr, "conversion_with_loss") == NOTOK) + return; + + if (check_crit (qp -> content_correlator_crit, mask, qp, adr, + "content_correlator") == NOTOK) + return; + + if (check_crit(qp -> originator_return_address_crit, mask, qp, + adr, "originator_return_address") == NOTOK) + return; + if (check_crit(qp -> forwarding_request_crit, mask, qp, adr, + "forwarding_request") == NOTOK) + return; + + if (check_crit(qp -> originator_certificate_crit, mask, qp, + adr, "originator_certificate") == NOTOK) + return; + + if (check_crit(qp -> algorithm_identifier_crit, mask, qp, + adr, "algorithm_identifier") == NOTOK) + return; + + if (check_crit(qp -> message_origin_auth_check_crit, mask, qp, + adr, "message_origin_auth_check") == NOTOK) + return; + if (check_crit(qp -> security_label_crit, mask, qp, adr, + "security_label") == NOTOK) + return; + + if (check_crit(qp -> proof_of_submission_crit, mask, qp, adr, + "proof_of_submission") == NOTOK) + return; + + if (check_crit (qp -> dl_expansion_history_crit, mask, qp, + adr, "dl_expansion_history") == NOTOK) + return; + + /* now do addr crits */ + if (check_crit( adr -> ad_orig_req_alt_crit, mask, qp, adr, + "ad_orig_req_alt") == NOTOK) + return; + + if (check_crit (adr -> ad_req_del_crit, mask, qp, adr, + "ad_req_del_crit") == NOTOK) + return; + + if (check_crit (adr -> ad_phys_forward_crit, mask, qp, adr, + "ad_phys_forward") == NOTOK) + return; + + if (check_crit (adr -> ad_phys_fw_ad_crit, mask, qp, adr, + "ad_phys_fw_ad") == NOTOK) + return; + + if (check_crit (adr -> ad_phys_modes_crit, mask, qp, adr, + "ad_phys_modes") == NOTOK) + return; + + if (check_crit (adr -> ad_reg_mail_type_crit, mask, qp, adr, + "ad_reg_mail_type") == NOTOK) + return; + + if (check_crit (adr -> ad_recip_number_for_advice_crit, mask, qp, + adr, "ad_recip_number_for_advice") == NOTOK) + return; + + if (check_crit (adr -> ad_phys_rendition_attribs_crit, mask, qp, + adr, "ad_phys_rendition_attribs") == NOTOK) + return; + + if (check_crit (adr -> ad_pd_report_request_crit, mask, qp, + adr, "ad_pd_report_request") == NOTOK) + return; + + if (check_crit (adr -> ad_redirection_history_crit, mask, qp, + adr, "ad_redirection_history") == NOTOK) + return; + + if (check_crit (adr -> ad_message_token_crit, mask, qp, adr, + "ad_message_token") == NOTOK) + return; + + if (check_crit (adr -> ad_content_integrity_crit, mask, qp, + adr, "ad_content_integrity") == NOTOK) + return; + + if (check_crit (adr -> ad_proof_delivery_crit, mask, qp, adr, + "ad_proof_delivery") == NOTOK) + return; + + ix = adr -> ad_per_recip_ext_list; + while (ix != NULL) { + if (check_crit (ix -> ext_criticality, CRITICAL_SUBMISSION, qp, + adr, "ad_per_recip_ext") == NOTOK) + return; + ix = ix -> ext_next; + } + +} + + + + +static void check_extn_crits (qp, ix, buf) +Q_struct *qp; +register X400_Extension *ix; +char *buf; +{ + while (ix != NULL) { + if (check_crit(ix -> ext_criticality, CRITICAL_SUBMISSION, + qp, NULLADDR, buf) == NOTOK) + return; + ix = ix -> ext_next; + } +} + +void check_report_level (qp) +Q_struct *qp; +{ + /* see x.411 12.2.1.1.18 */ + ADDR *ix; + + /* bad code relies on having same mapping into integers */ + /* see adr.h usrreq and mtareq declarations */ + + for (ix = qp->Raddress; ix; ix = ix -> ad_next) + if (ix -> ad_mtarreq < ix -> ad_usrreq) + ix -> ad_mtarreq = ix -> ad_usrreq; +} + +static CHAN *getsplitter () +{ + register CHAN *spltr, **chp; + + for (chp = ch_all; + (spltr = *chp) != NULLCHAN; + chp++) + if (spltr -> ch_chan_type == CH_SPLITTER) + return spltr; + return NULLCHAN; +} + +static int must_solo_proc(ad) +register ADDR *ad; +{ + register LIST_RCHAN *ix; + if (!ad->ad_resp) + return FALSE; + + if (ad->ad_outchan + && ad->ad_outchan->li_chan + && ad->ad_outchan->li_chan->ch_solo_proc == YES) + return TRUE; + + for (ix = ad->ad_fmtchan; ix != NULLIST_RCHAN; ix = ix -> li_next) + if (ix -> li_chan + && ix -> li_chan -> ch_solo_proc == YES) + return TRUE; + return FALSE; +} + +static void replace_with_splitter (ad, spltr) +register ADDR *ad; +CHAN *spltr; +{ + list_rchan_free (ad->ad_fmtchan); + ad->ad_fmtchan = NULLIST_RCHAN; + ad->ad_outchan->li_chan = spltr; + if (ad->ad_outchan->li_auth + && ad->ad_outchan->li_auth->chan) + ad->ad_outchan->li_auth->chan->li_chan = spltr; +} + +void check_splitter (qp) +Q_struct *qp; +{ + CHAN *spltr; + register ADDR *ix; + int count; + if ((spltr = getsplitter()) == NULLCHAN) + return; + + for (count = 0, ix = qp->Raddress; + ix != NULLADDR && count < 2; + ix = ix -> ad_next) + if (must_solo_proc (ix) == TRUE) + count++; + + if (count < 2) + return; + + /* have to replace some with splitter */ + + for (ix = qp->Raddress; + ix != NULLADDR; + ix = ix -> ad_next) { + if (must_solo_proc (ix) == TRUE) + replace_with_splitter(ix, spltr); + } +} + + diff --git a/Src/submit/submit_mgt.c b/Src/submit/submit_mgt.c new file mode 100644 index 0000000..447da95 --- /dev/null +++ b/Src/submit/submit_mgt.c @@ -0,0 +1,336 @@ +/* submit_mgt.c: management stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_mgt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_mgt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_mgt.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "dr.h" +#include "ap.h" +#include + +/* -- externals -- */ +extern int max_hops, max_loops; +extern time_t time(); +extern int privileged; +extern int return_interval_norm, + return_interval_low, + return_interval_high, + warn_interval; +extern int accept_all; +extern int notrace; +extern char *loc_dom_site, *loc_dom_mta, + *ia5_bp, *hdr_822_bp, + io_fpart[]; + +/* -- globals -- */ +CHAN *ch_inbound; +char *mgt_inhost; +int mgt_adtype = AD_822_TYPE; +extern void message_failure(); +extern void rd_rfchdr (); +extern void pro_reply (); +extern void err_abrt (); + + +/* -- local routines -- */ +int cntrl_mgt(); +int q_mgt(); +void message_failure(); +void msg_mgt(); +void time_mgt(); +void txt_mgt(); + +static void tracecheck_mgt(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int cntrl_mgt (prm, qp) +register struct prm_vars *prm; +register Q_struct *qp; +{ + CHAN *ch_in; + + PP_TRACE (("submit/cntrl_mgt (type = %d)", mgt_adtype)); + + accept_all = (prm -> prm_opts & PRM_ACCEPTALL) == PRM_ACCEPTALL; + notrace = (prm -> prm_opts & PRM_NOTRACE) == PRM_NOTRACE; + + /* -- what incomming channel is calling submit -- */ + + if (qp -> inbound == NULL || + (ch_inbound = ch_in = qp -> inbound -> li_chan) == NULLCHAN) + err_abrt (RP_MECH, "No channel given"); + + if (ch_in -> ch_access == CH_MTA) { + if (!privileged) + err_abrt (RP_USER, "Privileged channel"); + } + if (ch_in -> ch_chan_type != CH_BOTH && + ch_in -> ch_chan_type != CH_IN && + ch_in -> ch_chan_type != CH_WARNING) + err_abrt (RP_MECH, "Channel %s not inbound", + ch_in -> ch_name); + + if (ch_in -> ch_in_ad_subtype == AD_JNT + || ch_in -> ch_in_ad_subtype == AD_REAL733) + ap_use_percent(); + + if (ch_in -> ch_domain_norm == CH_DOMAIN_NORM_ALL) + ap_norm_all_domains(); + else + ap_norm_first_domain(); + + if ((mgt_inhost = qp -> inbound -> li_mta) == NULLCP) { + mgt_inhost = loc_dom_site; + } else { + char official[LINESIZE], *subdom; + + /* normalise inbound mta */ + if (tb_getdomain (mgt_inhost, NULLCP, official, + ch_in -> ch_ad_order, + &subdom) == OK + && official[0]) { + free(qp->inbound->li_mta); + mgt_inhost = qp->inbound->li_mta = strdup(official); + } + if (subdom != NULLCP) free (subdom); + } + + mgt_adtype = ch_in -> ch_in_ad_type; + + if (mgt_adtype == AD_822_TYPE) { + qp -> content_return_request = TRUE; + /* to cope with possible 1148 conversion */ + qp -> alternate_recip_allowed = TRUE; + } + + PP_TRACE (("submit/cntrl_mgt (type='%d', order='%d')", + mgt_adtype, ch_in -> ch_ad_order)); + + return (RP_OK); +} + + + +static void hdr_eit_swap (eits, hdrs) +LIST_BPT *eits; +LIST_BPT *hdrs; +{ + LIST_BPT *eits_ix, *hdrs_ix; + int cont; + + for (eits_ix = eits; + eits_ix != NULLIST_BPT; + eits_ix = eits_ix -> li_next) { + cont = TRUE; + for (hdrs_ix = hdrs; + hdrs_ix != NULLIST_BPT && cont == TRUE; + hdrs_ix = hdrs_ix -> li_next) { + if (lexnequ(eits_ix->li_name, + hdrs_ix->li_name, + strlen(eits_ix->li_name)) == 0 + && (int) strlen(eits_ix->li_name) < (int) strlen(hdrs_ix->li_name)) { + /* prefix and swap */ + free (eits_ix->li_name); + eits_ix->li_name = strdup(hdrs_ix->li_name); + cont = FALSE; + } + } + } +} + + +int q_mgt (qp) +register Q_struct *qp; +{ + PP_TRACE (("submit/q_mgt (qp)")); + + /* -- generate a submit-event-id -- */ + if (mgt_adtype == AD_822_TYPE || + qp -> msgid.mpduid_string == NULLCP) + MPDUid_new (&qp -> msgid); + + /* -- add trace info -- */ + trace_add (&qp -> trace, trace_new()); + + if (qp -> retinterval == 0) { + switch (qp -> priority) { + case PRIO_URGENT: + qp -> retinterval = return_interval_high; + break; + case PRIO_NONURGENT: + qp -> retinterval = return_interval_low; + break; + default: + qp -> retinterval = return_interval_norm; + break; + } + } + if (qp -> warninterval == 0) + qp -> warninterval = warn_interval; + + /* -- override hdr eits that lexnequ to those specified + in inbound channel */ + hdr_eit_swap(qp->encodedinfo.eit_types, + qp->inbound->li_chan->ch_hdr_in); + return (RP_OK); +} + + + + +void time_mgt(qp) +Q_struct *qp; +{ + time_t then, now; + char buf[BUFSIZ]; + + if (qp -> latest_time != NULLUTC) { + then = utc2time_t(qp -> latest_time); + (void) time(&now); + if (then < now) { + (void) sprintf (buf, + "This message's latest time has been exceeded"); + message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_MAX_TIME_EXPIRED, + buf); + } + } +} + + + + +void msg_mgt() +{ + PP_TRACE (("submit/msg_mgt()")); + ch_inbound = NULLCHAN; + mgt_inhost = NULLCP; +} + + + + +void txt_mgt(qp) /* -- management tasks on the input text -- */ +Q_struct *qp; +{ + PP_TRACE (("submit/txt_mgt()")); + + + /* -- if its an 822 body, check it's parts -- */ + if (qp -> msgtype == MT_UMPDU && + list_bpt_nfind (qp -> encodedinfo.eit_types, + hdr_822_bp, + strlen(hdr_822_bp)) != NULLIST_BPT) { + if (isnull (*io_fpart)) + err_abrt (RP_MECH, "Help - lost io_part"); + rd_rfchdr (io_fpart); + } + if (qp -> encodedinfo.eit_types == NULLIST_BPT) { + qp -> encodedinfo.eit_types = + list_bpt_dup (qp -> orig_encodedinfo.eit_types); + hdr_eit_swap(qp->encodedinfo.eit_types, + qp->inbound->li_chan->ch_hdr_in); + } + /* -- check for trace looping -- */ + tracecheck_mgt(qp); + /* -- currently ok -- */ + pro_reply (RP_OK, "text input successful"); +} + + + + +void message_failure (reason, diag, str) +int reason, diag; +char *str; +{ + ADDR *ap, *apf = NULLADDR; + extern ADDR *ad_recip; + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + if (ap -> ad_resp == FALSE) + continue; + if (ap -> ad_status != AD_STAT_PEND) + continue; + if (apf == NULLADDR) + apf = ap; + ap -> ad_status = AD_STAT_DRREQUIRED; + } + if (apf) { + apf -> ad_reason = reason; + apf -> ad_diagnostic = diag; + apf -> ad_add_info = strdup (str); + } +} + + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static void tracecheck_mgt (qp) +Q_struct *qp; +{ + register Trace *tp; + int nhops = 0, first = 0; + char buf[BUFSIZ]; + PP_TRACE (("submit/tracecheck_mgt (qp)")); + + for (tp = qp -> trace; tp != NULL; tp = tp -> trace_next) { + /* -- too many hops -- */ + + if (++nhops > max_hops) { + (void) sprintf (buf, + "%s%s %d", + "This Message has travelled a long time, ", + "there are too many Trace hops", nhops); + message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_LOOP_DETECTED, buf); + PP_LOG(LLOG_EXCEPTIONS, + ("%s", buf)); + return; + } + + if (tp -> trace_mta != NULLCP) { + /* can only check against those with mta specified */ + if (lexequ(tp -> trace_mta, loc_dom_mta) == 0) { + if (first >= max_loops) { + (void) sprintf (buf, "%s%s", + "A loop has been detected in the Trace at ", + "field for this Message"); + PP_LOG(LLOG_EXCEPTIONS, + ("tracecheck_mgt(%s)", buf)); + message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_LOOP_DETECTED, buf); + return; + } else + first++; + } + } + } +} diff --git a/Src/submit/submit_prm.c b/Src/submit/submit_prm.c new file mode 100644 index 0000000..a58fc8f --- /dev/null +++ b/Src/submit/submit_prm.c @@ -0,0 +1,77 @@ +/* submit_prm.c: read and process control switches */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_prm.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_prm.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_prm.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" + + +extern void err_abrt(); + + +/* -- local routines -- */ +int rd_prm_info(); +int rd_q_info(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int rd_prm_info (prm) /* -- read in a prm management structure -- */ +struct prm_vars *prm; +{ + int retval; + + PP_TRACE (("submit/rd_prm_info (prm)")); + + if (rp_isbad (retval = rd_prm (prm, stdin))) { + switch (retval) { + case RP_EOF: + break; + case RP_PARM: + err_abrt (RP_PARM, "Aborting message"); + } + } + return (retval); +} + + + + +int rd_q_info (qp) /* -- read in a queue structure -- */ +register Q_struct *qp; +{ + int retval; + + PP_TRACE (("submit/rd_q_info (qp)")); + + if (rp_isbad (retval = rd_q (qp, stdin))) { + switch (retval) { + case RP_EOF: + err_abrt (RP_EOF, "Can't read qstruct"); + break; + case RP_PARM: + err_abrt (RP_PARM, "Aborting message"); + break; + } + } + return (retval); +} diff --git a/Src/submit/submit_que.c b/Src/submit/submit_que.c new file mode 100644 index 0000000..0c9e771 --- /dev/null +++ b/Src/submit/submit_que.c @@ -0,0 +1,359 @@ +/* submit_que.c: store messages in the queue */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_que.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_que.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_que.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include "adr.h" +#include +#if defined(sun) || defined(SYS5) +#ifdef vfork +#undef vfork +#endif +#include +#endif +#include "sys.file.h" +#include + + +extern UTC time_t2utc(); +extern void err_abrt(); +extern long msg_size; +extern char *quedfldir; +extern char *aquefile; /* addr file */ +extern char *bquedir; /* Q/msg/msg.XXX/base dir */ +extern int queue_depth; +extern int queue_fanout; +extern int errno; +extern int disk_blocks, disk_percent; + +/* -- globals -- */ +char *msg_basedir; /* full pathname to bquedir */ +char *msg_unique; /* unique-part of Q/msg file name */ +char msg_fullpath[MAXPATHLENGTH]; /* full pathname to msg */ +static char *ad_file; /* the (temp) addr file */ + + +/* -- static variables -- */ +static FILE *ad_ffp; /* file pointer to address file */ + +/* -- local routines -- */ +void clear_q(); +int move_q(); +int winit_q(); +int write_q(); +static int make_temp(); +static void make_hier_queue (); +static void make_missing_dirs (); + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +/* -- initialise system to write a message into the queue. -- */ +int winit_q(rp) +RP_Buf *rp; +{ + char buf[MAXPATHLENGTH]; + char addition[BUFSIZ]; + + PP_TRACE (("submit/winit_q()")); + + (void) strcpy (msg_fullpath, quedfldir); + (void) strcat (msg_fullpath, "/"); + msg_unique = msg_fullpath + strlen (msg_fullpath); + if (queue_depth > 0) + make_hier_queue (addition); + if (make_temp (msg_unique, queue_depth > 0 ? addition : NULLCP, + msg_fullpath) == NOTOK) + return rplose (rp, RP_FCRT, "Can't create a unique Q file"); + + if (ad_file) + free (ad_file); + (void) sprintf (buf, "%s/%s.X", msg_fullpath, aquefile); + ad_file = strdup (buf); + + if ((ad_ffp = fopen (ad_file, "w")) == NULL) + rplose (rp, RP_FOPN, "Can't access text Q file %s", buf); + + (void) sprintf (buf, "%s/%s", msg_fullpath, bquedir); + msg_basedir = strdup (buf); + + if (fdiskfull (fileno(ad_ffp), disk_blocks, disk_percent) == NOTOK) { + (void) fclose (ad_ffp); + return rplose (rp, RP_FIO, "Disk usgae limit exceeded"); + } + return RP_OK; +} + +int move_q (rp) +RP_Buf *rp; +{ + char tfile[MAXPATHLENGTH]; + + (void) sprintf (tfile, "%s/%s", msg_fullpath, aquefile); + PP_TRACE (("Renames %s to %s", ad_file, tfile)); + if (rename (ad_file, tfile) == NOTOK) + return rplose (rp, RP_FCRT, "Can't rename %s to %s", + ad_file, tfile); + free (ad_file); + ad_file = NULLCP; + return RP_OK; +} + + + + +int write_q (qp, pr, rp) +register Q_struct *qp; +register struct prm_vars *pr; +RP_Buf *rp; +{ + int retval; + ADDR *ap; + + PP_TRACE (("submit/write_q (qp,pr)")); + + if (qp->msgsize == NULL) + qp->msgsize = msg_size; + + if (qp->queuetime == 0) + qp->queuetime = utcnow (); + + if (pr -> prm_opts) + pr -> prm_opts = PRM_NONE; + if (pr -> prm_passwd) { + free (pr -> prm_passwd); + pr -> prm_passwd = NULLCP; + } + + retval = wr_prm (pr, ad_ffp); + if (rp_isbad (retval)) + goto bad; + + retval = wr_q (qp, ad_ffp); + if (rp_isbad (retval)) + goto bad; + + retval = wr_adr (qp->Oaddress, ad_ffp, AD_ORIGINATOR); + if (rp_isbad (retval)) + goto bad; + + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) { + retval = wr_adr (ap, ad_ffp, AD_RECIPIENT); + if (rp_isbad (retval)) + goto bad; + } + + if (check_close (ad_ffp) == NOTOK) + err_abrt (RP_FIO, "Error writing address file"); + ad_ffp = NULLFILE; + return RP_OK; + +bad: + return rplose (rp, RP_FIO, "Error writing to q file"); +} + + + + +/* -- in case of error, zap all the work thats been done. -- */ +void clear_q() +{ + PP_TRACE (("clear_q ()")); + (void) txt_tend(); + if (ad_ffp != NULLFILE) { /* address file */ + (void) fclose (ad_ffp); + ad_ffp = NULLFILE; + } + if (ad_file) { + (void) recrm (msg_fullpath); + if(rmdir (msg_fullpath)) + PP_SLOG (LLOG_EXCEPTIONS, msg_fullpath, + ("failed to remove directory")); + else + PP_NOTICE(("Cleanup - zapped %s", msg_fullpath)); + } +} + + + + +/* --------------------- Static Routines ------------------------------- */ + +static int mypid = 0; + +static void make_missing_dirs (base, seper) +char *base; +char *seper; +{ + char buf[BUFSIZ]; + char *p; + + (void) strcpy (buf, base); + p = buf + strlen (buf); + (void) strcpy (p, seper); + + while ((p = index(p, '/')) != NULL) { + *p = '\0'; + if (mkdir(buf, 0777) == NOTOK && errno != EEXIST) { + *p = '/'; + err_abrt (RP_FIO, "Can't create directory %s", + buf); + } + *p = '/'; + p++; + } +} +#ifndef BSD42 +#define random rand +#define srandom srand +#endif + +static void make_hier_queue (buf) +char *buf; +{ + char *p; + static int init = 0; + int i; + + if (init == 0) { + if (mypid == 0) + mypid = getpid (); + srandom (mypid); + init = 1; + } + + p = buf; + for (i = 0; i < queue_depth; i++) { + (void) sprintf (p, "%d/", random() % queue_fanout); + p += strlen(p); + } +} + +/* + * mktemp gives up too easily - this ones goes on forever + * I think we'll run out of inodes long before this fails... + */ + + +static int make_temp (unique, seper, base) +char *base; +char *seper; +char *unique; +{ + static long tries = 0; + int made_dirs = 0; + + if (mypid == 0) mypid = getpid (); + + for (; tries < 32000; tries ++) { + if (seper) + (void) sprintf (unique, "%smsg.%05d-%d", + seper, mypid, tries); + else + (void) sprintf (unique, "msg.%05d-%d", + mypid, tries); + + if (mkdir (base, 0777) == OK) + return OK; + else if (seper && !made_dirs) { + tries --; /* try again after we created missing dirs */ + made_dirs = 1; + unique[0] = '\0'; + make_missing_dirs (base, seper); + } + + } + return NOTOK; +} + +static struct matrix_tbl { + char *name; + char *key; + char *directory; + int no; + struct matrix_tbl *m_next; +} *MTbl; + +static char *do_table (str, name) +char *str, *name; +{ + struct matrix_tbl **mp, *m; + int maxkeyno = 1; + char buf[BUFSIZ]; + + for (mp = &MTbl; + (m = *mp) != (struct matrix_tbl *) NULL; + mp = &(*mp) -> m_next) { + if (strcmp(m -> name, str) == 0) + return strdup(m -> directory); + else if (strcmp (m -> key, name) == 0) { + if (m -> no >= maxkeyno) + maxkeyno = m -> no + 1; + } + } + m = *mp = (struct matrix_tbl *) smalloc(sizeof **mp); + m -> name = strdup (str); + m -> key = strdup(name); + m -> no = maxkeyno; + (void) sprintf (buf, "%s.%d", name, maxkeyno); + m -> directory = strdup (buf); + m -> m_next = NULL; + return strdup (m -> directory); +} + +void free_table (mp) +struct matrix_tbl *mp; +{ + if (mp == (struct matrix_tbl *) NULL) + return; + if (mp -> name) free (mp -> name); + if (mp -> key) free (mp -> key); + if (mp -> directory) free (mp -> directory); + if (mp -> m_next) free_table(mp -> m_next); + free ((char *)mp); +} + +do_dirs (ap) +ADDR *ap; +{ + char buf[BUFSIZ]; + LIST_RCHAN *fmt; + + buf[0] = 0; + for (fmt = ap -> ad_fmtchan; fmt; fmt = fmt -> li_next) { + (void) strcat (buf, "/"); + (void) strcat (buf, fmt -> li_chan -> ch_name); + fmt -> li_dir = do_table (buf, fmt -> li_chan -> ch_name); + } +} + +setup_directories (qp) +Q_struct *qp; +{ + ADDR *ap; + do_dirs (qp -> Oaddress); + for (ap = qp -> Raddress; ap; ap = ap -> ad_next) + do_dirs (ap); + + free_table (MTbl); + MTbl = NULL; +} diff --git a/Src/submit/submit_srvr.c b/Src/submit/submit_srvr.c new file mode 100644 index 0000000..0601c81 --- /dev/null +++ b/Src/submit/submit_srvr.c @@ -0,0 +1,162 @@ +/* submit_srvr.c: submit running as a server */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_srvr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_srvr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_srvr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include +#include +#include +#include + +extern char *submit_addr; +extern int errno; + +#ifdef BSD42 +#include + +/* ARGSUSED */ +static SFD reaper (sig) +int sig; +{ + union wait status; + + while (wait3 (&status, WNOHANG, (struct rusage *)0) > 0) + continue; +} +#endif + +int server_start (host, statusp) +char *host; +int *statusp; +{ + struct servent *sp; + u_short port; + int sd; + struct sockaddr_in s_in; + int newsd, qfd; + int argc; + char *argv[20]; + char *subp; + + argc = sstr2arg (submit_addr, 50, argv, ","); + if (argc <= 0 || (subp = index(argv[0], ':')) == NULL) { + PP_OPER (NULLCP, ("Bad submit port specification")); + exit (1); + } + *subp ++ = '\0'; + + if (isdigit (*subp)) + port = htons ((u_short)atoi(subp)); + else if ((sp = getservbyname (subp, "tcp")) != NULL) + port = sp -> s_port; + else { + PP_OPER (NULLCP, ("Can't locate port %s", subp)); + exit (1); + } + if (tryfork ()) exit(0); + if ((sd = open ("/dev/null", O_RDWR)) != NOTOK) { + if (sd != 0) + (void) dup2 (sd, 0), (void) close (sd); + (void) dup2 (0, 1); + (void) dup2 (0, 2); + } +#ifdef SETSID + (void) setsid (); +#endif +#ifdef TIOCNOTTY +{ int i; + if ((i = open ("/dev/tty", O_RDWR)) != NOTOK) { + (void) ioctl (i, TIOCNOTTY, NULLCP); + (void) close (i); + } +} +#else +#ifdef SYS5 + (void) setpgrp (); + (void) signal (SIGINT, SIG_IGN); + (void) signal (SIGQUIT, SIG_IGN); +#endif +#endif + isodexport (NULLCP); /* re-initialize logfiles */ + + if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) { + PP_OPER ("socket", ("Can't create ")); + exit (1); + } + + bzero ((char *)&s_in, sizeof s_in); + s_in.sin_family = AF_INET; + s_in.sin_port = port; + + if (bind (sd, (struct sockaddr *)&s_in, sizeof s_in) == NOTOK || + listen(sd, 5) == NOTOK) { + PP_OPER ("bind/listen", ("failed to ")); + exit (1); + } + +#ifdef BSD42 + (void) signal (SIGCHLD, reaper); +#else + (void) signal (SIGCLD, SIG_IGN); +#endif + + PP_NOTICE (("Submit started")); + for (;;) { + struct tsapblk *tb; + qfd = qmgr_start (host, statusp, 0); + + PP_TRACE (("qmgr on ad %d, status = %d", qfd, *statusp)); + while ((newsd = accept (sd, (struct sockaddr *)0, NULLIP)) == NOTOK) { + if (errno != EINTR) { + PP_SLOG (LLOG_EXCEPTIONS, "accept", + ("problem with")); + sleep (1); + } + } + PP_TRACE (("new association on %d", newsd)); + switch (tryfork()) { + case NOTOK: + (void) close (newsd); + break; + + case 0: /* child */ + isodexport (NULLCP); + (void) dup2 (newsd, 0); + (void) dup2 (newsd, 1); + (void) close (newsd); + (void) close (sd); + ll_close (pp_log_stat); + ll_close (pp_log_oper); + ll_close (pp_log_norm); + return qfd; + + default: + if ((tb = findtblk (qfd)) != (struct tsapblk *) NULL) { + if ((*tb -> tb_closefnx) (tb -> tb_fd) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, + ("close failed on %d", + tb -> tb_fd)); + + PP_TRACE (("Closed qmgr %d", tb -> tb_fd)); + tb -> tb_fd = NOTOK; + freetblk (tb); + } + if (close (newsd) == NOTOK) + PP_LOG (LLOG_EXCEPTIONS, ("close failed on %d", + newsd)); + PP_TRACE (("Closed newsd %d", newsd)); + break; + } + } +} diff --git a/Src/submit/submit_txt.c b/Src/submit/submit_txt.c new file mode 100644 index 0000000..1814a19 --- /dev/null +++ b/Src/submit/submit_txt.c @@ -0,0 +1,489 @@ +/* submit_txt.c: handles the bodies of the messages */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_txt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/submit_txt.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: submit_txt.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "list_bpt.h" +#include "q.h" +#include "chan.h" +#include +#include +#include + + +extern LIST_BPT *bodies_all, *headers_all; +extern int privileged; +extern char *loc_dom_mta; +extern char *mgt_inhost; +extern char *msg_basedir; +extern char *msg_unique; +extern char *cont_p2; +extern char *cont_p22; +extern int submit_debug; +extern char msg_fullpath[]; +extern void pro_reply (); +extern void txt_mgt (), err_abrt(); + + +/* -- globals -- */ +char io_fpart[MAXPATHLENGTH]; +long msg_size; +int numBps; +int forwMsg; + +/* -- static variables -- */ +static FILE *io_ofp; /* -- output -- */ +static int io_linkpart; /* -- linked part so no txt copy -- */ +static char *io_ostrend; +static char io_tfname[MAXPATHLENGTH]; + + +/* -- local routines -- */ +int txt_tend(); +int txt_init(); +void txt_input(); +static int txt_bptfind(); +static int txt_pend(); +static int txt_pinit(); +static int txt_read(); +static void txt_bp_check(); +static void txt_in(); +static void txt_via(); +static void txt_in_debug(); + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void txt_input (qp, addvia) /* -- control the text -- */ +Q_struct *qp; +int addvia; +{ + int retval, + nparts = 0, + first = TRUE; + char lbuf[BUFSIZ]; + + PP_TRACE (("txt_input()")); + + /* -- set up to recieve text -- */ + if (rp_isbad (retval = txt_read (lbuf))) + err_abrt (retval, "Protocol failure"); + + if ((retval = txt_init(qp)) != RP_OK) + err_abrt (retval, "Text initialisation"); + + pro_reply (RP_OK, "base %s", io_tfname); + + while ((retval = txt_pinit(qp)) == RP_OK) { + PP_TRACE (("text loop")); + /* -- add 822 trace -- */ + if (first && !io_linkpart && addvia) + txt_via (qp, io_ofp); + first = FALSE; + nparts++; + if (io_linkpart) + continue; + if (submit_debug) + txt_in_debug (); + else + txt_in(); + if ((retval = txt_pend()) != RP_OK) + err_abrt (retval, "Text ending"); + } + + if (rp_isbad (txt_tend())) + retval = RP_MECH; + + if (retval != RP_DONE) + err_abrt (RP_MECH, "Unknown error in txt_input"); + + txt_mgt(qp); +} + + + + +int txt_tend() /* -- finally finish -- */ +{ + PP_TRACE (("txt_tend()")); + + if (io_ofp != NULLFILE) { + if(check_close (io_ofp) == NOTOK) + return RP_MECH; + io_ofp = NULLFILE; + } + + if (isstr (io_ostrend)) + * (io_ostrend - 1) = '\0'; + return RP_OK; +} + + + + +/* ---------------------- Static Routines -------------------------------- */ + + + + +int txt_init(qp) +Q_struct *qp; +{ + + PP_TRACE (("txt_init ('%s', '%s')", msg_fullpath, msg_basedir)); + + io_linkpart = FALSE; + *io_fpart = '\0'; + msg_size = 0; + qp -> msgsize = 0; + numBps = 0; + forwMsg = 0; + + if (mkdir (msg_basedir, 0777) < 0) + err_abrt (RP_FIO, "Cannot create base dir %s", msg_basedir); + + (void) strcpy (io_tfname, msg_basedir); + (void) strcat (io_tfname, "/"); + + /* -- make io_ostrend point to the end of the string. -- */ + io_ostrend = io_tfname + strlen (io_tfname); + io_ofp = NULLFILE; + + return (RP_OK); +} + + + + +/* -- initialise for reading a single part of a msg -- */ +static int txt_pinit(qp) +Q_struct *qp; +{ + char lbuf[LINESIZE], + *splt; + int retval; + + PP_DBG (("txt_pinit (%s)", io_tfname)); + + io_linkpart = FALSE; /* -- reset -- */ + + if (rp_isbad (retval = txt_read (lbuf))) + return (retval); + + if (lbuf[0] == '\0') + return (RP_DONE); + + if ((splt = index (lbuf, ' ')) != NULL) { + *splt++ = '\0'; + io_linkpart = TRUE; + if (!privileged) + err_abrt (RP_USER, "Mortals cannot link"); + } + + if(rp_isbad (retval = txt_psetup (qp, lbuf, splt))) + return retval; + + if (io_linkpart) + pro_reply (RP_OK, "linked the files"); + else + pro_reply (RP_OK, "file is '%s'", io_tfname); + + return (RP_OK); +} + +int txt_psetup (qp, bp, linkfile) +Q_struct *qp; +char *bp, *linkfile; +{ + char *p; + struct stat statbuf; + int fd; + + txt_bp_check (qp, bp); + + (void) strcpy (io_ostrend, bp); + + /* make relevant directories */ + for (p = io_ostrend; (p = index (p, '/')) != NULL; p++) { + *p = '\0'; + (void) mkdir (io_tfname, 0777); + *p = '/'; + } + + + if (io_linkpart) { + if (link (linkfile, io_tfname) < 0) + err_abrt (RP_FIO, "Cannot link file '%s' to '%s'", + linkfile, io_tfname); + + if (*io_fpart == '\0') + (void) strcpy (io_fpart, io_tfname); + + /* -- check message size -- */ + if (stat (io_tfname, &statbuf) >= 0) + msg_size += statbuf.st_size; + return (RP_OK); + } + + + if ((fd = open (io_tfname, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) + err_abrt (RP_FIO, "Can't create file '%s'", io_tfname); + + + if ((io_ofp = fdopen (fd, "w")) == NULLFILE) { + (void) close (fd); + (void) unlink (io_tfname); + *io_tfname = '\0'; + err_abrt (RP_FIO, "cannot open io_tfname"); + } + + + if (*io_fpart == '\0') + (void) strcpy (io_fpart, io_tfname); + return RP_OK; +} + + + + +static int txt_pend() /* -- end of the text input part -- */ +{ + int retval; + PP_TRACE (("txt_pend()")); + + if (rp_isbad (retval = txt_pfinish ())) + return retval; + pro_reply (RP_OK, "got this text part"); + + return (RP_OK); +} + +int txt_pfinish () +{ + if (check_close (io_ofp) == NOTOK) + err_abrt (RP_FIO, "Can't write text to disk"); + io_ofp = NULLFILE; + return RP_OK; +} + + +static void txt_in() /* -- input the text -- */ +{ + long datalen; + long len; + char buf[BUFSIZ]; + + PP_TRACE (("txt_in()")); + + while ((int)fread ((char *)&datalen, sizeof (datalen), 1, stdin) > 0) { + datalen = ntohl (datalen); + if ((len = datalen) == 0) + return; + while (len > 0) { + int dlen, nc; + + dlen = len < sizeof (buf) ? len : sizeof (buf); + nc = fread (buf, sizeof (buf[0]), dlen, stdin); + if (nc <= 0) + err_abrt (RP_FIO, "Read error"); + if (rp_isbad(txt_write (buf, nc))) + err_abrt (RP_FIO, "Data copy failed"); + len -= nc; + } + PP_DBG (("submit/txt_in copied %d bytes",datalen)); + } +} + +int txt_write (bp, nc) +char *bp; +int nc; +{ + msg_size += nc; + if (fwrite (bp, sizeof (*bp), nc, io_ofp) != nc) + return RP_FIO; + return RP_OK; +} + + +static int txt_from_file (file) +char *file; +{ + char *cp; + FILE *fp; + char buf[BUFSIZ]; + int n; + + file ++; + if ((cp = index(file, '\n')) != NULLCP) + *cp = 0; + if ((fp = fopen (file, "r")) == NULL) { + PP_LOG (LLOG_EXCEPTIONS, ("No such file %s", file)); + return NOTOK; + } + + while ((n = fread (buf, 1, sizeof buf, fp)) > 0) + if (rp_isbad (txt_write (buf, n))) + err_abrt (RP_FIO, "Copy failed"); + return OK; +} + +static void txt_in_debug () /* -- input the text -- */ +{ + char buf[BUFSIZ]; + int n; + int first = 1; + PP_TRACE (("txt_in_debug ()")); + + while (fgets (buf, sizeof buf, stdin) && strcmp(buf, ".\n") != 0) { + if (first && *buf == '<' && txt_from_file(buf) == OK) + return; + first = 0; + msg_size += n = strlen(buf); + if (rp_isbad(txt_write (buf, n))) + err_abrt (RP_FIO, "data copy failed"); + } +} + +static int txt_read (buf) /* -- read the control flow -- */ +char *buf; +{ + register int c; + register char *p; + + PP_TRACE (("txt_read()")); + for (p = buf; (c = getc (stdin)) != EOF && c != '\n'; *p++ = c) + continue; + *p = '\0'; + PP_DBG (("text_read - read '%.10s'", buf)); + return ((c == EOF) ? RP_EOF : RP_OK); +} + + + + +static void txt_via (qp, fp) +Q_struct *qp; +FILE *fp; +{ + char buf[BUFSIZ]; + char thedate[LINESIZE]; + char showstr[BUFSIZ]; + UTC ut, lt; + extern UTC utclocalise(); + CHAN *ch_in; + + ut = utcnow(); + lt = utclocalise(ut); + (void) UTC2rfc(lt, thedate); + free ((char *)ut); + free ((char *)lt); + + ch_in = qp -> inbound -> li_chan; + + if (ch_in -> ch_trace_type == CH_TRACE_VIA) + (void) sprintf (buf, "Via: %s; %s\n", + loc_dom_mta, thedate); + else { + if ( ch_in -> ch_show && + (strncmp (ch_in -> ch_show, "via", 3) == 0 + || strncmp (ch_in -> ch_show, "with", 4) == 0)) { + (void) strcpy (showstr, " "); + (void) strcat (showstr, ch_in -> ch_show); + } + else showstr[0] = '\0'; + + (void) sprintf (buf, "Received: from %s by %s%s id <%s@%s>; %s\n", + mgt_inhost, loc_dom_mta, + showstr, + msg_unique + 4, loc_dom_mta, + thedate); + } + fputs (buf, fp); +} + + + + +static void txt_bp_check (qp, file) +Q_struct *qp; +char *file; +{ + char *p; + + if (*file == '/') + err_abrt (RP_PARM, "File has full pathname %s", file); + + if ((p = index (file, '/')) != NULLCP) { + if (!isdigit (*file) || strncmp (p - 4, ".ipm", 4) != 0) + err_abrt (RP_PARM, "Not a forwarded message %s", file); + txt_bp_check (qp, ++p); + forwMsg++; + return; + } + + + /* -- check against content types -- */ + if (strcmp (file, cont_p2) == 0 + || strcmp (file, cont_p22) == 0 + || (isstr(qp->cont_type) && strcmp (file, qp->cont_type) == 0)) + return; + + if (isdigit (*file)) { + for (p = file + 1; isdigit (*p); p++) + continue; + if (*p != '.') + err_abrt (RP_PARM, "Bad filename syntax %s", file); + p++; + } + else p = file; + + + + /* -- check if this body part is allowed -- */ + + if (!txt_bptfind (bodies_all, p) + && !txt_bptfind(headers_all, p)) + err_abrt (RP_PARM, "Unknown body part '%s'", file); + + + + /* -- check the file against the list of eits in Q -- */ + + if (!txt_bptfind (qp->encodedinfo.eit_types, p)) + err_abrt (RP_PARM, + "'%s' is not specified in the orig encoded info", file); + + numBps++; + return; +} + + + + +static int txt_bptfind (list, item) +LIST_BPT *list; +char *item; +{ + + if (list_bpt_nfind (list, item, strlen(item))) + return TRUE; + + return FALSE; +} diff --git a/Src/submit/t-auth.c b/Src/submit/t-auth.c new file mode 100644 index 0000000..5c327c1 --- /dev/null +++ b/Src/submit/t-auth.c @@ -0,0 +1,103 @@ +/* t-auth.c: test authorisation */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/t-auth.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/t-auth.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: t-auth.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "adr.h" +#include "retcode.h" + +char *myname; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + sys_init (myname); + + while((opt = getopt(argc, argv, "")) != EOF) + switch (opt) { + default: + fprintf (stderr, "Usage: %s\n", myname); + exit (1); + } + argc -= optind; + argv += optind; + + pp_log_stat -> ll_stat |= LLOGTTY; + pp_log_stat -> ll_file = "-"; + + if (argc > 0) { + while (argc-- > 1) { + do_auth (*argv, *(argv+1)); + argv += 2; + } + } + else { + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + char *cp; + + while (fgets (buf, sizeof buf, stdin) && + fgets (buf2, sizeof buf2, stdin)) { + if ((cp = index(buf, '\n')) == NULL) + *cp = '\0'; + if ((cp = index(buf2, '\n')) == NULL) + *cp = '\0'; + + do_auth (buf, buf2); + } + } + exit (0); +} + + +do_auth (str1, str2) +char *str1; +char *str2; +{ + ADDR *sender, *recip; + RP_Buf rp; + int retval; + int type = AD_822_TYPE; + + sender = adr_new (str1, type, 0); + + if (rp_isbad (retval = ad_parse (sender, &rp, CH_USA_PREF))) { + printf ("Address parsing failed:\n\t%s\n", + sender -> ad_parse_message); + adr_free (sender); + return; + } + + if (rp_isbad (retval = ad_parse (recip, &rp, CH_USA_PREF))) { + printf ("Address parsing failed:\n\t%s\n", + recip -> ad_parse_message); + adr_free (sender); + adr_free (recip); + return; + } + + auth_start (sender, recip); + auth_finish (sender, recip); +} + + diff --git a/Src/submit/t-rd_rfchdr.c b/Src/submit/t-rd_rfchdr.c new file mode 100644 index 0000000..6ac2c9e --- /dev/null +++ b/Src/submit/t-rd_rfchdr.c @@ -0,0 +1,40 @@ +/* t-rd_rfchdr.c: small wrap around to test parseing of rfc hdrs in submit */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/t-rd_rfchdr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/t-rd_rfchdr.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: t-rd_rfchdr.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" + +Q_struct Qstruct; +CHAN *ch_inbound; + +main (argc, argv) +int argc; +char **argv; +{ + if (argc < 3) { + printf ("usage : %s channel filename", argv[0]); + exit(0); + } + sys_init(argv[0]); + or_myinit(); + if ((ch_inbound = ch_nm2struct(argv[1])) == NULL) { + printf ("Unknown channel '%s'", argv[1]); + exit(0); + } + q_init(&Qstruct); + rd_rfchdr(argv[2]); +} diff --git a/Src/submit/t-tracecheck.c b/Src/submit/t-tracecheck.c new file mode 100644 index 0000000..01e8bc7 --- /dev/null +++ b/Src/submit/t-tracecheck.c @@ -0,0 +1,114 @@ +/* t-tracecheck: small wrap around to test checking of traces */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/submit/RCS/t-tracecheck.c,v 6.0 1991/12/18 20:28:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Src/submit/RCS/t-tracecheck.c,v 6.0 1991/12/18 20:28:02 jpo Rel $ + * + * $Log: t-tracecheck.c,v $ + * Revision 6.0 1991/12/18 20:28:02 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "q.h" +#include "prm.h" +#include "dr.h" + +#define MAX_TRACE_HOPS 15 + +static int inTraceList (tp, list) +Trace *tp, *list; +{ + int retval = NOTOK; + + while (retval == NOTOK && list != NULL) { + if (trace_equ(tp, list) == 0) + retval = OK; + else + list = list -> trace_next; + } + return retval; +} + +static void addToTraceList(this, to) +Trace *this, **to; +{ + Trace *next; + if (this == NULL) + return; + next = this -> trace_next; + this -> trace_next = NULL; + trace_add(to, trace_dup(this)); + this -> trace_next = next; +} + + +void tracecheck_mgt (qp) +Q_struct *qp; +{ + register Trace *tp; + Trace *list = NULL; + int nhops = 0; + char buf[BUFSIZ]; + PP_DBG (("submit/tracecheck_mgt (qp)")); + + for (tp = qp->trace; tp; tp = tp -> trace_next) { + /* -- too many hops -- */ + + if (++nhops > MAX_TRACE_HOPS) { + (void) sprintf (buf, + "%s%s %d", + "This Message has travelled a long time, ", + "there are too many Trace hops", nhops); +/* message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_LOOP_DETECTED, buf);*/ + if (list != NULL) trace_free(list); + return; + } + + if (tp -> trace_mta != NULLCP) { + /* can only check against those with mta specified */ + if (inTraceList(tp, list) == OK) { + (void) sprintf (buf, "%s%s", + "A Loop has been detected in the Trace ", + "field for this Message"); +/* message_failure (DRR_UNABLE_TO_TRANSFER, + DRD_LOOP_DETECTED, buf);*/ + if (list != NULL) trace_free(list); + return; + } else + addToTraceList(tp, &list); + } + } + if (list != NULL) trace_free (list); +} + +main (argc, argv) +int argc; +char **argv; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + if (argc < 2) { + printf("usage : %s msg", argv[0]); + exit(0); + } + sys_init(argv[0]); + + if (rp_isbad(rd_msg(argv[1],&prm,&que,&sender,&recips,&rcount))) { + printf("rd_msg err: '%s'",argv[1]); + rd_end(); + exit(0); + } + tracecheck_mgt (&que); + rd_end(); +} diff --git a/Tools/Makefile b/Tools/Makefile new file mode 100644 index 0000000..fa76b78 --- /dev/null +++ b/Tools/Makefile @@ -0,0 +1,38 @@ +# Tools building Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/RCS/Makefile,v 6.0 1991/12/18 20:35:46 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:35:46 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = bin2hex ckadr ckchan ckconfig ckmail dbmbuild \ + dbmedit dbmunbuild hex2bin mkpasswd mlist mpp84 mpp88 \ + nsapexpand ntail probe splat tables statgen +ALLDIRS = $(SUBDIRS) bin2ascii ckor misc mu ean2real ppls ppbm + +default: make-bits + +make-bits: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x ; $(MAKE)"; cd $$x ; $(MAKE)); done + +clean tidy: + @for x in ${ALLDIRS} ; \ + do (echo "cd $$x ; $(MAKE) $@"; cd $$x ; $(MAKE) $@ ); done + rm -f core *.old *.BAK + +depend lint install: + @for x in ${SUBDIRS} ; \ + do (echo "cd $$x ; $(MAKE) $@"; cd $$x ; $(MAKE) $@ ); done diff --git a/Tools/bin2ascii/Makefile b/Tools/bin2ascii/Makefile new file mode 100644 index 0000000..d5897e4 --- /dev/null +++ b/Tools/bin2ascii/Makefile @@ -0,0 +1,92 @@ +# bin2ascii Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/bin2ascii/RCS/Makefile,v 6.0 1991/12/18 20:28:31 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:31 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = bin2ascii.c bin2ascii.c +OBJS = bin2ascii.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xbin2ascii + +default: $(PROGS) +all: default +lint: l-bin2ascii + +install: inst-dir inst-bin2ascii +inst-dir: $(TOOLDIR) + + +bin2ascii: xbin2ascii +xbin2ascii: bin2ascii.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ bin2ascii.o $(LIBPP) $(LIBSYS) + +l-bin2ascii: bin2ascii.c + $(LINT) $(LINTFLAGS) bin2ascii.c $(LINTLIBS) + + +inst-bin2ascii: $(TOOLDIR)/bin2ascii +$(TOOLDIR)/bin2ascii: xbin2ascii + -$(BACKUP) $@ zxbin2ascii + rm -f $@ + $(INSTALL) xbin2ascii $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "bin2ascii tool inst-talled normally"; echo "" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +bin2ascii.o: bin2ascii.c +bin2ascii.o: bin2ascii.c + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/bin2ascii/bin2ascii.c b/Tools/bin2ascii/bin2ascii.c new file mode 100644 index 0000000..8896c6c --- /dev/null +++ b/Tools/bin2ascii/bin2ascii.c @@ -0,0 +1,281 @@ +/* bin2ascii: converts a Binary file to a ascii one */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/bin2ascii/RCS/bin2ascii.c,v 6.0 1991/12/18 20:28:31 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/bin2ascii/RCS/bin2ascii.c,v 6.0 1991/12/18 20:28:31 jpo Rel $ + * + * $Log: bin2ascii.c,v $ + * Revision 6.0 1991/12/18 20:28:31 jpo + * Release 6.0 + * + */ + + + +#include + + +#define ASC_HT 0x09 +#define ASC_CR 0x0D +#define ASC_DC1 0x11 +#define ASC_DC3 0x13 + +#define ASC_0 0x30 +#define ASC_1 0x31 +#define ASC_2 0x32 +#define ASC_3 0x33 +#define ASC_4 0x34 +#define ASC_5 0x35 +#define ASC_6 0x36 +#define ASC_7 0x37 +#define ASC_8 0x38 +#define ASC_9 0x39 +#define ASC_A 0x41 +#define ASC_B 0x42 +#define ASC_C 0x43 +#define ASC_D 0x44 +#define ASC_E 0x45 +#define ASC_F 0x46 +#define ASC_X 0x58 + +#define ASC_DOLLAR 0x24 +#define ASC_TILDE 0x7E + +#define ASC_CTL 0x01 +#define ASC_NUM 0x02 +#define ASC_UPP 0x04 +#define ASC_LOW 0x08 +#define ASC_SPA 0x10 +#define ASC_PUN 0x20 + +#define ASC_ISCTL(chr) ( Asc_class[chr] & ASC_CTL ) +#define ASC_ISNUMER(chr) ( Asc_class[chr] & ASC_NUM ) +#define ASC_ISUPPER(chr) ( Asc_class[chr] & ASC_UPP ) +#define ASC_ISLOWER(chr) ( Asc_class[chr] & ASC_LOW ) +#define ASC_ISPUNCT(chr) ( Asc_class[chr] & ASC_PUN ) +#define ASC_ISSPACE(chr) ( Asc_class[chr] & ASC_SPA ) +#define ASC_ISALPHA(chr) ( Asc_class[chr] & (ASC_UPP|ASC_LOW) ) +#define ASC_ISALPHANUM(chr) ( Asc_class[chr] & (ASC_UPP|ASC_LOW|ASC_NUM) ) +#define ASC_ISPRINT(chr) \ + ( Asc_class[chr] & (ASC_UPP|ASC_LOW|ASC_NUM|ASC_PUN|ASC_SPA) ) + +#define ASC_ISDEC(chr) ( Asc_value[chr] < 10 ) +#define ASC_ISHEX(chr) ( Asc_value[chr] < 16 ) +#define ASC_ISBIN(chr) ( Asc_value[chr] < 2 ) +#define ASC_ISOCT(chr) ( Asc_value[chr] < 8 ) + +#define ASC_TOUPPER(chr) ( ASC_ISLOWER(chr) ? (chr)&~0x20 : (chr) ) +#define ASC_TOLOWER(chr) ( ASC_ISUPPER(chr) ? (chr)| 0x20 : (chr) ) + +extern char Asc_class[]; +extern char Asc_value[]; +extern char Asc_digit[]; + +#define ILG 64 + + +char Asc_class[256] = { + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_SPA, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + ASC_CTL, ASC_CTL, ASC_CTL, ASC_CTL, + + ASC_SPA, ASC_PUN, ASC_PUN, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_PUN, + + ASC_NUM, ASC_NUM, ASC_NUM, ASC_NUM, + ASC_NUM, ASC_NUM, ASC_NUM, ASC_NUM, + ASC_NUM, ASC_NUM, ASC_PUN, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_PUN, + + + ASC_PUN, ASC_UPP, ASC_UPP, ASC_UPP, + ASC_UPP, ASC_UPP, ASC_UPP, ASC_UPP, + ASC_UPP, ASC_UPP, ASC_UPP, ASC_UPP, + ASC_UPP, ASC_UPP, ASC_UPP, ASC_UPP, + + ASC_UPP, ASC_UPP, ASC_UPP, ASC_UPP, + ASC_UPP, ASC_UPP, ASC_UPP, ASC_UPP, + ASC_UPP, ASC_UPP, ASC_UPP, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_PUN, + + ASC_PUN, ASC_LOW, ASC_LOW, ASC_LOW, + ASC_LOW, ASC_LOW, ASC_LOW, ASC_LOW, + ASC_LOW, ASC_LOW, ASC_LOW, ASC_LOW, + ASC_LOW, ASC_LOW, ASC_LOW, ASC_LOW, + + ASC_LOW, ASC_LOW, ASC_LOW, ASC_LOW, + ASC_LOW, ASC_LOW, ASC_LOW, ASC_LOW, + ASC_LOW, ASC_LOW, ASC_LOW, ASC_PUN, + ASC_PUN, ASC_PUN, ASC_PUN, ASC_CTL, + + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + +char Asc_value[256] = { + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG, 10, 11, 12, 13, 14, 15,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG, 10, 11, 12, 13, 14, 15,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, + ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG, ILG,ILG,ILG,ILG + }; + + +char Asc_digit[16] = { + ASC_0, ASC_1, ASC_2, ASC_3, ASC_4, ASC_5, ASC_6, ASC_7, + ASC_8, ASC_9, ASC_A, ASC_B, ASC_C, ASC_D, ASC_E, ASC_F +}; + + +#define NUM 16 + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fd; + int c, i=0, flag=0; + char hex[80], ascii[80]; + + if (argc != 2) + return (printf ("\n\nUsage: bin2ascii file-name\n\n")); + + fd = fopen (argv[1], "r"); + + while ((c = getc(fd)) != EOF) + { + if (i == NUM) + { + sprbin (&ascii[0], &hex[0], NUM); + printf ("%s\n", &ascii[0]); + i=0; + } + + hex[i] = c; + i++; + flag++; + } + + if (flag) + { + sprbin (&ascii[0], &hex[0], NUM); + printf ("%s\n", &ascii[0]); + } + + fclose (fd); + return; + } + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static sprbin (line, buf, max) + unsigned char* line; + unsigned char* buf; + int max; + { + unsigned char *chrs, *nums; + int c, i; + + chrs = line; + nums = line + NUM; + + if (max > NUM) max = NUM; + + for (i=0; i>4]; + *nums++ = Asc_digit[c&0xF]; + c &= 0x7F; + *chrs++ = ASC_ISPRINT(c) && c!=ASC_HT ? c : '.'; + } + + while (i++ < NUM) *chrs++ = ' '; + + *nums = '\0'; + } diff --git a/Tools/bin2ascii/make b/Tools/bin2ascii/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/bin2ascii/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/bin2hex/Makefile b/Tools/bin2hex/Makefile new file mode 100644 index 0000000..59cfe86 --- /dev/null +++ b/Tools/bin2hex/Makefile @@ -0,0 +1,90 @@ +# bin2hex Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/bin2hex/RCS/Makefile,v 6.0 1991/12/18 20:28:39 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:39 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = bin2hex.c template.c +OBJS = bin2hex.o template.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xbin2hex + +default: $(PROGS) +all: default +lint: l-bin2hex + +install: inst-dir inst-bin2hex +inst-dir: $(TOOLDIR) + + +bin2hex: xbin2hex +xbin2hex: bin2hex.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ bin2hex.o $(LIBPP) $(LIBSYS) + +l-bin2hex: bin2hex.c + $(LINT) $(LINTFLAGS) bin2hex.c $(LINTLIBS) + + +inst-bin2hex: $(TOOLDIR)/bin2hex +$(TOOLDIR)/bin2hex: xbin2hex + -$(BACKUP) $@ zxbin2hex + rm -f $@ + $(INSTALL) xbin2hex $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "bin2hex tool inst-talled normally"; echo "" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/bin2hex/bin2hex.c b/Tools/bin2hex/bin2hex.c new file mode 100644 index 0000000..7c0010d --- /dev/null +++ b/Tools/bin2hex/bin2hex.c @@ -0,0 +1,68 @@ +/* bin2hex: Converts a binary file to hex */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/bin2hex/RCS/bin2hex.c,v 6.0 1991/12/18 20:28:39 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/bin2hex/RCS/bin2hex.c,v 6.0 1991/12/18 20:28:39 jpo Rel $ + * + * $Log: bin2hex.c,v $ + * Revision 6.0 1991/12/18 20:28:39 jpo + * Release 6.0 + * + */ + + + +#include + + + + +/* --------------------- Begin Routines -------------------------------- */ + + +main(argc, argv) +int argc; +char **argv; +{ + if (argc > 1) { + while (--argc > 0) { + FILE *fp; + + if ((fp = fopen (*++argv, "r")) == NULL) { + fprintf (stderr, "Can't open file %s", *argv); + perror(""); + exit (1); + } + bin2hex (fp); + (void) fclose (fp); + } + } + else + bin2hex (stdin); + +} + +bin2hex (fp) +FILE *fp; +{ + int zone, fold; + + fold = 0; + + while ((zone = getc(fp)) != EOF) { + + fold += 3; + + if (fold > 80) { + putchar ('\n'); + fold = 3; + } + + printf ("%02x ", zone); + } + if (fold) + putchar ('\n'); +} diff --git a/Tools/bin2hex/make b/Tools/bin2hex/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/bin2hex/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckadr/Makefile b/Tools/ckadr/Makefile new file mode 100644 index 0000000..6e9b99f --- /dev/null +++ b/Tools/ckadr/Makefile @@ -0,0 +1,137 @@ +# Makefile for ckaddress program +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ckadr/RCS/Makefile,v 6.0 1991/12/18 20:28:46 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:46 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ckadr.c +OBJS = ckadr.o + +HEADERS = ../../h -I/usr/include/isode +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -u $(INCLUDE) +LINTLIBS = $(LINTISODE) ../../Lib/llib-lpp.ln + +PROGS = xckadr + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# CheckAdr +# +############################################################ + +ckadr: xckadr + +xckadr: $(OBJS) $(LIBPP) + rm -f $@ + $(CC) $(LDFLAGS) -o $@ $(OBJS)\ + $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + + +install: inst-dir inst-ckadr +inst-ckadr: $(TOOLDIR)/ckadr +$(TOOLDIR)/ckadr: xckadr + -$(BACKUP) $@ zxckadr + rm -f $@ + $(INSTALL) xckadr $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ckadr tool installed normally"; echo "" + +inst-dir: $(TOOLDIR) + + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old $(PROGS) *.BAK zx* + + +lint: l-ckadr + +l-ckadr: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ckadr.o: ckadr.c +ckadr.o: ../../h/util.h +ckadr.o: ../../h/config.h +ckadr.o: ../../h/ll_log.h +ckadr.o: ../../h/adr.h +ckadr.o: ../../h/list_rchan.h +ckadr.o: ../../h/chan.h +ckadr.o: ../../h/table.h +ckadr.o: ../../h/list_bpt.h +ckadr.o: ../../h/auth.h +ckadr.o: ../../h/list_bpt.h +ckadr.o: ../../h/extension.h +ckadr.o: ../../h/mta.h +ckadr.o: ../../h/adr.h +ckadr.o: ../../h/list_bpt.h +ckadr.o: ../../h/aparse.h +ckadr.o: ../../h/ap.h +ckadr.o: ../../h/util.h +ckadr.o: ../../h/or.h +ckadr.o: ../../h/chan.h +ckadr.o: ../../h/auth.h +ckadr.o: ../../h/list_rchan.h +ckadr.o: ../../h/retcode.h +ckadr.o: ../../h/list_rchan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ckadr/ckadr.c b/Tools/ckadr/ckadr.c new file mode 100644 index 0000000..e02137e --- /dev/null +++ b/Tools/ckadr/ckadr.c @@ -0,0 +1,188 @@ +/* adr_check.c: check command line argument is a valid address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckadr/RCS/ckadr.c,v 6.0 1991/12/18 20:28:46 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckadr/RCS/ckadr.c,v 6.0 1991/12/18 20:28:46 jpo Rel $ + * + * $Log: ckadr.c,v $ + * Revision 6.0 1991/12/18 20:28:46 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "retcode.h" +#include "list_rchan.h" + +static int responsibility = YES; +#ifdef UKORDER +static int dmnorder = CH_UK_PREF; +#else +static int dmnorder = CH_USA_ONLY; +#endif +static void parse_address(); +static int ad_type = AD_822_TYPE; +static int percents = FALSE; +static int normalised = APARSE_NORM_NEXTHOP; +static int full = NOTOK; +static int adno = 1; +/* --------------------- Begin Routines ---------------------------------- */ + + +extern ADDR *adr_new_new(); + +main(argc, argv) +int argc; +char **argv; +{ + char buf[BUFSIZ]; + CHAN *inchan; + extern int optind; + extern char *optarg; + int opt; + ad_type = AD_822_TYPE; + + sys_init(argv[0]); + while ((opt = getopt (argc, argv, "ofrxanpbl0123i:")) != EOF) + switch (opt) { + case 'o': + /* originator address */ + adno = 0; + break; + case 'i': + /* inbound channel to set addressing */ + if ((inchan = ch_nm2struct (optarg)) == NULLCHAN) { + printf("Unknown channel '%s'\n", + optarg); + exit(1); + } + if (inchan -> ch_chan_type != CH_IN + && inchan -> ch_chan_type != CH_BOTH) { + printf("Channel '%s' is not an inbound channel\n", + inchan -> ch_name); + exit (1); + } + ad_type = inchan -> ch_in_ad_type; + dmnorder = inchan -> ch_ad_order; + + if (inchan -> ch_in_ad_subtype == AD_JNT + || inchan -> ch_in_ad_subtype == AD_REAL733) + percents = TRUE; + + if (inchan -> ch_domain_norm == CH_DOMAIN_NORM_ALL) + normalised = APARSE_NORM_ALL; + + case 'f': + full = OK; + break; + + case 'r': + ad_type = AD_822_TYPE; + break; + + case 'x': + ad_type = AD_X400_TYPE; + break; + + case 'a': + normalised = APARSE_NORM_ALL; + break; + case 'n': + responsibility = NO; + break; + case 'p': + percents = TRUE; + break; + case 'l': + dmnorder = CH_USA_PREF; + break; + case 'b': + dmnorder = CH_UK_PREF; + break; + case '0': + case '1': + case '2': + case '3': + dmnorder = opt - '0'; + break; + default: + printf("usage: %s [-i inboundChan] [-x] [-r] [-a] [-n] [-p] [-b] [-o] [-l] [-0] [-1] [-2] [-3]\n", argv[0]); + exit(1); + break; + } + argc -= optind; + argv += optind; + + if (argc == 0) + while (gets(buf) != NULL) + parse_address(buf); + else + while (argc--) + parse_address(*argv++); +} + + + + +static void parse_address(str) +char *str; +{ + ADDR *ad; + RP_Buf rp; + int origType; + int first, retval; + LIST_RCHAN *ix; + + ad = adr_new(str, ad_type, adno); + ad -> ad_resp = responsibility; + origType = ad->ad_type; + ad -> aparse -> percents = percents; + ad -> aparse -> normalised = normalised; + ad -> aparse -> dmnorder = dmnorder; + ad -> aparse -> full = full; + + if (rp_isbad(retval = ad_parse_aux(ad, &rp))) + printf("Address parsing failed:\nReason: %s\nParsing gave this:\n\n", ad->ad_parse_message); + + + + + if (ad->ad_type == AD_X400_TYPE) { + if (isstr(ad->ad_r400adr)) + printf("%s -> (x400) %s\n", str, ad->ad_r400adr); + + if (isstr(ad->ad_r822adr)) + printf("%s -> (rfc822) %s\n", str, ad->ad_r822adr); + } + else { + if (isstr(ad->ad_r822adr)) + printf("%s -> (rfc822) %s\n", str, ad->ad_r822adr); + + if (isstr(ad->ad_r400adr)) + printf("%s -> (x400) %s\n", str, ad->ad_r400adr); + } + + ix = ad -> ad_outchan; + first = 0; + + if (!rp_isbad(retval)) { + while (ix) { + if (first == 0) + printf ("\n"); + + printf("%s to %s by %s\n", + (first++ == 0) ? "Delivered" : "Or delivered", + ix -> li_mta, + (ix -> li_chan) ? + ix -> li_chan -> ch_name : "no channel given"); + ix = ix -> li_next; + } + } + printf ("\n"); +} diff --git a/Tools/ckadr/make b/Tools/ckadr/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ckadr/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckchan/Makefile b/Tools/ckchan/Makefile new file mode 100644 index 0000000..b26772e --- /dev/null +++ b/Tools/ckchan/Makefile @@ -0,0 +1,154 @@ +# makefile for q checker +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ckchan/RCS/Makefile,v 6.0 1991/12/18 20:28:55 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:28:55 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ckchan.c qcheck.c +OBJS = ckchan.o qcheck.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -u $(INCLUDE) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xckchan + + +############################################################ +# +# Building Rules +# +############################################################ + + +default: $(PROGS) + +queue: xqcheck + +xqcheck: qcheck.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ qcheck.o $(LIBPP) $(LIBSYS) + +chan: xckchan + +xckchan: ckchan.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ ckchan.o $(LIBPP) $(LIBSYS) + +saber_src: ckchan.c + #load -C $(CFLAGS) ckchan.c $(LIBPP) $(LIBSYS) + +saber_obj: ckchan.o + #load -C ckchan.o $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-ckchan + +inst-qcheck: $(CMDDIR)/qcheck +$(CMDDIR)/qcheck: xqcheck + -$(BACKUP) $@ zxqcheck + rm -f $@ + $(INSTALL) xqcheck $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "qcheck installed normally"; echo "" + +inst-ckchan: $(CMDDIR)/ckchan +$(CMDDIR)/ckchan: xckchan + -$(BACKUP) $@ zxckchan + rm -f $@ + $(INSTALL) xckchan $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ckchan installed normally"; echo "" + +inst-dir: $(CMDDIR) + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core a.out xckchan xqcheck *.old *.BAK zxckchan zxqcheck + +lint: l-check + +l-check: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ckchan.o: ckchan.c +ckchan.o: ../../h/util.h +ckchan.o: ../../h/config.h +ckchan.o: ../../h/ll_log.h +ckchan.o: ../../h/q.h +ckchan.o: ../../h/adr.h +ckchan.o: ../../h/list_rchan.h +ckchan.o: ../../h/chan.h +ckchan.o: ../../h/table.h +ckchan.o: ../../h/list_bpt.h +ckchan.o: ../../h/auth.h +ckchan.o: ../../h/list_bpt.h +ckchan.o: ../../h/extension.h +ckchan.o: ../../h/mta.h +ckchan.o: ../../h/adr.h +ckchan.o: ../../h/list_bpt.h +ckchan.o: ../../h/mta.h +ckchan.o: ../../h/retcode.h +ckchan.o: ../../h/prm.h +qcheck.o: qcheck.c +qcheck.o: ../../h/util.h +qcheck.o: ../../h/config.h +qcheck.o: ../../h/ll_log.h +qcheck.o: ../../h/q.h +qcheck.o: ../../h/adr.h +qcheck.o: ../../h/list_rchan.h +qcheck.o: ../../h/chan.h +qcheck.o: ../../h/table.h +qcheck.o: ../../h/list_bpt.h +qcheck.o: ../../h/auth.h +qcheck.o: ../../h/list_bpt.h +qcheck.o: ../../h/extension.h +qcheck.o: ../../h/mta.h +qcheck.o: ../../h/adr.h +qcheck.o: ../../h/list_bpt.h +qcheck.o: ../../h/mta.h +qcheck.o: ../../h/retcode.h +qcheck.o: ../../h/prm.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ckchan/ckchan.c b/Tools/ckchan/ckchan.c new file mode 100644 index 0000000..96821c8 --- /dev/null +++ b/Tools/ckchan/ckchan.c @@ -0,0 +1,844 @@ +/* ckchan.c: standalone channel checker */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckchan/RCS/ckchan.c,v 6.0 1991/12/18 20:28:55 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckchan/RCS/ckchan.c,v 6.0 1991/12/18 20:28:55 jpo Rel $ + * + * $Log: ckchan.c,v $ + * Revision 6.0 1991/12/18 20:28:55 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include +#include +#include + +#include "q.h" +#include "retcode.h" +#include "prm.h" + + +extern void getfpath (); +extern CHAN *ch_nm2struct(); +extern char *quedfldir; +#define TABSIZE 6 + +static void build_chanlist(); +static struct my_chan_struct *get_chan(); +static struct my_chan_struct *add_chan(); +static void order_mtas(); +static void add_msg(); +static void add_to_chanlist(); +static void print_chanlist(); +static void print_chan(); +static void print_mta(); +static void print_msg(); +static void print_drmta(); +static void print_drmsg(); +static void dirinit(); +static void free_chanlist(); +static LIST_RCHAN *getnthchannel(); + +#define TIMETROUBLE 24 * 60 * 60 +time_t timetrouble = TIMETROUBLE; +#define noMTA "NO MTA!" + +typedef struct recip_struct { + char *recip; + int status; + struct recip_struct *recip_next; +} Recip_struct; + +typedef struct msg_struct { + time_t age; + char *msg; + char *ad_value; + struct recip_struct *recips; + struct msg_struct *msg_next; +} Msg_struct; + +typedef struct mta_struct { + char *mta; + int nmsgs; + time_t oldestmsg; + struct msg_struct *msgs; + struct mta_struct *mta_next; +} Mta_struct; + +typedef struct my_chan_struct { + char *name; + struct mta_struct *mtas; + struct mta_struct *drmtas; + struct my_chan_struct *chan_next; +} My_chan_struct; + +int all, + verbose, + summary; +struct my_chan_struct *chan_list = NULL; + +main (argc, argv) +int argc; +char **argv; +{ + struct stat statbuf; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int rcount; + int opt, + flags; + extern int optind; + extern char *optarg; + char **msgs = NULLVP; + extern char *quedfldir; + extern char *aquefile, *postmaster; + int num, i; + all = FALSE; + flags = 0; + verbose = FALSE; + summary = FALSE; + + while ((opt = getopt(argc, argv, "vs")) != EOF) { + switch (opt) { + case 'v': + /* verbose output */ + verbose = TRUE; + flags++; + break; + case 's': + /* summary output */ + summary = TRUE; + flags++; + break; + default: + printf("usage : %s [-v] [-s] [ chan ...]\n",argv[0]); + exit(1); + } + } + + sys_init(argv[0]); + (void) signal(SIGPIPE, SIG_DFL); + dirinit(); + argv += flags + 1; + + if (*argv == NULL) + all=TRUE; + else + build_chanlist(argv); + + if (stat(quedfldir, &statbuf) != OK) { + printf("Unable to find spool area\nPlease inform %s\n", postmaster); + (void) exit(1); + } + printf("Please wait while information is processed..."); + fflush(stdout); + num = i = 0; + hier_scanQ (quedfldir, NULLCP, &num, &msgs, &i, NULLIFP); + for (i = 0; i < num; i++) { + sender = NULL; + recips = NULL; + prm_init (&prm); + q_init(&que); + if (rp_isbad(rd_msg_file(msgs[i], + &prm,&que, + &sender,&recips, + &rcount, + RDMSG_RDONLY))) { + rd_end(); + printf("Bad message %s : rd_msg fails\n",msgs[i]); + } else { + rd_end(); + add_to_chanlist(msgs[i],&que); + q_free(&que); + } + + + + } + printf("done\n"); + print_chanlist(); + + + if (num > 0 && msgs != NULLVP) + free_hier(msgs, num); + free_chanlist(); + exit(0); +} + +static void dirinit() +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + " Unable to change directory to '%s'", + quedfldir); +} + +static char *time_t2str(in) +time_t in; +{ + char buf[BUFSIZ]; + time_t result; + buf[0] = '\0'; + + if (in < 0) + return strdup("still in the womb"); + + if ((result = in / (60 * 60 * 24)) != 0) { + sprintf(buf, "%d days",result); + in = in % (60 * 60 * 24); + } + + if ((result = in / (60 * 60)) != 0) { + sprintf(buf, (buf[0] == '\0') ? "%s%d hrs" : "%s %d hrs", + buf, result); + in = in % (60 * 60); + } + if ((result = in / 60) != 0) { + sprintf(buf, (buf[0] == '\0') ? "%s%d mins" : "%s %d mins", + buf, result); + in = in % 60; + } + + if (buf[0] == '\0' && in != 0) + sprintf(buf, "%d secs", in); + if (buf[0] == '\0') + sprintf(buf, "just born"); + return strdup(buf); +} + +static char *time_t2RFC(in) +time_t in; +{ + char buf[BUFSIZ], + *str; + time_t curr, + delta; + + curr = time(0); + delta = curr - in; + + str = time_t2str(delta); + sprintf(buf,"%s%s", + str, + (delta > timetrouble) ? " *****" : ""); + free(str); + return strdup(buf); +} + +static void build_chanlist(chans) +char **chans; +{ + CHAN *chan; + char **ix = chans; + while (*ix != NULL) { + if (lexequ(*ix, "ALL") == 0) + all = TRUE; + else if ((chan = ch_nm2struct(*ix)) == NULLCHAN) + printf("unknown channel '%s'\n",*ix); + else + (void) add_chan(chan); + ix++; + } +} + + +static struct mta_struct *get_mta(list, mta) +struct mta_struct *list; +char *mta; +{ + struct mta_struct *ix = list; + + while (ix != NULL && (strcmp(ix->mta,mta) != 0)) + ix = ix -> mta_next; + return ix; +} + +static struct msg_struct *get_msg(list, key) +struct msg_struct *list; +char *key; +{ + struct msg_struct *ix = list; + + while (ix != NULL && (strcmp(ix->msg,key) != 0)) + ix = ix -> msg_next; + return ix; +} + +static struct my_chan_struct *get_chan(chan) +CHAN *chan; +{ + struct my_chan_struct *ix = chan_list; + + while ((ix != NULL) && (strcmp(ix->name,chan->ch_name) != 0)) + ix = ix->chan_next; + return ix; +} + +static struct my_chan_struct *add_chan(chan) +CHAN *chan; +{ + struct my_chan_struct *temp = (struct my_chan_struct *) calloc(1, sizeof(*temp)); + temp->name = strdup(chan->ch_name); + temp->chan_next = chan_list; + chan_list = temp; + return chan_list; +} + +static void add_recip(plist, adr) +struct recip_struct **plist; +ADDR *adr; +{ + struct recip_struct *ret = (struct recip_struct *) calloc(1, sizeof(*ret)); + + ret -> recip = strdup(adr -> ad_value); + ret -> status = adr -> ad_status; + + ret -> recip_next = *plist; + *plist = ret; +} + +static struct msg_struct *new_msg(msg, que, recip) +char *msg; +Q_struct *que; +ADDR *recip; +{ + struct msg_struct *ret = (struct msg_struct *) calloc(1, sizeof(*ret)); + + ret -> age = utc2time_t(que -> queuetime); + ret -> msg = strdup(msg); + ret -> ad_value = strdup(que->Oaddress->ad_value); + add_recip(&ret -> recips, recip); + + return ret; +} +static void add_msg(plist, msg) +struct msg_struct **plist, + *msg; +{ + struct msg_struct *ix = *plist; + + if (*plist == NULL + || (*plist) -> age > msg -> age) { + msg -> msg_next = *plist; + *plist = msg; + } else { + while ( ix -> msg_next != NULL + && ix -> msg_next -> age <= msg -> age) + ix = ix -> msg_next; + msg -> msg_next = ix -> msg_next; + ix -> msg_next = msg; + } +} + +#define NEW 0 +#define OLD 1 + +static int update_msg(plist,msg,que,recip) +struct msg_struct **plist; +char *msg; +Q_struct *que; +ADDR *recip; +{ + struct msg_struct *temp; + + if ((temp = get_msg(*plist,msg)) == NULL) { + temp = new_msg(msg, que, recip); + add_msg(plist, temp); + return NEW; + } else { + add_recip(&temp->recips, recip); + return OLD; + } +} + +static void update_mta(mta, msg, que, recip) +struct mta_struct *mta; +char *msg; +Q_struct *que; +ADDR *recip; +{ + time_t qtime; + + qtime = utc2time_t(que->queuetime); + if (qtime < mta -> oldestmsg) + mta -> oldestmsg = qtime; + if (update_msg(&mta->msgs, msg, que, recip) == NEW) + mta->nmsgs++; + +} + +static void new_mta(plist, msg, que, recip, inmta) +struct mta_struct **plist; +char *msg; +Q_struct *que; +ADDR *recip; +char *inmta; +{ + struct mta_struct *temp = (struct mta_struct *) calloc(1, sizeof(*temp)); + if (recip ->ad_outchan && recip->ad_outchan->li_mta != NULLCP) + temp -> mta = strdup(recip -> ad_outchan -> li_mta); + else if (inmta != NULL) + temp -> mta = strdup(inmta); + else + temp->mta = strdup(noMTA); + + temp -> nmsgs = 1; + temp -> oldestmsg = utc2time_t(que -> queuetime); + update_msg(&temp->msgs, msg, que, recip); + temp -> mta_next = *plist; + *plist = temp; +} + +static void add_mta(msg,que,recip,chan) +char *msg; +Q_struct *que; +ADDR *recip; +CHAN *chan; +{ + struct my_chan_struct *temp; + struct mta_struct *mta; + char *chmta; + if ((temp = get_chan(chan)) == NULL && all == TRUE) + temp = add_chan(chan); + + if (temp == NULL) + /* not interested in this channel */ + return; + + if (recip->ad_outchan && recip->ad_outchan->li_mta) + chmta = recip->ad_outchan->li_mta; + else + chmta = noMTA; + if ((mta = get_mta(temp -> mtas,chmta)) == NULL) + new_mta(&(temp -> mtas), + msg, + que, + recip, + chmta); + else + update_mta(mta,msg,que,recip); +} + +static void add_drmta(msg,que,sender,chan) +char *msg; +Q_struct *que; +ADDR *sender; +LIST_RCHAN *chan; +{ + struct my_chan_struct *temp; + struct mta_struct *mta; + char *chmta; + + if (chan->li_chan == NULL + || chan->li_chan->ch_name == NULL) { + PP_OPER(NULL, ("Outchan for DR not set (sorry can't be of more help !)")); + return; + } + if ((temp = get_chan(chan->li_chan)) == NULL && all == TRUE) + temp = add_chan(chan->li_chan); + + if (temp == NULL) + /* not interested in this channel */ + return; + if (sender->ad_outchan && sender->ad_outchan->li_mta) + chmta = sender->ad_outchan->li_mta; + else if (chan->li_mta) + chmta = chan->li_mta; + else + chmta = noMTA; + if ((mta = get_mta(temp -> drmtas, chmta)) == NULL) + new_mta(&(temp -> drmtas), + msg, + que, + sender, + chmta); + else + update_mta(mta,msg,que,sender); +} + +static void add_to_chanlist(msg,que) +char *msg; +Q_struct *que; +{ + ADDR *ix = que->Raddress; + LIST_RCHAN *chan, + *chanix; + while (ix != NULL) { + if (ix -> ad_status == AD_STAT_DRWRITTEN + || ix -> ad_status == AD_STAT_DRREQUIRED) { + if ((chan = getnthchannel(que->Oaddress->ad_fmtchan, + que->Oaddress->ad_rcnt)) != NULL) + add_drmta(msg,que, que->Oaddress, chan); + else { + chanix = que->Oaddress->ad_outchan; + + while (chanix != NULL) { + add_drmta(msg, que, que->Oaddress, chanix); + chanix = chanix->li_next; + } + } + + } else if (ix -> ad_status != AD_STAT_DONE) { + /* must be on a channel */ + /* check reformaters */ + if ((chan = getnthchannel(ix->ad_fmtchan, ix -> ad_rcnt)) != NULL) + /* still needs reformating */ + add_mta(msg,que,ix,chan->li_chan); + else { + /* on outbound channel */ + chanix = ix->ad_outchan; + + while (chanix != NULL) { + add_mta(msg,que,ix,chanix->li_chan); + chanix = chanix->li_next; + + } + } + } + ix = ix->ad_next; + } +} + +int total_nummsgs = 0, total_nummtas = 0; +time_t veryoldest = 0; +int total_numdrs = 0, total_numdrmtas = 0; +time_t veryoldestdr = 0; + +static void print_chanlist() +{ + struct my_chan_struct *ix = chan_list; + + + while (ix != NULL) { + print_chan(ix); + ix = ix -> chan_next; + } + if (summary == TRUE && + (total_numdrs != 0 || total_nummsgs != 0)) { + char *timestring; + printf ("\nTotals\n======\n"); + if (total_nummsgs != 0) { + timestring = time_t2RFC(veryoldest); + printf("%d msgs on %d mtas (oldest %s)\n", + total_nummsgs, total_nummtas, timestring); + free(timestring); + } + if (total_numdrs != 0) { + timestring = time_t2RFC(veryoldestdr); + printf("%d DRs on %d mtas (oldest %s)\n", + total_numdrs, total_numdrmtas, timestring); + free(timestring); + } + } + +} + +static void print_chan(chanptr) +struct my_chan_struct *chanptr; +{ + struct mta_struct *ix; + int num_mtas = 0, num_msgs = 0; + time_t oldestmsg = 0; + int num_drmtas = 0, num_drs = 0; + time_t oldestdr = 0; + char *timestring; + + if (summary == TRUE) { + for (ix = chanptr->mtas; + ix != (struct mta_struct *) NULL; + ix = ix -> mta_next) { + num_mtas++; + num_msgs += ix -> nmsgs; + if (ix -> oldestmsg < oldestmsg || + oldestmsg == 0) + oldestmsg = ix -> oldestmsg; + } + total_nummtas += num_mtas; + total_nummsgs += num_msgs; + if (oldestmsg < veryoldest || + veryoldest == 0) + veryoldest = oldestmsg; + + for (ix = chanptr -> drmtas; + ix != (struct mta_struct *) NULL; + ix = ix -> mta_next) { + num_drmtas++; + num_drs += ix -> nmsgs; + if (ix -> oldestmsg < oldestdr || + oldestdr == 0) + oldestdr = ix -> oldestmsg; + } + total_numdrmtas += num_drmtas; + total_numdrs += num_drs; + if (oldestdr < veryoldestdr || + veryoldestdr == 0) + veryoldestdr = oldestdr; + printf ("%s ", chanptr->name); + if (num_msgs != 0) { + timestring = time_t2RFC(oldestmsg); + printf("%d msgs on %d mtas (oldest %s)\n", + num_msgs, num_mtas, timestring); + free(timestring); + } + if (num_drs != 0) { + if (num_msgs != 0) + printf ("%*c",strlen(chanptr->name), ' '); + timestring = time_t2RFC(oldestdr); + printf("%d DRs on %d mtas (oldest %s)\n", + num_drs, num_drmtas, timestring); + free(timestring); + } + } else { + printf("%s\n",chanptr->name); + + order_mtas(&(chanptr->mtas)); + if ((ix = chanptr -> mtas) != NULL) + printf("%*smessages\n",TABSIZE/2,""); + while (ix != NULL) { + print_mta(ix); + ix = ix -> mta_next; + } + + order_mtas(&(chanptr->drmtas)); + if ((ix = chanptr -> drmtas) != NULL) + printf("%*sDRs\n",TABSIZE/2,""); + while (ix != NULL) { + print_drmta(ix); + ix = ix -> mta_next; + } + } +} + +static void print_mta(mta) +struct mta_struct *mta; +{ + struct msg_struct *ix; + char *timestring; + if (verbose == TRUE) { + printf("%*s%s\n",TABSIZE,"",mta->mta); + ix = mta->msgs; + while (ix != NULL) { + print_msg(ix); + ix = ix -> msg_next; + } + } else { + timestring = time_t2RFC(mta->oldestmsg); + printf("%*s%-25s %d%*s%s\n", + TABSIZE,"", + mta -> mta, + mta -> nmsgs, + TABSIZE,"", + timestring); + free(timestring); + } +} + +static void print_drmta(mta) +struct mta_struct *mta; +{ + struct msg_struct *ix; + char *timestring; + + if (verbose == TRUE) { + printf("%*s%s\n",TABSIZE,"",mta->mta); + ix = mta->msgs; + while (ix != NULL) { + print_drmsg(ix); + ix = ix -> msg_next; + } + } else { + timestring = time_t2RFC(mta->oldestmsg); + printf("%*s%-25s %d%*s%s\n", + TABSIZE,"", + mta -> mta, + mta -> nmsgs, + TABSIZE,"", + timestring); + free(timestring); + } +} +char *status_str[] = { + "unknown", + "pend", + "dr req", + "dr written", + "done" + }; + +static void print_msg(msg) +struct msg_struct *msg; +{ + char *timestring = time_t2RFC(msg->age); + struct recip_struct *ix = msg -> recips; + + printf("%*s%-25s %s\n", + 2*TABSIZE,"", + msg->msg, + timestring); + printf("%*sfrom %-30s", + 3*TABSIZE,"", + msg->ad_value); + + if (ix == NULL) + printf (" %s\n", status_str[AD_STAT_DRWRITTEN]); + else + printf("\n"); + + while (ix != NULL) { + printf("%*sto %-30s %s\n", + 3*TABSIZE,"", + ix -> recip, + status_str[ix -> status]); + ix = ix -> recip_next; + } + free(timestring); +} + +static void print_drmsg(msg) +struct msg_struct *msg; +{ + char *timestring = time_t2RFC(msg->age); + struct recip_struct *ix = msg -> recips; + + printf("%*s%-25s %s\n", + 2*TABSIZE,"", + msg->msg, + timestring); + + printf("%*sto %-30s\n", + 3*TABSIZE,"", + msg->ad_value); + + while (ix != NULL) { + printf("%*sfrom recip %-30s\n", + 3*TABSIZE,"", + ix -> recip); + ix = ix -> recip_next; + } + free(timestring); +} + +static LIST_RCHAN *getnthchannel(chans,num) +LIST_RCHAN *chans; +int num; +{ + LIST_RCHAN *ix = chans; + int icount = 0; + + while ((ix != NULL) && (icount++ < num)) + ix = ix->li_next; + + return ix; +} + +static void insert_mta(plist, mta) +struct mta_struct **plist, + *mta; +{ + struct mta_struct *ix = *plist; + + if (*plist == NULL + || (*plist) -> oldestmsg > mta -> oldestmsg) { + mta -> mta_next = *plist; + *plist = mta; + } else { + while ( ix -> mta_next != NULL + && ix -> mta_next -> oldestmsg <= mta -> oldestmsg) + ix = ix -> mta_next; + mta -> mta_next = ix -> mta_next; + ix -> mta_next = mta; + } +} + +static void order_mtas(plist) +struct mta_struct **plist; +{ + struct mta_struct *new = NULL, + *head = *plist, + *tail; + + while (head != NULL) { + tail = head -> mta_next; + insert_mta(&new, head); + head = tail; + } + + *plist = new; +} + +/* */ + +static void free_recips(recips) +struct recip_struct *recips; +{ + struct recip_struct *temp; + + while (recips != NULL) { + temp = recips; + if (temp->recip) + free(temp->recip); + recips = temp -> recip_next; + free((char *) temp); + } +} + +static void free_msgs (msgs) +struct msg_struct *msgs; +{ + struct msg_struct *temp; + + while (msgs != NULL) { + temp = msgs; + if (temp->msg) + free(temp->msg); + if (temp->ad_value) + free(temp->ad_value); + if (temp->recips) + free_recips(temp->recips); + msgs = temp->msg_next; + free((char *) temp); + } +} + +static void free_mtas(mtas) +struct mta_struct *mtas; +{ + struct mta_struct *temp; + + while (mtas != NULL) { + temp = mtas; + if (mtas->mta) + free(mtas->mta); + if (mtas->msgs) + free_msgs(mtas->msgs); + mtas = mtas->mta_next; + free((char *) temp); + } +} + +static void free_chanlist() +{ + struct my_chan_struct *temp; + while (chan_list != NULL) { + temp = chan_list; + if (temp -> name) + free(temp->name); + if (temp->mtas) + free_mtas(temp->mtas); + if (temp->drmtas) + free_mtas(temp->drmtas); + chan_list = temp->chan_next; + free((char *) temp); + } +} + diff --git a/Tools/ckchan/make b/Tools/ckchan/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ckchan/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckchan/qcheck.c b/Tools/ckchan/qcheck.c new file mode 100644 index 0000000..b993b2e --- /dev/null +++ b/Tools/ckchan/qcheck.c @@ -0,0 +1,190 @@ +/* qcheck.c: stand alone checker of q */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckchan/RCS/qcheck.c,v 6.0 1991/12/18 20:28:55 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckchan/RCS/qcheck.c,v 6.0 1991/12/18 20:28:55 jpo Rel $ + * + * $Log: qcheck.c,v $ + * Revision 6.0 1991/12/18 20:28:55 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +#include "q.h" +#include "retcode.h" +#include "prm.h" + + +static int QPrint(); +static int RecipPrint(); +static LIST_RCHAN *getnthchannel(); +static char **get_all_messages(); + +main (argc, argv) +int argc; +char **argv; +{ + char **all_msgs; + if (argc < 2) { + printf("usage : %s [all | msg.XXXX ...]\n",argv[0]); + exit(1); + } + sys_init(argv[0]); + argv++; + + if (strcmp(*argv,"all") == 0) { + /* get all messages in addr, directory */ + all_msgs = get_all_messages(); + qcheck(all_msgs); + } else + qcheck(argv); +} + +int isMsg(entry) +struct dirent *entry; +{ + if (strncmp(entry->d_name,"msg.",4) == 0) + return 1; + else + return 0; +} + +static char **get_all_messages() +{ + int num, + i = 0; + struct dirent **namelist = NULL, + **ix; + char **ret; + extern char *quedfldir; + + num = _scandir(quedfldir, &namelist, isMsg, NULL); + + ret = (char **) calloc((num+1), sizeof(char *)); + ix = namelist; + while ((i < num) && (*ix != 0)) { + ret[i++] = (*ix)->d_name; + ix++; + } + + if (namelist) free((char *) namelist); + + return ret; +} + + +qcheck(argv) +char **argv; +{ + char *file = NULL; + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + ADDR *ix; + int rcount; + + prm_init (&prm); + q_init (&que); + qinit (&que); + + + while ((file = *argv++) != NULLCP) { + sender = NULL; + recips = NULL; + prm_init (&prm); + q_init (&que); + if (rp_isbad(rd_msg(file,&prm,&que,&sender,&recips,&rcount))) { + rd_end(); + printf("Bad message %s : rd_msg fails\n",file); + } else { + rd_end(); + QPrint(file,&que,sender); + ix = recips; + while (ix != NULL) { + RecipPrint(ix); + ix = ix->ad_next; + } + printf("***** End of Message *****\n\n"); + + } + q_free (&que); + } +} + + +static int QPrint(file, que,sender) +char *file; +Q_struct *que; +ADDR *sender; +{ + printf("***** Message %s *****\n",file); + printf("From %s # On host %s # Inbound channel %s\n\n", + (sender->ad_type == AD_X400_TYPE) ? + sender->ad_r400adr : sender->ad_r822adr, + que->inbound && que -> inbound -> li_mta ? + que -> inbound -> li_mta : "(none)", + que->inbound && que -> inbound -> li_chan ? + que -> inbound->li_chan->ch_name : "(none)"); +} + +static LIST_RCHAN *getnthchannel(chans,num) +LIST_RCHAN *chans; +int num; +{ + LIST_RCHAN *ix = chans; + int icount = 0; + + while ((ix != NULL) && (icount++ < num)) + ix = ix->li_next; + + return ix; +} + +static RecipPrint(recip) +ADDR *recip; +{ + LIST_RCHAN *ix; + printf("To %s #", + (recip->ad_type == AD_X400_TYPE) ? recip->ad_r400adr : recip->ad_r822adr); + if (recip->ad_outchan == NULL) + printf(" NO OUTBOUND CHANNEL # Status "); + else + printf(" On outbound channel %s # Status ", + recip->ad_outchan->li_chan->ch_name); + + switch(recip->ad_status) { + case AD_STAT_PEND: + printf("pending\n"); + break; + case AD_STAT_DRREQUIRED: + printf("delivery notification required\n"); + break; + case AD_STAT_DRWRITTEN: + printf("delivery notification written\n"); + break; + case AD_STAT_DONE: + printf("done\n"); + return; + case AD_STAT_UNKNOWN: + default: + printf("unknown\n"); + break; + } + + if ((ix = getnthchannel(recip->ad_fmtchan,recip->ad_rcnt)) != NULL) { + printf("Reformating channels left = "); + while (ix != NULL) { + printf(" %s -> ",ix->li_chan->ch_name); + ix = ix->li_next; + } + printf("\n"); + } +} diff --git a/Tools/ckconfig/Makefile b/Tools/ckconfig/Makefile new file mode 100644 index 0000000..3bb7c14 --- /dev/null +++ b/Tools/ckconfig/Makefile @@ -0,0 +1,122 @@ +# ckconfig: management program to check the configuration of the PP system. +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ckconfig/RCS/Makefile,v 6.0 1991/12/18 20:29:03 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:29:03 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ckconfig.c +OBJS = ckconfig.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +PROGS = xckconfig + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# CheckConfig +# +############################################################ +ckconfig: xckconfig +xckconfig: $(OBJS) $(LIBPP) + rm -f $@ + $(CC) $(LDFLAGS) -o $@ $(OBJS) \ + $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + + +install: inst-dir inst-ckconfig +inst-ckconfig: $(CMDDIR)/ckconfig +$(CMDDIR)/ckconfig: xckconfig + -$(BACKUP) $@ zxckconfig + rm -f $@ + $(INSTALL) xckconfig $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ckconfig tool installed normally"; echo "" + +inst-dir: $(TOOLDIR) + + +clean: tidy + rm -f $(PROGS) +tidy: + rm -f $(OBJS) core a.out *.old *.BAK zxckconfig + +lint: l-ckconfig + +l-ckconfig: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +true:; + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ckconfig.o: ckconfig.c +ckconfig.o: ../../h/util.h +ckconfig.o: ../../h/config.h +ckconfig.o: ../../h/ll_log.h +ckconfig.o: ../../h/chan.h +ckconfig.o: ../../h/table.h +ckconfig.o: ../../h/list_bpt.h +ckconfig.o: ../../h/table.h +ckconfig.o: ../../h/list_bpt.h +ckconfig.o: ckconfig.c +ckconfig.o: ../../h/util.h +ckconfig.o: ../../h/config.h +ckconfig.o: ../../h/ll_log.h +ckconfig.o: ../../h/chan.h +ckconfig.o: ../../h/table.h +ckconfig.o: ../../h/list_bpt.h +ckconfig.o: ../../h/table.h +ckconfig.o: ../../h/list_bpt.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ckconfig/ckconfig.c b/Tools/ckconfig/ckconfig.c new file mode 100644 index 0000000..20eff19 --- /dev/null +++ b/Tools/ckconfig/ckconfig.c @@ -0,0 +1,1330 @@ +/* ckconfig.c: management tool to check configuration of PP system */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckconfig/RCS/ckconfig.c,v 6.0 1991/12/18 20:29:03 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckconfig/RCS/ckconfig.c,v 6.0 1991/12/18 20:29:03 jpo Rel $ + * + * $Log: ckconfig.c,v $ + * Revision 6.0 1991/12/18 20:29:03 jpo + * Release 6.0 + * + */ + + + +#include "qmgr.h" +#include "util.h" +#include "chan.h" +#include "table.h" +#include "list_bpt.h" +#include "adr.h" +#include "retcode.h" +#include +#include +#include +#include +#include + +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif + +extern struct passwd *getpwnam(), *getpwuid(); +extern void getfpath(), dsap_init(); + +typedef enum { + ok, + notExist, + highMode, + lowMode, + wrongOwner, + wrongGroup + } Retvals; + +static Retvals check_file(); +static int check_main_vars(); +static int check_dirs(); +static int check_chans(); +static int check_channel(); +static int check_filter(); +static int check_tables(); +static int check_table_file(); +static int check_table(); +static int check_bps(), check_hdrs(); +static int check_822address(); +static int yesorno(); +static int check_hardwired(); +static int makedirectory(); +static int changemode(); +static int changeowner(); +static void check_dsap (); +static void perrstr (); +static int pok(); +static int ptabss(); +static int ptabsd(); +static void ckerror (); +#define OPEN_MODE 0777 +#define CLOSED_MODE 0700 + +#define DIR_MODE 0775 +#define EXEC_MODE 0755 +#define RSEXEC_MODE 0700 +#define TABLE_MODE 0644 +#define RSTABLE_MODE 0600 + +int interactive, + monitoring, + verbose; +extern char *ppversion, *pptailor; +extern void sys_init(); + +main(argc, argv) +int argc; +char **argv; +{ + int opt; + Retvals retval; + unsigned int fileMode = 0; + char *myname = argv[0], prompt[BUFSIZ], owner[MAXPATHLENGTH]; + extern int optind; + extern char *optarg; + + interactive = TRUE; + monitoring = FALSE; + verbose = FALSE; + + while ((opt = getopt (argc, argv, "fnvt:")) != EOF) { + switch (opt) { + case 'f': + interactive = FALSE; + break; + + case 'n': + monitoring = TRUE; + break; + + case 'v': + verbose = TRUE; + break; + case 't': + pptailor = optarg; + break; + + default: + printf("Usage: %s [-n] [-f] [-v] [-t tailorfile]\n",myname); + exit(1); + break; + } + } + retval = check_file(pptailor, 0644, 0600, &fileMode, owner); + switch (retval) { + case notExist: + perrstr("Tailor file does not exist\n\tShould be in %s\n\n",pptailor); + exit(1); + break; + + case lowMode: + perrstr("The tailor file '%s' has too low a permission mode.\n", + pptailor); + sprintf(prompt, "Change mode of %s from %o to %o", + pptailor, + fileMode, + 0600); + if (yesorno(prompt) == TRUE) + changemode(pptailor, 0600); + break; + + case highMode: + perrstr("The tailor file '%s' has too high a permission mode.\n", + pptailor); + sprintf(prompt, "Change mode of %s from %o to %o", + pptailor, + fileMode, + 0644); + if (yesorno(prompt) == TRUE) + changemode(pptailor, 0644); + break; + + default: + break; + } + pok("Tailor file",pptailor); + tai_seterrorhandler (ckerror); + sys_init (myname); + (void) signal (SIGPIPE, SIG_DFL); + + check_dsap (); + check_main_vars(); + check_dirs(); + check_chans(); + check_tables(); + check_hardwired(); +} + +static void ckerror (str) +char *str; +{ + fprintf (stderr, "%s", str); +} + +/* */ +extern char *loc_dom_mta, + *loc_dom_site, + *loc_or, + *x400_mta, + *postmaster, + *pplogin, + *pptsapd_addr, + *mboxname, + *qmgr_hostname; +extern int max_hops, max_loops; + +extern LIST_BPT *bodies_all, *headers_all; +int ppuid = 0, ppgid = 0; + +static int check_main_vars() +/* really just print them out */ +{ + struct passwd *password = NULL; + LIST_BPT *ix; + RP_Buf rp; + ADDR *ad; + AEI aei; + register struct PSAPaddr *pa; + + if (str2paddr (pptsapd_addr) == NULLPA) + perrstr ("Invalid pptsapd address '%s'\n\n", + pptsapd_addr); + else + pok("pptsapd address", pptsapd_addr); + + if ((aei = _str2aei (qmgr_hostname, "pp qmgr", + QMGR_CTX_OID, 0, dap_user, + dap_passwd)) == NULLAEI) + if ((aei = _str2aei (qmgr_hostname, "pp-qmgr", + QMGR_CTX_OID, + 0, dap_user, dap_passwd)) != NULLAEI) + perrstr ("Old form of AEI \"pp-qmgr\" %s\n", + "change to \"pp qmgr\" in isoentites"); + + if (aei == NULLAEI) + perrstr ("Invalid qmgr hostname: %s-pp qmgr unknown application-entity\n\n", + qmgr_hostname); + else if ((pa = aei2addr(aei)) == NULLPA) + perrstr ("Invalid qmgr hostname '%s': address translation failed\n\n", + qmgr_hostname); + else + pok ("qmgr hostname", qmgr_hostname); + + + if ((password = getpwnam(pplogin)) == NULL) + perrstr("Cannot access password entry for PP login '%s'\n\n",pplogin); + else if (verbose == TRUE) { + ptabss("PP login", pplogin); + ptabsd("uid", password->pw_uid); + ptabsd("guid",password->pw_gid); + pnewline(); + } + if (password != NULL) { + ppuid = password->pw_uid; + ppgid = password->pw_gid; + } + + pok("Local Mta",loc_dom_mta); + pok("Local Site", loc_dom_site); + pok("Local O/R address",loc_or); + pok("X400 MTA name", x400_mta); + + if (max_hops <= 0 || max_hops >= 100) + perrstr("WARNING: Maximum number of hops (trace fields) is set to %d", + (char *) max_hops); + else if (verbose == TRUE) { + char buf[BUFSIZ]; + (void) sprintf(buf, "%d", max_hops); + pok("Maximum hops", buf); + } + + if (max_loops <= 0 || max_loops >= 100) + perrstr("WARNING: Maximum nmber of local loops is set to %d", + (char *) max_loops); + else if (verbose == TRUE) { + char buf[BUFSIZ]; + (void) sprintf(buf, "%d", max_loops); + pok("Maximum loops", buf); + } + + pok("Mailbox name", mboxname); + + ad = adr_new(postmaster, AD_822_TYPE, 0); +#ifdef UKORDER + if (rp_isbad(ad_parse(ad, &rp, CH_UK_PREF))) +#else + if (rp_isbad(ad_parse(ad, &rp, CH_USA_PREF))) +#endif + perrstr("Postmaster '%s' is an invalid address (reason = '%s').\n", + postmaster, + ad->ad_parse_message); + else + pok("Post Master", postmaster); + adr_free(ad); + + check_822address("postmaster"); + if (verbose == TRUE) check_822address("support"); + if (verbose == TRUE) check_822address("operator"); + if (verbose == TRUE) check_822address("admin"); + + /* print list of body types */ + if (bodies_all == NULLIST_BPT) + perrstr("System does not recognise any body parts\n\n",""); + else if (verbose == TRUE) { + + ix = bodies_all; + printf("The system reconises the following body parts :-\n"); + while (ix != NULLIST_BPT) { + ptabss("",ix->li_name); + ix = ix->li_next; + } + pnewline(); + } +} + +/* */ + +typedef struct direntry { + char **fldirname; + char *name; + int maxmode, minmode; +} Direntry; + +extern char *quedfldir, + *cmddfldir, + *chndfldir, + *formdfldir, + *tbldfldir, + *logdfldir, + *ppdbm, + *wrndfldir; + +/* 0700 = rwx------ + 0777 = rwxrwxrwx + 0711 = rwx--x--x + 0775 = rwxrwxr-x */ + +struct direntry dirs[] = { + &quedfldir, "queue", 0700, 0700, + &cmddfldir, "commands", 0775, 0711, + &chndfldir, "channels", 0775, 0711, + &formdfldir, "format", 0775, 0711, + &tbldfldir, "table", 0775, 0711, + &logdfldir, "logging", 0775, 0711, + &wrndfldir, "warnings", 0775, 0711, + 0, 0 + }; + +/* */ +/* file and directory checking routines */ +static Retvals check_file(name, himode, lomode, pfileMode, owner) +char *name; +unsigned int himode, lomode, *pfileMode; +char *owner; +{ + struct stat statbuf; + struct passwd *temp; + + if (stat(name, &statbuf) != OK) + return notExist; + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) + *pfileMode = statbuf.st_mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX); + else + *pfileMode = statbuf.st_mode & ~S_IFMT; + if (*pfileMode & lomode != lomode) + return lowMode; + if (((*pfileMode) & (~himode)) != 0) + return highMode; + if (statbuf.st_uid != ppuid) { + if ((temp = getpwuid(statbuf.st_uid)) == NULL) { + if (verbose == TRUE) + printf("**** "); + printf("Unknown uid '%o' owns %s.\n", + statbuf.st_uid, + name); + owner[0] = '\0'; + } else { + (void) sprintf(owner, "%s", temp->pw_name); + } + return wrongOwner; + } + return ok; +} + +static int check_directory(dir) +struct direntry *dir; +{ + char prompt[BUFSIZ], owner[MAXPATHLENGTH]; + Retvals retval; + unsigned int fileMode = 0; + + while ((retval = check_file(*(dir->fldirname), + (unsigned int) dir->maxmode, + (unsigned int) dir->minmode, + &fileMode, + owner)) != ok) { + switch (retval) { + + case notExist: + perrstr("The %s directory does not exist.\n", + dir->name); + sprintf(prompt, "Make directory %s with mode %o", + *(dir->fldirname), dir->maxmode); + if (yesorno(prompt) == TRUE) + makedirectory(*(dir->fldirname), dir->maxmode); + else + return; + break; + + case highMode: + if (dir -> maxmode == dir -> minmode) + perrstr("The directory '%s' has the wrong permission modes.\n", + *(dir->fldirname)); + else + perrstr("The directory '%s' has too high a permission mode.\n", + *(dir->fldirname)); + sprintf(prompt, "Change mode of %s from %o to %o", + *(dir->fldirname), + fileMode, + dir->maxmode); + if (yesorno(prompt) == TRUE) + changemode(*(dir->fldirname), dir->maxmode); + else + return; + break; + + case lowMode: + if (dir -> maxmode == dir -> minmode) + perrstr("The directory '%s' has the wrong permission modes.\n", + *(dir->fldirname)); + else + perrstr("The directory '%s' has too low a permission mode.\n", + *(dir->fldirname)); + + sprintf(prompt, "Change mode of %s from %o to %o", + *(dir->fldirname), + fileMode, + dir->minmode); + if (yesorno(prompt) == TRUE) + changemode(*(dir->fldirname), dir->minmode); + else + return; + break; + + case wrongOwner: + perrstr("The directory '%s' is not owned by the PP uid.\n", + *(dir->fldirname)); + if (owner[0] == '\0') + (void) sprintf(prompt, + "Change owner of %s to %s", + *(dir->fldirname), + pplogin); + else + (void) sprintf(prompt, + "Change owner of %s from %s to %s", + *(dir->fldirname), + owner, + pplogin); + if (yesorno(prompt) == TRUE) + changeowner(*(dir->fldirname), + ppuid, + ppgid); + else + return; + break; + + default: + break; + } + } + pok(dir->name, *(dir->fldirname)); +} + +static int check_dirs() +{ + int i = 0; + char *ix; + struct direntry temp; + char fullpath[MAXPATHLENGTH]; + if (verbose == TRUE) + printf("Checking the various directories\n\n"); + + while (dirs[i].name != NULL) + check_directory(&(dirs[i++])); + /* special cases */ + /* ppdbm */ + if ((ix = rindex(ppdbm, '/')) != NULL) { + *ix = '\0'; + if (verbose == TRUE) + printf("Checking the directory for ppdbm file exist\n"); + temp.fldirname = &ppdbm; + temp.name = "dbm"; + temp.maxmode = 0775; + temp.minmode = 0711; + check_directory(&temp); + *ix = '/'; + } +} + +/* */ +/* check the executables for the channels */ +/* and the filter executables for the filtercontrol channels */ +/* then print out some nice info */ + +static int warning, + delete, + qmgr_load, + debris, + time_out; + +#define spec_chan_error "There is no %s channel.\n" +static int check_special_channels() +{ + if (warning == 0) + perrstr(spec_chan_error, "warning"); + if (delete == 0) + perrstr(spec_chan_error, "delete"); + if (qmgr_load == 0) + perrstr(spec_chan_error, "qmgr-load"); + if (debris == 0) + perrstr(spec_chan_error, "debris"); + if (time_out == 0) + perrstr(spec_chan_error, "timeout"); +} + +static int check_chans() +{ + CHAN **ix = ch_all; + + warning = delete = qmgr_load = debris = time_out = 0; + + if (verbose == TRUE) + printf("\nChecking the various channels\n\n"); + + while (*ix != NULL) + check_channel(*ix++); + check_special_channels(); +} + +static char *chan_type(chan) +CHAN *chan; +{ + char *str = NULLCP; + switch(chan->ch_chan_type) { + case CH_SHAPER: + str = "formatter channel"; + break; + case CH_IN: + str = "listener channel"; + break; + case CH_OUT: + str = "transmitter channel"; + break; + case CH_BOTH: + str = "listener/transmitter channel"; + break; + case CH_WARNING: + str = "warning channel"; + warning = 1; + break; + case CH_DELETE: + str = "deletion channel"; + delete = 1; + break; + case CH_QMGR_LOAD: + str = "loader channel"; + qmgr_load = 1; + break; + case CH_DEBRIS: + str = "debris cleaning channel"; + debris = 1; + break; + case CH_TIMEOUT: + str = "timeout channel"; + time_out = 1; + break; + case CH_SPLITTER: + str = "splitter"; + break; + default: + str = "Unknown type"; + break; + } + return str; +} + +static int check_channel(chan) +CHAN *chan; +{ + struct stat statbuf; + char fullname[MAXPATHLENGTH], + *ch_type, + *margv[100]; + int margc; + + ch_type = chan_type(chan); + + /* do checking */ + if (chan->ch_progname != NULLCP) { + if ((margc = sstr2arg(chan->ch_progname, 100, margv, " \t")) < 1) { + perrstr("Unable to parse program '%s' for channel '%s'\n", + chan->ch_progname, + chan->ch_name); + return; + } + if (margv[0][0] == '/') + sprintf(fullname,"%s",margv[0]); + else + sprintf(fullname,"%s/%s",chndfldir,margv[0]); + + if (stat(fullname, &statbuf) != OK) + perrstr("The program %s for channel %s does not exist\n", + fullname, chan->ch_name); + else if (!(statbuf.st_mode & S_IEXEC)) + perrstr("The program %s for the channel %s is not executable\n", + fullname, chan->ch_name); + else if (statbuf.st_mode & S_ISUID + && chan->ch_access != CH_MTS + && (chan->ch_chan_type != CH_OUT + || chan->ch_chan_type != CH_BOTH)) { + perrstr("WARNING The program %s for the channel %s is set uid.\n", + fullname, chan->ch_name); + if (verbose == TRUE) + printf("**** "); + printf("Only local channels should be set uid\n"); + + } + + if (chan->ch_access == CH_MTS + && (chan->ch_chan_type == CH_OUT + || chan->ch_chan_type == CH_BOTH)) { + /* local delivery */ + if (statbuf.st_uid != 0) + perrstr("WARNING Channel '%s' is local delivery\n\tbut program '%s' isn't owned by root.\n", + chan->ch_name, + fullname); + } else if (statbuf.st_uid != ppuid) + perrstr("WARNING program '%s' for channel '%s' is not owned by '%s'\n", + fullname, + chan->ch_name, + pplogin); + + if (chan->ch_access == CH_MTS + && (chan->ch_chan_type == CH_OUT || chan->ch_chan_type == CH_BOTH) + && !(statbuf.st_mode & S_ISUID)) + perrstr("WARNING Channel '%s' is local delivery\n\tbut program '%s' isn't set uid.\n", + chan->ch_name, + fullname); + } else if (chan->ch_chan_type != CH_IN) + perrstr("WARNING No program given for channel %s\n",chan->ch_name); + if (chan->ch_out_info != NULL + && chan->ch_chan_type == CH_SHAPER) + /* assume is a filter control channel */ + check_filter(chan->ch_name, chan->ch_out_info); + + if (chan->ch_table != NULL) + check_table_file(chan->ch_table,0644, 0600); + + if (chan->ch_mta_table != NULL) + check_table_file(chan->ch_mta_table,0644, 0600); + + if (chan->ch_in_table != NULL) + check_table_file(chan->ch_in_table,0644, 0600); + + if (chan->ch_hdr_in != NULL) + check_hdrs(chan->ch_name, chan->ch_hdr_in); + + if (chan->ch_hdr_out != NULL) + check_hdrs(chan->ch_name, chan->ch_hdr_out); + + if (chan->ch_bpt_in != NULL) + check_bps(chan->ch_name, chan->ch_bpt_in); + + if (chan->ch_bpt_out != NULL) + check_bps(chan->ch_name, chan->ch_bpt_out); + + if (chan->ch_drchan != NULLCP && + chan->ch_chan_type != CH_BOTH && + chan->ch_chan_type != CH_OUT) + perrstr("drchan '%s' specified for channel '%s'\n\tOnly outbound channels should have drchan specified\n", + chan->ch_drchan, chan->ch_name); + if (chan -> ch_drchan) { + CHAN *drc = ch_nm2struct(chan -> ch_drchan); + if (drc == NULLCHAN) + perrstr ("drchan '%s' for channel %s does not exist\n", + chan -> ch_drchan, chan -> ch_name); + else if (drc -> ch_chan_type != CH_BOTH && + drc -> ch_chan_type != CH_OUT) + perrstr ("drchan '%s' for channel %s is not outbound type\n", + chan -> ch_drchan, chan -> ch_name); + } + if (chan->ch_badSenderPolicy != CH_BADSENDER_STRICT + && chan->ch_chan_type != CH_BOTH + && chan->ch_chan_type != CH_IN) + perrstr("bad-sender-policy specified for channel '%s'\n\tOnly inbound channels should have bad-sender-policy specified\n", + chan->ch_name); + + if (chan->ch_out_ad_type == AD_ANY_TYPE) + perrstr("WARNING address type set to any for channel %s.\n\tThis may cause address parsing problems.\n",chan->ch_name); + if (chan->ch_in_ad_type == AD_ANY_TYPE) + perrstr("WARNING address type set to any for channel %s.\n\tThis may cause address parsing problems.\n",chan->ch_name); + + if (verbose == TRUE) { + /* print info */ + ptabss(chan->ch_name, + (chan->ch_show == NULL) ? chan->ch_name : chan->ch_show); + if (chan->ch_progname != NULLCP) + ptabss("program", chan->ch_progname); + + if (chan->ch_drchan != NULLCP) + ptabss("drchan", chan->ch_drchan); + + ptabss("type", ch_type); + + if (chan->ch_out_info != NULL) + ptabss("filter run as", chan->ch_out_info); + + if (chan->ch_table == NULL) + ptabss("channel outbound table", "none"); + else + ptabss("channel outbound table",chan->ch_table->tb_name); + + if (chan->ch_in_table == NULL) + ptabss("channel inbound table", "none"); + else + ptabss("channel inbound table",chan->ch_in_table->tb_name); + + if (chan->ch_mta_table == NULL) + ptabss("channel MTA table", "none"); + else + ptabss("channel MTA table",chan->ch_mta_table->tb_name); + pnewline(); + } +} + +static int check_filter(chan, info) +char *chan, + *info; +{ + char fullname[MAXPATHLENGTH], + *ix = info, + saved; + struct stat statbuf; + + while (*ix != '\0' && !isspace(*ix)) + ix++; + saved = *ix; + *ix = '\0'; + + if (info[0] == '/') + sprintf(fullname, "%s", info); + else + sprintf(fullname, "%s/%s",formdfldir,info); + + *ix = saved; + + if (stat(fullname, &statbuf) != OK) { + if (verbose == TRUE) + printf("**** "); + printf("The filter %s for channel %s does not exist\n", + fullname, chan); + return; + } + if (!(statbuf.st_mode & S_IEXEC)) { + if (verbose == TRUE) + printf("**** "); + printf("The filter %s for channel %s is not executable\n", + fullname, chan); + return; + } +} + +/* */ +/* check the tables */ + +static int check_tables() +{ + Table **ix = tb_all; + + if (verbose == TRUE) + printf("\nChecking the various tables\n\n"); + while (*ix != NULL) { + check_table(*ix++); + pnewline(); + } +} + +static int check_table_file(tbl, maxmode, minmode) +Table *tbl; +int maxmode, minmode; +{ + char fullname[MAXPATHLENGTH], owner[MAXPATHLENGTH], prompt[BUFSIZ]; + unsigned int fileMode = 0; + Retvals retval; + + if (tbl->tb_file[0] == '/') + sprintf(fullname,"%s",tbl->tb_file); + else + sprintf(fullname,"%s/%s",tbldfldir,tbl->tb_file); + + while ((retval = check_file(fullname, (unsigned int) maxmode, + (unsigned int) minmode, + &fileMode, owner)) != ok) { + switch (retval) { + case notExist: + perrstr("The file %s is not present for table %s\n", + fullname, tbl->tb_name); + return; + + case highMode: + if (maxmode == minmode) + perrstr("The table file '%s' has the wrong permission modes.\n", + fullname); + else + perrstr("The table file '%s' has too high a permission mode.\n", + fullname); + sprintf(prompt, "Change mode of %s from %o to %o", + fullname, + fileMode, + maxmode); + if (yesorno(prompt) == TRUE) + changemode(fullname, maxmode); + else + return; + break; + + case lowMode: + if (maxmode == minmode) + perrstr("The table file '%s' has the wrong permission modes.\n", + fullname); + else + perrstr("The table file '%s' has too low a permission mode.\n"); + + sprintf(prompt, "Change mode of %s from %o to %o", + fullname, + fileMode, + minmode); + if (yesorno(prompt) == TRUE) + changemode(fullname, minmode); + else + return; + break; + + case wrongOwner: + perrstr("The table file '%s' is not owned by the PP uid.\n", + fullname); + if (owner[0] == '\0') + (void) sprintf(prompt, + "Change owner of %s to %s", + fullname, + pplogin); + else + (void) sprintf(prompt, + "Change owner of %s from %s to %s", + fullname, + owner, + pplogin); + if (yesorno(prompt) == TRUE) + changeowner(fullname, + ppuid, + ppgid); + else + return; + break; + + default: + break; + } + } +} + +static int check_table(tbl) +Table *tbl; +{ + char fullname[MAXPATHLENGTH], owner[MAXPATHLENGTH], prompt[BUFSIZ]; + unsigned int fileMode = 0; + Retvals retval; + + if (tbl->tb_file[0] == '/') + sprintf(fullname,"%s",tbl->tb_file); + else + sprintf(fullname,"%s/%s",tbldfldir,tbl->tb_file); + + while ((retval = check_file(fullname, 0644, 0600, + &fileMode, owner)) != ok) { + switch (retval) { + case notExist: + perrstr("The file %s is not present for table %s\n", + fullname, tbl->tb_name); + return; + + case highMode: + perrstr("The table file '%s' has too high a permission mode.\n", + fullname); + sprintf(prompt, "Change mode of %s from %o to %o", + fullname, + fileMode, + 0644); + if (yesorno(prompt) == TRUE) + changemode(fullname, 0644); + else + break; + continue; + + case lowMode: + perrstr("The table file '%s' has too low a permission mode.\n", + fullname); + sprintf(prompt, "Change mode of %s from %o to %o", + fullname, + fileMode, + 0600); + if (yesorno(prompt) == TRUE) + changemode(fullname, 0600); + else + break; + continue; + + case wrongOwner: + perrstr("The table file '%s' is not owned by the PP uid.\n", + fullname); + if (owner[0] == '\0') + (void) sprintf(prompt, + "Change owner of %s to %s", + fullname, + pplogin); + else + (void) sprintf(prompt, + "Change owner of %s from %s to %s", + fullname, + owner, + pplogin); + if (yesorno(prompt) == TRUE) + changeowner(fullname, + ppuid, + ppgid); + else + break; + continue; + + default: + continue; + } + break; + } + + ptabss(tbl->tb_name,tbl->tb_show); + ptabss("file",fullname); + switch (tbl->tb_flags) { + case TB_DBM: + ptabss("Storage","database"); + break; + case TB_LINEAR: + ptabss("Storage", "linear"); + break; + default: + ptabss("Storage","unknown option"); + break; + } +} + +static int check_bps(channame, list) +char *channame; +LIST_BPT *list; +{ + LIST_BPT *ix; + + while (list != NULL) { + ix = bodies_all; + while (ix != NULL + && strcmp(ix->li_name, list->li_name) != 0) + ix = ix->li_next; + if (ix == NULLIST_BPT) + perrstr("The channel '%s' has an unrecognised bodypart '%s'.\n", + channame, + list->li_name); + list = list->li_next; + } +} + +static int check_hdrs(channame, list) +char *channame; +LIST_BPT *list; +{ + LIST_BPT *ix; + + while (list != NULL) { + ix = headers_all; + while (ix != NULL + && strcmp(ix->li_name, list->li_name) != 0) + ix = ix->li_next; + if (ix == NULLIST_BPT) + perrstr("The channel '%s' has an unrecognised header '%s'.\n", + channame, + list->li_name); + list = list->li_next; + } +} + +/* */ +static int yesorno(prompt) +char *prompt; +{ + if (monitoring == TRUE) { + printf("%s\n",prompt); + return FALSE; + } + + if (interactive == TRUE) { + char buf[BUFSIZ], + *ix; + int noAnswer = TRUE, + answer = FALSE; + + /* output a yes/no query and return result */ + while (noAnswer == TRUE) { + printf("%s (y/n) ?",prompt); + fgets(buf, BUFSIZ, stdin); + ix = buf; + while (*ix != NULL && isspace(*ix) != 0) + ix++; + switch (*ix) { + case 'y': + case 'Y': + noAnswer = FALSE; + answer = TRUE; + break; + case 'n': + case 'N': + noAnswer = FALSE; + answer = FALSE; + break; + default: + break; + } + } + return answer; + } else { + /* see if can do automatically and if so try it */ + pnewline(); + return TRUE; + } +} + +/* */ + +static int doneMsg; + +static int check_htable(name) +char *name; +{ + /* check table with hardwired name 'name' exists */ + if (tb_nm2struct(name) == NULLTBL) { + if (doneMsg == 0) { + printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n"); + doneMsg = 1; + } + perrstr("A table with the hardwired name '%s' is not present\n", + name); + } else if (verbose == TRUE) + pok("Hardwired table", name); + +} + +static int check_hprog(name, defaultdir) +char *name; +char *defaultdir; +{ + struct stat statbuf; + char fullname[MAXPATHLENGTH]; + + if (name[0] == '/') + strcat(fullname, name); + else + sprintf(fullname, "%s/%s", defaultdir, name); + + if (stat(fullname, &statbuf) != OK) + perrstr("The hardwired program %s does not exist\n", + fullname); + else if (!(statbuf.st_mode & S_IEXEC)) + perrstr("The hardwired program %s is not executable\n", + fullname); + else if (statbuf.st_uid != ppuid) + perrstr("WARNING hardwired program %s is not owned by '%s'\n", + fullname, + pplogin); + else if (verbose == TRUE) + /* print info */ + pok ("Hardwired program", name); +} + + +static int check_hchan(name) +char *name; +{ + + if (ch_nm2struct(name) == NULLCHAN) { + if (doneMsg == 0) { + printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n"); + doneMsg = 1; + } + perrstr("A channel with the hardwired name '%s' is not present\n", + name); + } else if (verbose == TRUE) + pok("Hardwired channel", name); +} + +static int check_hbp(name) +char *name; +{ + LIST_BPT *ix = bodies_all; + + while (ix != NULL + && strcmp(name, ix->li_name) != 0) + ix = ix->li_next; + if (ix == NULLIST_BPT) { + if (doneMsg == 0) { + printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n"); + doneMsg = 1; + } + perrstr("A bodypart with the hardwired name '%s' is not present\n", + name); + } else if (verbose == TRUE) + pok("Hardwired body part", name); +} + +static int check_hhdr(name) +char *name; +{ + LIST_BPT *ix = headers_all; + + while (ix != NULL + && strcmp(name, ix->li_name) != 0) + ix = ix->li_next; + if (ix == NULLIST_BPT) { + if (doneMsg == 0) { + printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n"); + doneMsg = 1; + } + perrstr("A header with the hardwired name '%s' is not present\n", + name); + } else if (verbose == TRUE) + pok("Hardwired header", name); +} + +static int check_hardwired() +{ + extern char *submit_prog, *uucpin_chan, *local_822_chan, + *alias_tbl, *channel_tbl, + *list_tbl, *user_tbl, *or_tbl, *or2rfc_tbl, + *rfc2or_tbl, *chan_auth_tbl, *rfc1148gateway_tbl, + *mta_auth_tbl, *user_auth_tbl, *qmgr_auth_tbl, + *hdr_822_bp, *hdr_p2_bp, *hdr_ipn_bp, *ia5_bp; + if (verbose == TRUE) + printf("\nChecking the various hardwired names (static.c)\n\n"); + if (verbose == TRUE) { + printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n"); + doneMsg = 1; + } else + doneMsg = 0; + + check_hprog(submit_prog, cmddfldir); + check_hchan(uucpin_chan); + check_hchan(local_822_chan); + check_htable(alias_tbl); + check_htable(channel_tbl); + check_htable(list_tbl); + check_htable(user_tbl); + check_htable(or_tbl); + check_htable(or2rfc_tbl); + check_htable(rfc2or_tbl); + check_htable(chan_auth_tbl); + check_htable(mta_auth_tbl); + check_htable(user_auth_tbl); + check_htable(rfc1148gateway_tbl); + check_hhdr(hdr_822_bp); + check_hhdr(hdr_p2_bp); + check_hhdr(hdr_ipn_bp); + check_hbp(ia5_bp); + check_htable(qmgr_auth_tbl); +} + +/* */ +static int makedirectory(name, mode) +char *name; +int mode; +{ + char *ix, *last; + struct stat statbuf; + + last = ix = name; + if (*ix == '/') ix++; + while (*ix != '\0') { + while (*ix != '\0' && *ix != '/') ix++; + if (*ix != '\0' ) { + *ix = '\0'; + if (stat(name, &statbuf) != OK) { + if (mkdir(name, mode) != 0) { + printf("!*!* Failed to make directory %s\n",name); + *ix = '/'; + return; + } else + printf("---> Made directory %s\n",name); + } + *ix = '/'; + last = ix; + ix++; + } else { + if (ix != last + 1) { + /* doesn't end with / so check last segment */ + if (stat(name, &statbuf) != OK) { + if (mkdir(name, mode) != 0) + printf("!*!* Failed to make directory %s\n",name); + else + printf("---> Made directory %s\n",name); + } + /* reached end so return */ + } + return; + } + } + +/* if (mkdir(name, mode) != 0) + printf("!*!* Failed to make directory %s\n",name); + else + printf("---> Made directory %s\n",name);*/ +} + +static int changeowner(file, uid, gid) +char *file; +int uid, gid; +{ + if (chown(file, uid, gid) != 0) + printf("!*!* Failed to change owner of %s to %o and group %o\n", + file, uid, gid); + else + printf("---> Changed owner of %s to %o\n", + file, uid); +} + +static int changemode(file, mode) +char *file; +int mode; +{ + if (chmod(file,mode) != 0) + printf("!*!* Failed to change mode of %s to %o\n", + file, mode); + else + printf("---> Changed mode of %s to %o\n", + file,mode); +} + +/* */ +/* output routines */ + +pnewline() +{ + if (verbose == TRUE) + printf("\n"); +} + +#ifdef lint +/*VARARGS1*/ +static void perrstr(str) +char *str; +{ + perrstr(str); +} +#else +static void perrstr(va_alist) +va_dcl +{ + char buf[BUFSIZ]; + va_list ap; + + va_start (ap); + _asprintf (buf, NULLCP, ap); + fputs (buf, stdout); + va_end (ap); +} +#endif + +#define tab 20 +static int pok(one,two) +char *one, + *two; +{ + if (verbose == TRUE) { + ptabss(one,two); + pnewline(); + } +} + +static int ptabss(one,two) +char *one, + *two; +{ + if (verbose == TRUE) + printf("%-*s: %s\n",tab, one, two); +} + +static int ptabsd(one,two) +char *one; +int two; +{ + if (verbose == TRUE) + printf("%-*s: %d\n",tab,one,two); +} + +static int check_822address(str) +char *str; +{ + ADDR *ad; + RP_Buf rp; + ad = adr_new(str, AD_822_TYPE, 0); +#ifdef UKORDER + if (rp_isbad(ad_parse(ad, &rp, CH_UK_PREF))) +#else + if (rp_isbad(ad_parse(ad, &rp, CH_USA_PREF))) +#endif + perrstr("rfc822 required address '%s' is an invalid address (reason = '%s').\n", + str, + ad->ad_parse_message); + adr_free(ad); +} + +static void check_dsap () +{ + int pid, cpid; + + if ((pid = tryfork ()) == -1) + return; + if (pid == 0) { /* child */ + dsap_init((char ***)NULL, (int *) NULL); + _exit (0); + } + else { +#ifdef SYSV + int w; + while ((cpid = wait (&w)) != pid && cpid != NOTOK) + continue; +#else + union wait w; + while ((cpid = wait (&w.w_status)) != pid && cpid != NOTOK) + continue; +#endif + if (!WIFSIGNALED(w) && WEXITSTATUS(w) == 0) { + dsap_init((char ***)NULL, (int *) NULL); + return; + } + perrstr("dsap error: probably quipu oid tables not installed?\n"); + } +} diff --git a/Tools/ckconfig/make b/Tools/ckconfig/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ckconfig/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckmail/Makefile b/Tools/ckmail/Makefile new file mode 100644 index 0000000..6ae2852 --- /dev/null +++ b/Tools/ckmail/Makefile @@ -0,0 +1,150 @@ +# Makefile for checkmail program +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/Makefile,v 6.0 1991/12/18 20:29:15 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:29:15 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ckmail.c ryinitiator.c +OBJS = ckmail.o ryinitiator.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h -I/usr/include/isode +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) + +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -u $(INCLUDE) +LINTLIBS = $(LINTISODE) ../../Lib/llib-lpp.ln + +PROGS = xcheckmail + +############################################################ +# +# Building Rules +# +############################################################ + +default: $(PROGS) + +############################################################ +# +# CheckMail +# +############################################################ + +checkmail: xcheckmail + +xcheckmail: $(OBJS) $(LIBPP) + -rm -f $@ + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +ckmail.o: ryinitiator.h +ryinitiator.o: ryinitiator.h + +saber_ckmail: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +############################################################ +# +# Misc stuff +# +############################################################ + + +install: inst-dir inst-checkmail +inst-checkmail: $(USRBINDIR)/checkmail +$(USRBINDIR)/checkmail: xcheckmail + -$(BACKUP) $@ zxcheckmail + -rm -f $@ + $(INSTALL) xcheckmail $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "checkmail tool installed normally"; echo "" + +inst-dir: $(TOOLDIR) + + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core a.out *.old $(PROGS) *.BAK zx* + + +lint: l-checkmail + +l-checkmail: $(SRCS) true + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +true:; + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ckmail.o: ckmail.c +ckmail.o: ../../h/util.h +ckmail.o: ../../h/config.h +ckmail.o: ../../h/ll_log.h +ckmail.o: ../../h/Qmgr-ops.h +ckmail.o: ../../h/Qmgr-types.h +ckmail.o: ../../h/retcode.h +ckmail.o: ../../h/adr.h +ckmail.o: ../../h/list_rchan.h +ckmail.o: ../../h/chan.h +ckmail.o: ../../h/table.h +ckmail.o: ../../h/list_bpt.h +ckmail.o: ../../h/auth.h +ckmail.o: ../../h/list_bpt.h +ckmail.o: ../../h/extension.h +ckmail.o: ../../h/mta.h +ckmail.o: ../../h/adr.h +ckmail.o: ../../h/list_bpt.h +ckmail.o: ../../h/aparse.h +ckmail.o: ../../h/ap.h +ckmail.o: ../../h/util.h +ckmail.o: ../../h/or.h +ckmail.o: ../../h/chan.h +ckmail.o: ../../h/auth.h +ckmail.o: ../../h/list_rchan.h +ckmail.o: ../../h/alias.h +ckmail.o: ../../h/ap.h +ckmail.o: ../../h/or.h +ckmail.o: ./ryinitiator.h +ryinitiator.o: ryinitiator.c +ryinitiator.o: ../../h/util.h +ryinitiator.o: ../../h/config.h +ryinitiator.o: ../../h/ll_log.h +ryinitiator.o: ../../h/qmgr.h +ryinitiator.o: ../../h/Qmgr-types.h +ryinitiator.o: ../../h/Qmgr-ops.h +ryinitiator.o: ./ryinitiator.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ckmail/ckmail.c b/Tools/ckmail/ckmail.c new file mode 100644 index 0000000..cc42904 --- /dev/null +++ b/Tools/ckmail/ckmail.c @@ -0,0 +1,771 @@ +/* ckmail.c: tool to allow user to query status of users msgs */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/ckmail.c,v 6.0 1991/12/18 20:29:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/ckmail.c,v 6.0 1991/12/18 20:29:15 jpo Rel $ + * + * $Log: ckmail.c,v $ + * Revision 6.0 1991/12/18 20:29:15 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "Qmgr-ops.h" /* operation definitions */ +#include "Qmgr-types.h" /* type definitions */ +#include "retcode.h" +#include +#include "adr.h" +#include "alias.h" +#include "ap.h" +#include "or.h" +#include +#include "ryinitiator.h" /* for generic interactive initiators */ + +/* */ +extern CMD_TABLE + atbl_ctrl_addrs[/* Env-crl-address */]; +extern char *loc_dom_site, *pplogin, *postmaster; +extern UTC utclocalise(); +/* DATA */ +static char *myservice = "pp qmgr"; + +/* OPERATIONS */ +static int do_readmsginfo(), + do_quit(), + p_msg(), + p_msginfo(), + p_recip(), + isPP(); + + +/* RESULTS */ +int readmsginfo_result(); + +/* ERRORS */ +int general_error (); + +#define readmsginfo_error general_error + +static struct client_dispatch dispatches[] = { +{ + "readmsginfo", operation_Qmgr_readmsginfo, + do_readmsginfo, +#ifdef PEPSY_VERSION + &_ZQmgr_mod, _ZReadMessageArgumentQmgr, +#else + free_Qmgr_readmsginfo_argument, +#endif + readmsginfo_result, readmsginfo_error, + "Read set of messages" +}, +{ + "quit", 0, do_quit, +#ifdef PEPSY_VERSION + NULL, 0, +#else + NULLIFP, +#endif + NULLIFP, NULLIFP, + "terminate the association and exit", +}, +{ + NULL +} +}; + +char *qhost; /* host to query */ +int first; +int all = FALSE; +int verbose = FALSE; +int time_out, first, do_loop = FALSE; +int haveUid, userId; +int debug = 0; +char *userAlias; +ADDR *ad; +char *name; +extern char *qmgr_hostname; +#define MAX_NUM_IGNORES 30 +static char *ignores[MAX_NUM_IGNORES]; +static int numIgnores; + +/* */ +main(argc, argv) +int argc; +char **argv; +{ + char *myname; + int opt; + extern char *optarg; + extern int optind; + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + sys_init(myname); + or_myinit(); + + qhost = strdup(qmgr_hostname); + all = FALSE; + numIgnores = 0; + ignores[numIgnores++] = "msg-clean"; + verbose = FALSE; + do_loop = FALSE; + first = 0; + haveUid = NOTOK; + userAlias = NULLCP; + while ((opt = getopt(argc, argv, "dvVaAh:H:l:L:u:U:i:I:c:C:")) != EOF) { + switch (opt) { + case 'a': + case 'A': + all = TRUE; + break; + case 'd': + debug = 1; + break; + case 'v': + case 'V': + verbose = TRUE; + break; + case 'h': + case 'H': + if (optarg[0] == '-') { + printf("Illegal host '%s' (starts with a '-')\n", + optarg); + exit(0); + } + qhost = optarg; + break; + case 'l': + case 'L': + if (optarg[0] =='-') { + printf ("Expecting time in minutes got '%s'", optarg); + exit(0); + } + time_out = atoi(optarg); + do_loop = TRUE; + break; + + case 'u': + case 'U': + if (isPP() == NOTOK) { + printf("You are not a mail superuser and so cannot use the '-u' flag\n"); + exit(0); + } + userAlias = optarg; + break; + + case 'i': + case 'I': + if (isPP() == NOTOK) { + printf("You are not a mail superuser and so cannot use the '-i' flag\n"); + exit(0); + } + userId = atoi(optarg); + haveUid = OK; + break; + + case 'c': + case 'C': + if (numIgnores >= MAX_NUM_IGNORES) { + printf("can only ignore %d channels\n", MAX_NUM_IGNORES); + exit (0); + } + ignores[numIgnores++] = optarg; + break; + default: + printf("usage: %s [-v] [-a] [-c channel] [-h host] [-l time] [-u user] [-i uid]\n",argv[0]); + exit(0); + } + } + fillinaddr(); + if (verbose == TRUE) { + printf("Please wait while attempt to connect to %s....",qhost); + fflush(stdout); + } + if (do_loop == TRUE) { + while (TRUE) { + (void) ryinitiator (myname, qhost, + argc, argv, myservice, + table_Qmgr_Operations, + dispatches, do_quit); + first++; + sleep (time_out*60); + } + } else + (void) ryinitiator (myname, qhost, + argc, argv, myservice, + table_Qmgr_Operations, + dispatches, do_quit); + + exit(0); +} + +/* */ +/* OPERATIONS */ + +/* ARGSUSED */ +static int do_quit (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; +char **arg; +{ + struct AcSAPrelease acrs; + register struct AcSAPrelease *acr = &acrs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + + if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci) == NOTOK) + acs_adios (aca, "A-RELEASE.REQUEST"); + + if (!acr -> acr_affirmative) { + (void) AcUAbortRequest (sd, NULLPEP, 0, aci); + adios (NULLCP, "Release rejected by peer: %d", acr -> acr_reason); + } + + ACRFREE (acr); + +/* exit (0);*/ + +} + +static struct type_Qmgr_Filter *fillin_1_to(name) +char *name; +{ + struct type_Qmgr_Filter *ret = (struct type_Qmgr_Filter *) + calloc(1, sizeof(*ret)); + ret->recipient = str2qb(name, strlen(name), 1); + return ret; +} + +static struct type_Qmgr_Filter *fillin_1_from(name) +char *name; +{ + struct type_Qmgr_Filter *ret = (struct type_Qmgr_Filter *) + calloc(1, sizeof(*ret)); + ret->originator = str2qb(name, strlen(name), 1); + return ret; +} + +static struct type_Qmgr_FilterList *fillinfilters(args) +char **args; +{ + struct type_Qmgr_FilterList *head = NULL, + *tail = NULL, + *ix; + + ix = (struct type_Qmgr_FilterList *) calloc(1, sizeof(*ix)); + ix->Filter = fillin_1_from(ad->ad_r822adr); + if (head == NULL) + head = tail = ix; + else { + tail->next = ix; + tail = ix; + } + + ix = (struct type_Qmgr_FilterList *) calloc(1, sizeof(*ix)); + ix->Filter = fillin_1_from(ad->ad_r400adr); + if (head == NULL) + head = tail = ix; + else { + tail->next = ix; + tail =ix; + } + if (all == FALSE) + return head; + + ix = (struct type_Qmgr_FilterList *) calloc(1, sizeof(*ix)); + ix->Filter = fillin_1_to(ad->ad_r822adr); + if (head == NULL) + head = tail = ix; + else { + tail->next = ix; + tail = ix; + } + + ix = (struct type_Qmgr_FilterList *) calloc(1, sizeof(*ix)); + ix->Filter = fillin_1_to(ad->ad_r400adr); + if (head == NULL) + head = tail = ix; + else { + tail->next = ix; + tail =ix; + } + return head; +} + +/* ARGSUSED */ +static do_readmsginfo (sd, ds, args, arg) +int sd; +struct client_dispatch *ds; +char **args; /* contains various filters */ +struct type_Qmgr_ReadMessageArgument **arg; +{ + char *str; + UTC utc; + + *arg = (struct type_Qmgr_ReadMessageArgument *) malloc(sizeof(**arg)); + + /* fillin time */ + utc = (UTC) malloc (sizeof(struct UTCtime)); + + utc->ut_flags = UT_SEC; + utc->ut_sec = 0; + str = utct2str(utc); + (*arg)->interval = str2qb(str, strlen(str), 1); + (*arg)->filters = fillinfilters(args); + if (debug) print_filterlist ((*arg)->filters); + return OK; +} + +/* */ +/* RESULTS */ + +static int isIgnored(chan) +char *chan; +{ + int ix; + + for (ix = 0;ix < numIgnores;ix++) + if (lexequ(ignores[ix], chan) == 0) + return 1; + return 0; +} + +static char *getChan(recip) +struct type_Qmgr_RecipientInfo *recip; +{ + struct type_Qmgr_ChannelList *ic; + int ix; + char *chan = NULLCP; + + if (!recip) return NULLCP; + + for (ix = 0, ic = recip->channelList; + ix < recip->channelsDone && ic != NULL; + ix++, ic = ic -> next); + + if (ic && ic -> Channel) { + chan = qb2str(ic -> Channel); + if (isIgnored(chan)) { + free(chan); + chan = NULLCP; + } + } + return chan; +} + +static int isSender(msg) +struct type_Qmgr_MsgStruct *msg; +{ + char *orig = qb2str(msg->recipientlist->RecipientInfo->user); + int retval = 1; + if (strcmp(orig, ad->ad_r822adr) != 0 + && strcmp(orig, ad->ad_r400adr) != 0) + /* to user */ + retval = 0; + free(orig); + return retval; +} + +static int isPrintable(msg, sender) +struct type_Qmgr_MsgStruct *msg; +int sender; +{ + char *chan = NULLCP; + struct type_Qmgr_RecipientList *ix; + + if (!sender) + return 1; + /* go through recip and see if getChan */ + ix = msg->recipientlist; + ix = ix -> next; /* skip past sender */ + while (ix != NULL && chan == NULLCP) { + chan = getChan(ix -> RecipientInfo); + ix = ix -> next; + } + if (chan == NULLCP) + return 0; + free(chan); + return 1; +} + +static int isPrintableMsg(msgs) +struct type_Qmgr_MsgStructList *msgs; +{ + struct type_Qmgr_MsgStructList *ix = msgs; + int printable = 0; + + while (ix != NULL && printable == 0) { + printable = isPrintable(ix -> MsgStruct, + isSender(ix->MsgStruct)); + ix = ix -> next; + } + return printable; +} + + +/* ARGSUSED */ +int readmsginfo_result (sd, id, dummy, result, roi) +int sd, + id, + dummy; +register struct type_Qmgr_MsgList *result; +struct RoSAPindication *roi; +{ + struct type_Qmgr_MsgStructList *ix; + if (result == NULL || result->msgs == NULL + || !isPrintableMsg(result->msgs)) { + if (do_loop == FALSE || first == 0) + printf("There are no messages %s %s at %s\n", + (all == TRUE) ? "to or from" : "from", + name, qhost); + } else { + printf("The messages %s %s on %s are as follows:\n", + (all == TRUE) ? "to or from" : "from", + name, qhost); + ix = result->msgs; + while (ix != NULL) { + p_msg(ix->MsgStruct, isSender(ix->MsgStruct)); + ix = ix->next; + } + } + return OK; +} + +static int p_msg(msg, sender) +struct type_Qmgr_MsgStruct *msg; +{ + int len, tlen; + struct type_Qmgr_RecipientList *ix; + + first = 1; + + if (!sender) { + /* to user */ + if ((len = p_msginfo(msg->messageinfo, sender)) == 0) + return; + printf(" is from"); + tlen = len + strlen(" is from") + 1; + p_recip(msg->recipientlist->RecipientInfo, tlen, 1); + if (verbose) { + printf ("\n%*s is pending delivery to", len, ""); + first = 1; + for (ix = msg->recipientlist -> next; + ix; ix = ix -> next) + p_recip (ix -> RecipientInfo, len, 0); + } + printf("\n"); + + } else if (isPrintable(msg, sender)) { + ix = msg->recipientlist; + if ((len = p_msginfo(msg->messageinfo, sender)) == 0) + return; + if (verbose) { + printf (" is from"); + p_recip (ix -> RecipientInfo, len, 1); + printf ("\n%*s", len, ""); + first = 1; + } + ix = ix -> next; + if (ix != NULL) { + printf(" is pending delivery to"); + len += strlen(" is pending delivery to") +1; + while (ix != NULL) { + p_recip(ix->RecipientInfo, len, 0); + ix = ix -> next; + } + } else + printf(" is waiting for notification/deletion"); + printf("\n"); + } +} + +static int p_msginfo(info, sender) +struct type_Qmgr_PerMessageInfo *info; +int sender; +{ + char *id, buf[BUFSIZ]; + int retval; + UTC ut, lut; + + id = qb2str(info->queueid); + retval = strlen(id); + printf("%s",id); + free(id); + if (info -> uaContentId != NULL) { + id = qb2str (info -> uaContentId); + printf (" with content id '%s'\n%*s", id, retval, " "); + free(id); + } + if (info -> age != NULL) { + id = qb2str(info -> age); + ut = str2utct(id, strlen(id)); + lut = utclocalise (ut); + if (UTC2rfc (lut, buf) != NOTOK) + printf (" submitted at %s\n%*s", buf, retval, " "); + if (lut) free ((char *) lut); + free(id); + } + if (verbose != TRUE) + return retval; + if (info -> expiryTime != NULL) { + id = qb2str (info -> expiryTime); + ut = str2utct(id, strlen(id)); + lut = utclocalise(ut); + if (UTC2rfc (lut, buf) != NOTOK) + printf (" will expire at %s\n%*s", buf, retval, " "); + if (lut) free ((char *) lut); + free(id); + } + if (info -> priority && info -> priority -> parm != 1) + printf (" priority %d\n%*s", info -> priority -> parm, + retval, ""); + if (info -> size) + printf (" size %d\n%*s", info -> size, retval, ""); + if (info -> numberWarningsSent) + printf (" %d warnings sent\n%*s", info -> numberWarningsSent, + retval, ""); + if ((info -> optionals & opt_Qmgr_PerMessageInfo_errorCount) && + info -> errorCount) + printf (" %d errors accumulated\n%*s", info -> errorCount, + retval, ""); + + if (info -> deferredTime != NULL) { + id = qb2str (info -> deferredTime); + ut = str2utct(id, strlen(id)); + lut = utclocalise(ut); + if (UTC2rfc (lut, buf) != NOTOK) + printf (" deferred until %s\n%*s", buf, retval, " "); + if (lut) free ((char *) lut); + free(id); + } + + return retval; +} + +static int p_recip(recip, tab, sender) +struct type_Qmgr_RecipientInfo *recip; +int tab; +int sender; +{ + char *usr, *chan = NULLCP; + + if (!sender && (chan = getChan(recip)) == NULLCP) + return; + + if (first != 1) + printf(",\n%*s", tab, " "); + else + printf(" "); + first = 0; + + usr = qb2str(recip->user); + + if (sender || chan == NULLCP) + printf("%s", usr); + else { + printf("%s (channel = %s)",usr, chan); + free(chan); + } + free(usr); +} + +/* */ +/* ERRORS */ + +/* ARGSUSED */ +general_error (sd, id, error, parameter, roi) +int sd, + id, + error; +caddr_t parameter; +struct RoSAPindication *roi; +{ + register struct RyError *rye; + + if (error == RY_REJECT) { + advise (NULLCP, "%s", RoErrString ((int) parameter)); + return OK; + } + + if (rye = finderrbyerr (table_Qmgr_Errors, error)) + advise (NULLCP, "%s", rye -> rye_name); + else + advise (NULLCP, "Error %d", error); + + return OK; +} + +/* */ +/* fillin an ADDR struct for person running this program */ + +fillinaddr() +{ + struct passwd *pwd; + RP_Buf rp; + + if (userAlias != NULLCP) { + if ((pwd = getpwnam(userAlias)) == NULL) + name = userAlias; + else name = pwd -> pw_name; + } else if (haveUid == OK) { + if ((pwd = getpwuid(userId)) == NULL) + adios (NULLCP, + "Cannot get passwd entry for uid '%d'", + userId); + name = pwd -> pw_name; + } else { + if ((pwd = getpwuid(getuid())) == NULL) + adios(NULLCP,"Cannot get your password entry"); + name = pwd -> pw_name; + } + ad = adr_new(name, AD_ANY_TYPE, 0); +#ifdef UKORDER + if (rp_isbad(ad_parse(ad, &rp, CH_UK_PREF))) +#else + if (rp_isbad(ad_parse(ad, &rp, CH_USA_PREF))) +#endif + adios(NULLCP, + "Address parse failed\nReason : %s\n",rp.rp_line); +} + +static int isPP() +{ + RP_Buf rp; + int uid; + struct passwd *tmp; + ADDR *tmpadr; + + if ((uid = getuid()) == 0) + /* super user */ + return OK; + if ((tmp = getpwuid(uid)) == NULL) { + printf("Cannot get your passwd entry\n"); + exit(0); + } + tmpadr = adr_new(tmp->pw_name, AD_ANY_TYPE, 0); + +#ifdef UKORDER + if (rp_isbad(ad_parse(tmpadr, &rp, CH_UK_PREF))) { +#else + if (rp_isbad(ad_parse(tmpadr, &rp, CH_USA_PREF))) { +#endif + printf("Cannot parse your mail address\nReason : %s\n",rp.rp_line); + exit(1); + } + + if ((strcmp(tmp->pw_name, pplogin) == 0) + || (strcmp(tmpadr->ad_r822adr, postmaster) == 0)) { + adr_free(tmpadr); + return OK; + } + adr_free(tmpadr); + return NOTOK; +} + +static int indent = 0; + +static void print_qb (str, qb) +char *str; +struct qbuf *qb; +{ + struct qbuf *qp; + + printf ("%*s", indent * 2, ""); + if (str) + printf ("%s: ", str); + for (qp = qb -> qb_forw; qp != qb; qp = qp -> qb_forw) + printf ("%*.*s", qp -> qb_len, qp -> qb_len, + qp -> qb_data); + putchar ('\n'); +} + +static void print_eit (eit) +struct type_Qmgr_EncodedInformationTypes *eit; +{ + printf("%*sEncodedInformationTypes\n", indent * 2, ""); + indent ++; + while (eit) { + print_qb (NULLCP, eit -> PrintableString); + eit = eit -> next; + } + indent --; +} + +static void print_priority (prio) +struct type_Qmgr_Priority *prio; +{ + printf ("%*sPriority: ", indent * 2, ""); + switch (prio -> parm) { + case int_Qmgr_Priority_low: + printf ("low\n"); + break; + case int_Qmgr_Priority_normal: + printf ("normal\n"); + break; + case int_Qmgr_Priority_high: + printf ("high\n"); + break; + default: + printf ("%d\n", prio -> parm); + break; + } +} + +static void print_mpdu (mpdu) +struct type_Qmgr_MPDUIdentifier *mpdu; +{ + printf ("%*smpduiden\n", indent * 2, ""); +} + +static void print_filter(f) +struct type_Qmgr_Filter *f; +{ + printf ("%*sFilter\n", indent * 2, ""); + indent ++; + if (f -> contenttype) + print_qb ("ContentType", f -> contenttype); + if (f -> eit) + print_eit (f->eit); + if (f -> priority) + print_priority (f->priority); + if (f -> moreRecentThan) + print_qb ("moreRecentThan", f -> moreRecentThan); + if (f -> earlierThan) + print_qb ("earlierThan", f -> earlierThan); + if (f -> maxSize) + printf ("%*smaxsize: %d\n", indent * 2, "", f -> maxSize); + if (f -> originator) + print_qb ("Originator", f -> originator); + if (f -> recipient) + print_qb ("Recipient", f -> recipient); + if (f -> channel) + print_qb ("Channel", f -> channel); + if (f -> mta) + print_qb ("Mta", f->mta); + if (f -> queueid) + print_qb ("Queueid", f -> queueid); + if (f -> mpduiden) + print_mpdu(f -> mpduiden); + if (f -> uaContentId) + print_qb ("UAContentId", f -> uaContentId); + indent --; +} + +print_filterlist (filterl) +struct type_Qmgr_FilterList *filterl; +{ + while(filterl) { + print_filter (filterl -> Filter); + filterl = filterl -> next; + } +} diff --git a/Tools/ckmail/make b/Tools/ckmail/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ckmail/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckmail/ryinitiator.c b/Tools/ckmail/ryinitiator.c new file mode 100644 index 0000000..f7b2eb9 --- /dev/null +++ b/Tools/ckmail/ryinitiator.c @@ -0,0 +1,330 @@ +/* ryinitiator.c - generic interactive initiator */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/ryinitiator.c,v 6.0 1991/12/18 20:29:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/ryinitiator.c,v 6.0 1991/12/18 20:29:15 jpo Rel $ + * + * $Log: ryinitiator.c,v $ + * Revision 6.0 1991/12/18 20:29:15 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "util.h" +#include "qmgr.h" +#include "ryinitiator.h" + + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + + +static int invoke(); +/* DATA */ + +static char *myname = "ckmail"; + + +extern char *isodeversion; +extern int verbose; + +/* INITIATOR */ + +ryinitiator (name, host, argc, argv, myservice, ops, dispatches, quit) +char *name, + *host; +int argc; +char **argv, + *myservice; +struct RyOperation ops[]; +struct client_dispatch *dispatches; +IFP quit; +{ + int sd; + register struct client_dispatch *ds; + struct SSAPref sfs; + register struct SSAPref *sf; + register struct PSAPaddr *pa; + struct AcSAPconnect accs; + register struct AcSAPconnect *acc = &accs; + struct AcSAPindication acis; + register struct AcSAPindication *aci = &acis; + register struct AcSAPabort *aca = &aci -> aci_abort; + AEI aei; + OID ctx, + pci; + struct PSAPctxlist pcs; + register struct PSAPctxlist *pc = &pcs; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + if (name != NULLCP) + myname = strdup(name); + if ((aei = _str2aei (host, myservice, QMGR_CTX_OID, + 0, dap_user, dap_passwd)) == NULLAEI) + adios (NULLCP, "%s-%s: unknown application-entity", + host, myservice); + if ((pa = aei2addr (aei)) == NULLPA) + adios (NULLCP, "address translation failed"); + + if ((ctx = oid_cpy (QMGR_AC)) == NULLOID) + adios (NULLCP, "out of memory"); + if ((pci = oid_cpy (QMGR_PCI)) == NULLOID) + adios (NULLCP, "out of memory"); + pc -> pc_nctx = 1; + pc -> pc_ctx[0].pc_id = 1; + pc -> pc_ctx[0].pc_asn = pci; + pc -> pc_ctx[0].pc_atn = NULLOID; + + if ((sf = addr2ref (host)) == NULL) { + sf = &sfs; + (void) bzero ((char *) sf, sizeof *sf); + } + + for (ds = dispatches; ds -> ds_name; ds++) + if (strcmp (ds -> ds_name, "readmsginfo") == 0) + break; + if (ds -> ds_name == NULL) + adios (NULLCP, "unknown operation \"%s\"", "newmessage"); + + if (AcAssocRequest (ctx, NULLAEI, aei, NULLPA, pa, pc, NULLOID, + 0, ROS_MYREQUIRE, SERIAL_NONE, 0, sf, NULLPEP, 0, NULLQOS, + acc, aci) + == NOTOK) + acs_adios (aca, "A-ASSOCIATE.REQUEST"); + + if (acc -> acc_result != ACS_ACCEPT) { + adios (NULLCP, "Association rejected: [%s]", + AcErrString (acc -> acc_result)); + } + sd = acc -> acc_sd; + ACCFREE (acc); + + if (RoSetService (sd, RoPService, roi) == NOTOK) + ros_adios (rop, "set RO/PS fails"); + if (verbose == TRUE) { + printf("connected\n"); + fflush(stdout); + } + invoke (sd, ops, ds, argv); + + (*quit) (sd, (struct client_dispatch *) NULL, (char **) NULL, (caddr_t *) NULL); +} + +/* */ + +static invoke (sd, ops, ds, args) +int sd; +struct RyOperation ops[]; +register struct client_dispatch *ds; +char **args; +{ + int result; + caddr_t in; + struct RoSAPindication rois; + register struct RoSAPindication *roi = &rois; + register struct RoSAPpreject *rop = &roi -> roi_preject; + + in = NULL; + + if (ds -> ds_argument && (*ds -> ds_argument) (sd, ds, args, &in) != OK) { + printf("Failed in attempting %s\n",*args); + } + + switch (result = RyStub (sd, ops, ds -> ds_operation, RyGenID (sd), + NULLIP, in, ds -> ds_result, + ds -> ds_error, ROS_SYNC, roi)) { + case NOTOK: /* failure */ + if (ROS_FATAL (rop -> rop_reason)) + ros_adios (rop, "STUB"); + ros_advise (rop, "STUB"); + break; + + case OK: /* got a result/error response */ + break; + + case DONE: /* got RO-END? */ + adios (NULLCP, "got RO-END.INDICATION"); + /* NOTREACHED */ + + default: + adios (NULLCP, "unknown return from RyStub=%d", result); + /* NOTREACHED */ + } + +#ifdef PEPSY_VERSION + if (ds -> ds_fr_mod && in) + fre_obj (in, ds -> ds_fr_mod -> md_dtab[ds -> ds_fr_index], + ds -> ds_fr_mod); +#else + if (ds -> ds_free && in) + (*ds -> ds_free)(in); +#endif +} + +/* */ + +void ros_adios (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + ros_advise (rop, event); + + _exit (1); +} + + +void ros_advise (rop, event) +register struct RoSAPpreject *rop; +char *event; +{ + char buffer[BUFSIZ]; + + if (rop -> rop_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), + rop -> rop_cc, rop -> rop_cc, rop -> rop_data); + else + (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); + + advise (NULLCP, "%s: %s", event, buffer); +} + +/* */ + +void acs_adios (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + acs_advise (aca, event); + + _exit (1); +} + + +void acs_advise (aca, event) +register struct AcSAPabort *aca; +char *event; +{ + char buffer[BUFSIZ]; + + if (aca -> aca_cc > 0) + (void) sprintf (buffer, "[%s] %*.*s", + AcErrString (aca -> aca_reason), + aca -> aca_cc, aca -> aca_cc, aca -> aca_data); + else + (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); + + advise (NULLCP, "%s: %s (source %d)", event, buffer, + aca -> aca_source); +} + +/* */ + +#ifndef lint +static void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + + +#ifndef lint +void ryr_advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} +#else +/* VARARGS */ + +void ryr_advise (what, fmt) +char *what, + *fmt; +{ + ryr_advise (what, fmt); +} +#endif diff --git a/Tools/ckmail/ryinitiator.h b/Tools/ckmail/ryinitiator.h new file mode 100644 index 0000000..bcc9207 --- /dev/null +++ b/Tools/ckmail/ryinitiator.h @@ -0,0 +1,44 @@ +/* ryinitiator.h - include file for the generic interactive initiator */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Tools/ckmail/RCS/ryinitiator.h,v 6.0 1991/12/18 20:29:15 jpo Rel $ + * + * $Log: ryinitiator.h,v $ + * Revision 6.0 1991/12/18 20:29:15 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGRLOAD_RYINITIATOR +#define _H_QMGRLOAD_RYINITIATOR + +#include + + +struct client_dispatch { + char *ds_name; + int ds_operation; + + IFP ds_argument; +#ifdef PEPSY_VERSION + modtyp *ds_fr_mod; + int ds_fr_index; +#else + IFP ds_free; +#endif + IFP ds_result; + IFP ds_error; + + char *ds_help; +} Client_dispatch; + + +void adios(), advise(); +void acs_adios(), acs_advise(); +void ros_adios(), ros_advise(); +int ryinitiator(); + +#endif diff --git a/Tools/ckor/Makefile b/Tools/ckor/Makefile new file mode 100644 index 0000000..b8fb999 --- /dev/null +++ b/Tools/ckor/Makefile @@ -0,0 +1,118 @@ +# OR address mappings +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ckor/RCS/Makefile,v 6.0 1991/12/18 20:29:26 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:29:26 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = or2rfc.c rfc2or.c +OBJS = or2rfc.o rfc2or.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xor2rfc xrfc2or + +default: $(PROGS) +all: default +lint: l-rfc2or l-or2rfc + +install: inst-dir inst-rfc2or inst-or2rfc +inst-dir: $(TOOLDIR) + + +or2rfc: xor2rfc +xor2rfc: or2rfc.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ or2rfc.o $(LIBPP) $(LIBSYS) +l-or2rfc: or2rfc.c + $(LINT) $(LINTFLAGS) or2rfc.c $(LINTLIBS) +inst-or2rfc: $(TOOLDIR)/or2rfc +$(TOOLDIR)/or2rfc: xor2rfc + -$(BACKUP) $@ zxor2rfc + rm -f $@ + $(INSTALL) xor2rfc $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "or2rfc tool inst-talled normally"; echo "" + + +rfc2or: xrfc2or +xrfc2or: rfc2or.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ rfc2or.o $(LIBPP) $(LIBSYS) +l-rfc2or: rfc2or.c + $(LINT) $(LINTFLAGS) rfc2or.c $(LINTLIBS) +inst-rfc2or: $(TOOLDIR)/rfc2or +$(TOOLDIR)/rfc2or: xrfc2or + -$(BACKUP) $@ zxrfc2or + rm -f $@ + $(INSTALL) xrfc2or $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "rfc2or tool inst-talled normally"; echo "" + + + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) +define: + $(DEFINE) Makefile + + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +or2rfc.o: or2rfc.c +or2rfc.o: ../../h/head.h +or2rfc.o: ../../h/util.h +or2rfc.o: ../../h/config.h +or2rfc.o: ../../h/ll_log.h +or2rfc.o: ../../h/retcode.h +or2rfc.o: ../../h/or.h +rfc2or.o: rfc2or.c +rfc2or.o: ../../h/head.h +rfc2or.o: ../../h/util.h +rfc2or.o: ../../h/config.h +rfc2or.o: ../../h/ll_log.h +rfc2or.o: ../../h/retcode.h +rfc2or.o: ../../h/or.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ckor/make b/Tools/ckor/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ckor/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ckor/or2rfc.c b/Tools/ckor/or2rfc.c new file mode 100644 index 0000000..2ec1a18 --- /dev/null +++ b/Tools/ckor/or2rfc.c @@ -0,0 +1,105 @@ +/* or2rfc.c: Parses an RFC address using the tables or, or2rfc and rfc2or */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckor/RCS/or2rfc.c,v 6.0 1991/12/18 20:29:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckor/RCS/or2rfc.c,v 6.0 1991/12/18 20:29:26 jpo Rel $ + * + * $Log: or2rfc.c,v $ + * Revision 6.0 1991/12/18 20:29:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "or.h" + +extern char or_error[]; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +main (argc, argv) +int argc; +char *argv[]; +{ + char buf[BUFSIZ]; + int i = 1; + + sys_init (argv[0]); + + if (or_init() == NOTOK ) { + printf ("or_init() failed\n"); + exit (1); + } + + if (argc == 1) + while (gets (buf) != NULL) + parse_address (buf); + else + while (i < argc) + parse_address (argv[i++]); +} + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int parse_address (str) +char *str; +{ + char rfcbuf [BUFSIZ]; + char x400buf [BUFSIZ]; + OR_ptr or = NULLOR; + + or_error[0] = x400buf[0] = rfcbuf[0] = '\0'; + + if ((or = or_std2or (str)) == NULLOR) + goto error; + + if (or_or2rfc (or, rfcbuf) == NOTOK) + goto error; + + if (isstr (or_error)) + goto error; + + or_free (or); + or = NULLOR; + + if (or_rfc2or (rfcbuf, &or) == NOTOK) + goto error; + + if (isstr (or_error)) + goto error; + + or_or2std (or, x400buf, FALSE); + + printf ("\n%s -> (rfc822) %s\n%-*s -> (x400) %s\n", + str, rfcbuf, strlen(str), "", x400buf); + + goto finish; + + +error: ; + printf ("\nAddress parsing failed \nReason : %s\n", or_error); + if (rfcbuf[0] != '\0') + printf ("%s -> (rfc822) %s\n", str, rfcbuf); + if (x400buf[0] != '\0') + printf ("%s -> (x400) %s\n", str, x400buf); + +finish: ; + printf ("\n"); + fflush (stdout); + if (or) + or_free (or); + return; +} diff --git a/Tools/ckor/rfc2or.c b/Tools/ckor/rfc2or.c new file mode 100644 index 0000000..a2d3c71 --- /dev/null +++ b/Tools/ckor/rfc2or.c @@ -0,0 +1,101 @@ +/* rfc2or.c: Parses an RFC address using the tables or, or2rfc and rfc2or */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckor/RCS/rfc2or.c,v 6.0 1991/12/18 20:29:26 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ckor/RCS/rfc2or.c,v 6.0 1991/12/18 20:29:26 jpo Rel $ + * + * $Log: rfc2or.c,v $ + * Revision 6.0 1991/12/18 20:29:26 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "or.h" + +extern char or_error[]; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +main (argc, argv) +int argc; +char *argv[]; +{ + char buf[BUFSIZ]; + int i = 1; + + sys_init (argv[0]); + + if (or_init() == NOTOK ) { + printf ("or_init() failed\n"); + exit (1); + } + + if (argc == 1) + while (gets (buf) != NULL) + parse_address (buf); + else + while (i < argc) + parse_address (argv[i++]); +} + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int parse_address (str) +char *str; +{ + char rfcbuf [BUFSIZ]; + char x400buf [BUFSIZ]; + OR_ptr or = NULLOR; + + or_error[0] = x400buf[0] = rfcbuf[0] = '\0'; + + /* --- Perform the x400 addressing --- */ + if ((or_rfc2or (str, &or) != OK) || (or == NULLOR)) + goto error; + + if (isstr (or_error)) + goto error; + + or_or2std (or, x400buf, FALSE); + + /* --- Perform the rfc822 address parsing --- */ + if (or_or2rfc (or, rfcbuf) == NOTOK) + goto error; + + if (isstr (or_error)) + goto error; + + printf ("\n%s -> (x400) %s\n%-*s -> (rfc822) %s\n", + str, x400buf, strlen(str), "", rfcbuf); + + goto finish; + + +error: ; + printf ("Address parsing rfc2or failed \nReason : %s\n", or_error); + if (rfcbuf[0] != '\0') + printf ("%s -> (rfc822) %s\n", str, rfcbuf); + if (x400buf[0] != '\0') + printf ("%s -> (x400) %s\n", str, x400buf); + + +finish: ; + printf ("\n"); + fflush (stdout); + or_free (or); + return; +} diff --git a/Tools/dbmbuild/Makefile b/Tools/dbmbuild/Makefile new file mode 100644 index 0000000..afc3040 --- /dev/null +++ b/Tools/dbmbuild/Makefile @@ -0,0 +1,100 @@ +# Build the PP database +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/dbmbuild/RCS/Makefile,v 6.0 1991/12/18 20:29:34 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:29:34 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = dbmbuild.c +OBJS = dbmbuild.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xdbmbuild + +default: $(PROGS) + +dbmbuild: xdbmbuild +xdbmbuild: dbmbuild.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ dbmbuild.o $(LIBPP) $(LIBSYS) + +dbmbuild.o: dbmbuild.c + $(OLDCC) -c $(CFLAGS) dbmbuild.c + +install: inst-dir inst-dbmbuild + +inst-dbmbuild: $(CMDDIR)/dbmbuild +$(CMDDIR)/dbmbuild: xdbmbuild + -$(BACKUP) $@ zxdbmbuild + rm -f $@ + $(INSTALL) xdbmbuild $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dbmbuild installed normally"; echo "" + +inst-dir: $(CMDDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxdbmbuild *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +dbmbuild.o: dbmbuild.c +dbmbuild.o: ../../h/head.h +dbmbuild.o: ../../h/util.h +dbmbuild.o: ../../h/config.h +dbmbuild.o: ../../h/ll_log.h +dbmbuild.o: ../../h/retcode.h +dbmbuild.o: ../../h/util.h +dbmbuild.o: ../../h/chan.h +dbmbuild.o: ../../h/table.h +dbmbuild.o: ../../h/list_bpt.h +dbmbuild.o: ../../h/dbase.h +dbmbuild.o: ../../h/config.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/dbmbuild/dbmbuild.c b/Tools/dbmbuild/dbmbuild.c new file mode 100644 index 0000000..ea3c4e5 --- /dev/null +++ b/Tools/dbmbuild/dbmbuild.c @@ -0,0 +1,742 @@ +/* dbmbuild: build the database of information */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/dbmbuild/RCS/dbmbuild.c,v 6.0 1991/12/18 20:29:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/dbmbuild/RCS/dbmbuild.c,v 6.0 1991/12/18 20:29:34 jpo Rel $ + * + * $Log: dbmbuild.c,v $ + * Revision 6.0 1991/12/18 20:29:34 jpo + * Release 6.0 + * + */ + + + +/* --------------------------------------------------------------------------- + + + Database builder for PP address database + + Command line: + dbmbuild [-flags] [outfile] + + where flags are: + d - debugging output + v - verbose output + k - keep going if a table is missing + n - don't make a new database file + + output-file is name of EXISTING dbm file to insert entires. + Note it is two files, an output-file.dir and an output-file.pag. + +--------------------------------------------------------------------------- */ + + +#include "head.h" +#include "util.h" +#include "chan.h" +#include "dbase.h" +#include "sys.file.h" +#include + +extern int errno; +extern char *tbldfldir, + *ppdbm; + +#ifdef GDBM +GDBM_FILE thedb; +#define store(x,y) gdbm_store (thedb, x, y, GDBM_REPLACE) +#define fetch(x) gdbm_fetch (thedb, x) +#else +#ifndef GCC_DBM_OK +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ + #error GCC and dbm do not get along on a sparc - compile with cc. +#endif +#endif +#endif + +#ifdef NDBM +DBM *thedb; +#define store(x,y) dbm_store (thedb, (x), (y), DBM_REPLACE) +#define fetch(x) dbm_fetch (thedb, (x)) +#endif + + +int error, + Debug, + Verbose, + newflag = 1, + keepgoing; + +char dbfile [128], + *dblock; + +static char *myname; +static short tb_nopen; /* -- no of opened file descriptors -- */ +void adios (), advise (); + +static int theinit (), theend (); +static int dbfinit (), dbfclose (); +static int process (); +static int install (); +static int prdatum (); +static int check (); +static int tb_open (), tb_close (), tb_free (); +static void cleanup (); + +/* --------------------- Begin Routines -------------------------------- */ + + +/* +Process arguments, set flags and invoke file processing. +then clean up and exit properly. +*/ + + +main (argc, argv) +char **argv; +{ + register Table *tp; + char *p, + *outfile = NULLCP; + int ind; + int opt; + extern char *optarg; + extern int optind; + + myname = argv[0]; + sys_init (myname); + + while ((opt = getopt (argc, argv, "dknv")) != EOF) { + switch (opt) { + case 'd': + Debug++; + break; + case 'k': + keepgoing++; + break; + case 'n': + newflag = 0; + break; + case 'v': + Verbose++; + break; + default: + adios (NULLCP, "Usage: %s [-vnkd] [database]", myname); + } + } + + if (optind < argc) + optarg = argv[optind++]; + + /* -- use default database -- */ + + if (outfile == NULLCP) { + if (!isstr (ppdbm)) { + adios (NULLCP, + "no default data base, in 'ppdbm' variable"); + } + outfile = ppdbm; + } + + + /* -- check for existence first -- */ + + error = 0; + + if (optind >= argc) { + + for (ind = 0; ch_all[ind] != NULLCHAN; ind++) { + if (ch_all[ind] -> ch_table != NULLTBL) + error += check (ch_all[ind] -> ch_table); + + if (Debug) + fprintf (stderr, "ch_show = '%s' - %d\n", + ch_all[ind] -> ch_show, error); + } + + + for (ind = 0; (tp = tb_all[ind]) != NULLTBL; ind++) { + error += check (tp); + if (Debug) + fprintf (stderr, "tb_show = '%s' - %d\n", + tp -> tb_show, error); + } + } + else { + int ac = optind; + while (ac < argc) { + if ((tp = tb_nm2struct (argv[ac++])) == NULLTBL) { + advise (NULLCP, "Table '%s' is unknown", + argv[ac - 1]); + error++; + } + error += check (tp); + } + } + + if (error) + adios (NULLCP, "Some tables are missing. dbmbuild aborted."); + + getfpath (tbldfldir, outfile, dbfile); + + if (Verbose || Debug) + fprintf (stderr, +"database info:\n\ttables from %s\n\tdatabase = %s{.dir,.pag}\n\tpath = %s\n", + tbldfldir, outfile, dbfile); + + dblock = multcat (dbfile, ".lck", NULLCP); + + (void) close (creat (dblock, 0444 )); + + if (!theinit (newflag)) + cleanup (NOTOK); + + if (optind >= argc) { + + /* -- process for real! -- */ + + for (ind = 0; ch_all[ind] != NULLCHAN; ind++) + process (ch_all[ind] -> ch_table); + + + for (ind = 0; (tp = tb_all[ind]) != NULLTBL; ind++) { + + /* -- in case table used by chan -- */ + + if (tp -> tb_fp != (FILE *)EOF) { + if (Debug) + fprintf (stderr, "Table '%s'\n", tp -> tb_name); + process (tp); + } + } + + } + else + while (optind < argc) { + + if ((tp = tb_nm2struct (argv[optind++])) == NULLTBL) { + (void) fflush (stdout); + adios (NULLCP, "Table '%s' is unknown", + argv[optind-1]); + } + process (tp); + } + + cleanup (theend (newflag)); +} + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static int theinit (new) /* -- initialize the dbm files -- */ +int new; +{ + char tmpfile [100]; + + + /* -- start with fresh files -- */ + + if (new) { + if (Verbose || Debug) + fprintf (stderr, "Temporary database: %s$\n", dbfile); +#ifdef DBM + (void) sprintf (tmpfile, "%s$.pag", dbfile); + + if (Debug) + fprintf (stderr, "creating '%s'\n", tmpfile); + + + if (close (creat (tmpfile, 0644)) < 0) + adios (tmpfile, "could not creat"); + + (void) chmod (tmpfile, 0644); /* -- in case umask screwed us -- */ + + (void) sprintf (tmpfile, "%s$.dir", dbfile); + + if (Debug) + fprintf (stderr, "creating '%s'\n", tmpfile); + + + /* -- create and/or zero the file -- */ + + if (close (creat (tmpfile, 0644)) < 0) + adios (tmpfile, "could not creat"); + + (void) chmod (tmpfile, 0644); /* -- in case umask screwed us -- */ +#endif +#ifdef GDBM + (void) sprintf (tmpfile, "%s$.gdbm", dbfile); +#else + (void) sprintf (tmpfile, "%s$", dbfile); +#endif + return (dbfinit (tmpfile)); + } + + return (dbfinit (dbfile)); +} + + + + +static theend (new) /* cleanup the dbm files */ +int new; +{ + char fromfile [100], + tofile [100]; + + + dbfclose(); + + /* -- started with fresh files -- */ + + if (new) { + if (Verbose || Debug) + fprintf (stderr, "Moving to database: %s\n", dbfile); + +#ifdef GDBM + (void) sprintf (fromfile, "%s$.gdbm", dbfile); + (void) sprintf (tofile, "%s.gdbm", dbfile); + if (Debug) + fprintf (stderr, "moving '%s'\n", fromfile); + if (rename (fromfile, tofile) == NOTOK) + adios (tofile, "could not rename %s to ", fromfile); +#else + (void) sprintf (fromfile, "%s$.pag", dbfile); + + (void) sprintf (tofile, "%s.pag", dbfile); + + if (Debug) + fprintf (stderr, "moving '%s'\n", fromfile); + + (void) unlink (tofile); + + /* -- create and/or zero the file -- */ + + if (rename (fromfile, tofile ) < 0 ) + adios (tofile, "could not rename %s to ", fromfile); + + (void) sprintf (fromfile, "%s$.dir", dbfile); + + (void) sprintf (tofile, "%s.dir", dbfile); + + if (Debug) + fprintf (stderr, "moving '%s'\n", fromfile); + + (void) unlink (tofile); + + /* -- create and/or zero the file -- */ + + if (rename (fromfile, tofile ) == NOTOK) + adios (tofile, "could not rename %s to ", fromfile); +#endif + + return (TRUE); + } + + return (TRUE); +} + + + + +/* +Initialize the dbm file. Fetch the local name datum +Init to 1 and store it if there is no datum by that name. +*/ + +static dbfinit (filename) +char *filename; +{ +#ifdef GDBM + if ((thedb = gdbm_open (filename, 0, GDBM_NEWDB, 0644, NULL)) == NULL) +#else +#ifdef NDBM + if ((thedb = dbm_open (filename, O_CREAT|O_RDWR, 0644)) == NULL) +#else + if (dbminit (filename) < 0) +#endif +#endif + adios (filename, "could not initialize data base"); + return (1); +} + + + + +/* +Close the dbm datafile. +Can't close the file because the library does not provide the call... +*/ + +static dbfclose() +{ +#ifdef NDBM + dbm_close (thedb); +#endif +#ifdef GDBM + gdbm_close (thedb); +#endif +} + + + + +/* +Process a sequential file and insert items into the database +Opens argument assumes database is initialized. +*/ + +static process (tp) +Table *tp; +{ + datum key, + value; + char tbkey [LINESIZE], + tbvalue [LINESIZE], + *cp; + int status; + + if (tp == NULLTBL) + return; + + if (Verbose || Debug) + fprintf (stderr, tp -> tb_fp == (FILE *)EOF ? + "%s (%s) already done\n" : "%s (%s)\n", + tp -> tb_show, tp -> tb_name); + + if (tp -> tb_fp == (FILE *)EOF) + return; + + + /* -- gain access to a channel table -- */ + + if (!tb_open (tp)) { + fprintf (stderr, "could not open table \"%s\" (%s, file = '%s'):\n\t", + tp -> tb_show, tp -> tb_name, + tp -> tb_file); + perror (""); + + /* -- don't try again -- */ + tp -> tb_fp = (FILE *)EOF; + + if (keepgoing) + return; + cleanup (NOTOK); + } + + + tbkey[0] = tbvalue[0] = '\0'; + while ((status = tab_fetch (tp -> tb_fp, tbkey, tbvalue)) != DONE) { + + if (status == NOTOK) { + if (!keepgoing) + adios (NULLCP, "Bad record in file %s (last was %s:%s)", + tp -> tb_name, tbkey, tbvalue); + advise (NULLCP, "Bad record in file %s (last was %s:%s)", + tp -> tb_name, tbkey, tbvalue); + continue; + } + + value.dptr = tbvalue; + value.dsize = strlen (tbvalue) + 1; + + /* -- all keys are lower case -- */ + for (cp = tbkey; *cp != 0; cp++) + *cp = uptolow (*cp); + + key.dptr = tbkey; + key.dsize = strlen (tbkey) + 1; + + if (Debug) + fprintf (stderr, " (%d)'%s': (%d)'%s'\n", + key.dsize, key.dptr, value.dsize, value.dptr); + + install (key, value, tp -> tb_name); + } + + if (ferror (tp -> tb_fp)) + advise ("", "i/o error with table %s (%s, file = %s)", + tp -> tb_show, tp -> tb_name, + tp -> tb_file); + + (void) tb_close (tp); + + /* -- don't try again -- */ + tp -> tb_fp = (FILE *)EOF; +} + + + + +/* +Install a datum into the database. +Fetch entry first to see if we have to append name for building entry. +*/ + +static install (key, value, tbname) +datum key, + value; +char tbname[]; +{ + datum old; + char newentry [ENTRYSIZE], + *p, + *q; + + p = newentry; + + old = fetch (key); + + if (old.dptr != NULLCP) { + if (Debug) { + fprintf (stderr, "\tFound old entry\n\t"); + prdatum (old); + } + for (p = newentry, q = old.dptr ; *p++ = *q++;); + *(p-1) = FS; + } + else + *p = '\0'; + + (void) sprintf (p, "%s %s", tbname, value.dptr); + + old.dptr = newentry; + old.dsize = strlen (newentry)+1; + + if (Debug) { + fprintf (stderr, "\tNew datum\n\t"); + prdatum (old); + } + + + /* -- put the datum back -- */ + + if (store (key, old) < 0) { + advise ("", + "store failed; key='%s'", key.dptr); + prdatum (old); + cleanup (NOTOK); + } + +} + + + + +/* +Print a datum. +Takes the datum arg & prints it so it can be read as either a key or entry. +*/ + +static prdatum (value) +datum value; +{ + int cnt; + char data [512]; + + (void) strcpy (data, value.dptr); + + for (cnt = 0; cnt < value.dsize; cnt++) { + if (value.dptr [cnt] >= ' ' && value.dptr [cnt] <= '~') + putc (value.dptr [cnt], stderr); + else + fprintf (stderr, "<\\%03o>", value.dptr [cnt]); + } + + putc ('\n', stderr); +} + + + + +static check (tp) +Table *tp; +{ + + /* -- its bad -- */ + if (tp == NULLTBL) { + if (Debug) + fprintf (stderr, "check's tp is NULL\n"); + return (1); + } + + if (tp->tb_fp == (FILE *)EOF) { + if (Debug) + fprintf (stderr, "check's tp has a EOF FILE \n"); + return (1); + } + + /* -- gain access to a channel table -- */ + if (!tb_open (tp)) { + advise ("", "could not open table \"%s\" (%s, file = '%s')", + tp -> tb_show, tp -> tb_name, tp -> tb_file); + tp -> tb_fp = (FILE *)EOF; + return (1); + } + + (void) tb_close (tp); + tp -> tb_fp = NULLFILE; + return (0); +} + + + + +static void cleanup (exitval) +int exitval; +{ + exit (exitval == TRUE? 0 : 1); /* TRUE is non-zero */ +} + +/* ------------- Basic File Action ------------------------------------ */ + +static tb_open (tp) +register Table *tp; /* -- table's state information -- */ +{ + char temppath [128]; + + + /* + currently, there is one file (descriptor) per table. for a large + configuration, you will run out of fd's. until/unless you run + a single-file dbm-based version, there is a hack, below, which + limits the number of open file-descriptors to 6. Trying to open + a 7th will cause a currently-opened one to be closed. + */ + + if (tp == NULLTBL) { + if (Debug) + fprintf (stderr, "tb_open's table is NULL\n"); + return (FALSE); + } + + if (tb_nopen < 6 || tb_free()) { + + getfpath (tbldfldir, tp -> tb_file, temppath); + + /* -- add on directory portion -- */ + if ((tp -> tb_fp = fopen (temppath, "r")) != NULLFILE) { + tb_nopen++; + return (TRUE); + } + } + + printf ("cannot open %s\n", temppath); + + return (FALSE); +} + + + + +static tb_close (tp) +register Table *tp; +{ + if (tp -> tb_fp == (FILE *)NOTOK || tp -> tb_fp == NULLFILE) + return (FALSE); + + (void) fclose (tp -> tb_fp); + + /* -- mark as free -- */ + tp -> tb_fp = 0; + + tb_nopen--; + + return (TRUE); +} + + + + +static tb_free() /* -- create a free file descriptor -- */ +{ + register Table **tpp; + + /* + step from the lowest search priority to the highest, looking for a + channel to close. return success as soon as one is done. + */ + + for (tpp = tb_all; *tpp != 0; tpp++) { + if (tb_close (*tpp)) + return (TRUE); /* -- got a channel closed -- */ + } + return (FALSE); /* -- couldn't get any closed -- */ +} + + +#ifndef lint +static void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint + +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Tools/dbmbuild/make b/Tools/dbmbuild/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/dbmbuild/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/dbmedit/Makefile b/Tools/dbmedit/Makefile new file mode 100644 index 0000000..b3cee59 --- /dev/null +++ b/Tools/dbmedit/Makefile @@ -0,0 +1,97 @@ +# Edits the PP database +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/dbmedit/RCS/Makefile,v 6.0 1991/12/18 20:29:41 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:29:41 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = dbmedit.c +OBJS = dbmedit.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xdbmedit + +default: $(PROGS) + +dbmedit: xdbmedit +xdbmedit: dbmedit.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ dbmedit.o $(LIBPP) $(LIBSYS) + +dbmedit.o: dbmedit.c + $(OLDCC) -c $(CFLAGS) dbmedit.c + +install: inst-dir inst-dbmedit + +inst-dbmedit: $(CMDDIR)/dbmedit +$(CMDDIR)/dbmedit: xdbmedit + -$(BACKUP) $@ zxdbmedit + rm -f $@ + $(INSTALL) xdbmedit $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dbmedit installed normally"; echo "" + +inst-dir: $(CMDDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxdbmedit *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +dbmedit.o: dbmedit.c +dbmedit.o: ../../h/head.h +dbmedit.o: ../../h/util.h +dbmedit.o: ../../h/config.h +dbmedit.o: ../../h/ll_log.h +dbmedit.o: ../../h/retcode.h +dbmedit.o: ../../h/util.h +dbmedit.o: ../../h/dbase.h +dbmedit.o: ../../h/config.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/dbmedit/dbmedit.c b/Tools/dbmedit/dbmedit.c new file mode 100644 index 0000000..4954124 --- /dev/null +++ b/Tools/dbmedit/dbmedit.c @@ -0,0 +1,436 @@ +/* dbmedit: edit a dbm file */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/dbmedit/RCS/dbmedit.c,v 6.0 1991/12/18 20:29:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/dbmedit/RCS/dbmedit.c,v 6.0 1991/12/18 20:29:41 jpo Rel $ + * + * $Log: dbmedit.c,v $ + * Revision 6.0 1991/12/18 20:29:41 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "dbase.h" +#include "sys.file.h" +#include + +extern char *ppdbm; +extern char *dupfpath(); +extern char *multcat(); + +#ifdef GDBM +GDBM_FILE thedb; +#define store(x,y) gdbm_store (thedb, x, y, GDBM_REPLACE) +#define fetch(x) gdbm_fetch (thedb, x) +#else +#ifndef GCC_DBM_OK +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ + #error GCC and dbm do not get along on a sparc - compile with cc. +#endif +#endif +#endif + +# ifdef NDBM +# define fetch(x) dbm_fetch(thedb, (x)) +# define store(x, y) dbm_store(thedb, (x), (y), DBM_REPLACE) +# define delete(x) dbm_delete(thedb, (x)) +DBM *thedb; +# endif + + +datum dcons(); + +char ibuf[LINESIZE]; +#define MARGS 100 +char *cargv[MARGS]; /* max number of args on a line */ +int cargc; + +int help(), add(), del(), change(), print(), quit(); + +struct cmds { + char *cm_name; + int (*cm_func)(); + char *cm_help; +} cmds[] = { + "help", help, "Print out help text", + "add", add, "Add an entry", + "delete", del, "Delete an entry", + "change", change, "Change an entry", + "print", print, "Print an entry", + "quit", quit, "Quit the program", + "h", help, 0, /* single character aliases */ + "a", add, 0, + "d", del, 0, + "c", change, 0, + "p", print, 0, + "q", quit, 0, + "?", help, 0, +}, *curcmd; + +int verbose; + +/* + * dbm expanded structure + */ + +#define MDB 50 + +int ndbents; + +struct db { + char *d_table; + char *d_value; +} dbs[MDB], *lastdb; + +main(argc, argv) +int argc; +char **argv; +{ + int opt; + extern int optind; + extern char *optarg; + + sys_init(argv[0]); + + while ((opt = getopt (argc, argv, "vd:")) != EOF) { + switch (opt) { + case 'v': + verbose++; + break; + case 'd': + ppdbm = optarg; + break; + default: + fprintf(stderr, "dbmedit: unknown argument '%c'\n", + opt); + exit(NOTOK); + } + } + argv += optind; + argc -= optind; + if(!isstr(ppdbm)) { + fprintf(stderr, "dbmedit: cannot find database path\n"); + exit(NOTOK); + } + dbfinit(ppdbm); + + /* if got command line arguments process these instead */ + if(argc > 0){ + avfix(argc, argv); + if(findcmd() < 0) + exit(1); + exit((*curcmd->cm_func)()); + } + + for(;;){ + printf("dbmedit> "); + (void) fflush(stdout); + if (gets(ibuf) == NULL) + exit(0); + if (!isstr(ibuf)) + continue; + if ((cargc = sstr2arg(ibuf, MARGS, cargv, " \t")) == 0) + continue; + if(findcmd() < 0) + continue; + (*curcmd->cm_func)(); + } +} + +avfix(ac, av) +int ac; +register char **av; +{ + register char **ap; + + for(ap = cargv; ac ; ac--, cargc++) + *ap++ = *av++; +} + +findcmd() +{ + register struct cmds *cp; + + for(cp = cmds ; cp < &cmds[sizeof(cmds)/sizeof(cmds[0])] ; cp++) + if(lexequ(cp->cm_name, cargv[0]) == 0){ + curcmd = cp; + return(0); + } + fprintf(stderr, "dbmedit: unknown command '%s'\n", cargv[0]); + return(-1); +} + +help() +{ + register struct cmds *cp; + + for(cp = cmds ; cp < &cmds[sizeof(cmds)/sizeof(cmds[0])] ; cp++) + if(cp->cm_help != 0) + printf("%s\t\t%s\n", cp->cm_name, cp->cm_help); +} + +datum +dcons(value) +char *value; +{ + datum d; + + d.dptr = value; + d.dsize = strlen(value)+1; + return(d); +} + +datum +dconskey(value) +char *value; +{ + char *p; + + for (p = value; *p; p++) + if (isupper(*p)) + *p = tolower(*p); + return(dcons(value)); +} + +dssplit(str) +register char *str; +{ + register struct db *dp; + static char ti[512]; + + ndbents = 0; + str = strcpy(ti, str); + for(dp = dbs ; dp < &dbs[sizeof(dbs)/sizeof(dbs[0])]; dp++){ + if(*str == 0) + break; + dp->d_table = str; + while(*str && *str != ' ') + str++; + *str++ = 0; + dp->d_value = str; + while(*str && *str != FS) + str++; + ndbents++; + if(*str == FS) + *str++ = 0; + } + lastdb = dbs + ndbents; +} + +add() +{ + datum d; + register struct db *dp; + + if(cargc != 4){ + fprintf(stderr, "Usage: add key table value\n"); + return(9); + } + d = fetch(dconskey(cargv[1])); + if(d.dptr == 0){ + if (verbose) + printf("Creating new key \"%s\" value \"%s %s\"\n", + cargv[1], cargv[2], cargv[3]); + dp = lastdb = dbs; + goto newalias; + } + dssplit(d.dptr); + for(dp = dbs ; dp < lastdb ; dp++){ + if(lexequ(dp->d_table, cargv[2]) == 0){ + fprintf(stderr, + "key \"%s\" already has a value in table \"%s\"\n", + cargv[1], cargv[2]); + return(99); + } + } +newalias:; + lastdb++; + dp->d_table = cargv[2]; + dp->d_value = cargv[3]; + return(dscons()); +} + +del() +{ + int i; + datum d; + register struct db *dp; + int changed = 0; + + if (cargc <= 2) { + fprintf(stderr, "Usage: delete key table|* [table ...]\n"); + return(9); + } + + d = fetch(dconskey(cargv[1])); + if (d.dptr == 0) { + fprintf(stderr, "key \"%s\" not found in database\n", cargv[1]); + return(99); + } + if (strcmp(cargv[2], "*") == 0) { /* all entries */ + if (verbose) + printf("Deleteing key \"%s\"\n", cargv[1]); + goto delall; + } + dssplit(d.dptr); + for(i = 2 ; i < cargc ; i++) { + for(dp = dbs ; dp < lastdb ; dp++) { + if(dp->d_table && lexequ(dp->d_table, cargv[i]) == 0) { + if (verbose) + printf("deleting \"%s\" from table \"%s\"\n", + cargv[1], cargv[i]); + changed++; + dp->d_table = 0; + break; + } + } + if(dp >= lastdb){ + fprintf(stderr, + "\"%s\" does not have a value in table \"%s\"\n", + cargv[1], cargv[i]); + continue; + } + } + if(!changed) + return(99); + if(lastdb - changed <= dbs) { + if (verbose) + printf("All values deleted for \"%s\" - deleting key\n", + cargv[1]); +delall:; + if(delete(dcons(cargv[1])) < 0) + fprintf(stderr, "Delete failed\n"); + return(0); + } + return(dscons()); +} + +change() +{ + datum d; + register struct db *dp; + + if(cargc < 3 || cargc > 4) { + fprintf(stderr, "Usage: change key table [value]\n"); + return(9); + } + + d = fetch(dconskey(cargv[1])); + if(d.dptr == 0) { + if (verbose) + fprintf(stderr, "key \"%s\" not found in database\n", + cargv[1]); + if (cargc == 4) + return(add()); + return(0); + } + dssplit(d.dptr); + for(dp = dbs ; dp < lastdb ; dp++) + if(lexequ(dp->d_table, cargv[2]) == 0){ + if (cargc == 3) + return(del()); + if (verbose) + printf("changing \"%s\" to \"%s\"\n", + dp->d_value, cargv[3]); + dp->d_value = cargv[3]; + break; + } + + if(dp >= lastdb){ + if (cargc == 4) + return(add()); + return(0); + } + return(dscons()); +} + +print() +{ + datum d; + register struct db *dp; + + if(cargc < 2){ + fprintf(stderr, "Usage: print key [table]\n"); + return(9); + } + + d = fetch(dconskey(cargv[1])); + if(d.dptr == 0){ + fprintf(stderr, "key \"%s\" not found in database\n", cargv[1]); + return(99); + } + dssplit(d.dptr); + for(dp = dbs ; dp < lastdb ; dp++) + if (cargc == 2 || lexequ(dp->d_table, cargv[2]) == 0 || + lexequ("*", cargv[2]) == 0) + printf("key \"%s\": table \"%s\": value \"%s\"\n", + cargv[1], dp->d_table, dp->d_value); + return(0); +} + +dscons() +{ + char tbuf[ENTRYSIZE]; + datum d; + register struct db *dp; + register char *p, *q; + int changed = 0; + + for(p = tbuf, dp = dbs ; dp d_table) == 0) + continue; + if(p != tbuf) + *(p-1) = FS; + changed++; + while(*p++ = *q++); + *(p-1) = ' '; + for(q = dp->d_value ; *p++ = *q++;); + } + if (!changed) { + fprintf(stderr, "dbmedit: internal error 'no change'\n"); + return(99); + } + d = dcons (tbuf); + + if (store(dconskey(cargv[1]), d) < 0) { + fprintf(stderr, "dbmedit: cannot store new value for '%s'\n", cargv[1]); + } + return(0); +} + +/* + * Initialize the dbm file. + */ + +dbfinit(filename) +char *filename; +{ +#ifdef GDBM + char name[BUFSIZ]; + (void) sprintf (name, "%s.gdbm", filename); + filename = name; + if ((thedb = gdbm_open (filename, 0, GDBM_WRITER, 0666, NULL)) == NULL) { +#else +# ifdef NDBM + if((thedb = dbm_open(filename, O_RDWR, 0666)) == NULL) { +# else + if(dbminit(filename) < 0) { +# endif +#endif + fprintf (stderr, "could not initialize data base '%s'", filename); + perror(""); + exit(99); + } +} + +quit() +{ + exit(0); +} diff --git a/Tools/dbmedit/make b/Tools/dbmedit/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/dbmedit/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/dbmunbuild/Makefile b/Tools/dbmunbuild/Makefile new file mode 100644 index 0000000..0ec3c11 --- /dev/null +++ b/Tools/dbmunbuild/Makefile @@ -0,0 +1,101 @@ +# Unbuild the PP database +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/dbmunbuild/RCS/Makefile,v 6.0 1991/12/18 20:30:06 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:30:06 jpo +# Release 6.0 +# +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = dbmunbuild.c +OBJS = dbmunbuild.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xdbmunbuild + +default: $(PROGS) + +dbmunbuild: xdbmunbuild +xdbmunbuild: dbmunbuild.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ dbmunbuild.o $(LIBPP) $(LIBSYS) + +dbmunbuild.o: dbmunbuild.c + $(OLDCC) -c $(CFLAGS) dbmunbuild.c + +install: inst-dir inst-dbmunbuild + +inst-dbmunbuild: $(CMDDIR)/dbmunbuild +$(CMDDIR)/dbmunbuild: xdbmunbuild + -$(BACKUP) $@ zxdbmunbuild + rm -f $@ + $(INSTALL) xdbmunbuild $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "dbmunbuild installed normally"; echo "" + +inst-dir: $(CMDDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxdbmunbuild *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +dbmunbuild.o: dbmunbuild.c +dbmunbuild.o: ../../h/head.h +dbmunbuild.o: ../../h/util.h +dbmunbuild.o: ../../h/config.h +dbmunbuild.o: ../../h/ll_log.h +dbmunbuild.o: ../../h/retcode.h +dbmunbuild.o: ../../h/util.h +dbmunbuild.o: ../../h/chan.h +dbmunbuild.o: ../../h/table.h +dbmunbuild.o: ../../h/list_bpt.h +dbmunbuild.o: ../../h/dbase.h +dbmunbuild.o: ../../h/config.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/dbmunbuild/dbmunbuild.c b/Tools/dbmunbuild/dbmunbuild.c new file mode 100644 index 0000000..05b6e7b --- /dev/null +++ b/Tools/dbmunbuild/dbmunbuild.c @@ -0,0 +1,371 @@ +/* dbmunbuild.c: dump database into files. */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/dbmunbuild/RCS/dbmunbuild.c,v 6.0 1991/12/18 20:30:06 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/dbmunbuild/RCS/dbmunbuild.c,v 6.0 1991/12/18 20:30:06 jpo Rel $ + * + * $Log: dbmunbuild.c,v $ + * Revision 6.0 1991/12/18 20:30:06 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "table.h" +#include "dbase.h" +#include "sys.file.h" +#include +#include + +extern char *ppdbm; +extern char *dupfpath(); +extern char *multcat(); + +extern Table **tb_all; + +#ifdef GDBM +GDBM_FILE thedb; +#define store(x,y) gdbm_store (thedb, x, y, GDBM_REPLACE) +#define fetch(x) gdbm_fetch (thedb, x) +#define firstkey() gdbm_firstkey(thedb) +#define nextkey(x) gdbm_nextkey(thedb, (x)) +#else +#ifndef GCC_DBM_OK +#if sparc && defined(__GNUC__) /* work around bug in gcc 1.37 sparc version */ + #error GCC and dbm do not get along on a sparc - compile with cc. +#endif +#endif +#endif + +#ifdef NDBM +#define fetch(x) dbm_fetch(thedb, (x)) +#define store(x, y) dbm_store(thedb, (x), (y), DBM_REPLACE) +#define delete(x) dbm_delete(thedb, (x)) +#define firstkey() dbm_firstkey(thedb) +#define nextkey(x) dbm_nextkey(thedb) +DBM *thedb; +# endif + +#define TB_FLAG_MAGIC 0x100 +#define TB_FLAG_NOTTHISONE 0x200 + +/* + * dbm expanded structure + */ + +#define MDB 50 + +static int ndbents; + +struct db { + char *d_table; + char *d_value; +} dbs[MDB], *lastdb; + +static int verbose; +static int markedtbls; +#define MARKED_IN 1 +#define MARKED_OUT 2 + +static char *myname; +static char *Usage = "Usage: %s [-d database] [-t table] [-v] directory"; + +static void dumpdb (); +static void write_records (); +static void write_entry (); +static void dssplit (); +static void dbfinit (); +static void open_table (); +static void close_a_file (); +static void adios (), advise (); +static void mark_table (); + +main(argc, argv) +int argc; +char **argv; +{ + int opt; + extern char *optarg; + extern int optind; + sys_init(myname = argv[0]); + + while ((opt = getopt (argc, argv, "d:t:T:v")) != EOF) { + switch (opt) { + case 'd': + ppdbm = optarg; + break; + case 'v': + verbose = 1; + break; + case 't': + if (markedtbls == MARKED_OUT) + adios (NULLCP, "Can't have -T and -t"); + markedtbls = MARKED_IN; + mark_table (optarg); + break; + case 'T': + if (markedtbls == MARKED_IN) + adios (NULLCP, "Can't have -T and -t"); + markedtbls = MARKED_OUT; + mark_table (optarg); + break; + + default: + adios (NULLCP, Usage, myname); + } + } + argc -= optind; + argv += optind; + if (argc != 1) + adios (NULLCP, Usage, myname); + + if(!isstr(ppdbm)) + adios (NULLCP, "cannot find database path\n"); + dbfinit(ppdbm); + + dumpdb (*argv); + exit (0); +} +static void mark_table (str) +char *str; +{ + Table *tb; + + if ((tb = tb_nm2struct (str)) == NULL) + adios (NULLCP, "Unknown table %s", str); + tb -> tb_flags |= TB_FLAG_NOTTHISONE; +} + +static void dumpdb (dir) +char *dir; +{ + datum key; + datum value; + + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + value = fetch(key); + if (value.dptr == NULLCP) + adios (NULLCP, "Database fetch failed"); + write_records (&key, &value, dir); + } + close_tables (); +} + + +static void write_records (key, val, dir) +datum *key, *val; +char *dir; +{ + struct db *dp; + + dssplit (val -> dptr); + for (dp = dbs; dp < lastdb; dp++) + write_entry (key, dp, dir); +} + +static void write_entry (key, dp, dir) +datum *key; +struct db *dp; +char *dir; +{ + Table *tb; + + if ((tb = tb_nm2struct (dp -> d_table)) == NULL) { + advise (NULLCP, "No such table %s", dp -> d_table); + return; + } + if (markedtbls == MARKED_OUT && + (tb -> tb_flags & TB_FLAG_NOTTHISONE)) + return; + if (markedtbls == MARKED_IN && + (tb -> tb_flags & TB_FLAG_NOTTHISONE) == 0) + return; + + if (tb -> tb_fp == NULL) + open_table (tb, dir); + fprintf (tb -> tb_fp, "%s:%s\n", key -> dptr, dp -> d_value); + if (ferror (tb -> tb_fp)) + adios (dp -> d_table, "Write error on table"); +} + + +static void dssplit(str) +register char *str; +{ + register struct db *dp; + static char ti[BUFSIZ]; + + ndbents = 0; + str = strcpy(ti, str); + for(dp = dbs ; dp < &dbs[sizeof(dbs)/sizeof(dbs[0])]; dp++){ + if(*str == 0) + break; + dp->d_table = str; + while(*str && *str != ' ') + str++; + *str++ = 0; + dp->d_value = str; + while(*str && *str != FS) + str++; + ndbents++; + if(*str == FS) + *str++ = 0; + } + lastdb = dbs + ndbents; +} + +/* + * Initialize the dbm file. + */ + +static void dbfinit(filename) +char *filename; +{ +#ifdef GDBM + char name[BUFSIZ]; + (void) sprintf (name, "%s.gdbm", filename); + filename = name; + if ((thedb = gdbm_open (filename, 0, GDBM_READER, 0666, NULL)) == NULL) { +#else +# ifdef NDBM + if((thedb = dbm_open(filename, O_RDONLY, 0666)) == NULL) { +# else + if(dbminit(filename) < 0) { +# endif +#endif + adios (filename, "Can't initialize data base"); + } +} + + +static void open_table (tb, dir) +Table *tb; +char *dir; +{ + char filename[MAXPATHLENGTH]; + char *mode; + + if (tb -> tb_fp != NULL) + return; + + (void) sprintf (filename, "%s/%s", dir, tb -> tb_file); + + if (verbose) + printf ("Opening %s\n", filename); + mode = (tb -> tb_flags & TB_FLAG_MAGIC) ? "a" : "w"; + if ((tb -> tb_fp = fopen (filename, mode)) == NULL) { + if (errno == EMFILE) { + close_a_file (); + + } + if ((tb -> tb_fp = fopen (filename, mode)) == NULL) + adios (filename, "Can't open file"); + } +} + +static void close_a_file () +{ + + static Table **tbstart; + Table **tb; + + if (tbstart == NULL) + tbstart = tb_all; + + tb = tbstart; + + for (;;) { + if ((*tb) -> tb_fp != NULL) { + if (fclose ((*tb) -> tb_fp) == EOF) + adios ("failed", "Write"); + (*tb) -> tb_fp = NULL; + (*tb) -> tb_flags |= TB_FLAG_MAGIC; + break; + } + tb ++; + if (*tb == NULL) + tb = tb_all; + } + tbstart = tb; +} + +close_tables () +{ + Table **tb; + + for (tb = tb_all; *tb; tb++) + if ((*tb) -> tb_fp) + if (fclose ((*tb) -> tb_fp) == EOF) + adios ("failed", "fclose"); +} + +#ifndef lint +static void _advise (); + +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +static void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Tools/dbmunbuild/make b/Tools/dbmunbuild/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/dbmunbuild/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ean2real/Makefile b/Tools/ean2real/Makefile new file mode 100644 index 0000000..6bc388b --- /dev/null +++ b/Tools/ean2real/Makefile @@ -0,0 +1,99 @@ +# ean2real Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ean2real/RCS/Makefile,v 6.0 1991/12/18 20:30:18 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:30:18 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ean2real.c +OBJS = ean2real.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xean2real + +default: $(PROGS) +all: default +lint: l-ean2real + +install: inst-dir inst-ean2real +inst-dir: $(TOOLDIR) + + +ean2real: xean2real +xean2real: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +l-ean2real: $(SRCS) + $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) + + +inst-ean2real: $(TOOLDIR)/ean2real +$(TOOLDIR)/ean2real: xean2real + -$(BACKUP) $@ zxean2real + rm -f $@ + $(INSTALL) xean2real $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ean2real tool installed normally"; echo "" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +ean2real.o: ean2real.c +ean2real.o: ../../h/util.h +ean2real.o: ../../h/config.h +ean2real.o: ../../h/ll_log.h +ean2real.o: ean2real.c +ean2real.o: ../../h/util.h +ean2real.o: ../../h/config.h +ean2real.o: ../../h/ll_log.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ean2real/ean2real.c b/Tools/ean2real/ean2real.c new file mode 100644 index 0000000..84a75d9 --- /dev/null +++ b/Tools/ean2real/ean2real.c @@ -0,0 +1,232 @@ +/* ean2real.c: convert ean funny representation to real P1 */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ean2real/RCS/ean2real.c,v 6.0 1991/12/18 20:30:18 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ean2real/RCS/ean2real.c,v 6.0 1991/12/18 20:30:18 jpo Rel $ + * + * $Log: ean2real.c,v $ + * Revision 6.0 1991/12/18 20:30:18 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +void advise(); + + + + +/* --------------------- Begin Routines -------------------------------- */ +char *myname; +int process (); +int skiphdr = 0; + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + extern char *optarg; + extern int optind; + int opt; + register char *cp; + register FILE * fp; + int status = 0; + + myname = argv[0]; + while((opt = getopt(argc, argv, "ils")) != EOF) + switch (opt) { + case 'i': + ps_len_strategy = PS_LEN_INDF; + break; + case 'l': + ps_len_strategy = PS_LEN_LONG; + break; + case 's': + skiphdr = 1; + break; + default: + fprintf (stderr, "Usage: %s [-s] [file...]", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc == 0) + status = process ("(stdin)", stdin); + else + while (cp = *argv++) { + if ((fp = fopen (cp, "r")) == NULL) { + advise (cp, "unable to read"); + status++; + continue; + } + status += process (cp, fp); + (void) fclose (fp); + } + + exit (status); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int process (file, fp) +register char *file; +register FILE *fp; +{ + register PE pe, pe2; + register PS ps; + + if (skiphdr) { + int i; + for (i = 0; i < 12; i++) + (void) getc (fp); /* remove junk */ + } + + + if ((ps = ps_alloc (std_open)) == NULLPS) { + advise ("process", "ps_alloc"); + return 1; + } + if (std_setup (ps, fp) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + if ((pe = ps2pe (ps)) == NULLPE) { + if (ps -> ps_errno) + advise (NULLCP, "ps2pe: %s", ps_error(ps -> ps_errno)); + ps_free (ps); + return 1; + } + pe = prim2seq (pe); + if ((pe2 = ps2pe(ps)) == NULLPE) { + if (ps -> ps_errno) + advise (NULLCP, "ps2pe: %s", ps_error(ps -> ps_errno)); + ps_free (ps); + return 1; + } + ps_free (ps); + + if ((ps = ps_alloc(str_open)) == NULLPS) { + advise ("process", "ps_alloc"); + return 1; + } + if (str_setup (ps, NULLCP, 0, 0) == NOTOK) { + advise (NULLCP, "str_setup loses"); + return 1; + } + if (pe2ps (ps, pe2) == NOTOK) { + if (ps -> ps_errno) + advise (NULLCP, "ps2pe: %s", ps_error(ps -> ps_errno)); + ps_free (ps); + return 1; + } + pe_free (pe2); + if((pe2 = oct2prim (ps -> ps_base, ps -> ps_ptr - ps -> ps_base)) == NULLPE || + seq_add (pe, pe2, NOTOK) == NOTOK) { + advise (NULLCP, "Can't build new pe"); + return 1; + } + + ps_free (ps); + if ((ps = ps_alloc (std_open)) == NULLPS) { + advise ("process", "ps_alloc"); + return 1; + } + if (std_setup (ps, stdout) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + (void) ps_get_abs (pe); + if (pe2ps (ps, pe) == NOTOK) { + if (ps -> ps_errno) + advise (NULLCP, "ps2pe: %s", ps_error(ps -> ps_errno)); + ps_free (ps); + return 1; + } + ps_free (ps); + pe_free (pe); + return 0; +} + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + diff --git a/Tools/ean2real/make b/Tools/ean2real/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ean2real/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/hex2bin/Makefile b/Tools/hex2bin/Makefile new file mode 100644 index 0000000..5debb99 --- /dev/null +++ b/Tools/hex2bin/Makefile @@ -0,0 +1,92 @@ +# hex2bin Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/hex2bin/RCS/Makefile,v 6.0 1991/12/18 20:30:25 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:30:25 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = hex2bin.c hex2bin.c +OBJS = hex2bin.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xhex2bin + +default: $(PROGS) +all: default +lint: l-hex2bin + +install: inst-dir inst-hex2bin +inst-dir: $(TOOLDIR) + + +hex2bin: xhex2bin +xhex2bin: hex2bin.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ hex2bin.o $(LIBPP) $(LIBSYS) + +l-hex2bin: hex2bin.c + $(LINT) $(LINTFLAGS) hex2bin.c $(LINTLIBS) + + +inst-hex2bin: $(TOOLDIR)/hex2bin +$(TOOLDIR)/hex2bin: xhex2bin + -$(BACKUP) $@ zxhex2bin + rm -f $@ + $(INSTALL) xhex2bin $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "hex2bin tool inst-talled normally"; echo "" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +hex2bin.o: hex2bin.c +hex2bin.o: hex2bin.c + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/hex2bin/hex2bin.c b/Tools/hex2bin/hex2bin.c new file mode 100644 index 0000000..ad72181 --- /dev/null +++ b/Tools/hex2bin/hex2bin.c @@ -0,0 +1,102 @@ +/* hex2bin: Converts a hex file to binary */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/hex2bin/RCS/hex2bin.c,v 6.0 1991/12/18 20:30:25 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/hex2bin/RCS/hex2bin.c,v 6.0 1991/12/18 20:30:25 jpo Rel $ + * + * $Log: hex2bin.c,v $ + * Revision 6.0 1991/12/18 20:30:25 jpo + * Release 6.0 + * + */ + + + +#include + + + +/* --------------------- Begin Routines -------------------------------- */ + + +main(argc, argv) +int argc; +char **argv; +{ + if (argc > 1) { + while (--argc > 0) { + FILE *fp; + + if ((fp = fopen (*++argv, "r")) == NULL) { + fprintf (stderr, "Can't open file %s", *argv); + perror(""); + exit (1); + } + hex2bin(fp); + (void) fclose (fp); + } + } + else + hex2bin (stdin); + + +} + +hex2bin (fp) +FILE *fp; +{ + int zone, first_zone, octet; + + first_zone = 1; + octet = 0; + while ((zone = getc(fp)) != EOF) + { + switch (zone) + { + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : zone -= '0'; + break; + case 'a' : + case 'b' : + case 'c' : + case 'd' : + case 'e' : + case 'f' : zone = zone - 'a' + 10; + break; + + case 'A' : + case 'B' : + case 'C' : + case 'D' : + case 'E' : + case 'F' : zone = zone - 'A' + 10; + break; + default: + continue; + } + if (first_zone) + { + octet = zone * 16; + first_zone = 0; + } + else + { + octet += zone; + putchar(octet); + first_zone = 1; + } + } + if (!first_zone) + putchar(octet); +} diff --git a/Tools/hex2bin/make b/Tools/hex2bin/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/hex2bin/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/make b/Tools/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Tools/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/make-lists/Makefile b/Tools/make-lists/Makefile new file mode 100644 index 0000000..2d17660 --- /dev/null +++ b/Tools/make-lists/Makefile @@ -0,0 +1,82 @@ +# Generate distribution list file from sendmail aliases +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/make-lists/RCS/Makefile,v 6.0 1991/12/18 20:30:32 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:30:32 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = make-lists.c +OBJS = make-lists.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xmake-lists + +default: $(PROGS) + +make-lists: xmake-lists +xmake-lists: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBSYS) + + +install: inst-dir inst-make-lists + +inst-make-lists: $(TOOLDIR)/make-lists +$(TOOLDIR)/make-lists: xmake-lists + -$(BACKUP) $@ zxmake-lists + rm -f $@ + $(INSTALL) xmake-lists $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "make-lists installed normally"; echo "" + +inst-dir: $(TOOLDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxmake-lists *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow diff --git a/Tools/make-lists/README b/Tools/make-lists/README new file mode 100644 index 0000000..d1d7fd2 --- /dev/null +++ b/Tools/make-lists/README @@ -0,0 +1,9 @@ +This is a program to help adapt large sendmail alias files +into the format required by PP. It should be noted that only +comma separated lists are transformed by this process. Aliases +such as + + postmaster:jpo + +are not output, and such expansions must be added by hand into the +PP alias table. diff --git a/Tools/make-lists/make b/Tools/make-lists/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/make-lists/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/make-lists/make-lists.8 b/Tools/make-lists/make-lists.8 new file mode 100644 index 0000000..4bcb5f4 --- /dev/null +++ b/Tools/make-lists/make-lists.8 @@ -0,0 +1,61 @@ +.TH MAKE-LISTS 8 "August 1990" +.\" @(#) $Header: /xtel/pp/pp-beta/Tools/make-lists/RCS/make-lists.8,v 6.0 1991/12/18 20:30:32 jpo Rel $ +.\" +.\" $Log: make-lists.8,v $ +.\" Revision 6.0 1991/12/18 20:30:32 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +make-lists \- Convert sendmail alias-file lists for PP +.SH SYNOPSIS +.B make-lists +.B /etc/aliases +.B ch.list +.B listdir/ +.SH DESCRIPTION +The +.I make-lists +program is a transition tool for sendmail users. +.IP /etc/aliases +is the sendmail alias file to be processed. +.IP ch.list +\- the file to contain the PP list-table entries. +.IP listdir/ +\- the lists found in the sendmail alias file will be collected +into seperate files in +.BR listdir , +after which they may be maintained with +.BR mlist(1) . +.PP +A sendmail alias file handles mailing lists in two ways. The first is by +including a user-maintained file, one user per line. This is equivalent to +PP's way of doing things, and is not supported by this tool. The other is +by forming a comma-seperated set of list members: + +.nf +list: member1, member2, member3 +.fi + +these groups are extracted into seperate files in +.BR listdir , +and a pp list-control line added to +.BR ch.list . +.PP +Each +.B list +has an associated +.BR list -request +created at the same time. If one existed in the sendmail-alias file, it is +used, otherwise +.I postmaster +is elected. +.SH SEE ALSO +sendmail(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP +.SH AUTHORS +M.A.Scott and A.Macpherson, STC Technology Ltd +.br +Program donated for use with PP August 1990 diff --git a/Tools/make-lists/make-lists.c b/Tools/make-lists/make-lists.c new file mode 100644 index 0000000..aba75d4 --- /dev/null +++ b/Tools/make-lists/make-lists.c @@ -0,0 +1,472 @@ +/* make-lists.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/make-lists/RCS/make-lists.c,v 6.0 1991/12/18 20:30:32 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/make-lists/RCS/make-lists.c,v 6.0 1991/12/18 20:30:32 jpo Rel $ + * + * $Log: make-lists.c,v $ + * Revision 6.0 1991/12/18 20:30:32 jpo + * Release 6.0 + * + */ + + + +/* + * + * Reads usernames aliases file, and creates quipu distribution list + * channel files. + * + * Usage: + * + * make-lists input channel-file list-directory + * + * A line starting with '#' is a comment. Else, a line containg both + * ':' and ',' is assumed to be the first line of a list; it continues + * while succeeding lines start with whitespace. + * + * Note that the list directory must be in a form suitable for + * prefixing directly a filename (ie ends in / on unix, or is like + * [zxc] or thing: on VMS), this name is placed into the channel-file. + * + * (nb vms/unix compatible, mainly so I can debug with a *decent* debugger. + * It'll only be run 'in anger' on un*x) (M.A.Scott) + * + * + * Modified, fairly extensively A.Macpherson. + * + */ + + +static char sccsid[] = { "%W%\t-\t%E%\tSTL\n" }; + +#include + +extern char *malloc(); +extern char *realloc(); +extern char *strchr(), *strrchr(); +extern char *strcpy(); + +static int readline (); +static int addusers (); +static void panic (); + +#define MAXMODERATOR 6 +struct list { + struct list *next; /* link pointer */ + struct list *left; /* other link */ + char *list_name; /* name of the list (eg "200") */ + char *users; /* points to '\n' separated record of users */ + int users_alloc; /* currently allocated space INCLUDING the + * '\0' */ + int users_used; /* currently used space including the null */ + char *moderator[MAXMODERATOR]; /* list-request person(s) */ +}; + +#define USERS_INCR 512 /* increment for 'users' area */ + +static struct list *list_pointer; + +#ifndef BUFSIZ +# define BUFSIZ 255 /* input line length allowed */ +#endif + +#ifdef VMS +# define ERROR (USER_FATAL|USER_INHIBIT) +# define OK USER_SUCCESS +# include +#else +# define ERROR 1 +# define OK 0 +# define EOS '\0' +#endif + + +#define FIRST 0 +#define CONTIN 1 + +static struct list *get_list(); +static void write_tables(); +static int trim(); +static int analyse_first(); +static int analyse_contin(); +static int analyse_request(); + +static char * + mymalloc(n) +int n; +{ + char *p = malloc((unsigned) n); + + if (p == 0) { + perror("mymalloc"); + exit(ERROR); + } + return p; +} + +main(argc, argv) +int argc; +char *argv[]; + +{ + FILE *input; + static char buffer[BUFSIZ + 1]; + int state; + struct list *current = 0; + + if (argc != 4) { + (void) printf("usage: %s input-file channel-table dislist-directory\n", + argv[0]); + exit(ERROR); + } + input = fopen(argv[1], "r"); + if (input == 0) { + perror("cannot read input"); + exit(ERROR); + } + /* read entire input file.... */ + state = FIRST; + + while (readline(buffer, BUFSIZ, input) != EOF) { + + if (buffer[0] == '#' || buffer[0] == '\0') + continue; /* comment line */ + + switch (state) { + case FIRST: + if (buffer[0] == ' ') { + (void) printf("unexpected continuation line - ignored!\n%s\n", buffer); + continue; + } + trim(buffer); + /* + * it's not an error if it's not a list, but we need to check for a + * request line + */ + if (analyse_request(buffer, current)) + break; + if (analyse_first(buffer, ¤t)) + state = CONTIN; + break; + + case CONTIN: + if (!analyse_contin(buffer, current)) + state = FIRST; + break; + + default: + panic(); + break; + } + } + (void) fclose(input); + + write_tables(argv[2], argv[3]); +} + + +/* returns 1 if user list end in ',' else 0 */ +static int analyse_first(buffer, current_pointer) +char *buffer; +struct list **current_pointer; +{ + struct list *p; + char *rest; + int i; + + /* get dis list name */ + rest = strchr(buffer, ':'); + if (rest == 0) + panic(); + *rest++ = EOS; + + p = get_list(buffer); + + *current_pointer = p; + return addusers(rest, p); /* and user list */ +} + +/* returns 1 if user list end in ',' else 0 */ +static int + analyse_contin(buffer, current_pointer) +char *buffer; +struct list *current_pointer; +{ + if ((strchr(buffer, ':') != 0) || (buffer[0] != ' ')) { + (void) printf("continuation line of list expected - ignored!\n%s\n", + buffer); + return 0; + } + trim(buffer); + return addusers(buffer, current_pointer); +} + + +/* + * check for a -request, ie moderator, line. This is assumed to occur after + * the list is defined. Duplicate moderators are appended, up to a maximum. + */ +static + analyse_request(buffer, current_pointer) +char *buffer; +struct list *current_pointer; +{ + char *moderator = strchr(buffer, ':'); + char *dash; + char *at; + struct list *p = current_pointer; + int i; + + if (moderator == 0) + return(0); + + *moderator++ = EOS; + dash = strrchr(buffer, '-'); + if (dash == 0 || strncmp(dash + 1, "request", 7) != 0) { + *--moderator = ':'; + return(0); + } + + *dash = EOS; /* buffer now points to list name */ + + /* + * good chance current list is the one! If not, scan whole list. + */ + if ((p == 0) || strcmp(p->list_name, buffer) != 0) + p = get_list(buffer); + + for (i = 0; i < MAXMODERATOR; ++i) { + if (dash = strchr(moderator, ',')) + *dash++ = EOS; + if (p->moderator[i] == 0) + p->moderator[i] = mymalloc(strlen(moderator) + 1); + at = strchr(moderator, '@'); + if (at != 0) + *at = EOS; + (void) strcpy(p->moderator[i], moderator); + if (dash) + moderator = dash; + else + break; + } + if (i >= MAXMODERATOR) + (void) printf("too many moderators for list %s: %s ignored!\n", + buffer, moderator); + return(1); +} + + +static void + write_tables(channel_file, table_dir) +char *channel_file, *table_dir; +{ + struct list *p; + FILE *fch; + void inorder_lists(); + + fch = fopen(channel_file, "w"); + if (fch == 0) { + (void) printf("channel file open error\n"); + perror(channel_file); + exit(ERROR); + } + if (chdir(table_dir) != 0) { + (void) printf("list directory error\n"); + perror(table_dir); + unlink(channel_file); + exit(ERROR); + } + + inorder_lists(list_pointer, fch, table_dir); + + if (ferror(fch) != 0 || (fclose(fch) != 0)) { + (void) printf("channel file write error\n"); + perror(channel_file); + exit(ERROR); + }; +} + +char modbuff[BUFSIZ]; + +void + inorder_lists(p, fch, table_dir) +struct list *p; +FILE *fch; +char *table_dir; +{ + FILE *flist; + int i; + + if (!p) + return; + + inorder_lists(p->next, fch, table_dir); + + if (p->moderator[0] || strchr(p->users, '\n') != (char *)0) { + flist = fopen(p->list_name, "w"); + if (flist == 0) { + (void) printf("list file open error\n"); + perror(p->list_name); + exit(ERROR); + } + /* + * there's a bug in printf in VMS C, at least for old versions, for >512 + * chars output at once, so... + */ +#ifdef VMS + { + char *c; + + for (c = p->users; *c != EOS; ++c) + fputc(*c, flist); + fputc('\n', flist); + } +#else + (void) fputs(p->users, flist); + (void) fputc('\n', flist); +#endif + if (ferror(flist) != 0 || (fclose(flist) != 0)) { + (void) printf("list file write error\n"); + perror(p->list_name); + exit(ERROR); + } + + (void) fprintf(fch, "%s:%s", /* listname */ + p->list_name, + p->moderator[0] != 0 ? p->moderator[0]: "postmaster"); + for (i = 1; i < MAXMODERATOR && p->moderator[i] != 0; ++i) + (void) fprintf(fch, "|%s", p->moderator[i]); + (void) fprintf(fch, ",file=%s%s,%s\n", + table_dir, p->list_name, + p->list_name); /* filename, description */ + strcpy(modbuff, p->list_name); + strcat(modbuff, "-request"); + if ( p->moderator[0] == 0 || strcmp(modbuff, p->moderator[0])) { + (void) fprintf(fch, "%s-request:postmaster,%s", p->list_name, + p->moderator[0] != 0 ? p->moderator[0]: "postmaster"); + for (i = 1; i < MAXMODERATOR && p->moderator[i] != 0; ++i) + (void) fprintf(fch, "|%s", p->moderator[i]); + (void) fprintf(fch, ",Moderators for list %s\n", + p->list_name); /* filename, description */ + } + } + inorder_lists(p->left, fch, table_dir); +} + +/* remove blanks from string in place */ +static int + trim(s) +char *s; +{ + char *t; + + for (t = s; *s != EOS; ++s) + if (*s != ' ' && *s != '\t') + *t++ = *s; + *t++ = EOS; + return; +} + + +/* add users to list, converting ',' to '\n',and increasing space as needed */ +/* returns 1 if a trailing comma found, else 0 */ +static int + addusers(users, p) +char *users; +struct list *p; +{ + int l = strlen(users); + char *s; + int comma; + + /* get enough space and some more */ + if (p->users_used + l > p->users_alloc) { + p->users = realloc(p->users, (unsigned) (p->users_alloc + l + USERS_INCR)); + if (p->users == 0) { + (void) printf("out of memory!\n"); + exit(ERROR); + } + p->users_alloc += (l + USERS_INCR); + } + /* copy across list */ + comma = 0; + for (s = p->users + p->users_used - 1; *users != EOS; ++s, ++users) + if (comma = (*users == ',')) + *s = '\n'; + else + *s = *users; + + p->users_used += l; + + return comma; +} + + +static int + readline(buffer, len, input) +char *buffer; +int len; +FILE *input; +{ + int i; + + if (fgets(buffer, len, input) == 0) { + if (!feof(input)) { + perror("read error"); + exit(ERROR); + } else + return EOF; + } + i = strlen(buffer); + if (buffer[i - 1] != '\n') + (void) printf("line too long (data may be lost):\n%s\n", buffer); + else + buffer[i - 1] = EOS; + return 0; +} + + +static void panic() +{ + (void) printf("internal error!!\n"); + exit(ERROR); +} + +static struct list * + get_list(name) +char *name; +{ + register struct list **p; + int lr; + + /* Double de-reference so only one pointer needed, and + the empty tree is not a special case */ + + for (p = &list_pointer; *p != 0; ) { + if ((lr = strcmp((*p)->list_name, name)) == 0){ + return(*p); + } + p = (lr > 0) ? &(*p)->next : &(*p)->left; + } + + /* grab some store and init it... */ + *p = (struct list *) mymalloc(sizeof(struct list)); + + (*p)->users = mymalloc(USERS_INCR + 1); + (*p)->users[0] = EOS; + (*p)->users_alloc = USERS_INCR + 1; + (*p)->users_used = 1; /* the EOS */ + for (lr = 0; lr < MAXMODERATOR; ++lr) + (*p)->moderator[lr] = 0; + + (*p)->next = (struct list *) 0; + (*p)->left = (struct list *) 0; + + (*p)->list_name = mymalloc(strlen(name) + 1); + (void) strcpy((*p)->list_name, name); /* copy list name */ + return (*p); +} diff --git a/Tools/misc/Makefile b/Tools/misc/Makefile new file mode 100644 index 0000000..77604bb --- /dev/null +++ b/Tools/misc/Makefile @@ -0,0 +1,331 @@ +# miscellaneous - used by pp-hackers only +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/misc/RCS/Makefile,v 6.0 1991/12/18 20:30:40 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:30:40 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = t-chkpe.c t-conf.c t-norm.c t-pefrag.c t-prf.c t-rdmsg.c \ + t-single.c t-time.c t-rtime.c t-txt2dr.c +OBJS = t-chkpe.o t-conf.o t-norm.o t-pefrag.o t-prf.o t-rdmsg.o \ + t-single.o t-time.o t-rtime.o t-txt2dr.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = xt-chkpe xt-conf xt-norm xt-pefrag xt-prf xt-rdmsg \ + xt-single xt-time xt-rtime xt-txt2dr + +default: $(PROGS) +all: default + +lint: l-t-chkpe l-t-conf l-t-norm l-t-pefrag l-t-prf l-t-rdmsg \ + l-t-single l-t-time l-t-txt2dr + +install: inst-dir inst-t-chkpe inst-t-conf inst-t-norm inst-t-pefrag \ + inst-t-prf inst-t-rdmsg inst-t-single inst-t-time inst-t-txt2dr + +inst-dir: $(TOOLDIR) + + +############################################################ +# +# Start of Program compilations & installations +# +############################################################ + + +t-chkpe: xt-chkpe +xt-chkpe: t-chkpe.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-chkpe.o $(LIBPP) $(LIBSYS) +l-t-chkpe: t-chkpe.c + $(LINT) $(LINTFLAGS t-chkpe.c $(LINTLIBS) +inst-t-chkpe: $(TOOLDIR)/t-chkpe +$(TOOLDIR)/t-chkpe: xt-chkpe + -$(BACKUP) $@ zxt-chkpe + rm -f $@ + $(INSTALL) xt-chkpe $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-chkpe tool installed normally"; echo "" + + + +t-conf: xt-conf +xt-conf: t-conf.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-conf.o $(LIBPP) $(LIBSYS) +l-t-conf: t-conf.c + $(LINT) $(LINTFLAGS t-conf.c $(LINTLIBS) +inst-t-conf: $(TOOLDIR)/t-conf +$(TOOLDIR)/t-conf: xt-conf + -$(BACKUP) $@ zxt-conf + rm -f $@ + $(INSTALL) xt-conf $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-conf tool installed normally"; echo "" + + +t-norm: xt-norm +xt-norm: t-norm.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-norm.o $(LIBPP) $(LIBSYS) +l-t-norm: t-norm.c + $(LINT) $(LINTFLAGS) t-norm.c $(LINTLIBS) +inst-t-norm: $(TOOLDIR)/t-norm +$(TOOLDIR)/t-norm: xt-norm + -$(BACKUP) $@ zxt-norm + rm -f $@ + $(INSTALL) xt-norm $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-norm tool installed normally"; echo "" + + +t-pefrag: xt-pefrag +xt-pefrag: t-pefrag.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-pefrag.o $(LIBPP) $(LIBSYS) +l-t-pefrag: t-pefrag.c + $(LINT) $(LINTFLAGS) t-pefrag.c $(LINTLIBS) +inst-t-pefrag: $(TOOLDIR)/t-pefrag +$(TOOLDIR)/t-pefrag: xt-pefrag + -$(BACKUP) $@ zxt-pefrag + rm -f $@ + $(INSTALL) xt-pefrag $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-pefrag tool installed normally"; echo "" + + +t-prf: xt-prf +xt-prf: t-prf.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-prf.o $(LIBPP) $(LIBSYS) +l-t-prf: t-prf.c + $(LINT) $(LINTFLAGS t-prf.c $(LINTLIBS) +inst-t-prf: $(TOOLDIR)/t-prf +$(TOOLDIR)/t-prf: xt-prf + -$(BACKUP) $@ zxt-prf + rm -f $@ + $(INSTALL) xt-prf $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-prf tool installed normally"; echo "" + + +t-rdmsg: xt-rdmsg +xt-rdmsg: t-rdmsg.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-rdmsg.o $(LIBPP) $(LIBSYS) +l-t-rdmsg: t-rdmsg.c + $(LINT) $(LINTFLAGS t-rdmsg.c $(LINTLIBS) +inst-t-rdmsg: $(TOOLDIR)/t-rdmsg +$(TOOLDIR)/t-rdmsg: xt-rdmsg + -$(BACKUP) $@ zxt-rdmsg + rm -f $@ + $(INSTALL) xt-rdmsg $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-rdmsg tool installed normally"; echo "" + + +t-single: xt-single +xt-single: t-single.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-single.o \ + $(LIBPP) $(LIBSYS) +l-t-single: t-single.c + $(LINT) $(LINTFLAGS) t-single.c $(LINTISODE) +inst-t-single: $(TOOLDIR)/t-single +$(TOOLDIR)/t-single: xt-single + -$(BACKUP) $@ zxt-single + rm -f $@ + $(INSTALL) xt-single $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-single tool installed normally"; \ + echo "" + + +t-time: xt-time +xt-time: t-time.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-time.o $(LIBPP) $(LIBSYS) +l-t-time: t-time.c + $(LINT) $(LINTFLAGS t-time.c $(LINTLIBS) +inst-t-time: $(TOOLDIR)/t-time +$(TOOLDIR)/t-time: xt-time + -$(BACKUP) $@ zxt-time + rm -f $@ + $(INSTALL) xt-time $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-time tool installed normally"; echo "" + +t-rtime: xt-rtime +xt-rtime: t-rtime.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-rtime.o $(LIBPP) $(LIBSYS) +l-t-rtime: t-rtime.c + $(LINT) $(LINTFLAGS t-rtime.c $(LINTLIBS) +inst-t-rtime: $(TOOLDIR)/t-rtime +$(TOOLDIR)/t-rtime: xt-rtime + -$(BACKUP) $@ zxt-rtime + rm -f $@ + $(INSTALL) xt-rtime $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-rtime tool installed normally"; echo "" + + +t-txt2dr: xt-txt2dr +xt-txt2dr: t-txt2dr.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ t-txt2dr.o $(LIBPP) $(LIBSYS) +l-t-txt2dr: t-txt2dr.c + $(LINT) $(LINTFLAGS t-txt2dr.c $(LINTLIBS) +inst-t-txt2dr: $(TOOLDIR)/t-txt2dr +$(TOOLDIR)/t-txt2dr: xt-txt2dr + -$(BACKUP) $@ zxt-txt2dr + rm -f $@ + $(INSTALL) xt-txt2dr $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "t-txt2dr tool installed normally"; echo "" + + + + + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zxt-* *.old *.BAK +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) +define: + $(DEFINE) Makefile + + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +t-chkpe.o: t-chkpe.c +t-chkpe.o: ../../h/head.h +t-chkpe.o: ../../h/util.h +t-chkpe.o: ../../h/config.h +t-chkpe.o: ../../h/ll_log.h +t-chkpe.o: ../../h/retcode.h +t-chkpe.o: ../../h/or.h +t-conf.o: t-conf.c +t-norm.o: t-norm.c +t-norm.o: ../../h/util.h +t-norm.o: ../../h/config.h +t-norm.o: ../../h/ll_log.h +t-norm.o: ../../h/chan.h +t-norm.o: ../../h/table.h +t-norm.o: ../../h/list_bpt.h +t-pefrag.o: t-pefrag.c +t-pefrag.o: ../../h/util.h +t-pefrag.o: ../../h/config.h +t-pefrag.o: ../../h/ll_log.h +t-prf.o: t-prf.c +t-prf.o: ../../h/head.h +t-prf.o: ../../h/util.h +t-prf.o: ../../h/config.h +t-prf.o: ../../h/ll_log.h +t-prf.o: ../../h/retcode.h +t-rdmsg.o: t-rdmsg.c +t-rdmsg.o: ../../h/head.h +t-rdmsg.o: ../../h/util.h +t-rdmsg.o: ../../h/config.h +t-rdmsg.o: ../../h/ll_log.h +t-rdmsg.o: ../../h/retcode.h +t-rdmsg.o: ../../h/prm.h +t-rdmsg.o: ../../h/q.h +t-rdmsg.o: ../../h/adr.h +t-rdmsg.o: ../../h/list_rchan.h +t-rdmsg.o: ../../h/chan.h +t-rdmsg.o: ../../h/table.h +t-rdmsg.o: ../../h/list_bpt.h +t-rdmsg.o: ../../h/auth.h +t-rdmsg.o: ../../h/list_bpt.h +t-rdmsg.o: ../../h/extension.h +t-rdmsg.o: ../../h/mta.h +t-rdmsg.o: ../../h/adr.h +t-rdmsg.o: ../../h/list_bpt.h +t-rdmsg.o: ../../h/mta.h +t-single.o: t-single.c +t-single.o: ../../h/util.h +t-single.o: ../../h/config.h +t-single.o: ../../h/ll_log.h +t-single.o: ../../h/ap.h +t-single.o: ../../h/util.h +t-single.o: ../../h/chan.h +t-single.o: ../../h/table.h +t-single.o: ../../h/list_bpt.h +t-single.o: ../../h/retcode.h +t-time.o: t-time.c +t-time.o: ../../h/util.h +t-time.o: ../../h/config.h +t-time.o: ../../h/ll_log.h +t-txt2dr.o: t-txt2dr.c +t-txt2dr.o: ../../h/util.h +t-txt2dr.o: ../../h/config.h +t-txt2dr.o: ../../h/ll_log.h +t-txt2dr.o: ../../h/q.h +t-txt2dr.o: ../../h/adr.h +t-txt2dr.o: ../../h/list_rchan.h +t-txt2dr.o: ../../h/chan.h +t-txt2dr.o: ../../h/table.h +t-txt2dr.o: ../../h/list_bpt.h +t-txt2dr.o: ../../h/auth.h +t-txt2dr.o: ../../h/list_bpt.h +t-txt2dr.o: ../../h/extension.h +t-txt2dr.o: ../../h/mta.h +t-txt2dr.o: ../../h/adr.h +t-txt2dr.o: ../../h/list_bpt.h +t-txt2dr.o: ../../h/mta.h +t-txt2dr.o: ../../h/dr.h +t-txt2dr.o: ../../h/extension.h +t-txt2dr.o: ../../h/mta.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/misc/README b/Tools/misc/README new file mode 100644 index 0000000..9835f65 --- /dev/null +++ b/Tools/misc/README @@ -0,0 +1,20 @@ +[ README for the Tools/misc directory - jpo Tue Mar 28 15:53:21 1989 ] + +The files in this directory are intended for use in debuging PP and +for doing simple tasks. They are as follows. + +adrchk - does a variety of strange things with a given address to see + if it's parseable and if so in what manner. + +norm - Attempts to normalise a list of addresses given as arguments + to the program. It has two flags -t type specifies the type of + ordering you want to try (pick from uk, us, ukpref, uspref) + and -a which syas try all address styles. + +testrfc - A program to check and see how the RFC/UTC time strings + interwork - if at all. Type in an RFC style string and it will + convert it to a UTC time structure, print that out as both + universal & generalised time - then convert it back to RFC and + you should have something similar to the input (except the + timezone may have been normalised). + diff --git a/Tools/misc/make b/Tools/misc/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/misc/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/misc/t-chkpe.c b/Tools/misc/t-chkpe.c new file mode 100644 index 0000000..f126732 --- /dev/null +++ b/Tools/misc/t-chkpe.c @@ -0,0 +1,120 @@ +/* t-chkpe.c: Checks the pe2or and or2pe routines using an RFC address */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-chkpe.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-chkpe.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-chkpe.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "or.h" + +extern char or_error[]; + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +main (argc, argv) +int argc; +char *argv[]; +{ + char buf[BUFSIZ]; + int i = 1; + + sys_init (argv[0]); + + if (or_init() == NOTOK ) { + printf ("or_init() failed\n"); + exit (1); + } + + if (argc == 1) + while (gets (buf) != NULL) + parse_address (buf); + else + while (i < argc) + parse_address (argv[i++]); +} + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int parse_address (str) +char *str; +{ + char rfcbuf [BUFSIZ]; + char x400buf_orig [BUFSIZ]; + char x400buf_after [BUFSIZ]; + OR_ptr or = NULLOR; + PE pe = NULLPE; + + x400buf_orig[0] = x400buf_after[0] = rfcbuf[0] = '\0'; + + /* --- Perform the x400 addressing --- */ + if ((or_rfc2or (str, &or) != OK) || (or == NULLOR)) + goto error; + or_or2std (or, x400buf_orig, FALSE); + + + /* --- Do the pe routines -- */ + pe = ora2pe (or); + if (pe == NULLPE) + goto error; + + or_free (or); + or = pe2ora (pe); + pe_free (pe); + + if (or == NULLOR) + goto error; + + /* --- Perform the rfc822 address parsing --- */ + or_or2std (or, x400buf_after, FALSE); + if (or_or2rfc (or, rfcbuf) == NOTOK) + goto error; + + printf ("PE check Succeded\n"); + printf ("%s -> (x400 orig) %s\n%-*s -> (x400 after) %s\n%-*s -> (rfc822) %s\n", + str, x400buf_orig, strlen(str), "", x400buf_after, + strlen(str), "", rfcbuf); + + goto finish; + + +error: ; + printf ("PE check Failed \nReason : %s\n", or_error); + if (x400buf_orig[0] != '\0') + printf ("%s -> (x400 orig) %s\n", str, x400buf_orig); + if (x400buf_after[0] != '\0') + printf ("%s -> (x400 after) %s\n", str, x400buf_after); + if (rfcbuf[0] != '\0') + printf ("%s -> (rfc822) %s\n", str, rfcbuf); + + +finish: ; + fflush (stdout); + if (or) or_free (or); + if (pe) pe_free (pe); + return; +} + + +int advise () +{ + return; +} diff --git a/Tools/misc/t-conf.c b/Tools/misc/t-conf.c new file mode 100644 index 0000000..0533753 --- /dev/null +++ b/Tools/misc/t-conf.c @@ -0,0 +1,40 @@ +/* t-conf.c: tests the Lib/pp/conf.c variables */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-conf.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-conf.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-conf.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include + +extern char *pptailor, + *cmddfldir, + *logdfldir, + *quedfldir, + *tbldfldir, + *niftpquedir, + *niftpcpf; + + +main () +{ + sys_init ("testconf"); + printf ("tailor = %s\n", pptailor); + printf ("cmddfldir = %s\n", cmddfldir); + printf ("logdfldir = %s\n", logdfldir); + printf ("quedfldir = %s\n", quedfldir); + printf ("tbldfldir = %s\n", tbldfldir); + printf ("niftpquedir = %s\n", niftpquedir); + printf ("niftpcpf = %s\n", niftpcpf); + return; +} diff --git a/Tools/misc/t-norm.c b/Tools/misc/t-norm.c new file mode 100644 index 0000000..06c79b0 --- /dev/null +++ b/Tools/misc/t-norm.c @@ -0,0 +1,95 @@ +/* norm.c: test out normalisation stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-norm.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-norm.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-norm.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "chan.h" +#include + +static CMD_TABLE chtbl_ad_order[] = { + "usa", CH_USA_ONLY, + "uk", CH_UK_ONLY, + "usapref", CH_USA_PREF, + "ukpref", CH_UK_PREF, + 0, -1 +}; + +char *myname; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + int i; + int type = CH_USA_PREF; + int all_types = 0; + + myname = argv[0]; + sys_init (myname); + + while((opt = getopt(argc, argv, "at:")) != EOF) + switch (opt) { + case 'a': + all_types = 1; + break; + case 't': + i = cmd_srch (optarg, chtbl_ad_order); + if (i != -1) + type = i; + else fprintf (stderr, "Bad type %s\n", optarg); + break; + default: + fprintf (stderr, "Usage: %s [-a] [-t type] domain", myname); + break; + } + argc -= optind; + argv += optind; + + for (i = 0; i < argc; i++) { + if (all_types) { + CMD_TABLE *cp; + + for (cp = chtbl_ad_order; cp -> cmd_key; cp ++) + do_domain (argv[i], cp -> cmd_value); + } + else + do_domain (argv[i], type); + } + exit (0); +} + +do_domain (str, type) +char *str; +int type; +{ + char chanbuf[BUFSIZ]; + char normalised[BUFSIZ]; + char *subdom = NULLCP; + printf ("Domain %s (type %s) -> ", + str, rcmd_srch (type, chtbl_ad_order)); + if (tb_getdomain (str, chanbuf, normalised, type, &subdom) == NOTOK) + printf ("failed\n"); + else { + printf ("normalised=%s chan=%s\n", normalised, chanbuf); + if (subdom != NULLCP) { + printf ("loacl subdomain=%s\n", subdom); + free(subdom); + } + } +} diff --git a/Tools/misc/t-pefrag.c b/Tools/misc/t-pefrag.c new file mode 100644 index 0000000..4f54d2b --- /dev/null +++ b/Tools/misc/t-pefrag.c @@ -0,0 +1,108 @@ +/* pe_frag.c: test out the fragmentation stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-pefrag.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-pefrag.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-pefrag.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +#define DEF_FRAGSIZE 128 + +char *myname; +int fragsize = DEF_FRAGSIZE; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + int i; + + myname = argv[0]; + sys_init (myname); + + while((opt = getopt(argc, argv, "f:")) != EOF) + switch (opt) { + case 'f': + fragsize = atoi (optarg); + if (fragsize <= 0) + fragsize = DEF_FRAGSIZE; + break; + default: + fprintf (stderr, "Usage: %s [-f size] [file]", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc > 0) { + FILE *fp; + if ((fp = fopen (*argv, "r")) == NULL) { + fprintf (stderr, "Can't open file"); + perror (&argv); + exit(1); + } + process (fp); + (void) fclose (fp); + } + else process (stdin); + exit (0); +} + +process (fp) +FILE *fp; +{ + PS ps; + PE pe; + + if ((ps = ps_alloc (std_open)) == NULLPS) + ps_adios (ps, "ps_alloc (read)"); + + if (std_setup (ps, fp) == NOTOK) + ps_adios (ps, "Setup failed (read)"); + + if ((pe = ps2pe (ps)) == NULLPE) + ps_adios (ps, "ps2pe"); + + ps_free (ps); + + if (pe_fragment (pe, fragsize) == NOTOK) + ps_adios (ps, "pe_fragment"); + + if ((ps = ps_alloc (std_open)) == NULLPS) + ps_adios (ps, "ps_alloc (write)"); + + if (std_setup (ps, stdout) == NOTOK) + ps_adios (ps, "Setup failed (write)"); + + if (pe2ps (ps, pe) == NOTOK) + ps_adios (ps, "pe2ps"); + + ps_free (ps); +} + +ps_adios (ps, str) +PS ps; +char *str; +{ + fprintf (stderr, "%s: %s", myname, str); + if (ps -> ps_errno) + fprintf (stderr, " %s", ps_error (ps->ps_errno)); + putc ('\n', stderr); + (void) fflush(stderr); + exit(1); +} diff --git a/Tools/misc/t-prf.c b/Tools/misc/t-prf.c new file mode 100644 index 0000000..43fc3d2 --- /dev/null +++ b/Tools/misc/t-prf.c @@ -0,0 +1,44 @@ +/* t-prf.c tests the PerrRecipientFlag */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-prf.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-prf.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-prf.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "head.h" + + + +/* --------------------- Begin Routines -------------------------------- */ + + + +main (argc, argv) +int argc; +char *argv[]; +{ + int prf, resp, mta, usr; + + if (argc != 2) { + printf ("\n\nUsage: t-prf value\n\n"); + exit (1); + } + + prf = atoi (argv[1]); + prf2mem (prf, &resp, &mta, &usr); + printf ("\n%d - resp=%d mta=%d usr=%d\n", prf, resp, mta, usr); + + printf ("mem2prf returns %d\n\n", mem2prf(resp, mta, usr)); + + return; +} diff --git a/Tools/misc/t-rdmsg.c b/Tools/misc/t-rdmsg.c new file mode 100644 index 0000000..2e7dca0 --- /dev/null +++ b/Tools/misc/t-rdmsg.c @@ -0,0 +1,49 @@ +/* t-rdmsg.c - tests for erroneous messages */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-rdmsg.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-rdmsg.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-rdmsg.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" + + +main (argc, argv) +int argc; +char *argv[]; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULL; + ADDR *recips = NULL; + int retval, rcount; + char *name = argv[1]; + + + if (argc != 2) { + printf ("\n\nUsage: t-rdmsg msg.XXXX\n\n"); + return; + } + + sys_init (argv[0]); + + prm_init (&prm); + q_init (&que); + + retval = rd_msg (name,&prm,&que,&sender,&recips,&rcount); + printf ("%s: %s %s\n", argv[0], argv[1], rp_valstr (retval)); + rd_end(); + return; +} diff --git a/Tools/misc/t-rtime.c b/Tools/misc/t-rtime.c new file mode 100644 index 0000000..2def51f --- /dev/null +++ b/Tools/misc/t-rtime.c @@ -0,0 +1,36 @@ +/* t-time.c: tests the time routines rfc2UTC and UTC2rfc */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-rtime.c,v 6.0 1991/12/18 20:31:14 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-rtime.c,v 6.0 1991/12/18 20:31:14 jpo Rel $ + * + * $Log: t-rtime.c,v $ + * Revision 6.0 1991/12/18 20:31:14 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + +main () +{ + char buf[BUFSIZ]; + UTC ut; + + while (fputs ("UTC Time> ", stdout), fflush(stdout), gets (buf)) { + if ((ut = str2utct (buf, strlen(buf))) == NULLUTC) + printf ("str2utct failed\n"); + printf ("UTC time = %s\n", utct2str (ut)); + printf ("GEN time = %s\n", gent2str (ut)); + if (UTC2rfc (ut, buf) == NOTOK) + printf ("UTC2rfc failed\n"); + printf ("rfc = %s\n", buf); + } + exit (0); +} diff --git a/Tools/misc/t-single.c b/Tools/misc/t-single.c new file mode 100644 index 0000000..23e4a26 --- /dev/null +++ b/Tools/misc/t-single.c @@ -0,0 +1,265 @@ +/* single_parse.c: test program to parse a single address from stdin */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-single.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-single.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-single.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +/* --------------------------------------------------------------------------- + +This tool allows a user to input one line of addresses from stdin. +Each address on this line id parsed, normalised and output on stdout. + +The tool is useful for examining (via gdb or such) how the address +parsing and normalising routines operate. + +As it was derived during the development of the rfc822norm filter, it +takes that filters arguments, in particular -822, -733, -jnt, -bigend, +-littleend and -fold. + +---------------------------------------------------------------------------- */ + + + +#include "util.h" +#include +#include "ap.h" +#include "chan.h" +#include "retcode.h" + + +#define OPT_822 1 +#define OPT_733 2 +#define OPT_JNT 3 +#define OPT_BIGEND 4 +#define OPT_LITTLEEND 5 +#define OPT_FOLD 10 + +CMD_TABLE tbl_options [] = { /* single_parse commandline options */ + "-822", OPT_822, + "-733", OPT_733, + "-jnt", OPT_JNT, + "-bigend", OPT_BIGEND, + "-littleend", OPT_LITTLEEND, + "-fold", OPT_FOLD, + 0, -1 + }; + +typedef enum {maj_none, rfc822, rfc733, jnt} Major_options; +typedef enum {min_none, bigend, littleend} Minor_options; + +static int getch(); +int pcol; +int nonempty; +int fold_width; +int order_pref; +char *myname; +int nadrs; +extern AP_ptr ap_pinit(); +extern int ap_outtype; +extern int ap_perlev; +extern char *calloc(); + +#define DEFAULT_FOLD_WIDTH 78 + +/* ARGSUSED */ +main(argc,argv) +int argc; +char **argv; +{ + /* parse flags */ + Major_options maj = maj_none; + Minor_options mino = min_none; + + myname = *argv++; + sys_init(myname); +/* malloc_debug(2);*/ + ap_outtype = AP_PARSE_SAME; + fold_width = DEFAULT_FOLD_WIDTH; + order_pref = CH_USA_PREF; + + /* parse command arguments */ + while (*argv != NULL) { + switch(cmd_srch(*argv,tbl_options)) { + case -1: + printf("unknown option '%s'",*argv); + exit(1); + + case OPT_FOLD: + if (*(argv+1) == NULL) { + printf("no fold width given"); + exit(1); + } else { + ++argv; + fold_width = atoi(*argv); + } + break; + + case OPT_822: + if ((maj == maj_none) || (maj == rfc822)) { + ap_outtype |= AP_PARSE_822; + maj = rfc822; + break; + } + + case OPT_733: + if ((maj == maj_none) || (maj == rfc733)) { + ap_outtype |= AP_PARSE_733; + maj = rfc733; + break; + } + + case OPT_JNT: + if ((maj == maj_none || maj == jnt) + && (mino == min_none || mino == bigend)) { + ap_outtype |= AP_PARSE_822; + maj = jnt; + ap_outtype |= AP_PARSE_BIG; + mino = bigend; + order_pref = CH_UK_PREF; + break; + } + printf("multiple major parse options"); + exit(1); + + case OPT_BIGEND: + if (mino == min_none || mino == bigend) { + ap_outtype |= AP_PARSE_BIG; + mino = bigend; + order_pref = CH_UK_PREF; + break; + } + + case OPT_LITTLEEND: + if (mino == min_none || mino == littleend) { + mino = littleend; + break; + } + printf("multiple minor parse options"); + exit(1); + + default: + printf("unknown option '%s'",*argv); + exit(1); + } + argv++; + } + + /* ap_outype set so read in address */ + proc(); + exit(0); +} + +/* */ +/* parse one line of addresses fro stdin to stdout */ +proc () +{ + int amp_fail; + int res; + int done; + + ap_clear(); + nadrs = 0; + amp_fail = FALSE; + nonempty = FALSE; + done = FALSE; + while (done == FALSE) { + if (ap_pinit(getch) == BADAP) { + printf("ap_pinit failed\n"); + exit(1); + } + res = ap_1adr(); /* parse one adr */ + switch(res) { + case DONE: /* done */ + done = TRUE; + break; + case NOTOK: + amp_fail = TRUE; + break; + default: + break; + } + + if (done == FALSE) { + res = out_adr(ap_pstrt); + } + ap_sqdelete(ap_pstrt, NULLAP); + ap_free(ap_pstrt); + ap_pstrt = NULLAP; + } + + putchar('\n'); + if (ap_perlev) { + printf("nested level %d\n",ap_perlev); + amp_fail++; + } + if (amp_fail == TRUE) + printf("Parse error in original version\n"); +} + +static int out_adr(ap) +register AP_ptr ap; +{ + AP_ptr loc_ptr, /* -- in case fake personal name needed -- */ + group_ptr, + name_ptr, + dom_ptr, + route_ptr, + return_tree; + char *addrp; + int len; + + if (ap->ap_obtype == AP_NIL) + return OK; + + if (nadrs != 0) { + printf(", "); + pcol += 2; + } + + ap = ap_normalize(ap, order_pref); + + return_tree = ap_t2p (ap, &group_ptr, &name_ptr, &loc_ptr, + &dom_ptr, &route_ptr); + + if (return_tree == BADAP) { + printf("error from ap_t2p\n"); + exit(1); + } else { + addrp = ap_p2s(group_ptr, name_ptr, loc_ptr, + dom_ptr, route_ptr); + + if (addrp == (char *) NOTOK) { + printf("error from ap_p2s()\n"); + } + } + + if ((len = strlen(addrp)) > 0) { /* print */ + pcol += len; + if (pcol >= fold_width && nonempty) { + pcol = 2 + len; + printf("\n%*s", 2, ""); + } else + nonempty = TRUE; + + printf("%s",addrp); + nadrs++; + } + free(addrp); + return OK; +} + +static int getch() +{ + return getchar(); +} diff --git a/Tools/misc/t-time.c b/Tools/misc/t-time.c new file mode 100644 index 0000000..2c03ff4 --- /dev/null +++ b/Tools/misc/t-time.c @@ -0,0 +1,36 @@ +/* t-time.c: tests the time routines rfc2UTC and UTC2rfc */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-time.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-time.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-time.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + + +main () +{ + char buf[BUFSIZ]; + UTC ut; + + while (fputs ("Time> ", stdout), fflush(stdout), gets (buf)) { + if (rfc2UTC (buf, &ut) == NOTOK) + printf ("rfc2UTC failed\n"); + printf ("UTC time = %s\n", utct2str (ut)); + printf ("GEN time = %s\n", gent2str (ut)); + if (UTC2rfc (ut, buf) == NOTOK) + printf ("UTC2rfc failed\n"); + printf ("new rfc = %s\n", buf); + } + exit (0); +} diff --git a/Tools/misc/t-txt2dr.c b/Tools/misc/t-txt2dr.c new file mode 100644 index 0000000..a088f48 --- /dev/null +++ b/Tools/misc/t-txt2dr.c @@ -0,0 +1,55 @@ +/* program/subroutines name: brief description of what this is */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-txt2dr.c,v 6.0 1991/12/18 20:30:40 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/misc/RCS/t-txt2dr.c,v 6.0 1991/12/18 20:30:40 jpo Rel $ + * + * $Log: t-txt2dr.c,v $ + * Revision 6.0 1991/12/18 20:30:40 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "dr.h" + +main (ac, av) +int ac; +char *av[]; +{ + char buffer[BUFSIZ]; + char c; + FILE *fp; + + fp = stdin; + + if (fgets (&buffer[0], BUFSIZ, fp) == NULL) + return; + + do_routine (buffer); +} + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + +static do_routine (str) +char *str; +{ + DRmpdu drmpdu; + dr_init (&drmpdu); + if (txt2dr (&drmpdu, str) == NOTOK) + printf ("NOTOK\n"); + else + printf ("OK\n"); +} diff --git a/Tools/mkpasswd/Makefile b/Tools/mkpasswd/Makefile new file mode 100644 index 0000000..21ed8fc --- /dev/null +++ b/Tools/mkpasswd/Makefile @@ -0,0 +1,82 @@ +# Generate encoded/encrypted passwds +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/mkpasswd/RCS/Makefile,v 6.0 1991/12/18 20:31:22 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:31:22 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = mkpasswd.c +OBJS = mkpasswd.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xmkpasswd + +default: $(PROGS) + +mkpasswd: xmkpasswd +xmkpasswd: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBSYS) + + +install: inst-dir inst-mkpasswd + +inst-mkpasswd: $(TOOLDIR)/mkpasswd +$(TOOLDIR)/mkpasswd: xmkpasswd + -$(BACKUP) $@ zxmkpasswd + rm -f $@ + $(INSTALL) xmkpasswd $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "mkpasswd installed normally"; echo "" + +inst-dir: $(TOOLDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxmkpasswd *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow diff --git a/Tools/mkpasswd/make b/Tools/mkpasswd/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/mkpasswd/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/mkpasswd/mkpasswd.c b/Tools/mkpasswd/mkpasswd.c new file mode 100644 index 0000000..95422a3 --- /dev/null +++ b/Tools/mkpasswd/mkpasswd.c @@ -0,0 +1,78 @@ +/* mkpasswd.c: generate encryped/encoed passwd */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/mkpasswd/RCS/mkpasswd.c,v 6.0 1991/12/18 20:31:22 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/mkpasswd/RCS/mkpasswd.c,v 6.0 1991/12/18 20:31:22 jpo Rel $ + * + * $Log: mkpasswd.c,v $ + * Revision 6.0 1991/12/18 20:31:22 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +#ifdef BSD42 +#define RAND random +#define SRAND srandom +#else +#define RAND rand +#define SRAND srand +#endif + +char *myname; + +static void findpass (); + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + char *pass; + + myname = argv[0]; + while((opt = getopt(argc, argv, "")) != EOF) + switch (opt) { + default: + fprintf (stderr, "Usage: %s", myname); + break; + } + argc -= optind; + argv += optind; + + + findpass (); + +} + +char saltkeys[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./"; +extern char *crypt (); + +static void findpass () +{ + char *pass, *epass; + char saltc[3]; + time_t now; + + (void) time (&now); + SRAND (now); + + saltc[0] = saltkeys[RAND () % ((sizeof saltkeys) - 1)]; + saltc[1] = saltkeys[RAND () % ((sizeof saltkeys) - 1)]; + saltc[2] = 0; + + pass = getpassword ("Password: "); + epass = crypt (pass, saltc); + + bzero (pass, strlen (pass)); + + printf ("%s\n", epass); +} diff --git a/Tools/mlist/Makefile b/Tools/mlist/Makefile new file mode 100644 index 0000000..8b52c73 --- /dev/null +++ b/Tools/mlist/Makefile @@ -0,0 +1,122 @@ +# List maintance tool +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/mlist/RCS/Makefile,v 6.0 1991/12/18 20:31:28 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:31:28 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS =mlist.c +OBJS =mlist.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +INCLUDE = -I$(HEADERS) +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS=xmlist + +default: $(PROGS) + +mlist:xmlist + +xmlist: $(OBJS) $(LIBPP) + rm -f $@ + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + chmod u+s $@ + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) + +lint: l-mlist + +l-mlist: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +install: inst-dir inst-mlist + +inst-dir: $(USRBINDIR) + +inst-mlist: $(USRBINDIR)/mlist + +$(USRBINDIR)/mlist: xmlist + -$(BACKUP) $@ zxmlist + -rm -f $@ + $(INSTALL) xmlist $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -$(CHMOD) u+s $@ + -rm -f $(USRBINDIR)/malias + ln -s $@ $(USRBINDIR)/malias + -@ls -ls $@ $(USRBINDIR)/malias + -@echo "mlist and malias installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f $(PROGS) core a.out Makefile.old zxmlist + +depend: + $(DEPEND) $(INCLUDE) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +mlist.o: mlist.c +mlist.o: ../../h/head.h +mlist.o: ../../h/util.h +mlist.o: ../../h/config.h +mlist.o: ../../h/ll_log.h +mlist.o: ../../h/retcode.h +mlist.o: ../../h/adr.h +mlist.o: ../../h/list_rchan.h +mlist.o: ../../h/chan.h +mlist.o: ../../h/table.h +mlist.o: ../../h/list_bpt.h +mlist.o: ../../h/auth.h +mlist.o: ../../h/list_bpt.h +mlist.o: ../../h/extension.h +mlist.o: ../../h/mta.h +mlist.o: ../../h/adr.h +mlist.o: ../../h/list_bpt.h +mlist.o: ../../h/or.h +mlist.o: ../../h/dl.h +mlist.o: ../../h/alias.h +mlist.o: ../../h/chan.h +mlist.o: ../../h/retcode.h +mlist.o: ../../h/ap.h +mlist.o: ../../h/util.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/mlist/make b/Tools/mlist/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/mlist/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/mlist/mlist.c b/Tools/mlist/mlist.c new file mode 100644 index 0000000..6de369a --- /dev/null +++ b/Tools/mlist/mlist.c @@ -0,0 +1,1621 @@ +/* mlist: list maintaining and viewing tool */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/mlist/RCS/mlist.c,v 6.0 1991/12/18 20:31:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/mlist/RCS/mlist.c,v 6.0 1991/12/18 20:31:28 jpo Rel $ + * + * $Log: mlist.c,v $ + * Revision 6.0 1991/12/18 20:31:28 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "adr.h" +#include "or.h" +#include "dl.h" +#include "alias.h" +#include "chan.h" +#include "retcode.h" +#include "ap.h" +#include +#include +#include "sys.file.h" +#include +#include + +int (*work_proc) (); +int (*menu_proc) (); + +static int init(); +static void user_init(); +static int display(); +static int display_menu(); +static int modify(); +static int modify_menu(); +static int verifyList(); +static int verifyUser(); +static int inList(); +static int addUser(); +static int isPP(); +static int removeUser(); +static int findUser(); +static void openpager(); +static void closepager(); +static void changeAdrType(); +static int m_createList(); +static int m_alterInLine(); +static int m_addReq(); +static int m_delReq(); +static int m_createListFile(); +static int m_alterExpansion(); +static int permission(); +static void listLists(); +static int isModerator(); +static int listOnLocal(); +static void master_modify(); +static void restrict_modify(); +static char *lowerfy (); +extern int errno; +extern char *compress(); + +/* copied from Lib/tai/tai_chan.c */ +static CMD_TABLE chtbl_ad_order[] = { + "usa", CH_USA_ONLY, + "us", CH_USA_ONLY, + "uk", CH_UK_ONLY, + "usapref", CH_USA_PREF, + "uspref", CH_USA_PREF, + "ukpref", CH_UK_PREF, + 0, -1 + }; + + +extern Name *new_Name(); +extern char *loc_dom_site, + *loc_dom_mta, + *loc_dist_prefix, + *list_tbl_comment, + *ad_getlocal(); +extern char *tbldfldir; +char *pager; +FILE *out; +char *list_table_file, *userAlias; +int haveUid, userId; +int superUser, + curmode, + menudriven, +#ifdef UKORDER + dmnorder = CH_UK_PREF, +#else + dmnorder = CH_USA_ONLY, +#endif + pipeopen = 0, + adrType = AD_822_TYPE; + +typedef struct _desc { + char *name; + char *desc; +} Desc; + +Desc *Descriptions = NULL; +int noLists = 0; +static void init_descs(); + +main (argc, argv) +int argc; +char **argv; +{ + int i, args; + + init(argv[0]); + + superUser = FALSE; + menudriven = TRUE; + + if (strcmp(argv[0], "malias") == 0) { + work_proc = display; + menu_proc = display_menu; + } else { + work_proc = modify; + menu_proc = modify_menu; + } + i = 1; + userAlias = NULLCP; + haveUid = NOTOK; + args = TRUE; + + while (args == TRUE && i < argc) { + if (lexequ(argv[i], "-help") == 0) { + printf("%s [-order 'domain_order'] [-user 'username'] [-uid 'user Id'] [-x] [-r] [listname ...]\n", + argv[0]); + exit(0); + } else if (lexequ(argv[i], "-x") == 0) { + adrType = AD_X400_TYPE; + } else if (lexequ(argv[i], "-r") == 0) { + adrType = AD_822_TYPE; + } else if (lexequ(argv[i], "-user") == 0) { + /* run as -user foo */ + if (isPP() == NOTOK) { + fprintf(stderr, + "You are not a mail superuser and so cannot use the '%s' flag\n", + argv[i]); + exit(1); + } + if (i+1 < argc) + userAlias = argv[++i]; + else { + fprintf(stderr, + "No user name given with flag '%s'\n", + argv[i]); + exit (0); + } + } else if (lexequ(argv[i], "-uid") == 0) { + /* run as -uid 6 */ + if (isPP() == NOTOK) { + fprintf(stderr, + "You are not a mail superuser and so cannot use the '%s' flag\n", + argv[i]); + exit(1); + } + if (i+1 < argc) { + haveUid = OK; + userId = atoi(argv[++i]); + } else { + fprintf (stderr, + "No user id given with flag '%s'\n", + argv[i]); + exit (0); + } + } else if (lexequ(argv[i], "-order") == 0) { + if (i+1 < argc) { + if ((dmnorder = cmd_srch(argv[++i], + chtbl_ad_order)) == NOTOK) { + fprintf(stderr, + "Unknown domain ordering '%s'\n", + argv[i]); + exit (0); + } + } else { + fprintf(stderr, + "No domain ordering given with flag '%s'\n", + argv[i]); + exit (0); + } + } else + args = FALSE; + if (args == TRUE) + i++; + } + + user_init(); + + if (i == argc) + (*menu_proc)(); + else { + menudriven = FALSE; + for (; i < argc; i++) + (*work_proc) (argv[i]); + } +} + +/* */ +/* initialisation routines */ +static Table *List = NULLTBL; + +extern char *list_tbl; + +static int init(myname) +char *myname; +{ + char buf[BUFSIZ]; + sys_init(myname); + or_myinit(); + if ((pager = getenv("PAGER")) == NULL) + pager = "more"; + if ((List = tb_nm2struct(list_tbl)) == NULLTBL) { + fprintf(stderr, "Cannot initialise table 'list'\n"); + exit(1); + } + if (List->tb_file[0] == '/') + strcpy(buf, List->tb_file); + else + sprintf(buf,"%s/%s",tbldfldir,List->tb_file); + list_table_file = strdup(buf); +} + +struct passwd *pwd; +ADDR *adr; +extern char *postmaster, + *pplogin; + + +static int isPP() +{ + RP_Buf rp; + int uid; + struct passwd *tmp; + ADDR *tmpadr; + + if ((uid = getuid()) == 0) + /* super user */ + return OK; + if ((tmp = getpwuid(uid)) == NULL) { + fprintf(stderr, "Cannot get your passwd entry\n"); + exit(1); + } + tmpadr = adr_new(tmp->pw_name, AD_ANY_TYPE, 0); + + if (rp_isbad(ad_parse(tmpadr, &rp, dmnorder))) { + fprintf(stderr, + "Cannot parse your mail address\nReason : %s\n", + rp.rp_line); + exit(1); + } + + if ((strcmp(tmp->pw_name, pplogin) == 0) + || (strcmp(tmpadr->ad_r822adr, postmaster) == 0)) { + adr_free(tmpadr); + return OK; + } + adr_free(tmpadr); + return NOTOK; +} + +static void user_init () +{ + RP_Buf rp; + if (userAlias != NULLCP) { + if ((pwd = getpwnam(userAlias)) == NULL) { + fprintf(stderr, + "Cannot get passwd entry for user '%s'\n", + userAlias); + exit (1); + } + printf("Running as user '%s'\n", userAlias); + } else if (haveUid == OK) { + if ((pwd = getpwuid(userId)) == NULL) { + fprintf (stderr, + "Cannot get passwd entry for uid '%d'\n", + userId); + exit (1); + } + printf("Running as uid '%d'\n", userId); + } else { + if ((pwd = getpwuid(getuid())) == NULL) { + fprintf(stderr, "Cannot get your passwd entry\n"); + exit(1); + } + } + adr = adr_new(pwd->pw_name, AD_ANY_TYPE, 0); + + if (rp_isbad(ad_parse(adr, &rp, dmnorder))) { + fprintf(stderr, + "Cannot parse your mail address\nReason : %s\n", + rp.rp_line); + exit(1); + } + if ((strcmp(pwd->pw_name, pplogin) == 0) + || (strcmp(adr->ad_r822adr, postmaster) == 0)) { + printf ("You are a mail super-user\n"); + superUser = TRUE; + } +} + +/* */ +/* display mode routines */ + +static char *getx400name(name) +char *name; +{ + OR_ptr or; + char buf[BUFSIZ]; + + or = or_buildpn(name); + or = or_default(or); + or_or2std(or, buf, 0); + or_free(or); + return strdup(buf); +} + +static dl *readList(name) +char *name; +{ + dl *list; + char newname[BUFSIZ], *x400name, *local; + + if (tb_getdl(name,&list,OK) == OK + || list != NULL) + return list; + + /* try local variant of list */ + if ((local = ad_getlocal(name,(name[0] == '/') ? AD_X400_TYPE : AD_822_TYPE)) != NULLCP) { + if (tb_getdl(local, &list,OK) == OK + || list != NULL) { + free(local); + return list; + } + free(local); + } + + /* try various conversion on name */ + + /* with locdomsite */ + sprintf(newname, "%s@%s",name,loc_dom_site); + if (tb_getdl(newname,&list,OK) == OK + || list != NULL) + return list; + + /* with locdommta */ + sprintf(newname, "%s@%s",name,loc_dom_mta); + if (tb_getdl(newname,&list,OK) == OK + || list != NULL) + return list; + + /* x400 type address */ + x400name = getx400name(name); + if (tb_getdl(x400name, &list,OK) == OK + || list != NULL) { + free(x400name); + return list; + } + free(x400name); + return NULL; +} + +static int writeList(list) +dl *list; +{ + Name *ix; + + openpager(); + + if (strncmp(list->dl_listname, loc_dist_prefix, strlen(loc_dist_prefix)) == 0) { + char *ix2 = list->dl_listname + strlen(loc_dist_prefix); + if (pipeopen) + fprintf(out, "Local Expansion of List: %s\t%s\n-------------------------\n", + ix2, list->dl_desc); + } else { + if (pipeopen) + fprintf(out,"List: %s\t%s\n-----\n",list->dl_listname,list->dl_desc); + } + if (pipeopen) + fprintf(out,"Moderator's mail address: %s\n", + (list -> dl_moderator == NULL) ? postmaster : list -> dl_moderator); + if (isModerator(list)) { + if ((ix = list -> dl_uids) != NULL) { + if (pipeopen) + fprintf(out,"Moderator%s uids: ", + (ix -> next == NULL) ? "" : "s"); + while (ix != NULL) { + if (pipeopen) + fprintf(out,"%*s%s\n", + (ix == list -> dl_uids) ? 0 : strlen("Moderators uids: "), + "", + ix -> name); + ix = ix -> next; + } + } + } + + ix = list -> dl_list; + if (pipeopen) + fprintf(out,"Expands to -> "); + while (ix != NULL && pipeopen) { + if (pipeopen) + fprintf(out,"%*s%s\t%s\n", + (ix == list -> dl_list) ? 0 : strlen("Expands to -> "), + "", + ix -> name, + (ix -> file == NULL) ? "{inline-member}" : ""); + ix = ix -> next; + } + if (pipeopen) + fprintf(out,"\n"); + closepager(); +} + +static int display(name) +char *name; +{ + dl *list; + char distList[BUFSIZ]; + + (void) sprintf(distList, "%s%s", loc_dist_prefix, name); + + if ((list = readList(name)) != NULL + || (list = readList(distList)) != NULL) { + if (permission(list) != SECRMODE) { + writeList(list); + dl_free(list); + } else + printf("You do not have permission to read this list\n"); + } else + printf("unknown list '%s'\n",name); +} + +static int display_menu() +{ + int quit = FALSE; + char buf[BUFSIZ], *tix; + + while (quit == FALSE) { + printf("\n> "); + fflush (stdout); + if (gets (buf) == NULL) + exit(OK); + (void) compress (buf, buf); + if (buf[0] == NULL || strlen(buf) == 0) { + printf("\nType 'h' or '?' for help\n"); + continue; + } + if (strlen(buf) == 1) + switch (buf[0]) + { + case '\0': + case '\n': + printf("\nType 'h' or '?' for help\n"); + continue; + case 'q': + case 'Q': + printf("\nBye...\n"); + quit = TRUE; + continue; + case 't': + case 'T': + tix = &(buf[0]); + while (*tix != '\0' + && !isspace(*tix)) + tix ++; + while (*tix != '\0' + && isspace(*tix)) + tix++; + if (tix == buf) + tix++; + changeAdrType(tix); + continue; + case 'h': + case 'H': + case '?': + fprintf(stdout, + "\nOptions are:\n'l' ist the lists,\n'q' uit,\n't'ype - change type of addresses you're inputing,\n\nor the name of the list you wish to view\n"); + continue; + case 'l': + case 'L': + listLists(); + continue; + default: + break; + } + display(buf); + } +} + +/* */ +/* modify mode routines */ + +static int modify(name) +char *name; +{ + dl *list; + char distList[BUFSIZ]; + struct stat statbuf; + int fd; + char buf[BUFSIZ], *inListname; + + (void) sprintf(distList, "%s%s", loc_dist_prefix, name); + if ((list = readList(name)) == NULL + && (list = readList(distList)) == NULL) { + fprintf(stderr, "Unknown list '%s'\n",name); + return NOTOK; + } + + /* check in line or in file */ + if (list->dl_file == NULLCP) { + if (confirm("This list is an in-line list\nThis program is unable to modify in-line lists\nDo you want to send a request to change this ?") == TRUE) + m_alterInLine(list); + dl_free(list); + return NOTOK; + } + +/* if (listOnLocal(list -> dl_listname, hostname) == FALSE) { + printf("List '%s' is expanded on machine '%s'\n",name,hostname); + if (isModerator(list) == TRUE) { + if (confirm("do you wish to mail a request to change the expansion point ?") == TRUE) + m_alterExpansion(list); + } else + printf("This tool can not modify remotely expanded lists\n"); + dl_free(list); + return NOTOK; + }*/ + + if (stat(list->dl_file, &statbuf) < 0) { + if (isModerator(list) == FALSE) { + sprintf(buf, "File for list '%s' can only be created by a moderator\nDo you wish to send a message to the list moderator ?",name); + if (confirm(buf) == TRUE) + m_createListFile(list); + dl_free(list); + return NOTOK; + } + + /* work out modes for creation of file */ + printf("Creating file for list '%s'\n",name); + printf("Do you want other users to be able to add / remove their own names ?"); + if (confirm (NULLCP) == TRUE) { + printf("Do you want them to be able to add / remove anyone else's name ?"); + if (confirm(NULLCP) == TRUE) + curmode = FREEMODE; + else + curmode = PUBMODE; + } else { + printf("Do you want others to be able to see who is on the list ?"); + if (confirm (NULLCP)) + curmode = PRIVMODE; + else + curmode = SECRMODE; + } + + printf ("Creating file '%s' with list mode ", list->dl_file); + switch (curmode) { + case FREEMODE: + printf("free\n"); + break; + case PUBMODE: + printf("public\n"); + break; + case PRIVMODE: + printf("private\n"); + break; + case SECRMODE: + printf("secret\n"); + break; + } + if ((fd = creat(list->dl_file, curmode)) < 0) { + printf("Unable to create file '%s'\n",list->dl_file); + dl_free(list); + return NOTOK; + } + (void) fchmod(fd, curmode); + + } else { + curmode = (int) statbuf.st_mode; + curmode = curmode & 0777; + + if (!(isModerator(list) + || curmode == PUBMODE + || curmode == FREEMODE)) { + printf ("list '%s' can only be updated by it's moderators\n",name); + if (curmode != SECRMODE) { + printf("Do you want to see who is on the list ? "); + if (confirm (NULLCP)) + display(name); + } + + if (inList(pwd -> pw_name, list -> dl_list, &inListname) == TRUE) { + printf("You (%s) are already in this list\nDo you wish to mail a request to be removed",inListname); + if (confirm(NULLCP) == TRUE) + m_delReq(list); + } else { + printf ("Do you wish to mail a request to be added"); + if (confirm(NULLCP) == TRUE) + m_addReq(list); + } + dl_free(list); + return NOTOK; + } + } + + /* all prelimarys done */ + printf("Modifying list '%s'\n",name); + if (isModerator(list) || curmode == FREEMODE) + master_modify(list); + else + restrict_modify(list); + return OK; +} + +static int modify_menu() +{ + int quit = FALSE; + char buf[BUFSIZ], + *margv[20], + ch; + int margc; + + while (quit == FALSE) { + printf("\n> "); + fflush (stdout); + if (gets (buf) == NULL) + exit(OK); + compress (buf, buf); + if (buf[0] == NULL || strlen(buf) == 0) { + printf("\nType 'h' or '?' for help\n"); + continue; + } + margc = sstr2arg(buf, 20, margv, " \t"); + if ((int)strlen(margv[0]) > 1) + ch = 'A'; + else if (margv[0][0] == '?') + ch = '?'; + else + ch = uptolow(margv[0][0]); + switch (ch) + { + case '\0': + case '\n': + printf("\nType 'h' or '?' for help\n"); + continue; + case 'h': + case '?': + printf("\nOptions are:\n'l' ist the lists,\n'c' reate a list,\n"); + printf("'p' rint 'listname' to view a list,\n'q' uit,\n't'ype - change type of addresses you're inputing,\n\nor the name of the list you wish to modify\n"); + continue; + case 'q': + printf("\nBye...\n"); + quit = TRUE; + continue; + case 't': + changeAdrType(margv[1]); + continue; + case 'l': + listLists(); + continue; + case 'c': + m_createList(); + continue; + case 'p': + if (margc > 1) + display(margv[1]); + continue; + default: + break; + } + if (modify(margv[0]) == NOTOK) + printf("\nType 'h' or '?' for help\n"); + } + +} + +/* */ +/* routines to send messages to postmaster or moderators */ + +char input[BUFSIZ]; + +static int getinput() +{ + fflush(stdout); + if (gets (input) == NULL) { + exit (1); + } + compress (input, input); + if ((strlen(input) == 0) + || ((strlen(input) == 1) && (input[0] == '\n'))) { + printf("\t-> "); + return getinput(); + } + return OK; +} + +static int error_user() +{ + RP_Buf rp; + pps_end(NOTOK, &rp); +} + +static int error_pps(rp) +RP_Buf *rp; +{ + fprintf(stderr, "pps_error: %s\n",rp->rp_line); + fflush(stderr); +} + +static int m_createList() +{ + dl *list; + RP_Buf rp; + printf("Please wait while I initialise things ..."); + fflush(stdout); + + if (pps_1adr("Distribution/mailing List creation request", + postmaster, + &rp) != OK) + return error_pps(&rp); + printf("done\n"); + printf("Name of new list -> "); + if (getinput() == NOTOK) + return error_user(); + if ((list = readList(input)) != NULL) { + printf("'%s' list already exists ('%s')\n", + input, + list -> dl_listname); + dl_free(list); + return error_user(); + } + if (pps_txt("\nName of new list: ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + printf("\nDescription of list (one line only) -> "); + if (getinput() == NOTOK) + return error_user(); + if (pps_txt("\nFunction: ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + printf("\nModerators login names (separated by , again one line only)\n\t-> "); + if (getinput() == NOTOK) + return error_user(); + if (pps_txt("\nModerators: ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n",&rp) != OK) + return error_pps(&rp); + + printf("\nDo you want to pass this message on to the postmaster ?"); + if (confirm (NULLCP) == FALSE) { + pps_end(NOTOK,&rp); + return 0; + } + printf("Please wait while I tidy things up ..."); + fflush(stdout); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("done\n"); + fflush(stdout); + printf ("Your request has been passed to an administrator\n"); + printf ("You will be notified in a short time when the list has been created\n"); + printf ("You can then use this program to enter names into the list\n\n"); + fflush (stdout); + return 0; +} + +static int m_alterInLine(list) +dl *list; +{ + RP_Buf rp; + printf("Sending message to postmaster..."); + fflush(stdout); + if (pps_1adr("Distribution/mailing list alteration request", + postmaster, + &rp) != OK) + return error_pps(&rp); + if (pps_txt("\nPlease could you change the list ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(list->dl_listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\nfrom being inline to being contained within a file\n\nThank you\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("sent\n"); + fflush(stdout); + return 0; +} + +static int m_addReq(list) +dl *list; +{ + RP_Buf rp; + printf("Sending request message to moderator..."); + fflush(stdout); + if (pps_1adr("List addition request", + (list -> dl_moderator == NULL) ? postmaster : list -> dl_moderator, + &rp) != OK) + return error_pps(&rp); + + if (pps_txt("\nPlease add me to the list ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(list -> dl_listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n\nThank you.\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("sent\n"); + fflush(stdout); + return 0; +} + +static int m_delReq(list) +dl *list; +{ + RP_Buf rp; + printf("Sending request message to moderator..."); + fflush(stdout); + if (pps_1adr("Deletion from list request", + (list -> dl_moderator == NULL) ? postmaster : list -> dl_moderator, + &rp) != OK) + return error_pps(&rp); + + if (pps_txt("\nPlease remove me from the list ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(list -> dl_listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n\nThank you.\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("sent\n"); + fflush(stdout); + return 0; +} + +static int m_createListFile(list) +dl *list; +{ + RP_Buf rp; + printf("Sending request message to moderator..."); + fflush(stdout); + if (pps_1adr("List file creation request", + (list -> dl_moderator == NULL) ? postmaster : list -> dl_moderator, + &rp) != OK) + return error_pps(&rp); + + if (pps_txt("Please create the file for the list ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(list -> dl_listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n\nThank you.\n",&rp) != OK) + return error_pps(&rp); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("sent\n"); + fflush(stdout); + return 0; +} + +static int m_alterExpansion(list) +dl *list; +{ + RP_Buf rp; + printf("Please wait while I initialise things ..."); + fflush(stdout); + if (pps_1adr("List expansion alteration request", + postmaster, + &rp) != OK) + return error_pps(&rp); + + if (pps_txt("\nPlease change the host the list ",&rp) != OK) + return error_pps(&rp); + if (pps_txt(list -> dl_listname,&rp) != OK) + return error_pps(&rp); + if (pps_txt(" is distributed from\nto ->",&rp) != OK) + return error_pps(&rp); + printf("done\n"); + printf("Please input the host the list should be distrubuted from ->"); + if (getinput() == NOTOK) + return error_user(); + if (pps_txt(input,&rp) != OK) + return error_pps(&rp); + if (pps_txt("\n\nThank you.\n",&rp) != OK) + return error_pps(&rp); + + printf("Please wait while I tidy things up ..."); + fflush(stdout); + if (pps_end(OK,&rp) != OK) + return error_pps(&rp); + printf("done\n"); + fflush(stdout); + return 0; +} + +/* */ +/* general routines */ +#define INC 3 + +static void init_descs() +{ + int size = INC; + char buf[BUFSIZ], + *temp, + *name, + *ix; + FILE *fd; + + if ((fd = fopen(list_table_file, "r")) == NULL) { + fprintf(stderr, + "Unable to open list of list file '%s' : %s\n", + list_table_file, sys_errname (errno)); + return; + } + + Descriptions = (Desc *) calloc((unsigned int) size, sizeof(Desc)); + + while (fgets(buf, BUFSIZ, fd) != NULLCP) { + temp = strdup(buf); + if (temp[0] == '\n') { + free(temp); + continue; + } + + if (temp[0] != '#') { + if (strncmp(temp,loc_dist_prefix,strlen(loc_dist_prefix)) == 0) + name = temp+strlen(loc_dist_prefix); + else + name = temp; + ix = index(name, ':'); + if (ix == NULL) { + printf("unknown syntax line in list table '%s'\n",temp); + free(temp); + continue; + } + *ix++ = '\0'; + ix = rindex(ix, ','); + if (ix != NULL) + ix++; + } else { + if (strncmp(&temp[1], + list_tbl_comment, + strlen(list_tbl_comment)) == 0) { + name = temp+strlen(list_tbl_comment)+1; + ix = NULL; + } else + continue; + } + if (noLists >= size) { + size += INC; + Descriptions = (Desc *) realloc((char *) Descriptions, + (unsigned int)(size*sizeof(Desc))); + } + + Descriptions[noLists].name = strdup(name); + if (ix == NULLCP) + Descriptions[noLists].desc = NULLCP; + else + Descriptions[noLists].desc = strdup(ix); + noLists++; + free(temp); + } + Descriptions = (Desc *) realloc((char *) Descriptions, + (unsigned int) (noLists*sizeof(Desc))); +} + +static void listLists() +{ + int i; + + openpager(); + + if (Descriptions == NULL) + init_descs(); + for (i = 0; i < noLists && pipeopen; i++) { + if (Descriptions[i].desc == NULLCP) + fprintf(out, "%s", Descriptions[i].name); + else + fprintf(out, "%-30s: %s", + Descriptions[i].name,Descriptions[i].desc); + } + closepager(); +} + +/* */ +/* pager routines */ + +SFP oldpipe; + +static SFD piped(sig) +int sig; +{ + pipeopen = 0; +} + +static void openpager() +{ + oldpipe = signal(SIGPIPE, piped); + if (isatty(1) == 0) + out = stdout; + else if ((out = popen(pager,"w")) == NULL) { + fprintf(stderr, "unable to start pager '%s': %s\n", + pager, sys_errname (errno)); + out = stdout; + } + pipeopen = 1; +} + +static void closepager() +{ + if (out != stdout) { + pclose(out); + out = stdout; + } + pipeopen = 0; + signal(SIGPIPE, oldpipe); +} + +/* */ + +confirm (str) +char *str; +{ + register char c; + + if (str != NULL) { + fputs (str, stdout); + fflush(stdout); + } + printf (" [y/n] "); + fflush (stdout); + + c = ttychar (); + + switch (c) + { + case 'Y': + case 'y': + printf ("yes\r\n"); + fflush (stdout); + return (TRUE); + + case 'N': + case 'n': + printf ("no\r\n"); + fflush(stdout); + return (FALSE); + default: + printf ("Type y or n\n"); + fflush(stdout); + return (confirm (NULLCP)); + } +} + + +ttychar () +{ + register int c; + char buf[LINESIZE]; + + fflush (stdout); + if (fgets (buf, LINESIZE, stdin) == NULL) + exit (1); + c = buf[0]; + + c = toascii (c); /* get rid of high bit */ + + if (c == '\r') + c = '\n'; + + return (c); +} + +/* */ +static int permission(list) +dl *list; +{ + struct stat statbuf; + int mode; + + if (isModerator(list) == TRUE) + /* allowed to do anything */ + return FREEMODE; + if (list->dl_file == NULLCP + || stat(list->dl_file, &statbuf) < 0) + /* no file so can't do anything */ + return TOPMODE; + + mode = (int) statbuf.st_mode; + mode = mode & 0777; + + return mode; +} + +/* */ +static int listOnLocal(name, host) +char *name, + host[]; +{ + char *p; + + if ((p = index(name, '@')) == NULL) { + /* do x400 */ + sprintf(host,"unknown"); + return FALSE; + } + p++; + sprintf(host,"%s",p); + if (strcmp(p, loc_dom_mta) == 0 + || strcmp(p, loc_dom_site) == 0) + return TRUE; + + /* do x400 */ + return FALSE; +} + +static int isModerator(list) +dl *list; +{ + Name *ix = list -> dl_uids; + + if (superUser == TRUE) + return TRUE; + + while (ix != NULL && (strcmp(ix -> name, pwd -> pw_name) != 0)) + ix = ix -> next; + + return (ix == NULL) ? FALSE : TRUE; +} + +/* */ +/* main modify work routines */ +static char *ix; + +static int getbufchar() +{ + char ret = *ix; + if (ret != 0) ix++; + return (ret == 0) ? EOF : ret; +} + +static void master_modify(list) +dl *list; +{ + FILE *curfp; + int quit = FALSE, + done; + char tmpbuf[LINESIZE], *tix, + buf[BUFSIZ], + *adrstr, *orig_line, *inListname; + + if ((curfp = flckopen(list->dl_file, "r+")) == NULL) { + fprintf (stderr, "Can't open %s: %s\n", + list -> dl_file, sys_errname (errno)); + return; + } + + flckclose(curfp); + + while (quit == FALSE) { + fprintf(stdout, "\n%s%s", + list->dl_listname, + (menudriven == TRUE) ? ">> " : "> "); + fflush(stdout); + if (gets(tmpbuf) == NULL) { + exit(0); + } + compress (tmpbuf, tmpbuf); + + ix = &(tmpbuf[0]); + switch (tmpbuf[0]) + { + case '\0': + case '\n': + printf("\nType 'h' or '?' for help\n"); + continue; + + case 't': + case 'T': + tix = &(tmpbuf[0]); + while (*tix != '\0' + && !isspace(*tix)) + tix ++; + while (*tix != '\0' + && isspace(*tix)) + tix++; + if (tix == tmpbuf) + tix++; + changeAdrType(tix); + continue; + + case 'p': + case 'P': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace(*ix)) ix++; + display(list -> dl_listname); + continue; + } + case 'v': + case 'V': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace(*ix)) ix ++; + verifyList(list); + continue; + } + + case 'h': + case 'H': + case '?': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + fprintf(stdout, + "\nOptions are:\n'p' rint list,\n'v' erify list,\n'a' dd user,\n'f' ind user,\n'r' emove users,\n'l' ist the lists,\n'c' reate a new list,\n't'ype - change type of addresses you're inputting,\n"); + if (menudriven == TRUE) + fprintf(stdout, "'q' uit and return to top menu.\n\n"); + else + fprintf(stdout, "'q' uit.\n\n"); + fprintf(stdout, "If the input is none of the above options,\nit is assumed to be a user name to be added\n"); + fflush (stdout); + continue; + } + + case 'l': + case 'L': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + listLists(); + continue; + } + + case 'c': + case 'C': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' && + isspace(*ix)) ix++; + m_createList(); + continue; + } + case 'q': + case 'Q': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace(*ix)) ix ++; + if (*ix == '\0') { + quit = TRUE; + continue; + } + ix = &(tmpbuf[0]); + break; + } + case 'r': + case 'R': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace(*ix)) ix++; + if (*ix == '\0') { + printf ("give username to be removed (regex): "); + (void) fflush (stdout); + if (gets(tmpbuf) == NULL) + exit(0); + compress (tmpbuf, tmpbuf); + ix = &(tmpbuf[0]); + } + removeUser(ix, list); + continue; + } + + case 'f': + case 'F': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace(*ix)) ix++; + + if (*ix == '\0') { + printf ("give username to search for (regex): "); + if (gets(tmpbuf) == NULL) + exit(0); + compress (tmpbuf, tmpbuf); + ix = &(tmpbuf[0]); + } + + + findUser(ix, list); + continue; + } + case 'a': + case 'A': + if (tmpbuf[1] == '\0' + || isspace(tmpbuf[1])) { + ix = &(tmpbuf[1]); + while (*ix != '\0' + && isspace (*ix)) ix++; + + if (*ix == '\0') { + printf("give username to be added: "); + if (gets(tmpbuf) == NULL) + exit(0); + compress (tmpbuf, tmpbuf); + ix = &(tmpbuf[0]); + } + } + + default: + break; + } + done = FALSE; + + while (done == FALSE) { + orig_line = ix; + if (ap_pinit(getbufchar) == BADAP) { + printf("Cannot parse '%s'\n", + orig_line); + done = FALSE; + } else { + switch (ap_1adr()) { + case DONE: + done = TRUE; + break; + case NOTOK: + break; + default: + if (ap_t2s(ap_pstrt, &adrstr) != BADAP) { + if (rp_isbad(verifyUser(adrstr, buf))) + printf("Illegal address '%s'\n", + adrstr); + else { + if (inList(adrstr, list -> dl_list, &inListname) == TRUE) { + printf("User '%s' already in list", + adrstr); + if (lexequ(inListname, adrstr) != 0) + printf(" as '%s'", inListname); + printf("\n"); + } else + addUser(adrstr, list); + } + free(adrstr); + ap_pstrt = NULLAP; + } + break; + } + } + } + + } + if (menudriven == FALSE) + printf("\nBye...\n"); + +} + +static void restrict_modify(list) +dl *list; +{ + char buf[LINESIZE], + adr[BUFSIZ], + *nameinlist; + + printf("Would you like to see who's in the list ?"); + if (confirm(NULLCP) == TRUE) + display(list -> dl_listname); + if (!rp_isbad(verifyUser(pwd->pw_name, adr))) { + if (inList(adr, list -> dl_list, &nameinlist) == TRUE) { + + printf("You (%s) are already in this list\nDo you wish to be removed ?",pwd -> pw_name); + if (confirm(NULLCP) == TRUE) { + sprintf(buf, "^%s$",adr); + removeUser(buf, list); + } else + printf("You only have permission to add or remove yourself from this list\n"); + } else { + printf ("You (%s) are not in this list\nDo you wish to be added ?", pwd -> pw_name); + if (confirm(NULLCP) == TRUE) + addUser(adr, list); + else + printf("You only have permission to add or remove yourself from this list\n"); + } + } + +} + +/* */ +/* checking routines */ + +static int verifyUser(name, addr) +char *name, + *addr; +{ + RP_Buf rp; + ADDR *temp; + int ret, + type; + + temp = adr_new(name, adrType, 0); + + if (rp_isbad(ret = ad_parse(temp, &rp, dmnorder))) + fprintf(stderr, "Failed to parse '%s' (%s)\n", + name, + rp.rp_line); + if (temp -> ad_r400adr != NULL + && temp->ad_type == AD_X400_TYPE) + sprintf(addr, "%s", temp->ad_r400adr); + else if (temp -> ad_r822adr != NULL) + sprintf(addr, "%s", temp->ad_r822adr); + adr_free(temp); + + return ret; +} + +static int verifyList(list) +dl *list; +{ + char *name, + buf[BUFSIZ]; + + + Name *ix = list -> dl_list; + while (ix != NULL) { + printf("Checking '%s'...",ix -> name); + if (!rp_isbad(verifyUser(ix -> name, buf))) { + printf("ok\n"); + ix = ix -> next; + } else { + name = strdup(ix -> name); + ix = ix -> next; + removeUser(name,list); + free(name); + } +/* if (temp != NULL) *temp = '@';*/ + } +} + +static int inList(name, list, plistname) +char *name; +Name *list; +char **plistname; +{ + while (list != NULL + && ap_equ(list -> name, name) != TRUE) + list = list -> next; + if (list != NULL) + *plistname = list->name; + return (list != NULL) ? TRUE : FALSE; +} + +/* */ +/* list maintaince routines */ +extern char *re_comp(); +extern int re_exec(); + +static int findUser (name, list) +char *name; +dl *list; +{ + char *diag; + Name *ix; + + if ((diag = re_comp(name)) != 0) { + fprintf(stderr, + "re_comp error for '%s' [%s]\n", name, diag); + return; + } + ix = list -> dl_list; + openpager(); + while (ix != NULL && pipeopen) { + if (re_exec(lowerfy(ix -> name)) == 1) { + fprintf(out, "%s\n", ix -> name); + fflush(stdout); + } + ix = ix -> next; + } + closepager(); +} + +static int removeUser(name, list) +char *name; +dl *list; +{ + char *diag; + Name *ix, + *temp; + char buf[BUFSIZ]; + int len = 0, + found; + FILE *curfp; + + if ((diag = re_comp(name)) != 0) { + fprintf (stderr, + "re_comp error for '%s' [%s]\n",name,diag); + return; + } + if ((curfp = flckopen (list->dl_file, "r+")) == NULL) { + fprintf (stderr, "Can't open %s: %s\n", + list -> dl_file, sys_errname (errno)); + return; + } + + rewind(curfp); + ix = list -> dl_list; + found = FALSE; + while (ix != NULL) { + temp = NULL; + sprintf(buf, "Remove user '%s' ?", ix -> name); + if (re_exec(lowerfy(ix -> name)) == 1 + && confirm(buf) == TRUE) { + /* remove from list -> dl_list */ + if (ix -> file == NULL) + printf("User '%s' specified in-line, cannot remove\n",ix->name); + else { + found = TRUE; + temp = list -> dl_list; + if (ix == list -> dl_list) { + list -> dl_list = temp -> next; + } else { + while (temp -> next != ix) + temp = temp -> next; + temp -> next = ix -> next; + temp = ix; + } + } + } else if (ix -> file != NULL) { + /* put it out again */ + fputs (ix -> name, curfp); + fputc('\n', curfp); + len += strlen(ix -> name) + 1; + } + ix = ix -> next; + if (temp != NULL) { + temp -> next = NULL; + name_free(temp); + } + } + ftruncate(fileno(curfp), (off_t) len); + flckclose(curfp); + if (found == FALSE) + printf("No matches\n"); +} + +static int addUser(name, list) +char *name; +dl *list; +{ + FILE *curfp; + Name *temp, + *ix; + + if ((curfp = flckopen(list->dl_file, "a")) == NULL) { + fprintf (stderr, "Can't open file %s: %s\n", + list -> dl_file, sys_errname (errno)); + return; + } + + printf ("adding user '%s'\n", name); + fputs (name, curfp); + fputc ('\n', curfp); + flckclose (curfp); + temp = new_Name(name, list->dl_file); + if (list -> dl_list == NULL) + list -> dl_list = temp; + else { + ix = list -> dl_list; + + while (ix -> next != NULL) + ix = ix -> next; + ix -> next = temp; + } +} + +static char *lowerfy (s) +char *s; +{ + static char buf[BUFSIZ]; + char *cp; + + for (cp = buf; *s; s++) + if (isascii (*s) && isupper (*s)) + *cp++ = tolower (*s); + else + *cp ++ = *s; + *cp = NULL; + return buf; +} + +static void changeAdrType(buf) +char *buf; +{ + if (buf[0] == '\0') + printf ("Currently inputing %s style addresses\n", + (adrType == AD_X400_TYPE) ? "x400" : "rfc822"); + else if (lexnequ(buf, "x400", strlen("x400")) == 0) + adrType = AD_X400_TYPE; + else if (lexnequ(buf, "rfc822", strlen("rfc822")) == 0) + adrType = AD_822_TYPE; + else + printf("Unknown address type '%s' - try %s or %s", + buf, "x400", "rfc822"); +} diff --git a/Tools/mpp84/Makefile b/Tools/mpp84/Makefile new file mode 100644 index 0000000..96f51bd --- /dev/null +++ b/Tools/mpp84/Makefile @@ -0,0 +1,122 @@ +# mpp84 +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/Makefile,v 6.0 1991/12/18 20:31:34 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:31:34 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +LIBPP = ../../Lib/libpp.a + +SOCKET = + +CFLAGS = $(CCOPTIONS) $(LCF) +LDFLAGS = $(LDOPTIONS) $(LLF) + +############################################################ +# +# Suffix rules +# +############################################################ + +PROGS = xmpp84 + +.SUFFIXES: .py + +.py.c: + $(PEPY) $(PYFLAGS) $< + +.py.o: + $(PEPY) $(PYFLAGS) $< + $(CC) $(CFLAGS) -c $*.c + rm -f $*.c + +################################################################## +# mpp84 +################################################################## + +OBJS = UNIV.o T73.o SFD.o P1.o P3.o P2.o mpp84.o +SRCS = P1.c P2.c P3.c SFD.c T73.c UNIV.c mpp84.c + +all: $(PROGS) + + +mpp84: xmpp84 +xmpp84: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-dir inst-mpp84 +inst-dir: $(TOOLDIR) +inst-mpp84: $(TOOLDIR)/mpp84 +$(TOOLDIR)/mpp84: xmpp84 + -$(BACKUP) $@ zxmpp84 + rm -f $@ + $(INSTALL) xmpp84 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "mpp84 tool installed normally"; echo "" + + + +cfiles: $(SRCS) + +UNIV.o: UNIV.c +UNIV.c: UNIV.py + +mpp84.o: mpp84.c +mpp84.c: mpp84.py + +P1.o: P1.c +P1.c: P1.py + +P2.o: P2.c +P2.c: P2.py + +P3.o: P3.c +P3.c: P3.py + +SFD.o: SFD.c +SFD.c: SFD.py + +T73.o: T73.c +T73.c: T73.py + + +################################################################ +# clean +################################################################ + +clean: tidy + rm -f $(SRCS) $(OBJS) *.ph + +tidy: + rm -f *.a _* core xmpp84 *.BAK *.old zx* + +depend: ; +define: ; + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/mpp84/P1.py b/Tools/mpp84/P1.py new file mode 100644 index 0000000..16a1bc0 --- /dev/null +++ b/Tools/mpp84/P1.py @@ -0,0 +1,641 @@ +-- P1.py - MHS P1 definitions + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P1.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: P1.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + + +P1 DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P1.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint + +void parse_p2 (); +%} + +BEGIN + +PRINTER print + +-- P1 makes use of types defined in the following module: +-- Sa: Recommendation S.a[14] +-- T73: T.73, Section 5 + +MPDU ::= + CHOICE { + usermpdu + [0] IMPLICIT UserMPDU, + + ServiceMPDU + } + +ServiceMPDU ::= + CHOICE { + reportmpdu [1] + IMPLICIT DeliveryReportMPDU, + + probempdu [2] + IMPLICIT ProbeMPDU + } + +UserMPDU ::= + SEQUENCE { + envelope + UMPDUEnvelope, + + content + UMPDUContent + } + +UMPDUEnvelope ::= + SET { + mpduID + MPDUIdentifier, + + originator + ORName, + + encodedtypes + EncodedInformationTypes + OPTIONAL, + + contentype + ContentType, + + uacontentID + UAContentId OPTIONAL, + + priority + Priority DEFAULT normal, + + permsgflag + PerMessageFlag DEFAULT {}, + + deferredDelivery[0] + IMPLICIT Time + OPTIONAL, + + perdomain [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo + OPTIONAL, + + recipient [2] + IMPLICIT SEQUENCE OF RecipientInfo, + + trace + TraceInformation + } + +UMPDUContent ::= + OCTETSTRING + %{ parse_p2 ($$, $$_len); %} + + +-- time + +Time ::= + UniversalTime + + +-- various envelope information + +MPDUIdentifier ::= + [APPLICATION 4] IMPLICIT SEQUENCE { + globalid + GlobalDomainIdentifier, + IA5String + } + +ContentType ::= + [APPLICATION 6] + IMPLICIT INTEGER { + p2(2) + } + +UAContentId ::= + [APPLICATION 10] + IMPLICIT PrintableString + +Priority ::= + [APPLICATION 7] + IMPLICIT INTEGER { + normal(0), + nonUrgent(1), + urgent(2) + } + +PerMessageFlag ::= + [APPLICATION 8] + IMPLICIT BITSTRING { + discloseRecipients(0), + conversionProhibited(1), + alternateRecipientAllowed(2), + contentReturnRequest(3) + } + +-- per-domain bilateral information + +PerDomainBilateralInfo ::= + SEQUENCE { + country + CountryName, + admd + AdministrationDomainName, + bilateralinfo + BilateralInfo + } + +BilateralInfo ::= + ANY + +-- recipient information + +RecipientInfo ::= + SET { + recipname + ORName, + + extensionid [0] + IMPLICIT ExtensionIdentifier, + + perecipflag [1] + IMPLICIT PerRecipientFlag, + + explicitconversion [2] + IMPLICIT ExplicitConversion DEFAULT {} + + } + +ExtensionIdentifier ::= + INTEGER + +PerRecipientFlag ::= + BITSTRING -- See Figure 23/X.411 + +ExplicitConversion ::= + INTEGER { + iA5TextTeletex(0), + teletexTelex(1) + } + + +-- trace information + +TraceInformation ::= + [APPLICATION 9] + IMPLICIT SEQUENCE OF SEQUENCE { + domainid + GlobalDomainIdentifier, + + domainsupplied + DomainSuppliedInfo + } + +DomainSuppliedInfo ::= + SET { + arrival [0] + IMPLICIT Time, + + deferred [1] + IMPLICIT Time + OPTIONAL, + + action [2] + IMPLICIT INTEGER { + relayed(0), + + rerouted(1) + }, + + encodedtypes + EncodedInformationTypes + OPTIONAL, + + previous + GlobalDomainIdentifier OPTIONAL + } + + +-- global domain identifier + +GlobalDomainIdentifier ::= + [APPLICATION 3] + IMPLICIT SEQUENCE { + country + CountryName, + admd + AdministrationDomainName, + prmd + PrivateDomainIdentifier OPTIONAL + } + +CountryName ::= + [APPLICATION 1] + CHOICE { + NumericString, + PrintableString + } + +AdministrationDomainName ::= + [APPLICATION 2] + CHOICE { + NumericString, + PrintableString + } + +PrivateDomainIdentifier ::= + CHOICE { + NumericString, + PrintableString + } + + +-- O/R name + +ORName ::= + [APPLICATION 0] + IMPLICIT SEQUENCE { + standard + StandardAttributeList, + + domaindefined + DomainDefinedAttributeList + OPTIONAL + } + +StandardAttributeList ::= + SEQUENCE { + country + CountryName OPTIONAL, + + admd + AdministrationDomainName OPTIONAL, + + x121 [0] + IMPLICIT X121Address OPTIONAL, + + terminalID [1] + IMPLICIT TerminalID OPTIONAL, + + prmd [2] + PrivateDomainName OPTIONAL, + + org [3] + IMPLICIT OrganizationName OPTIONAL, + + uaID [4] + IMPLICIT UniqueUAIdentifier OPTIONAL, + + pname [5] + IMPLICIT PersonalName + OPTIONAL, + + orgUnit [6] + IMPLICIT SEQUENCE OF OrganizationalUnit OPTIONAL + } + +DomainDefinedAttributeList ::= + SEQUENCE OF DomainDefinedAttribute + +DomainDefinedAttribute ::= + SEQUENCE { + type + PrintableString, + + value + PrintableString + } + +X121Address ::= + NumericString + +TerminalID ::= + PrintableString + +OrganizationName ::= + PrintableString + +UniqueUAIdentifier ::= + NumericString + +PersonalName ::= + SET { + surName [0] + IMPLICIT PrintableString, + + givenName [1] + IMPLICIT PrintableString + OPTIONAL, + + initials [2] + IMPLICIT PrintableString + OPTIONAL, + + generalQualifier [3] + IMPLICIT PrintableString + OPTIONAL + } + +OrganizationalUnit ::= + PrintableString + +PrivateDomainName ::= + CHOICE { + NumericString, + PrintableString + } + + +-- encoded information types + +EncodedInformationTypes ::= + [APPLICATION 5] IMPLICIT SET { + bitstring [0] + IMPLICIT BITSTRING { + undefined(0), + tLX(1), + iA5Text(2), + g3Fax(3), + tIF0(4), + tTX(5), + videotex(6), + voice(7), + sFD(8), + tIF1(9) + }, + + [1] + IMPLICIT G3NonBasicParams + OPTIONAL, + + [2] + IMPLICIT TeletexNonBasicParams + OPTIONAL, + + [3] + IMPLICIT PresentationCapabilities + OPTIONAL + + -- other non-basic parameters are for further study + } + +G3NonBasicParams ::= + BITSTRING { + twoDimensional(8), + fineResolution(9), + unlimitedLength(20), + b4Length(21), + a3Width(22), + b4Width(23), + uncompressed(30) + } + +TeletexNonBasicParams ::= + SET { + graphicCharacterSets[0] + IMPLICIT T61String OPTIONAL, + + controlCharacterSets[1] + IMPLICIT T61String OPTIONAL, + + pageFormats[2] + IMPLICIT OCTETSTRING OPTIONAL, + + miscTerminalCapabilities[3] + IMPLICIT T61String OPTIONAL, + + privateUse[4] + IMPLICIT OCTETSTRING OPTIONAL + } + +PresentationCapabilities ::= + T73.PresentationCapabilities + + +-- Delivery Report MPDU + +DeliveryReportMPDU ::= + SEQUENCE { + envelope + DeliveryReportEnvelope, + + content + DeliveryReportContent + } + +DeliveryReportEnvelope ::= + SET { + report + MPDUIdentifier, + + originator + ORName, + + TraceInformation + } + +DeliveryReportContent ::= + SET { + original + MPDUIdentifier, + + intermediate + TraceInformation OPTIONAL, + + uacontentID + UAContentId OPTIONAL, + + reprecip [0] + IMPLICIT SEQUENCE OF ReportedRecipientInfo, + + returned [1] + IMPLICIT UMPDUContent OPTIONAL, + + billingInformation [2] + ANY + OPTIONAL + } + +ReportedRecipientInfo ::= + SET { + recipient[0] + IMPLICIT ORName, + + extensionID [1] + IMPLICIT ExtensionIdentifier, + + perecipflag [2] + IMPLICIT PerRecipientFlag, + + lastrace [3] + IMPLICIT LastTraceInformation, + + intendedRecipient[4] + IMPLICIT ORName + OPTIONAL, + + additional [5] + IMPLICIT SupplementaryInformation OPTIONAL + } + + +-- last trace information + +LastTraceInformation ::= + SET { + arrival [0] + IMPLICIT Time, + + encodedtypes + EncodedInformationTypes + OPTIONAL, + + report [1] + Report + } + +Report ::= + CHOICE { + delivered [0] + IMPLICIT DeliveredInfo, + + nondelivered [1] + IMPLICIT NonDeliveredInfo + } + +DeliveredInfo ::= + SET { + delivery [0] + IMPLICIT Time, + + typeOfUA [1] + IMPLICIT INTEGER { + public(0), + private(1) + } DEFAULT public + } + +NonDeliveredInfo::= + SET { + reason [0] + IMPLICIT ReasonCode, + + diagnostic [1] + IMPLICIT DiagnosticCode OPTIONAL + } + +ReasonCode ::= + INTEGER { + transferFailure(0), + unableToTransfer(1), + conversionNotPerformed(2) + } + +DiagnosticCode ::= + INTEGER { + unrecognizedORName(0), + + ambiguousORName(1), + + mtaCongestion(2), + + loopDetected(3), + + uaUnavailable(4), + + maximumTimeExpired(5), + + encodedInformationTypesUnsupported(6), + + contentTooLong(7), + + conversionImpractical(8), + + conversionProhibited(9), + + implicitConversionNotResgistered(10), + + invalidParameters(11) + } + + +-- supplementary information + +SupplementaryInformation ::= + PrintableString -- length limited and for further study + + +-- Probe MPDU + +ProbeMPDU ::= + ProbeEnvelope + +ProbeEnvelope ::= + SET { + probeid + MPDUIdentifier, + + originator + ORName, + + ContentType, + + UAContentId OPTIONAL, + + encodedtypes + EncodedInformationTypes + OPTIONAL, + + TraceInformation, + + PerMessageFlag DEFAULT {}, + + contentLength[0] + IMPLICIT INTEGER + OPTIONAL, + + [1] + IMPLICIT SEQUENCE OF PerDomainBilateralInfo + OPTIONAL, + + [2] + IMPLICIT SEQUENCE OF RecipientInfo +} + +END + +%{ + +void adios (); + + +void parse_p2 (octstr, len) +char *octstr; +int len; +{ + PS ps; + PE pe; + + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "ps_alloc"); + if (str_setup (ps, octstr, len, 0) == NOTOK) + adios (NULLCP, "str_setup (%s)", ps_error (ps -> ps_errno)); + + if ((pe = ps2pe (ps)) == NULLPE) + adios (NULLCP, "ps2pe (%s)", ps_error (ps -> ps_errno)); + + (void) print_P2_UAPDU (pe, 1, NULLIP, NULLVP, NullParm); + + pe_free (pe); + ps_free (ps); +} + +%} diff --git a/Tools/mpp84/P2.py b/Tools/mpp84/P2.py new file mode 100644 index 0000000..56631c9 --- /dev/null +++ b/Tools/mpp84/P2.py @@ -0,0 +1,400 @@ +-- P2.py - MHS P2 definitions + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P2.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: P2.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + +P2 DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P2.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint +%} + +BEGIN + +PRINTER print + +-- P2 makes use of types defined in the following moduls: +-- P1: X.411, Section 3.4 +-- P3: X.411, Section 4.3 +-- SFD: this Recommendation, Section 5 +-- T73: T.73, Section 5 + +UAPDU ::= + CHOICE { + im-uapdu [0] + IMPLICIT IM-UAPDU, + + sr-uapdu [1] + IMPLICIT SR-UAPDU + } + + +-- IP-message UAPDU + +IM-UAPDU ::= + SEQUENCE { + heading + Heading, + + body + Body + } + + +-- heading + +Heading ::= + SET { + messageID + IPMessageId, + + originator [0] + IMPLICIT ORDescriptor + OPTIONAL, + + authorizingUsers[1] + IMPLICIT SEQUENCE OF ORDescriptor + OPTIONAL, + -- only if not the originator + + primaryRecipients[2] + IMPLICIT SEQUENCE OF Recipient + OPTIONAL, + + copyRecipients[3] + IMPLICIT SEQUENCE OF Recipient + OPTIONAL, + + blindCopyRecipients[4] + IMPLICIT SEQUENCE OF Recipient + OPTIONAL, + + inReplyTo[5] + IMPLICIT IPMessageId + OPTIONAL, + -- omitted if not in reply to a previous message + + obsoletes[6] + IMPLICIT SEQUENCE OF IPMessageId + OPTIONAL, + + crossReferences[7] + IMPLICIT SEQUENCE OF IPMessageId + OPTIONAL, + + subject[8] + CHOICE { + T61String + } + OPTIONAL, + + expiryDate[9] + IMPLICIT P1.Time + OPTIONAL, + -- if omitted, expiry date is never + + replyBy[10] + IMPLICIT P1.Time + OPTIONAL, + + replyToUsers[11] + IMPLICIT SEQUENCE OF ORDescriptor + OPTIONAL, + -- each O/R descriptor must contain an O/R name + + importance[12] + IMPLICIT INTEGER { + low(0), + normal(1), + high(2) + } DEFAULT normal, + + sensitivity[13] + IMPLICIT INTEGER { + personal(1), + private(2), + companyConfidential(3) + } OPTIONAL, + + autoforwarded[14] + IMPLICIT BOOLEAN + DEFAULT FALSE + -- indicates that the forwarded message body + -- part(s) were autoforwarded + } + +IPMessageId ::= + [APPLICATION 11] IMPLICIT SET { + orname + ORName OPTIONAL, + PrintableString + } + +ORName ::= + P1.ORName + +ORDescriptor ::= + SET { -- at least one of the first two members must be present + orname + ORName OPTIONAL, + + freeformName[0] + IMPLICIT T61String + OPTIONAL, + + telephoneNumber[1] + IMPLICIT PrintableString + OPTIONAL + } + +Recipient ::= + SET { + ordesc [0] + IMPLICIT ORDescriptor, + + reportRequest [1] + IMPLICIT BITSTRING { + receiptNotification(0), + nonreceiptNotification(1), + returnIPMessage(2) + } + DEFAULT {}, + -- if requested, the O/R descriptor must contain an O/R name + + replyRequest[2] + IMPLICIT BOOLEAN + DEFAULT FALSE + -- if true, the O/R descriptor must contain an O/R name + } + + +-- body + +Body ::= + SEQUENCE OF BodyPart + +BodyPart ::= + CHOICE { + ia5text [0] + IMPLICIT IA5Text, + + tlx [1] + IMPLICIT TLX, + + voice [2] + IMPLICIT Voice, + + g3fax [3] + IMPLICIT G3Fax, + + tifo [4] + IMPLICIT TIF0, + + ttx [5] + IMPLICIT TTX, + + videotex [6] + IMPLICIT Videotex, + + nationallydef [7] + NationallyDefined, + + encrypted [8] + IMPLICIT Encrypted, + + forwardmsg [9] + IMPLICIT ForwardedIPMessage, + + sfd [10] + IMPLICIT SFD, + + tifi [11] + IMPLICIT TIF1 + } + + +-- body part types + +IA5Text ::= + SEQUENCE { + SET { + repertoire[0] + IMPLICIT INTEGER { + ia5(5), + + ita2(2) + } DEFAULT ia5 + -- additional members of this Set are a + -- possible future extension + }, + + IA5String + } + +TLX ::= + ANY -- for further study + +Voice ::= + SEQUENCE { + SET, -- members are for further study + BITSTRING + } + +G3Fax ::= + SEQUENCE { + SET { + numberOfPages[0] + IMPLICIT INTEGER OPTIONAL, + + [1] + IMPLICIT P1.G3NonBasicParams OPTIONAL + }, + + SEQUENCE OF BITSTRING + } + +TIF0 ::= + T73Document + +T73Document ::= + SEQUENCE OF T73.ProtocolElement + +TTX ::= + SEQUENCE { + SET { + numberOfPages[0] + IMPLICIT INTEGER OPTIONAL, + + telexCompatible[1] + IMPLICIT BOOLEAN DEFAULT FALSE, + + [2] + IMPLICIT P1.TeletexNonBasicParams OPTIONAL + }, + + SEQUENCE OF T61String + } + +Videotex ::= + SEQUENCE { + SET, -- members are for further study + VideotexString + } + +NationallyDefined ::= + ANY + +Encrypted ::= + SEQUENCE { + SET, -- members are for further study + BITSTRING + } + +ForwardedIPMessage ::= + SEQUENCE { + SET { + delivery[0] + IMPLICIT P1.Time + OPTIONAL, + + [1] + IMPLICIT DeliveryInformation + OPTIONAL + }, + + IM-UAPDU + } + +DeliveryInformation ::= + P3.DeliverEnvelope + +SFD ::= + SFD.Document + +TIF1 ::= + T73Document + + +-- IPM-status-report UAPDU + +SR-UAPDU ::= + SET { + choice [0] + CHOICE { + nonReceipt[0] + IMPLICIT NonReceiptInformation, + + receipt[1] + IMPLICIT ReceiptInformation + }, + + reported + IPMessageId, + + actualRecipient[1] + IMPLICIT ORDescriptor + OPTIONAL, + + intendedRecipient[2] + IMPLICIT ORDescriptor + OPTIONAL, + + converted + P1.EncodedInformationTypes + OPTIONAL + } + +NonReceiptInformation ::= + SET { + reason[0] + IMPLICIT INTEGER { + uaeInitiatedDiscard(0), + + autoForwarded(1) + }, + + nonReceiptQualifer[1] + IMPLICIT INTEGER { + expired(0), + + obsoleted(1), + + subscriptionTerminated(2) + } OPTIONAL, + + comments[2] + IMPLICIT PrintableString + OPTIONAL, + -- on auto-forward + + returned[3] + IMPLICIT IM-UAPDU + OPTIONAL + } + +ReceiptInformation ::= + SET { + receipt[0] + IMPLICIT P1.Time, + + typeOfReceipt[1] + IMPLICIT INTEGER { + explicit(0), + + automatic(1) + } DEFAULT explicit, + + supplementary [2] + IMPLICIT P1.SupplementaryInformation OPTIONAL + } + +END diff --git a/Tools/mpp84/P3.py b/Tools/mpp84/P3.py new file mode 100644 index 0000000..016dbc7 --- /dev/null +++ b/Tools/mpp84/P3.py @@ -0,0 +1,63 @@ +-- P3 Defined Types (stub) + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P3.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: P3.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + + +P3 DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/P3.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint +%} + +BEGIN + +PRINTER print + +DeliverEnvelope ::= + SET { + [0] + IMPLICIT P1.ContentType, + + originator + P1.ORName, + + original[1] + IMPLICIT P1.EncodedInformationTypes, + + P1.Priority DEFAULT normal, + + [2] + IMPLICIT DeliveryFlags, + + otherRecipients[3] + IMPLICIT SEQUENCE OF P1.ORName + OPTIONAL, + + thisRecipient[4] + IMPLICIT P1.ORName, + + intendedRecipient[5] + IMPLICIT P1.ORName + OPTIONAL, + + converted[6] + IMPLICIT P1.EncodedInformationTypes OPTIONAL, + + submission[7] + IMPLICIT P1.Time + } + +DeliveryFlags ::= + BITSTRING { conversionProhibited(2) } + +END diff --git a/Tools/mpp84/SFD.py b/Tools/mpp84/SFD.py new file mode 100644 index 0000000..945743e --- /dev/null +++ b/Tools/mpp84/SFD.py @@ -0,0 +1,110 @@ +-- SFD.py - MHS SFD definitions + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/SFD.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: SFD.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + +SFD DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/SFD.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint +%} + +BEGIN + +PRINTER print + +Document ::= SEQUENCE OF ProtocolElement + +ProtocolElement ::= CHOICE { + textUnit[3] IMPLICIT TextUnit, + specificLogicalDescriptor[5] + IMPLICIT LogicalDescriptor + } + + +-- text units + +TextUnit ::= SEQUENCE { + contentPortionAttributes ContentPortionAttributes, + textInformation TextInformation + } + +ContentPortionAttributes + ::= SET { --none at present-- } + +TextInformation ::= CHOICE { + T61String + } + + +-- logical descriptor + +LogicalDescriptor + ::= SEQUENCE { LogicalObjectType, LogicalDescriptorBody } + +LogicalObjectType + ::= INTEGER { + document (0), + paragraph (1) + } + +LogicalDescriptorBody + ::= SET { + -- variable attributes (if object is document) -- + pageHeading[3] IMPLICIT T61String OPTIONAL, + -- variable attributes (if object is paragraph) -- + layoutDirectives[4] IMPLICIT LayoutDirectives OPTIONAL, + presentationDirectives[5] IMPLICIT + PresentationDirectives OPTIONAL, + -- default variable attributes for subordinate objects + -- (if any) + defaultValueLists[6] IMPLICIT SEQUENCE { + DefaultValueList + } OPTIONAL + } + +LayoutDirectives::= SET { + leftIndentation[0] Offset OPTIONAL, + bottomBlankLines[3] Offset OPTIONAL + } + +Offset ::= CHOICE { [1] IMPLICIT INTEGER} + +PresentationDirectives + ::= SET { + alignment[0] IMPLICIT Alignment OPTIONAL, + graphicRendition[1] IMPLICIT GraphicRendition OPTIONAL + } + +Alignment ::= INTEGER { leftAligned(0), centered(2), justified(3) } + +GraphicRendition::= SEQUENCE OF GraphicRenditionAspect + +GraphicRenditionAspect + ::= INTEGER --an SGR parameter value; see T.61 + +DefaultValueList::= CHOICE { + paragraphAttributes[1] IMPLICIT ParagraphAttributes + } + +ParagraphAttributes + ::= SET { + layoutDirectives < Attribute OPTIONAL, + presentationDirectives < Attribute OPTIONAL + } + +Attribute ::= CHOICE { + layoutDirectives[0] IMPLICIT LayoutDirectives, + presentationDirectives[1] IMPLICIT PresentationDirectives + } + +END diff --git a/Tools/mpp84/T73.py b/Tools/mpp84/T73.py new file mode 100644 index 0000000..ed926cf --- /dev/null +++ b/Tools/mpp84/T73.py @@ -0,0 +1,34 @@ +-- T73 Defined Types (stub) + + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/T73.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: T73.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + + +T73 DEFINITIONS ::= + + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/T73.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint +%} + +BEGIN + +PRINTER print + +ProtocolElement ::= + ANY + +PresentationCapabilities ::= + SET { --unimportant-- } + +END diff --git a/Tools/mpp84/UNIV.py b/Tools/mpp84/UNIV.py new file mode 100644 index 0000000..9bb772d --- /dev/null +++ b/Tools/mpp84/UNIV.py @@ -0,0 +1,121 @@ +-- ASN.1 UNIVERSAL defined types + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/UNIV.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: UNIV.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + +UNIV DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/UNIV.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint + +#undef DEBUG +#define testdebug(pe,s) +%} + +BEGIN + + + -- ISO 646-1983 +IA5String ::= + [UNIVERSAL 22] IMPLICIT OCTETSTRING + +ISO646String ::= + IA5String + +NumericString ::= + [UNIVERSAL 18] IMPLICIT IA5String + +PrintableString ::= + [UNIVERSAL 19] IMPLICIT IA5String + + + -- ISO 6937/2-1983 +T61String ::= + [UNIVERSAL 20] IMPLICIT OCTETSTRING + +TeletexString ::= + T61String + + -- ISO 6937/2-1983 +VideotexString ::= + [UNIVERSAL 21] IMPLICIT OCTETSTRING + + + -- ISO 2014, 3307, 4031 + -- date, time, zone +GeneralizedTime ::= + [UNIVERSAL 24] IMPLICIT VisibleString + +GeneralisedTime ::= + GeneralizedTime + + +UTCTime ::= + [UNIVERSAL 23] IMPLICIT VisibleString + +UniversalTime ::= + UTCTime + + -- ISO 2375 +GraphicString ::= + [UNIVERSAL 25] IMPLICIT OCTETSTRING + +VisibleString ::= + [UNIVERSAL 26] IMPLICIT OCTETSTRING + +GeneralString ::= + [UNIVERSAL 27] IMPLICIT OCTETSTRING + + + -- ISO 8824 +EXTERNAL ::= + [UNIVERSAL 8] + IMPLICIT SEQUENCE { + data-value-identifier CHOICE { + -- only for prior argreement of transfer syntax + direct-reference OBJECT IDENTIFIER, + + -- only for presentation layer negotiation + indirect-reference INTEGER + }, + + data-value-descriptor ObjectDescriptor OPTIONAL, + + encodings CHOICE { + single-encoding Encoding-choice, + + multiple-encoding SEQUENCE OF SEQUENCE { + encoding-identifier OBJECT IDENTIFIER, + + encoding Encoding-choice + } + } + } + +Encoding-choice ::= + CHOICE { + single-ASN1-type[0] + ANY, + + octet-aligned[1] + IMPLICIT OCTETSTRING, + + arbitrary[2] + IMPLICIT BITSTRING + } + + + -- ISO 8824 +ObjectDescriptor ::= + [UNIVERSAL 7] IMPLICIT GraphicString + +END diff --git a/Tools/mpp84/make b/Tools/mpp84/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/mpp84/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/mpp84/mpp84.py b/Tools/mpp84/mpp84.py new file mode 100644 index 0000000..ddb1e52 --- /dev/null +++ b/Tools/mpp84/mpp84.py @@ -0,0 +1,285 @@ +-- mpp.py - test out PEPY + + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/mpp84.py,v 6.0 1991/12/18 20:31:34 jpo Rel $ +-- +-- $Log: mpp84.py,v $ +-- Revision 6.0 1991/12/18 20:31:34 jpo +-- Release 6.0 +-- +-- +-- + + +MPP DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp84/RCS/mpp84.py,v 6.0 1991/12/18 20:31:34 jpo Rel $"; +#endif lint + +#include + + +#define ps_advise(ps, f) \ + advise (NULLCP, "%s: %s", (f), ps_error ((ps) -> ps_errno)) + +/* DATA */ +int unpack = 1; + +static char *myname = "mpp84"; + +static enum { ps2mpp, pl2mpp } mode = ps2mpp; + +static enum format { p1, p2, sfd, p2hdr, p1hdr } topfmt = p2; + + +void adios (); + +/* MAIN */ + +/* ARGSUSED */ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + register int status = 0; + register char *cp; + register FILE *fp; + + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + for (argc--, argv++; cp = *argv; argc--, argv++) + if (*cp == '-') { + if (strcmp (cp + 1, "ps") == 0) { + mode = ps2mpp; + continue; + } + if (strcmp (cp + 1, "pl") == 0) { + mode = pl2mpp; + continue; + } + if (strcmp (cp + 1, "p1") == 0) { + topfmt = p1; + continue; + } + if (strcmp (cp + 1, "p2") == 0) { + topfmt = p2; + continue; + } + if (strcmp (cp + 1, "sfd") == 0) { + topfmt = sfd; + continue; + } + if (strcmp (cp + 1, "nounpack") == 0) { + unpack = 0; + continue; + } + if (strcmp (cp + 1, "p2hdr") == 0) { + topfmt = p2hdr; + continue; + } + if (strcmp (cp + 1, "p1hdr") == 0) { + topfmt = p1hdr; + continue; + } + adios (NULLCP, "usage: %s [-nounpck] [ -ps | -pe ] [-p1 | -p2 | -p2hdr | -p1hdr | -sfd ] [ files... ]", + myname); + } + else + break; + + if (argc == 0) + status = process ("(stdin)", stdin); + else + while (cp = *argv++) { + if ((fp = fopen (cp, "r")) == NULL) { + advise (cp, "unable to read"); + status++; + continue; + } + status += process (cp, fp); + (void) fclose (fp); + } + + exit (status); /* NOTREACHED */ +} + +/* */ + +static int process (file, fp) +register char *file; +register FILE *fp; +{ + enum format curfmt = topfmt; + register PE pe; + register PS ps; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + ps_advise (ps, "ps_alloc"); + return 1; + } + if (std_setup (ps, fp) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + for (;;) { + switch (mode) { + case ps2mpp: + if ((pe = ps2pe (ps)) == NULLPE) + if (ps -> ps_errno) { + ps_advise (ps, "ps2pe"); + you_lose: ; + if (pe != NULLPE) + pe_free (pe); + ps_free (ps); + return 1; + } + else { + done: ; + ps_free (ps); + return 0; + } + break; + + case pl2mpp: + if ((pe = pl2pe (ps)) == NULLPE) + if (ps -> ps_errno) { + ps_advise (ps, "pl2pe"); + goto you_lose; + } + else + goto done; + break; + } + + switch (curfmt) { + case p1: + default: + (void) print_P1_MPDU (pe, 1, NULLIP, NULLVP, NULLCP); + break; + + case p2: + (void) print_P2_UAPDU (pe, 1, NULLIP, NULLVP, NULLCP); + break; + + case sfd: + (void) print_SFD_Document (pe, 1, NULLIP, NULLVP, NULLCP); + break; + + case p2hdr: + (void) print_P2_Heading (pe, 1, NULLIP, NULLVP, NULLCP); + break; + + case p1hdr: + (void) print_P1_UMPDUEnvelope (pe, 1, NULLIP, NULLVP, NULLCP); + break; + + } + + pe_free (pe); + } +} + +/* */ + +%} + +BEGIN + +END + +%{ +/* DEBUG */ + +#ifdef DEBUG +testdebug (pe, s) +register PE pe; +register char *s; +{ + static int debug = OK; + char *cp; + register PS ps; + + switch (debug) { + case NOTOK: + break; + + case OK: + if ((debug = (cp = getenv ("PEPYDEBUG")) && *cp ? atoi (cp) + : NOTOK) == NOTOK) + break; + fprintf (stderr, "%s made with %s\n", myname, pepyid); + + default: + fprintf (stderr, "%s\n", s); + + if ((ps = ps_alloc (std_open)) == NULLPS) + return; + if (std_setup (ps, stderr) != NOTOK) + (void) pe2pl (ps, pe); + fprintf (stderr, "--------\n"); + ps_free (ps); + break; + } +} +#endif DEBUG + +/* ERRORS */ + +/* VARARGS2 */ + +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} + +/* */ + +/* VARARGS2 */ + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + (void) fflush (stderr); +} + +%} diff --git a/Tools/mpp88/Makefile b/Tools/mpp88/Makefile new file mode 100644 index 0000000..98cdd62 --- /dev/null +++ b/Tools/mpp88/Makefile @@ -0,0 +1,101 @@ +# mpp88 +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/mpp88/RCS/Makefile,v 6.0 1991/12/18 20:31:43 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:31:43 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +LIBPP = ../../Lib/libpp.a + +SOCKET = +HEADERS = ../../h +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +############################################################ +# +# Suffix rules +# +############################################################ + +PROGS = xmpp88 + + +################################################################## +# mpp88 +################################################################## + + +SRCS = mpp88.c +OBJS = mpp88.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +all: xmpp88 + +mpp88: xmpp88 + @true + +xmpp88: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-mpp88 +inst-dir: $(TOOLDIR) +inst-mpp88: $(TOOLDIR)/mpp88 +$(TOOLDIR)/mpp88: xmpp88 + -$(BACKUP) $@ zxmpp88 + rm -f $@ + $(INSTALL) xmpp88 $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "mpp88 tool installed normally"; echo "" + +mpp88.c:mpp88.py + $(PEPY) $(PYFLAGS) -o $@ mpp88.py + + + +################################################################ +# clean +################################################################ + +clean: tidy + rm -f $(SRCS) $(OBJS) *.ph + +tidy: + rm -f *.a _* core xmpp88 *.BAK *.old zx* + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +mpp88.o: mpp88.c +mpp88.o: mpp88.c + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/mpp88/make b/Tools/mpp88/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/mpp88/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/mpp88/mpp88.py b/Tools/mpp88/mpp88.py new file mode 100644 index 0000000..17c3ea2 --- /dev/null +++ b/Tools/mpp88/mpp88.py @@ -0,0 +1,272 @@ +-- mpp88.py: - test out PEPY + + +-- @(#) $Header: /xtel/pp/pp-beta/Tools/mpp88/RCS/mpp88.py,v 6.0 1991/12/18 20:31:43 jpo Rel $ +-- +-- $Log: mpp88.py,v $ +-- Revision 6.0 1991/12/18 20:31:43 jpo +-- Release 6.0 +-- +-- +-- + + +MPP DEFINITIONS ::= + +%{ +#ifndef lint +static char *rcsid = "$Header: /xtel/pp/pp-beta/Tools/mpp88/RCS/mpp88.py,v 6.0 1991/12/18 20:31:43 jpo Rel $"; +#endif lint + +#include +#include "Trans-types.h" +#include "IOB-types.h" + + +#define ps_advise(ps, f) \ + advise (NULLCP, "%s: %s", (f), ps_error ((ps) -> ps_errno)) + +/* DATA */ +int unpack = 1; +static char *myname = "mpp88"; +static enum { ps2mpp, pl2mpp } mode = ps2mpp; +static enum format { p1, p2, p2hdr, ipn} topfmt = p2; +void adios (); + + +/* MAIN */ + +/* ARGSUSED */ + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + register int status = 0; + register char *cp; + register FILE *fp; + + if (myname = rindex (argv[0], '/')) + myname++; + if (myname == NULL || *myname == NULL) + myname = argv[0]; + + for (argc--, argv++; cp = *argv; argc--, argv++) + if (*cp == '-') { + if (strcmp (cp + 1, "ps") == 0) { + mode = ps2mpp; + continue; + } + if (strcmp (cp + 1, "pl") == 0) { + mode = pl2mpp; + continue; + } + if (strcmp (cp + 1, "p1") == 0) { + topfmt = p1; + continue; + } + if (strcmp (cp + 1, "p2") == 0) { + topfmt = p2; + continue; + } + if (strcmp (cp + 1, "nounpack") == 0) { + unpack = 0; + continue; + } + if (strcmp (cp + 1, "p2hdr") == 0) { + topfmt = p2hdr; + continue; + } + if (strcmp (cp + 1, "ipn") == 0) { + topfmt = ipn; + continue; + } + adios (NULLCP, "usage: %s [ -ps | -pe ] [-p1 | -p2 | -p2hdr | -ipn ] [ files... ]", + myname); + } + else + break; + + if (argc == 0) + status = process ("(stdin)", stdin); + else + while (cp = *argv++) { + if ((fp = fopen (cp, "r")) == NULL) { + advise (cp, "unable to read"); + status++; + continue; + } + status += process (cp, fp); + (void) fclose (fp); + } + + exit (status); /* NOTREACHED */ +} + +/* */ + +static int process (file, fp) +register char *file; +register FILE *fp; +{ + enum format curfmt = topfmt; + register PE pe; + register PS ps; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + ps_advise (ps, "ps_alloc"); + return 1; + } + if (std_setup (ps, fp) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + for (;;) { + switch (mode) { + case ps2mpp: + if ((pe = ps2pe (ps)) == NULLPE) + if (ps -> ps_errno) { + ps_advise (ps, "ps2pe"); + you_lose: ; + if (pe != NULLPE) + pe_free (pe); + ps_free (ps); + return 1; + } + else { + done: ; + ps_free (ps); + return 0; + } + break; + + case pl2mpp: + if ((pe = pl2pe (ps)) == NULLPE) + if (ps -> ps_errno) { + ps_advise (ps, "pl2pe"); + goto you_lose; + } + else + goto done; + break; + } + + switch (curfmt) { + case p1: + default: + (void) print_Trans_MtsAPDU (pe, 1, 0, NULLCP, NULL); + break; + + case p2: + (void) print_IOB_InformationObject (pe, 1, NULLIP, NULLVP, NULLCP); + break; + case p2hdr: + (void) print_IOB_Heading (pe, 1, NULLIP, NULLVP, NULLCP); + break; + case ipn: + (void) print_IOB_IPN (pe, 1, NULLIP, NULLVP, NULLCP); + break; + } + + pe_free (pe); + } +} + +/* */ + +%} + +BEGIN + +END + +%{ +/* DEBUG */ + +#ifdef DEBUG +testdebug (pe, s) +register PE pe; +register char *s; +{ + static int debug = OK; + char *cp; + register PS ps; + + switch (debug) { + case NOTOK: + break; + + case OK: + if ((debug = (cp = getenv ("PEPYDEBUG")) && *cp ? atoi (cp) + : NOTOK) == NOTOK) + break; + fprintf (stderr, "%s made with %s\n", myname, pepyid); + + default: + fprintf (stderr, "%s\n", s); + + if ((ps = ps_alloc (std_open)) == NULLPS) + return; + if (std_setup (ps, stderr) != NOTOK) + (void) pe2pl (ps, pe); + fprintf (stderr, "--------\n"); + ps_free (ps); + break; + } +} +#endif DEBUG + +/* ERRORS */ + +/* VARARGS2 */ + +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + _exit (1); +} + +/* */ + +/* VARARGS2 */ + +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f, + *g, + *h, + *i, + *j; +{ + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + (void) fflush (stderr); +} + +%} diff --git a/Tools/mu/Makefile b/Tools/mu/Makefile new file mode 100644 index 0000000..0d49d5f --- /dev/null +++ b/Tools/mu/Makefile @@ -0,0 +1,129 @@ +# MTS user interface for PP ----> mu <---- +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/mu/RCS/Makefile,v 6.0 1991/12/18 20:31:54 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:31:54 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = argh.c mu.c +OBJS = argh.o mu.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIB = ../../Lib/llib-lpp.ln + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xmu + +default: $(PROGS) + +mu: xmu + +xmu: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o xmu $(OBJS) \ + $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-mu +inst-mu: $(TOOLDIR)/mu +$(TOOLDIR)/mu: xmu + -$(BACKUP) $@ zxmu + rm -f $@ + $(INSTALL) xmu $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Mu installed normally"; echo "" + + +inst-dir: $(TOOLDIR) + + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f core $(PROGS) zxmu *.old *.BAK + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +argh.o: argh.c +argh.o: ../../h/argh.h +argh.o: ../../h/util.h +argh.o: ../../h/config.h +argh.o: ../../h/ll_log.h +mu.o: mu.c +mu.o: ../../h/head.h +mu.o: ../../h/util.h +mu.o: ../../h/config.h +mu.o: ../../h/ll_log.h +mu.o: ../../h/retcode.h +mu.o: ../../h/util.h +mu.o: ../../h/q.h +mu.o: ../../h/adr.h +mu.o: ../../h/list_rchan.h +mu.o: ../../h/chan.h +mu.o: ../../h/table.h +mu.o: ../../h/list_bpt.h +mu.o: ../../h/auth.h +mu.o: ../../h/list_bpt.h +mu.o: ../../h/extension.h +mu.o: ../../h/mta.h +mu.o: ../../h/adr.h +mu.o: ../../h/list_bpt.h +mu.o: ../../h/aparse.h +mu.o: ../../h/ap.h +mu.o: ../../h/util.h +mu.o: ../../h/or.h +mu.o: ../../h/chan.h +mu.o: ../../h/auth.h +mu.o: ../../h/list_rchan.h +mu.o: ../../h/mta.h +mu.o: ../../h/prm.h +mu.o: ../../h/tb_prm.h +mu.o: ../../h/tb_q.h +mu.o: ../../h/tb_a.h +mu.o: ../../h/tb_dr.h +mu.o: ../../h/argh.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/mu/README b/Tools/mu/README new file mode 100644 index 0000000..2268af3 --- /dev/null +++ b/Tools/mu/README @@ -0,0 +1,5 @@ +mu/README +--------- +This directory contains the MTS user interface (jct) + +The interface program is mu - see PP manual volume 1. diff --git a/Tools/mu/argh.c b/Tools/mu/argh.c new file mode 100644 index 0000000..400d78a --- /dev/null +++ b/Tools/mu/argh.c @@ -0,0 +1,636 @@ +/* argh.c argument handling routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/mu/RCS/argh.c,v 6.0 1991/12/18 20:31:54 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/mu/RCS/argh.c,v 6.0 1991/12/18 20:31:54 jpo Rel $ + * + * $Log: argh.c,v $ + * Revision 6.0 1991/12/18 20:31:54 jpo + * Release 6.0 + * + */ + + + +#include "argh.h" +#include "util.h" + +extern struct argdef arg[]; /* defined in main program */ +static struct argfull *argfull; /* to point to full array */ +static struct arginst *ai; /* to point to linked lists */ +static asource; /* holds scan_args counter */ + +struct sort { + struct argfull *tag; + char *string; +} argsort[MAXFLAGS]; /* to hold sort sequence */ + +static char *aerrlist[] = { + + /* usage : printf(aerrlist[i],a,b,c,d); char *a,*b,*c,*d */ + + "unknown error\n", /* 0 */ + "flag %s not known\n", /* 1 */ + "flag %s ambiguous match\n", /* 2 */ + "invalid type for flag %s - fix source\n", /* 3 */ + "limit of %s argument instances - aborted\n", /* 4 */ + "flag %s value should be adjacent to '='\n", /* 5 */ + "flag %s (type adjacent) not followed by value\n", /* 6 */ + "flag %s - adjacent arguments not allowed without '='\n", /* 7 */ + "flag %s (type next) must use next argument\n", /* 8 */ + "flag %s (type next) has no next argument\n", /* 9 */ + "flag %s (type 0 valued ) should not have value\n", /*10 */ + "flag %s (type %s valued) has no value%s\n", /*11 */ + "flag %s (type %s valued) has only %s value%s\n", /*12 */ + "flag %s (type 1 or more) must have at least one value\n", /*13 */ + "duplicate flag %s in table - fix source\n", /*14 */ + "ambiguous flags %s and %s - fix source\n" /*15 */ +}; + +/* ----------------------------------------------------------------- */ +int prep_args(arg) /* scan flags list, count, set length, + sort and calculate match length */ +struct argdef arg[]; +{ + struct argdef *a; + struct argfull *af; + int i,j,cur,prev; + + for(i=0,a=arg; a->flag[0]; i++,a++); /* count arg[] */ + flagcount=i; /* flagcount is structure member for 'others' */ + + argfull = (struct argfull *) calloc( (flagcount+1), sizeof(struct argfull) ); + + asource=1; /* initialise scan_counter */ + + /* printf("flagcount %d\n",flagcount); */ + + for(i=0,a=arg,af=argfull; i<=flagcount; i++,a++,af++) { + + af->flag = a->flag; + af->function = a->function; + af->type = a->type; + af->match = a->match; + af->length = 0; + af->count = 0; + af->first = NULL; + af->last = NULL; + + if ( index(VALIDTYPES,af->type) == NULL ) { + arg_error(3,af->flag); + cleanquit(); + } + + argsort[i].tag = af; /* pointer to structure */ + argsort[i].string = af->flag; /* pointer to flag chars. */ + af->length=strlen(af->flag); + /* printf("length %d match %d type %c %s\n",af->length, af->match, af->type, af->flag); */ + } + + quick_string(argsort,flagcount+1); /* sort array argsort in flag order */ + + argsort[flagcount+1].tag = argsort[0].tag; /* both ends point to "" */ + +/* + for(j=0;j<=flagcount; j++) { + printf("argsort j=%d string=%s\n",j,argsort[j].string); + } +*/ + + for(j=0,prev=0; j<=flagcount; j++,prev=cur) { + af = argsort[j].tag; + cur=mincmp(af->flag,(argsort[j+1].tag)->flag); + if(!cur) { + arg_error(14,af->flag); + return(-1); + } + if (j && cur > af->length) { + arg_error(15,af->flag,(argsort[j+1].tag)->flag); + return(-1); + } + /* printf("sort %d %s type %c cur %d prev %d\n",j,af,af->type,cur,prev); */ + if(af->match <= 0) { + if(af->match < 0) + af->match=af->length; + else { + af->match = (cur < prev) ? (prev) : (cur); + } + } + } + return(0); +} + +/* ----------------------------------------------------------------- */ +int scan_args(argc,argv) /* returns incremented scan_counter */ +int argc; +char **argv; +{ + struct argdef *a=arg; /* passed in */ + struct argfull *af=argfull; /* generated internally */ + char **argvtemp=argv; + char *cp,*v; + char nullbyte='\0'; + int i,c,ca,offset,n; + + if (!flagcount) { + if ( (i=prep_args(arg)) ) + cleanquit(); + } +/* + The argument list is scanned, checking each argument against + entries in structure 'argfull'. Linked lists are generated + for all arguments of the same type, in command line sequence. + Any parameters which do not match one of the ->type's are + accumulated in a list of 'others'. + + sample flag + -samplearg complete match (adj) ok ( unless !ADJARGS ) + -sample arg complete match (next) ok + ^ offset + -sample=arg complete match with = (adj) ok + -sample= arg complete match with = (next) - error - "value should be adjacent to '='" + ^ offset + -samarg incomplete match (adj) - error - "flag not known/ambiguous match" + -sam arg incomplete match (next) ok + -sam=arg incomplete match with =arg ok + -sam= arg incomplete match with = (next) arg - error - "value should be adjacent to '='" + ^ offset +*/ + for(argcpi=1; argcpi < argc; argcpi++) { /* loop until arguments exhausted */ + cp = *++argvtemp; + if (**argvtemp == FLAGCHAR) { + + /* now test against each allowed type in turn */ + + for(i=0,af=argfull; i < flagcount; i++,af++) { + if (!mystrncmp(af->flag, &cp[1], af->match)) { + + /* found a match */ + + if(( v = index(cp,EQUCHAR) ) != NULL) { + if(*++v == '\0') { + arg_error(5,af->flag); + break; + } + } + else { + v = &nullbyte; + if(af->length == af->match) { + v=cp + af->match + 1; /* value starts at end of match (could point at '\0') */ + } + else { + + if ( (ONECHARARGS) && (af->match == 1)) { /* allow one char */ + v = cp + 2 ; + } + else { + + /* have matched on af->match chars - try on ca chars */ + + ca=strlen(cp)-1; /* length of current argument less '-' */ + if (mystrncmp(af->flag, &cp[1], ca)) { /* doesn't match */ + + /* now - try on af->length chars */ + + if (mystrncmp(af->flag, &cp[1], af->length)) { /* doesn't match */ + arg_error(2,af->flag); + break; + } + else { /* does match af->length chars */ + v=cp + af->length + 1; + } + } + else { /* does match ca chars */ + v=cp + ca + 1; + } + } + } + if ((*v != '\0') && !ADJARGS) { + arg_error(7,af->flag); + break; + } + } /* endif == EQUCHAR */ + offset=(v-cp); + c = count_to_flag(argc,argvtemp,v); + /* printf ("flag %s c-flag%s\n",af->flag,digit_word(c)); */ + + switch(af->type) { + + case 'a': + if (*v == '\0') + arg_error(6,af->flag); + else + take_next(1,af,&argvtemp,v,offset); + break; + + case 'n': + if (*v != '\0') { + arg_error(8,af->flag); + break; + } + if (c < 1 ) { + arg_error(9,af->flag); + break; + } + else + take_next(1,af,&argvtemp,v,offset); + break; + + case 'm': + if (c < 1 ) + arg_error(13,af->flag); + else + take_next(c,af,&argvtemp,v,offset); + break; + + case 'z': + take_next(c,af,&argvtemp,v,offset); + break; + + case '0': + if (c && ZEROCHECK) + arg_error(10,af->flag); + else + take_next(1,af,&argvtemp,*argvtemp,0); /* from add_link */ + break; + + default : + /* digit flag type 1-9 */ + n = af->type - '0'; + if( c < n ) { + if ( !c ) + arg_error(11,af->flag,digit_word(n),(n == 1 ? "" : "s" ) ); + else { + arg_error(12,af->flag,digit_word(n),digit_word(c),(c == 1 ? "" : "s" )); + } + } + else + take_next(n,af,&argvtemp,v,offset); + break; + + } /* end switch */ + break; + } + else { /* no match */ + if (i == flagcount-1 ) { /* have tried all flags */ + arg_error(1,cp); + /* take_next(1,&arg[flagcount],&argvtemp,*argvtemp,0); */ + take_next(1,af+flagcount,&argvtemp,*argvtemp,0); /* make it an 'other' */ + } + } /* end if */ + } /* end for */ + } /* end if == FLAGCHAR */ + else { + /* this is an 'other' */ + /* add argi to list pointed to by *next */ + take_next(1,af+flagcount,&argvtemp,*argvtemp,0); /* from add_link */ + } + } /* endfor */ + return(asource++); /* return value THEN increment */ +} + +/* ----------------------------------------------------------------- */ +void add_link(af,v,offset,argn,argof) /* extend linked list for flagnumber + ONLY called from take_next() */ +struct argfull *af; +char *v; +int offset,argn,argof; +{ + static int argi_count=0; /* to count number of entries */ + + ai = (struct arginst *) malloc(sizeof(struct arginst)); + + /* printf("add_link: %s %x %d %d\n",af->flag,ai,argcpi,offset); */ + if(!af->first) { + af->first=ai; + } + else { + (af->last)->next=ai; + } + ai->argcp=v; /* actual string of argument value */ + ai->argci=argcpi; + ai->argoi=offset; + ai->argn=argn; + ai->argof=argof; + ai->argsrc=asource; /* indicates source of value */ + ai->argused=0; + ai->next=NULL; + af->count++; + af->last=ai; + argi_count++; + if ( argi_count > MAXARGS ) { + arg_error(4,digit_word(MAXARGS)); + cleanquit(); + } + return; +} + +/* ----------------------------------------------------------------- */ +void take_next(i,af,p,v,offset) /* take next i arguments ( assumes i > 0 ) + offset used if first argument is adjacent */ +int i,offset; +struct argfull *af; +char ***p,*v; +{ + int argn=1; /* argn of argof=i */ + int argof=i; + + if (*v != '\0') { + add_link(af,v,offset,argn,argof); + i--; + argn++; + } + while(i) { + (*p)++; + argcpi++; + add_link(af,**p,0,argn,argof); + i--; + argn++; + } + return; +} + +/* ----------------------------------------------------------------- */ +void arg_error(i,a,b,c,d) /* general error message output */ +int i; +char *a,*b,*c,*d; +{ + printf("argh! : "); + printf(aerrlist[i],a,b,c,d); + return; +} + +/* ----------------------------------------------------------------- */ +int count_to_flag(argc,argvtemp,v) /* count arguments up to next flag */ +int argc; +char **argvtemp,*v; +{ + int i; + i=argcpi; + argvtemp++; + /* NOTE: this relies on left-right evaluation with && */ + while ((i < (argc-1)) && (**argvtemp != FLAGCHAR)) { + /* printf("loop i %d **argvtemp %c\n",i,**argvtemp); */ + i++; + argvtemp++; + }; + return(i-argcpi + ( *v == '\0' ? 0 : 1 )); +} +/* ----------------------------------------------------------------- */ +void show_args(argc,argv,fp,af) /* display (sorted) list of flags, arguments found */ +int argc; +char **argv; +FILE *fp; +struct argfull *af; /* points to command which invoked display */ +{ + int i; + + fprintf(fp,"\n%s : ",ARGHVER); + fprintf(fp,"%d flags %d command line arguments",flagcount,argc); + for(i=0; i <= flagcount; i++) { + af = argsort[i].tag; + fprintf(fp,(*af->flag == '\0') ? "\nothers ":"\nflag "); + fprintf(fp,"%-15s\011type %c\011match %d\011count %d : ",af->flag,af->type,af->match,af->count); + ai=af->first; + while (ai) { + /* fprintf(fp," %s",&argv[ai->argci][ai->argoi]); */ + fprintf(fp," %s",ai->argcp); + ai=ai->next; + } + } + fprintf(fp,"\n"); + return; +} +/* ----------------------------------------------------------------- */ +void call_args(argc,argv,fp) /* call any routines corresponding + to arguments found in flag + declaration order */ +FILE *fp; +int argc; +char **argv; +{ + struct argfull *af; + int i; + + for(i=0,af=argfull; i <= flagcount; i++,af++) { + if((af->count) && (af->function != NULL)) { + (*af->function)(argc,argv,fp,af); + } + } + return; +} +/* ----------------------------------------------------------------- */ +void list_args(fp,f) /* list arguments for flag f to file fp */ +FILE *fp; +char *f; +{ + char *p; + fprintf(fp,"%s_args : ",f); + while( p = next_arg(f) ) { + fprintf(fp,"<%s>",p); + } + fprintf(fp,"\n"); + return; +} +/* ----------------------------------------------------------------- */ +char *next_arg(f) /* get next arg for flag f - no ambiguity + in specification of f allowed - any level */ +char *f; +{ + int n,of; /* place holders */ + int s = 0; /* source not significant */ + return(nextc_arg(f,s,&n,&of)); +} + +/* ----------------------------------------------------------------- */ +char *nextc_arg(f,s,n,of) /* get next arg for flag f with counts - no ambiguity + in specification of f allowed */ +char *f; +int s,*n,*of; /* source, which, of how many */ +{ + static char lastf[MAXFLAGLEN]="?"; /* to compare with last call */ + static int source; /* ditto */ + struct argfull *af=argfull; + int i; + + if ((mystrcmp(f,lastf)) || (source != s)) { /* new value */ + /* printf("new value <%s>{%d}, old value <%s>{%d}\n",f,s,lastf,source); */ + strcpy(lastf,f); /* store for future reference */ + source = s; /* ditto */ + if (*f == '\0') { /* null string for 'others' */ + ai=(af+flagcount)->first; + } + else { + for(i=0,af=argfull; i <= flagcount; i++,af++) { + if(mystrcmp(f,af->flag)) + continue; + /* printf("flag found"); */ + ai=af->first; + break; + } + } + } + else { + ai=ai->next; + } + + if(source) { /* searching for source */ + while ( ai && (ai->argsrc != source)) + ai=ai->next; + } + if(ai) { + if(source) + ai->argsrc = 0; /* clear out source indicator */ + *n = ai->argn; + *of = ai->argof; + return(ai->argcp); + } + else { + *n = 0; + *of = 0; + return(NULL); + } +} + +/* ----------------------------------------------------------------- */ +char *digit_word(x) /* DANGER - do not expect to work for two + calls both >10 or negative in same printf() */ +int x; +{ + int sign; + static char buf[10]; + static char *words[]= { + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine" + }; + if (x < 0) { + sign = TRUE; + x = -x; + } + else + sign = FALSE; + + if (x < 10) + if (!sign) + return(words[x]); + else + sprintf( buf, "%s%s", (sign? "minus ":""), words[x] ); + else + sprintf( buf, "%s%d", (sign? "minus ":""), x ); + return( buf ); +} +/* ----------------------------------------------------------------- */ +void quick_string(a,count) /* quick sort string array + a[i]->tag is tag pointer + a[i]->string is pointer to character string + - to be sorted */ +struct sort a[]; +int count; +{ + qs_string(a,0,count-1,count); +} +void qs_string(a,left,right,count) /* recursive sort */ +struct sort a[]; +int left,right,count; +{ + register int i,j; + register char *x,*y; /* pointers to characters being sorted */ + + i=left; + j=right; + x=a[(left+right)/2].string; + + do { + while(mystrcmp(a[i].string,x)<0 && i0 && j>left) j--; + if( i <= j ) { + + y = a[i].string; + a[count+1].tag = a[i].tag; /* swap tag pointers */ + + a[i].string = a[j].string; + a[i].tag = a[j].tag; + + a[j].string = y; + a[j].tag = a[count+1].tag; + + i++; + j--; + } + } while ( i <= j ); + + if( left < j ) qs_string(a,left,j,count); + if( i < right ) qs_string(a,i,right,count); +} +/* ----------------------------------------------------------------- */ +int mincmp(a,b) /* minimum length reqd. to distinguish a, b + - this relies on the behaviour of strncmp, + when one or other string is exhausted first */ + +char *a,*b; +{ + int i; + if (!mystrcmp(a,b)) + return(0); /* cannot distinguish */ + + if( a == NULL || b == NULL ) /* strictly NULLCP */ + return(1); + + if( &a == '\0' || &b == '\0' ) + return(1); + + for(i=1;;i++) { + /* printf("a %s b %s i %d\n",a,b,i); */ + if(mystrncmp(a,b,i)) /* different at i */ + break; + } + return(i); +} +/* ----------------------------------------------------------------- */ +mystrcmp(a,b) /* to avoid null dereference */ +char *a,*b; +{ + if ((a == NULL) && (b == NULL)) + return(0); + + if ((a == NULL)) + return(-1); + + if ((b == NULL)) + return(1); + + return(strcmp(a,b)); +} +/* ----------------------------------------------------------------- */ +mystrncmp(a,b,i) /* to avoid null dereference */ +char *a,*b; +int i; +{ + if ((a == NULL) && (b == NULL)) + return(0); + + if ((a == NULL)) + return(-1); + + if ((b == NULL)) + return(1); + + return(strncmp(a,b,i)); +} +/* ----------------------------------------------------------------- */ + +cleanquit () +{ + exit (1); +} diff --git a/Tools/mu/make b/Tools/mu/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/mu/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/mu/mu.c b/Tools/mu/mu.c new file mode 100644 index 0000000..ee6ded4 --- /dev/null +++ b/Tools/mu/mu.c @@ -0,0 +1,1247 @@ +/* mu.c MTS user interface */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/mu/RCS/mu.c,v 6.0 1991/12/18 20:31:54 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/mu/RCS/mu.c,v 6.0 1991/12/18 20:31:54 jpo Rel $ + * + * $Log: mu.c,v $ + * Revision 6.0 1991/12/18 20:31:54 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "util.h" +#include "q.h" +#include "prm.h" +#include +#include "tb_prm.h" +#include "tb_q.h" +#include "tb_a.h" +#include "tb_dr.h" + +#include +#include +#include + + +#include "argh.h" /* jct only */ + +/* That's enough #includes - ed */ + +/* tailor'ed directory */ +extern char *cmddfldir; + +#define DEFAULT_FILENAME "mu.defaults" +#define MAXNAME_LENGTH 200 +#define MAXARG_COUNT 200 +#define COMMENTCHAR '#' +#define TOKENCHAR '$' +#define REPEATCHAR '*' +#define FILEMARKCHAR '*' +#define DISP_INDENT 2 +#define YES_STRING "Yy" +#define NO_STRING "Nn" +#define THREE_BAGS_FULL_STRING "" /* joke */ +#define CONFIRM_STRING "Confirm ( Y/N ) " + +/* ------ from : ut_msg.c: library of routines to read a message directory struct */ + +#define NULLDIR ((DIR*)0) +#define NULLDCT ((struct dirent *)0) + +extern int errno; +extern int fcmp(); + +static DIR *ST_dir = NULLDIR; +static char *ST_array[BUFSIZ]; +static char *ST_name = NULLCP; +static int ST_curr = NULL; +static int ST_level = NULL; +static int ST_no = NULL; +static int basedir_len; + +static int UM_rfile (), UM_push (), UM_isdir (), + UM_array_free (); +static struct dirent *UM_readdir(), *UM_pop(); +/* ------ from : ut_msg.c: library of routines to read a message directory struct */ + +void advise(); +void adios(); +SFD sig_cleanquit(); + +struct argdef arg[] = { /* program specific flag definitions */ + +/* flag function type match */ + + "default", NULL, '1', 0, + "file", NULL, 'm', 0, + "value", NULL, 'm', 0, + "body", NULL, 'm', 0, + "tree", NULL, '1', 0, + "confirm", NULL, '0', 0, + "nofix", NULL, '0', 0, + "prompt", NULL, '2', 0, + "group", NULL, '1', 0, + "logfile", NULL, '1', 0, + "help", show_args, '0', 0, + "-", show_args, '0', 0, + "!", NULL, '0', 0, + "0", NULL, '0', 0, + "1", NULL, '0', 0, + "2", NULL, '0', 0, + "3", NULL, '0', 0, + "4", NULL, '0', 0, + "5", NULL, '0', 0, + "", NULL, '?', 0 + /* "" is 'others' list, also terminates structure array */ +}; + +/* Other global variables */ +static struct prm_vars prm; +static struct Qstruct q; + +ADDR *ad_originator; /* address of sender */ +ADDR *ad_recipient; /* recipient list */ + +RP_Buf r,*rp = &r; /* reply value structure */ +int debug[6]={0,0,0,0,0,0}; /* interactive debug flags */ +int nest_level=0; /* to display level of recursion */ +int confirm_input = FALSE; +int fix_input = TRUE; +FILE *muout=stdout; /* progress messages to... */ +char *getcwd(); /* not used */ + +/* + In addition to the LLOG_TRACE, LLOG_DEBUG calls associated + with debug[0], debug[1] shown below, there are other + LLOG_FATAL and LLOG_EXCEPTIONS calls. Note that list_args + and show_args ( in argh.c ) do not generate LLOG events. + + debug[?] function + 0 log to muout progress messages, and PPLOG( LLOG_TRACE ...) + 1 log to muout command files as they are processed, and PPLOG( LLOG_DEBUG ...) + 2 list to muout body part files as they are io_tdata'ed + 3 list to muout structures prior to submit io_ calls + 4 abort prior to submit io_ calls + 5 append to logfile rather than overwrite +*/ + +/* ----------------------------------------------------------------- */ +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); + + signal(SIGINT,sig_cleanquit); + + msg_init(); /* initialise message structures */ + + in_all(argc,argv); + do_all(argc,argv); + + if (muout != stdout) + fclose(muout); + exit(0); +} +/* ----------------------------------------------------------------- */ +in_all(argc, argv) /* input from original or constructed command line */ + /* CALLED RECURSIVELY */ +int argc; +char **argv; +{ + int scan_counter; + + if (debug[0]) { + fprintf(muout,"in_all nest_level %d\n",nest_level); + PP_LOG (LLOG_TRACE,("mu: in_all nest_level %d",nest_level)); + } + /* printf("argc=%d argv=%h\n",argc,argv); */ + + scan_counter=scan_args(argc,argv); /* prep_args() called automatically */ + + get_debug(scan_counter); + + process_args(argv,scan_counter); +} +/* ----------------------------------------------------------------- */ +do_all(argc, argv) /* all post-input operations */ +int argc; +char **argv; +{ + if (debug[0]){ + list_args(muout,"default"); + list_args(muout,"logfile"); + list_args(muout,"file"); + list_args(muout,"value"); + list_args(muout,"body"); + list_args(muout,"tree"); + list_args(muout,"confirm"); + list_args(muout,"nofix"); +/* + list_args(muout,"prompt"); + list_args(muout,"group"); +*/ + list_args(muout,""); + } + + call_args(argc,argv,muout); /* pass output file pointer */ + + if (ad_originator == NULLADDR) + adios("","No originator specified"); /* ... and abort */ + + if (ad_recipient == NULLADDR) + adios("","No recipient specified"); /* ... and abort */ + + if( debug[3] ) + print_structures(); + + if( !debug[4] ) + submit_message(argv); + + return; +} +/* ----------------------------------------------------------------- */ +process_args(argv,scan_counter) +char **argv; +int scan_counter; +{ + FILE *fd; + static char default_filename[MAXNAME_LENGTH] = DEFAULT_FILENAME; + char *argvtemp[MAXARG_COUNT]; + char buf[BUFSIZ]; + char *p, *p_end; + int i,n,of,dummy; + + if (scan_counter == 1) { /* can override mu.defaults from command line only */ + if(p=nextc_arg("default",scan_counter,&n,&of)) + strcpy(default_filename,p); + else { + if ((fd = fopen(default_filename,"r")) == NULL ) + sprintf(default_filename,"%s/%s",cmddfldir,DEFAULT_FILENAME); + else + fclose(fd); + } + read_file(default_filename); /* into param_, queue_structure */ + } + /* read all -file arguments */ + while (p=nextc_arg("file",scan_counter,&n,&of)) { + read_file(p); /* into param_, queue_,addr_structure */ + } + /* scan all -body arguments */ + while (p=nextc_arg("body",scan_counter,&n,&of)) { + try_file(p); /* open and check file length */ + } + /* at least one call to next_arg/nextc_arg with different argument is + necessary before looping on "body" again; "tree" will do nicely ... */ + + /* scan all -tree arguments */ + while (p=nextc_arg("tree",scan_counter,&n,&of)) { + try_directory(p); /* check that it exists */ + } + /* similarly... at least one call to next_arg/nextc_arg with different argument is + necessary before looping on "tree" again; "value" will do nicely ... */ + + for (n=0,of=0;(p = nextc_arg("value",scan_counter,&n,&of)) != NULL;) { + sprintf (buf, "%s", p); + i = 1; + while (of-i) { + p = nextc_arg("value",scan_counter,&dummy,&dummy); + p_end = index( buf, '\0' ); + sprintf (p_end, " %s", p); /* i.e. concatenate parameters */ + i++; + } + /* this messy construction is necessary to put argvtemp in proper format */ + + of = str2arg (buf, MAXARG_COUNT, argvtemp, NULLCP); + + if ( debug[0] ) { + dump_args(of,argvtemp); + } + parse_txt(of,argvtemp); + } + return(TRUE); +} + +/* ----------------------------------------------------------------- */ +get_debug(scan_counter) /* check for action flags */ +{ + char deb[2]; /* very short string */ + char *p; + int i,n,of; + + for(i=0;i<=5;i++) { + deb[0]=('0'+i); + deb[1]='\0'; + if (nextc_arg(deb,scan_counter,&n,&of)) { + debug[i] = 1; + if ( debug[0] ) { + fprintf(muout,"debug flag %s set\n", deb); + PP_LOG (LLOG_TRACE,("mu: debug flag %s set", deb)); + } + } + } + if (nextc_arg("nofix",scan_counter,&n,&of)) + if ( debug[0] ) { + fprintf(muout,"nofix set\n"); + PP_LOG (LLOG_TRACE,("mu: nofix set")); + } + fix_input=FALSE; + + if (nextc_arg("confirm",scan_counter,&n,&of)) + if ( debug[0] ) { + fprintf(muout,"confirm set\n"); + PP_LOG (LLOG_TRACE,("mu: confirm set")); + } + confirm_input=TRUE; + + if (p=nextc_arg("logfile",scan_counter,&n,&of)) { + if ( debug[0] ) { + fprintf(muout,"logfile set to %s\n", p); + PP_LOG (LLOG_TRACE,("mu: logfile set to %s", p)); + } + if (muout != stdout) + fclose(muout); + + if ( debug[5] ) { + if ((muout = fopen(p,"a")) == NULL ) { + advise("","unable to append to %s",p); + muout = stdout; /* and send to screen */ + } + } + else { + if ((muout = fopen(p,"w")) == NULL ) { + advise("","unable to write to %s",p); + muout = stdout; + } + } + } +} +/* ----------------------------------------------------------------- */ +read_file(p) /* read file *p */ +char *p; +{ + FILE *fd; + + if (debug[0]) { + fprintf(muout,"start read_file : %s\n",p); + PP_LOG (LLOG_TRACE,("mu: start read_file : %s",p)); + } + if ((fd = fopen(p,"r")) == NULL ) { + adios("","unable to read %s",p); /* ... and abort */ + return; + } + /* Rather than call rd_prm, rd_q, rd_adr individually, each of which + expects to receive a subset of the control parameters, each line is + read with txt2buf to command-argument form with str2arg (was sstr2arg) then + offered to each of txt2prm, txt2q and txt2adr in turn to see if it + is valid for any - if not then an error is reported. */ + + rd_all(fd); + fclose(fd); + + if (debug[0]) { + fprintf(muout,"finish read_file : %s\n",p); + PP_LOG (LLOG_TRACE,("mu: finish read_file : %s",p)); + } + return; +} +/* ----------------------------------------------------------------- */ +try_file(p) /* open, check file length */ +char *p; +{ + FILE *fd; + long f; + char pp[MAXNAME_LENGTH],*r; + + strcpy(pp,p); + if (r=index(pp,FILEMARKCHAR)) { + *r = '\0'; + strcat(pp,r+1); + if (debug[0]) { + fprintf(muout,"body part %s FILEMARKCHAR detected : %s\n",p,pp); + PP_LOG (LLOG_TRACE,("mu: body part %s FILEMARKCHAR detected : %s",p,pp)); + } + } + if ((fd = fopen(pp,"r")) == NULL ) + adios("","unable to read body part %s",pp); + fseek(fd,0L,2); /* eof */ + if ((f=ftell(fd)) == 0 ) + adios("","body part %s is null file",pp); + fclose(fd); + return; +} +/* ----------------------------------------------------------------- */ +try_directory(p) /* check that it exists */ +char *p; +{ + char pp[MAXNAME_LENGTH],*r; + + strcpy(pp,p); + if (r=index(pp,FILEMARKCHAR)) { + *r = '\0'; + strcat(pp,r+1); + if (debug[0]) { + fprintf(muout,"directory %s FILEMARKCHAR detected : %s\n",p,pp); + PP_LOG (LLOG_TRACE,("mu: directory %s FILEMARKCHAR detected : %s",p,pp)); + } + } + + if (dir_rinit(pp) != RP_OK) + adios("","cannot initialise directory %s",pp); + dir_rend(); + return; +} +/* ----------------------------------------------------------------- */ +rd_all (fd) +FILE *fd; +{ + char buf[BUFSIZ],copybuf[BUFSIZ]; + char *argv[MAXARG_COUNT]; + int argc,retval,repeat,repeat_offset,user_input,parse_result; + int tokenfound; + + for (;;) { + retval = txt2buf (buf, fd); + if (rp_isbad (retval)) + return (retval); + + if(debug[1]) + display(buf,nest_level); + + if (*buf == REPEATCHAR) { + repeat = TRUE; + repeat_offset = 1; + } + else { + repeat = FALSE; + repeat_offset = 0; + } + + for(;;) { + /* copy buf to copybuf and check for TOKENCHAR */ + user_input=prompt(copybuf,buf,repeat,&tokenfound); + + if (repeat && !tokenfound) { + advise(NULL,"<<%s>>\nerror : no TOKENCHAR(s) in REPEAT line - REPEATCHAR ignored",buf); + repeat = FALSE; + } + if(repeat && !user_input) /* no more user input */ + break; + strip(copybuf); /* remove trailing spaces */ + /* argc = str2arg (copybuf+repeat_offset, 50, argv, " \t\n"); */ + argc = str2arg (copybuf+repeat_offset, MAXARG_COUNT, argv, NULLCP); + argv[argc] = NULLCP; +/* + if (debug[0]) { + dump_args(argc,argv); + } +*/ + if (argc == 0) { /* ignore empty lines */ + parse_result=OK; + } + else { + parse_result=parse_txt(argc,argv); /* parse_txt(argc,argv,ftell(fd)); */ + } + if(repeat || (fix_input && user_input && (parse_result == NOTOK)) ) { + continue; + } + else { + break; + } + } + } +} +/* ----------------------------------------------------------------- */ +parse_txt(argc,argv) /* returns OK || NOTOK */ +int argc; +char **argv; + +/* long fd_startln; /* for _offset calculations */ + +{ + char *p; + char buf[BUFSIZ]; + char *nargv[MAXARG_COUNT]; + int nargc; + int retval; + + if(**argv == COMMENTCHAR) { + if (debug[0] && !debug[1]) { /* avoids duplicatation */ + arg2vstr(BUFSIZ,BUFSIZ,buf,argv); + display(buf,nest_level); + } + } + else if(**argv == FLAGCHAR) { + + /* dump_args(-1,argv); */ + arg2vstr(BUFSIZ,BUFSIZ,buf,argv); + + /* + fflush(muout); + fprintf(muout,"muout flushed\n"); + */ + + if (debug[0]) { + fprintf(muout,"arg2vstr returns <%s>\n",buf); + PP_LOG (LLOG_TRACE,("mu: arg2vstr returns <%s>",buf)); + } + p=malloc(strlen(buf)+6); + sprintf(p,"DUMMY %s",buf); + if (debug[0]) { + fprintf(muout,"\nin_all RECURSION with %s\n\n",p); + PP_LOG (LLOG_TRACE,("mu: in_all RECURSION with %s",p)); + } + strip(p); /* remove trailing spaces */ + /* nargc = str2arg (p, 50, nargv, " \t\n"); */ + nargc = str2arg (p, MAXARG_COUNT, nargv, NULLCP); + nargv[nargc] = NULLCP; +/* + if (debug[0]) { + dump_args(nargc,nargv); + } +*/ + if (nargc != 0) { + nest_level++; + + in_all(nargc,nargv); /* ***** RECURSION ***** */ + + nest_level--; + } + } + else { + retval = txt2prm (&prm, argv, argc); + if (rp_isgood(retval) || retval == PRM_END) + return(OK); + + retval = txt2q (&q, (long)0, argv, argc); + if (rp_isgood(retval) || retval == Q_END) + return(OK); + + if (lexequ(argv[0],"Origs") == 0) { + if (debug[0]) { + fprintf(muout,"Origs in input\n"); + PP_LOG (LLOG_TRACE,("mu: Origs in input")); + } + if (ad_originator == NULLADDR) { /* Only one Origs */ + retval = txt2adr (&ad_originator, 0L, argv, argc); + if (rp_isgood(retval) || retval == AD_END) + return(OK); + } + } + else { + retval = txt2adr (&ad_recipient, 0L, argv, argc); + if (rp_isgood(retval) || retval == AD_END) + return(OK); + } + + /* error if get here */ + arg2vstr(BUFSIZ,BUFSIZ,buf,argv); + advise(NULL,"error `%s' (retval=%s)",buf,digit_word(retval)); + return(NOTOK); + } + return(OK); +} + +/* ----------------------------------------------------------------- */ +print_structures() /* print out result of merge */ +{ + ADDR *ap; + + fprintf (muout,"-----------------------------------------------------------------\n"); + prm2txt (muout,&prm); + q2txt (muout,&q); + adr2txt (muout,ad_originator,AD_ORIGINATOR); + ap = ad_recipient; + do { + adr2txt (muout,ap,AD_RECIPIENT); + ap = ap->ad_next; + } while ( ap != NULL ); + fprintf (muout,"-----------------------------------------------------------------\n"); +} +/* ----------------------------------------------------------------- */ +int prompt(copybuf,buf,repeat,tokenfound) /* user input to expand embedded TOKENCHAR's */ +char *copybuf,*buf; /* buf is original line from file */ +int repeat; +int *tokenfound; +{ + char *p; + char inbuf[BUFSIZ]; + int user_input=FALSE; + + strcpy(copybuf,buf); /* only modify copy */ + + *tokenfound = FALSE; /* to be tested with repeat */ + + if( (*buf != COMMENTCHAR) && (index(buf,TOKENCHAR)) ) { + for(;;) { /* Loop to allow line re-input if not confirmed */ + p=copybuf; + while (p = index(p,TOKENCHAR)) { + p++; + if ( *p == TOKENCHAR ) { /* $$ - do not set tokenfound */ + *p = '\0'; + strcat(copybuf,p+1); + } + else { + *tokenfound = TRUE; + *(--p) = '\0'; + printf("\n%s%c ",copybuf,TOKENCHAR); + scanfcr(inbuf); /* scanf("%s",inbuf); */ + if (repeat && (strlen(inbuf) == 0)) { + user_input=FALSE; + return(user_input); /* I HATE THIS */ + } + else { + user_input=TRUE; + strcat(inbuf,p+1); + strcat(p,inbuf); + } + } + } + if (user_input && confirm_input) { + if (confirm(copybuf)) { + break; + } + else { + strcpy(copybuf,buf); + continue; /* re-input whole line */ + } + } + else { + break; /* confirm_input FALSE or TRUE and confirmed */ + } + } + } + return(user_input); +} + +/* ----------------------------------------------------------------- */ +scanfcr(inbuf) /* equiv. to scanf("%s",inbuf) with CR only allowed */ +char *inbuf; +{ + int i; + char c; + + for(i=0,inbuf[i]='\0';((inbuf[i]=getchar()) != '\n');i++) { + } + inbuf[i]='\0'; +} +/* ----------------------------------------------------------------- */ +confirm(buf) /* offer confirmation of user input */ +char *buf; +{ + int i; + char s[10]; + + for(;;) { + printf("\n%s\n\t%s",buf,CONFIRM_STRING); + scanfcr(s); + if (s[0] == '\0') + continue; + if (index(YES_STRING,s[0])) { + i=TRUE; + break; + } + if (index( NO_STRING,s[0])) { + i=FALSE; + break; + } + } + return(i); +} +/* ----------------------------------------------------------------- */ +msg_init() +{ + /* prm_init (p); */ + q_init(&q); + ad_init(); +} +/* ----------------------------------------------------------------- */ +ad_init() /* -- initialise the linked lists -- */ +{ + if (ad_recipient != NULLADDR) adr_tfree (ad_recipient); + if (ad_originator != NULLADDR) adr_tfree (ad_originator); + ad_originator = NULLADDR; + ad_recipient = NULLADDR; +} + +/* ----------------------------------------------------------------- */ +submit_message(argv) +char **argv; +{ + int type = OK; + int offset; + char *p,*r; + char t[MAXPATHLENGTH]; /* for copy of directory specified in -tree */ + char dir_fname[MAXPATHLENGTH]; + char submit_fname[MAXPATHLENGTH]; + ADDR *ap; + + if (debug[0]) { + fprintf(muout,"submit_message io_init\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_init")); + } + if(rp_isbad(io_init(rp))) + rp_error(rp); + if (debug[0]) { + fprintf(muout,"submit_message io_wprm\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_wprm")); + } + if(rp_isbad(io_wprm(&prm,rp))) + rp_error(rp); + if (debug[0]) { + fprintf(muout,"submit_message io_wrq\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_wrq")); + } + if(rp_isbad(io_wrq(&q,rp))) + rp_error(rp); + + ap = ad_originator; + if (debug[0]) { + fprintf(muout,"submit_message io_wadr originator %s\n",ap->ad_value); + PP_LOG (LLOG_TRACE,("mu: submit_message io_wadr originator %s",ap->ad_value)); + } + if(rp_isbad(io_wadr(ap,AD_ORIGINATOR,rp))) + rp_error(rp); + + ap = ad_recipient; + do { + if (debug[0]) { + fprintf(muout,"submit_message io_wadr recipient %s\n",ap->ad_value); + PP_LOG (LLOG_TRACE,("mu: submit_message io_wadr recipient %s",ap->ad_value)); + } + if(rp_isbad(io_wadr(ap,AD_RECIPIENT,rp))) + rp_error(rp); + ap = ap->ad_next; + } while ( ap != NULL ); + + if (debug[0]) { + fprintf(muout,"submit_message io_adend\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_adend")); + } + if(rp_isbad(io_adend(rp))) + rp_error(rp); + + if(((p=next_arg("body",argv)) !=NULL) || ((p=next_arg("tree",argv)) != NULL)) { + + if (debug[0]) { + fprintf(muout,"submit_message io_tinit\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tinit")); + } + if(rp_isbad(io_tinit(rp))) + rp_error(rp); + + p=next_arg("",argv); /* dummy to clear next_args memory */ + + if(((p=next_arg("body",argv)) !=NULL) ) { + do { + if ((r=index(p,FILEMARKCHAR)) == NULL) + r=p; + else + ++r; + /* pass pointer just after FILECHARMARK */ + if (debug[0]) { + fprintf(muout,"submit_message io_tpart file %s\n",r); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tpart file %s",r)); + } + if(rp_isbad(io_tpart(r,FALSE,rp))) + rp_error(rp); + if (debug[0]) { + fprintf(muout,"submit_message io_tdata loop\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tdata loop")); + } + + loop_data(p); /* and transfer file */ + + if (debug[0]) { + fprintf(muout,"submit_message io_tdend\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tdend")); + } + if(rp_isbad(io_tdend(rp))) { + rp_error(rp); + } + } while(p=next_arg("body",argv)); + } + + p=next_arg("",argv); /* dummy to clear next_args memory */ + + if(((p=next_arg("tree",argv)) !=NULL) ) { + + do { + strcpy(t,p); /* copy for FILCHARMARK manipulation */ + if ((r=index(t,FILEMARKCHAR))) { + *r = '\0'; + strcat(t,r+1); + offset = r-t; /* offset to intended name - just after FILECHARMARK */ + } + else { + offset = 0; + } + + if (debug[0]) { + fprintf(muout,"submit_message dir_rinit %s\n",t); + PP_LOG (LLOG_TRACE,("mu: submit_message dir_rinit %s",t)); + } + if ( dir_rinit( t ) != RP_OK ) + adios (NULL,"Cannot initialise directory %s\n",t); + + while (dir_rfile(dir_fname) == RP_OK ) { + if (debug[0]) { + fprintf(muout,"mu: dir_rfile %s\n",dir_fname); + PP_LOG (LLOG_TRACE,("mu: mu/dir_rfile %s",dir_fname)); + } + + strcpy(submit_fname,&dir_fname[offset]); + + if (debug[0]) { + if (offset) { + fprintf(muout,"mu: offset %d submitted name io_tpart : %s\n",offset,submit_fname); + PP_LOG (LLOG_TRACE,("mu: offset %d submitted name io_tpart : %s",offset,submit_fname)); + } + } + if(rp_isbad(io_tpart(submit_fname,FALSE,rp))) + rp_error(rp); + if (debug[0]) { + fprintf(muout,"submit_message io_tdata loop\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tdata loop")); + } + + loop_data(dir_fname); + + if (debug[0]) { + fprintf(muout,"submit_message io_tdend\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tdend")); + } + if(rp_isbad(io_tdend(rp))) { + rp_error(rp); + } + } + dir_rend(); + } while(p=next_arg("tree",argv)); + } + } + + if (debug[0]) { + fprintf(muout,"submit_message io_tend\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_tend")); + } + if(rp_isbad(io_tend(rp))) + rp_error(rp); + + if (debug[0]) { + fprintf(muout,"submit_message io_end\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message io_end")); + } + if(io_end(type) == NOTOK) + rp_error(rp); + else { + if (debug[0]) { + fprintf(muout,"submit_message OK\n"); + PP_LOG (LLOG_TRACE,("mu: submit_message OK")); + } + } + return; +} +/* ----------------------------------------------------------------- */ +loop_data(p) +char *p; +{ + int length; + char buf[BUFSIZ]; + FILE *fd; + char pp[MAXNAME_LENGTH],*r; + + strcpy(pp,p); + if (r=index(pp,FILEMARKCHAR)) { + *r = '\0'; + strcat(pp,r+1); + } + + if ((fd = fopen(pp,"r")) == NULL ) + adios("","unable to open body part for reading %s",pp); + + while ( (length=fread(buf,1,BUFSIZ,fd)) ) { + if (debug[2]) + fwrite(buf,1,length,muout); + io_tdata(buf,length); + } + fclose(fd); +} +/* ----------------------------------------------------------------- */ +rp_error(rp) +RP_Buf *rp; +{ + adios (NULL,"RP_ERROR %d %s\n",rp->rp_val,rp->rp_line); +} + +/* ----------------------------------------------------------------- */ +display (s,level) +char *s; +int level; +{ + fprintf(muout,"%*s%s\n",level * DISP_INDENT, "", s); + PP_LOG (LLOG_DEBUG,("mu: input line %s", s)); +} +/* ----------------------------------------------------------------- */ +/* VARARGS */ +void adios (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what,*fmt,*a,*b,*c,*d,*e,*f,*g,*h,*i,*j; +{ + PP_LOG (LLOG_FATAL,(fmt, a, b, c, d, e, f, g, h, i, j)); + advise (what, fmt, a, b, c, d, e, f, g, h, i, j); + cleanquit (); +} +/* ----------------------------------------------------------------- */ +/* VARARGS */ +void advise (what, fmt, a, b, c, d, e, f, g, h, i, j) +char *what,*fmt,*a,*b,*c,*d,*e,*f,*g,*h,*i,*j; +{ + if (muout != stdout) { + fprintf (muout, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', muout), perror (what); + else + (void) fputc ('\n', muout); + (void) fflush (muout); + } + fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j); + if (what) + (void) fputc (' ', stderr), perror (what); + else + (void) fputc ('\n', stderr); + (void) fflush (stderr); + PP_LOG (LLOG_EXCEPTIONS,(fmt, a, b, c, d, e, f, g, h, i, j)); +} +/* ----------------------------------------------------------------- */ +/* ***************** These routines taken from :- ******************* + : ut_msg.c : library of routines to read a message directory struct */ + +dir_rinit (dir) /* was msg_rinit (dir) */ +char *dir; +{ /* Now pass full or relative path for each invocation - unlike msg_rinit */ + + PP_DBG (("mu: dir_rinit: (%s)", dir)); + + if (ST_dir) dir_rend(); + + ST_level = 0; + ST_name = malloc (LINESIZE); + bzero (ST_name, LINESIZE); + + /* + full path not assumed + */ + (void) sprintf (ST_name, "%s", dir); + + if (!UM_isdir (ST_name)) { + PP_LOG (LLOG_FATAL,("mu: dir_rinit: %s is not a dir", ST_name)); + return (RP_FOPN); + } + + if ((ST_dir = opendir (ST_name)) == NULLDIR) { + PP_LOG (LLOG_FATAL,("mu: dir_rinit: unable to open %s", ST_name)); + return (RP_FOPN); + } + + basedir_len = strlen(ST_name); + + return (RP_OK); + +} +/* ----------------------------------------------------------------- */ +dir_rfile (buf) /* was msg_rfile (dir) */ +char *buf; +{ + char *ptr; + + PP_DBG (("mu: dir_rfile: (%s)", ST_name)); + + if (ST_no == NULL) { + while (UM_rfile (buf) == RP_OK) { + ptr = strdup (buf); + ST_array [ST_no] = ptr; + ++ST_no; + } + + qsort ((char *)ST_array, + ST_no, + (sizeof (ST_array[0])), + fcmp); + + } + + if (ST_curr < ST_no) { + (void) strcpy (buf, ST_array[ST_curr]); + ++ST_curr; + return (RP_OK); + } + + return (RP_DONE); +} +/* ----------------------------------------------------------------- */ +dir_rend() /* was msg_rend (dir) */ +{ + PP_DBG (("mu: dir_rend: (%s)", ST_name)); + + if (ST_dir) { + closedir (ST_dir); + ST_dir = NULLDIR; + } + + if (ST_name) { + free (ST_name); + ST_name = NULLCP; + } + + if (ST_no) + UM_array_free(); + + ST_level = NULL; + return (RP_OK); +} +/* ----------------------------------------------------------------- */ +fcmp (f1, f2) +register char **f1, **f2; +{ + char *stripedf1, + *stripedf2; + + stripedf1 = (*f1)+basedir_len+1; + stripedf2 = (*f2)+basedir_len+1; + + return recur_fcmp(stripedf1,stripedf2); +} +/* ----------------------------------------------------------------- */ +recur_fcmp(f1,f2) +register char *f1, + *f2; +{ + /* atoi stops at the first non digit */ + int f1digit = atoi(f1); + int f2digit = atoi(f2); + + if (f1digit < f2digit) + return -1; + + else if (f1digit > f2digit) + return 1; + else { + int f1isdir, f2isdir; + char *ixf1, *ixf2; + /* dificult case may have to recurse */ + f1isdir = ((ixf1 = index(f1,'/')) != NULL); + f2isdir = ((ixf2 = index(f2,'/')) != NULL); + if (f1isdir && f2isdir) + return recur_fcmp(++ixf1,++ixf2); + return 0; + } + +} +/* -------------------------- Static Routines -------------------------- */ +static UM_rfile (buf) +char *buf; +{ + struct dirent *dp; + + if (ST_dir == NULLDIR) { + PP_LOG (LLOG_FATAL,("mu: UM_rfile: opendir not performed")); + return (RP_DONE); + } + + + dp = UM_readdir (NULLCP); + + if (dp == NULLDCT) + if (ST_level == 0) + return (RP_DONE); + else + if ((dp = UM_pop()) == NULLDCT) + return (RP_DONE); + + if (UM_isdir (dp->d_name)) { + /* + new subdir + */ + UM_push (dp->d_name); + return (UM_rfile (buf)); + } + + + if (isstr (ST_name)) + (void) sprintf (buf, "%s/%s", ST_name, dp->d_name); + else + (void) strcpy (buf, dp->d_name); + + return (RP_OK); + +} +/* ----------------------------------------------------------------- */ +static struct dirent *UM_pop() +{ + struct dirent *dp; + char tbuf[LINESIZE], + *ptr; + + --ST_level; + ptr = rindex (ST_name, '/'); + (void) strcpy (tbuf, ++ptr); + *--ptr = '\0'; + + PP_DBG (("mu: UM_pop: (%s, %d)", ST_name, ST_level)); + + closedir (ST_dir); + ST_dir = opendir (ST_name); + + dp = UM_readdir (&tbuf[0]); + + if (dp) + return (dp); + + if (ST_level) + return (UM_pop()); + + return (NULLDCT); +} +/* ----------------------------------------------------------------- */ +static UM_push (name) +char *name; +{ + char tbuf[LINESIZE]; + + (void) sprintf (tbuf, "%s/%s", ST_name, name); + + (void) strcpy (ST_name, tbuf); + + closedir (ST_dir); + + PP_DBG (("mu: UM_push: (%s, %d)", ST_name, ST_level+1)); + + if ((ST_dir = opendir (ST_name)) == NULLDIR) { + PP_LOG (LLOG_FATAL,("mu: UM_push: Unable to open %s", ST_name)); + return; + } + + ++ST_level; +} +/* ----------------------------------------------------------------- */ +static UM_isdir (name) +char *name; +{ + struct stat st_rec; + char tbuf[LINESIZE]; + + if (!isstr (name)) + return (FALSE); + + (void) strcpy (&tbuf[0], ST_name); + + if (strcmp (ST_name, name) != 0) { + (void) strcat (&tbuf[0], "/"); + (void) strcat (&tbuf[0], name); + } + fprintf(muout,"mu/UM_isdir testing %s as %s\n",name,tbuf); + + if (stat (&tbuf[0], &st_rec) == NOTOK) { + PP_LOG (LLOG_FATAL, ("mu: UM_isdir: Unable to stat %s %d",&tbuf[0], errno)); + return (FALSE); + } + + switch (st_rec.st_mode & S_IFMT) { + case S_IFDIR: + PP_DBG (("mu/: UM_isdir (%s = TRUE)", &tbuf[0])); + return (TRUE); + default: + PP_DBG (("mu: UM_isdir (%s = FALSE)", &tbuf[0])); + return (FALSE); + } +} +/* ----------------------------------------------------------------- */ +static struct dirent *UM_readdir (current) +char *current; +{ + struct dirent *dp; + int passed_current = FALSE; + + if (current) + PP_DBG (("mu: UM_readdir (current = %s)", current)); + + for (dp=readdir(ST_dir); dp != NULLDCT; dp=readdir(ST_dir)) { + if (strcmp (dp->d_name, ".") == 0) continue; + if (strcmp (dp->d_name, "..") == 0) continue; + if (current) + if (strcmp (dp->d_name, current) == 0) { + passed_current = TRUE; + continue; + } + else if (passed_current == FALSE) + continue; + break; + } + + if (dp) + PP_DBG (("mu: UM_readdir (%s)", dp->d_name)); + + return (dp); +} +/* ----------------------------------------------------------------- */ +static UM_array_free () +{ + int i; + + for (i=0; i < ST_no; i++) + if (ST_array[i]) { + free (ST_array [i]); + ST_array[i] = NULLCP; + } + + ST_no = NULL; + ST_curr = NULL; +} +/* ***************** End routines taken from ut_msg ******************* */ +/* ----------------------------------------------------------------- */ +strip(x) /* strip trailing spaces and tabs */ +char *x; +{ + int i = strlen(x); + char *p; + + PP_DBG (("mu: strip trailing spaces & tabs from <%s>", x)); + + if ( i ) { + p = &x[ i - 1 ]; + while ( i && (*p == ' ' || *p == '\t') ) { + *p-- = '\0'; + i--; + } + } +} +/* ----------------------------------------------------------------- */ +dump_args(argc, argv) +int argc; +char **argv; +{ + int i = 0; + int j = argc; + + fprintf(muout,"dump_args argc %d\n",argc); + PP_LOG (LLOG_TRACE,("dump_args argc %d",argc)); + while (j && (argv[i] != NULLCP)) { + fprintf(muout,"dump_args argv[%d] %s\n",i,argv[i]); + PP_LOG (LLOG_TRACE,("dump_args argv[%d] %s",i,argv[i])); + j--; + i++; + } +} + +/* ARGSUSED */ +SFD sig_cleanquit (sig) +int sig; +{ + cleanquit(); +} diff --git a/Tools/mu/mu.defaults b/Tools/mu/mu.defaults new file mode 100644 index 0000000..79f7081 --- /dev/null +++ b/Tools/mu/mu.defaults @@ -0,0 +1,4 @@ +-0 +-1 +logfile mu_test.log +level 0 diff --git a/Tools/nsapexpand/Makefile b/Tools/nsapexpand/Makefile new file mode 100644 index 0000000..12bd025 --- /dev/null +++ b/Tools/nsapexpand/Makefile @@ -0,0 +1,85 @@ +# Convert macro nsaps to full format +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/nsapexpand/RCS/Makefile,v 6.0 1991/12/18 20:32:03 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:03 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = nsapexpand.c +OBJS = nsapexpand.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xnsapexpand + +default: $(PROGS) + +nsapexpand: xnsapexpand +xnsapexpand: nsapexpand.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ nsapexpand.o $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-nsapexpand + +inst-nsapexpand: $(TOOLDIR)/nsapexpand +$(TOOLDIR)/nsapexpand: xnsapexpand + -$(BACKUP) $@ zxnsapexpand + rm -f $@ + $(INSTALL) xnsapexpand $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "nsapexpand installed normally"; echo "" + +inst-dir: $(TOOLDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxnsapexpand *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/nsapexpand/make b/Tools/nsapexpand/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/nsapexpand/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/nsapexpand/nsapexpand.c b/Tools/nsapexpand/nsapexpand.c new file mode 100644 index 0000000..2897dc1 --- /dev/null +++ b/Tools/nsapexpand/nsapexpand.c @@ -0,0 +1,106 @@ +/* nsapexpand.c: expand macro forms of NSAP to full form */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/nsapexpand/RCS/nsapexpand.c,v 6.0 1991/12/18 20:32:03 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/nsapexpand/RCS/nsapexpand.c,v 6.0 1991/12/18 20:32:03 jpo Rel $ + * + * $Log: nsapexpand.c,v $ + * Revision 6.0 1991/12/18 20:32:03 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +static char *myname; +int abortonerror = 0; + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + sys_init (*argv); + + while((opt = getopt(argc, argv, "a")) != EOF) + switch (opt) { + case 'a': + abortonerror = TRUE; + break; + + default: + fprintf (stderr, "Usage: %s [-a] [files]\n", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc <= 0) + process (stdin, "standard input"); + else { + while (argc > 0) { + FILE *fp = fopen (*argv, "r"); + if (fp == NULL) { + fprintf (stderr, "%s: Can't open file %s\n", + myname, *argv); + exit(1); + } + process (fp, *argv); + (void) fclose (fp); + + argv ++; + argc --; + } + } + exit (0); +} + +process (fp, name) +FILE *fp; +char *name; +{ + char key[BUFSIZ], value[BUFSIZ]; + struct PSAPaddr *pa; + char *cp; + + while (tab_fetch (fp, key, value) == OK) { + if (lexequ (key, "default") == 0) { + printf ("%s:%s\n", key, value); + continue; + } + if ((pa = str2paddr (key)) == NULLPA) { + PP_OPER (NULLCP, ("Bad psap address <%s> in %s", + key, name)); + fprintf (stderr, "Bad psap address <%s> in %s\n", + key, name); + if (abortonerror) + exit (1); + continue; + } + cp = _paddr2str (pa, NULLNA, -1); + if (cp == NULLCP) { + PP_OPER (NULLCP, + ("Can't convert psap <%s> to full form", + key)); + fprintf (stderr, + "Can't convert psap <%s> to full form\n", + key); + if (abortonerror) + exit (1); + continue; + } + printf ("%s:%s\n", cp, value); + } +} + + diff --git a/Tools/ntail/Makefile b/Tools/ntail/Makefile new file mode 100644 index 0000000..f67c352 --- /dev/null +++ b/Tools/ntail/Makefile @@ -0,0 +1,92 @@ +# ntail - log watcher... +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/Makefile,v 6.0 1991/12/18 20:32:10 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:10 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = entryfuncs.c miscfuncs.c ntail.c +OBJS = entryfuncs.o miscfuncs.o ntail.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xntail + +default: $(PROGS) + +ntail: xntail + @true + +xntail: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-ntail +inst-ntail: $(TOOLDIR)/ntail +$(TOOLDIR)/ntail: xntail + -$(BACKUP) $@ zxntail + rm -f $@ + $(INSTALL) xntail $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "ntail installed correctly"; echo "" +inst-dir: $(TOOLDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core* $(PROGS) zxntail xntail *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +entryfuncs.o: entryfuncs.c +entryfuncs.o: ./ntail.h +miscfuncs.o: miscfuncs.c +miscfuncs.o: ./ntail.h +ntail.o: ntail.c +ntail.o: ./ntail.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ntail/README b/Tools/ntail/README new file mode 100644 index 0000000..b57f0ac --- /dev/null +++ b/Tools/ntail/README @@ -0,0 +1,49 @@ +[ This is a copy of the program called xtail changed name to ntail for +bizzare reasons. It has been changed around a little to work happily +with PP but otherwise not changed much - JPO ] + + +"ntail" watches the growth of files. It is similar to "tail -f", but may +watch many files at once. The syntax is: + + ntail pathname ... + +"ntail" will monitor all the specified files and display information added +to them. If you specify a directory name, "ntail" will watch all the +files in that directory - including those created after "ntail" was +started. If you give "ntail" a name which doesn't exist, it will watch +for the creation of the named entry. My favorite usage is: + + ntail /usr/spool/uucp/.Log/* + +"ntail" is distributed with a configuration for SCO XENIX. It has also +been tested on MIPS System V. I took a shot at BSD portability. The +main difference is how the "directory" support library is accessed. + +To build "ntail": + + - edit the definitions in "ntail.h" + - run a "make" + +A version of "ntail" was originally posted in alt.sources a few months +back. There are several improvements between this version and the +original: + + - the ability to watch directories + - the ability to watch entries which don't exist yet + - the recently changed files display (given upon SIGINT) + - performance improvements + - portability improvements + +Many of these changes were suggested by David Dykstra . +The idea of keeping files open and use fstat() rather than stat() was +suggested by changes by another poster (sorry, I lost the article so I +can't provide credit). However, that version kept *everything* open, and +that just eats too many entries in the file table for me. You can tweak +the values in "ntail.h" to optimize the response/load characteristics of +"ntail". + +Chip Rosenthal + + +@(#) README 2.1 89/07/26 19:16:34 diff --git a/Tools/ntail/entryfuncs.c b/Tools/ntail/entryfuncs.c new file mode 100644 index 0000000..f261ac7 --- /dev/null +++ b/Tools/ntail/entryfuncs.c @@ -0,0 +1,237 @@ +/* entryfuncs.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ntail/RCS/entryfuncs.c,v 6.0 1991/12/18 20:32:10 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/entryfuncs.c,v 6.0 1991/12/18 20:32:10 jpo Rel $ + * + * $Log: entryfuncs.c,v $ + * Revision 6.0 1991/12/18 20:32:10 jpo + * Release 6.0 + * + */ + + + +/* + * @(#) entryfuncs.c 2.1 89/07/26 19:16:49 + * + * Package: ntail version 2 + * File: entryfuncs.c + * Description: procedures to manage individual entries + * + * Mon Jul 10 02:56:22 1989 - Chip Rosenthal + * Original composition. + */ + + +#include +#include +#include +#include +#include +#include "ntail.h" + +#ifdef M_XENIX +# undef NULL +# define NULL 0 +#endif + +extern int errno; + + +static struct entry_descrip *E_append(listp,entryp) +struct entry_list *listp; +struct entry_descrip *entryp; +{ + if ( listp->num >= MAX_ENTRIES ) { + (void) fprintf(stderr,"%s: too many entries (%d max)\n", + entryp->name, MAX_ENTRIES); + (void) exit(2); + } + listp->list[listp->num++] = entryp; + Sorted = FALSE; + return entryp; +} + + +static void E_remove(listp,entryno) +struct entry_list *listp; +int entryno; +{ + while ( ++entryno < listp->num ) + listp->list[entryno-1] = listp->list[entryno]; + --listp->num; + Sorted = FALSE; +} + + +static char *list_name(listp) /* for debug output only */ +struct entry_list *listp; +{ + if ( listp == &List_file ) return ""; + if ( listp == &List_dir ) return ""; + if ( listp == &List_zap ) return ""; + return "?unknown?"; +} + + +/* + * Create a new entry description and append it to a list. + */ +struct entry_descrip *new_entry(listp,name) +struct entry_list *listp; +char *name; +{ + struct entry_descrip *entryp; + static char malloc_error[] = "malloc: out of space\n"; + + Dprintf(stderr, ">>> creating entry '%s' on %s list\n", + name, list_name(listp)); + + entryp = (struct entry_descrip *) malloc( sizeof(struct entry_descrip) ); + if ( entryp == NULL ) { + (void) fputs(malloc_error,stderr); + (void) exit(2); + } + + entryp->name = malloc( (unsigned) strlen(name) + 1 ); + if ( entryp->name == NULL ) { + (void) fputs(malloc_error,stderr); + (void) exit(2); + } + (void) strcpy(entryp->name,name); + + entryp->fd = 0; + entryp->size = 0; + entryp->mtime = 0; + + return E_append(listp,entryp); +} + + +/* + * Remove an entry from a list and free up its space. + */ +void rmv_entry(listp,entryno) +struct entry_list *listp; +int entryno; +{ + struct entry_descrip *entryp = listp->list[entryno]; + extern void free(); + + Dprintf(stderr, ">>> removing entry '%s' from %s list\n", + listp->list[entryno]->name, list_name(listp)); + E_remove(listp,entryno); + if ( entryp->fd > 0 ) + (void) close(entryp->fd); + free( entryp->name ); + free( (char *) entryp ); +} + + +/* + * Move an entry from one list to another. + * In addition we close up the entry if appropriate. + */ +void move_entry(dst_listp,src_listp,src_entryno) +struct entry_list *dst_listp; +struct entry_list *src_listp; +int src_entryno; +{ + struct entry_descrip *entryp = src_listp->list[src_entryno]; + + Dprintf(stderr, ">>> moving entry '%s' from %s list to %s list\n", + src_listp->list[src_entryno]->name, + list_name(src_listp), list_name(dst_listp)); + if ( entryp->fd > 0 ) { + (void) close(entryp->fd); + entryp->fd = 0; + } + E_remove(src_listp,src_entryno); + (void) E_append(dst_listp,entryp); + if ( Reset_status ) { + entryp->size = 0; + entryp->mtime = 0; + } +} + + +/* + * Get the inode status for an entry. + * Returns code describing the status of the entry. + */ +int stat_entry(listp,entryno,sbuf) +struct entry_list *listp; +int entryno; +register struct stat *sbuf; +{ + register int status; + register struct entry_descrip *entryp = listp->list[entryno]; + static int my_gid = -1; + static int my_uid = -1; + + if ( my_gid < 0 ) { + my_gid = getegid(); + my_uid = geteuid(); + } + + status = + ( entryp->fd > 0 ? fstat(entryp->fd,sbuf) : stat(entryp->name,sbuf) ); + + if ( status != 0 ) + return ( errno == ENOENT ? ENTRY_ZAP : ENTRY_ERROR ); + + if ( + ( ( sbuf->st_mode & 0004 ) == 0 ) && + ( ( sbuf->st_mode & 0040 ) == 0 || sbuf->st_gid != my_gid ) && + ( ( sbuf->st_mode & 0400 ) == 0 || sbuf->st_uid != my_uid ) + ) { + errno = EACCES; + return ENTRY_ERROR; + } + + switch ( sbuf->st_mode & S_IFMT ) { + case S_IFREG: return ENTRY_FILE; + case S_IFDIR: return ENTRY_DIR; + default: return ENTRY_SPECIAL; + } + + /*NOTREACHED*/ +} + + +/* + * Open an entry. + * Returns 0 if the open is successful, else returns errno. In the case + * of an error, an appropriate diagnostic will be printed, and the entry + * will be moved or deleted as required. If the entry is already opened, + * then no action will occur and 0 will be returned. + */ +int open_entry(listp,entryno) +struct entry_list *listp; +int entryno; +{ + struct entry_descrip *entryp = listp->list[entryno]; + + if ( entryp->fd > 0 ) + return 0; + + Dprintf(stderr, ">>> opening entry '%s' on %s list\n", + listp->list[entryno]->name, list_name(listp)); + if ( (entryp->fd=open(entryp->name,O_RDONLY)) > 0 ) + return 0; + + if ( errno == ENOENT ) { + message( MSSG_ZAPPED, entryp ); + move_entry( &List_zap, listp, entryno ); + } else { + message( MSSG_OPEN, entryp ); + rmv_entry( listp, entryno ); + } + return -1; +} + + diff --git a/Tools/ntail/make b/Tools/ntail/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ntail/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ntail/miscfuncs.c b/Tools/ntail/miscfuncs.c new file mode 100644 index 0000000..62c7491 --- /dev/null +++ b/Tools/ntail/miscfuncs.c @@ -0,0 +1,240 @@ +/* miscfuncs.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ntail/RCS/miscfuncs.c,v 6.0 1991/12/18 20:32:10 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/miscfuncs.c,v 6.0 1991/12/18 20:32:10 jpo Rel $ + * + * $Log: miscfuncs.c,v $ + * Revision 6.0 1991/12/18 20:32:10 jpo + * Release 6.0 + * + */ + + + +/* + * @(#) miscfuncs.c 2.1 89/07/26 19:16:50 + * + * Package: ntail version 2 + * File: miscfuncs.c + * Description: miscelaneous support procedures + * + * Mon Jul 10 02:56:22 1989 - Chip Rosenthal + * Original composition. + */ + +#ifndef LINT +static char SCCSID[] = "@(#) miscfuncs.c 2.1 89/07/26 19:16:50"; +#endif + +#include +#include +#include +#include +#include +#include "ntail.h" + +#ifdef M_XENIX +# undef NULL +# define NULL 0 +#endif + +extern int errno; + +extern char *sys_errlist[]; + + +/* + * Scan a directory for files not currently on a list. + */ +int scan_directory(dirname) +char *dirname; +{ + register int i; + register struct dirent *dp; + register struct entry_descrip **elist, *entryp; + char *basename; + struct stat sbuf; + DIR *dirp; + static char pathname[MAXNAMLEN]; + + Dprintf(stderr, ">>> scanning directory '%s'\n", dirname); + if ( (dirp=opendir(dirname)) == NULL ) + return -1; + + (void) strcat( strcpy(pathname,dirname), "/" ); + basename = pathname + strlen(pathname); + +#define SKIP_DIR(D) \ + ( D[0] == '.' && ( D[1] == '\0' || ( D[1] == '.' && D[2] == '\0' ) ) ) + + while ( (dp=readdir(dirp)) != NULL ) { + + if ( SKIP_DIR(dp->d_name) ) + continue; + (void) strcpy( basename, dp->d_name ); + if ( stat(pathname,&sbuf) != 0 ) + continue; + if ( (sbuf.st_mode&S_IFMT) != S_IFREG ) + continue; + + for ( i=List_file.num, elist=List_file.list ; i > 0 ; --i, ++elist ) { + if ( strcmp( (*elist)->name, pathname ) == 0 ) + break; + } + if ( i > 0 ) + continue; + + for ( i=List_zap.num, elist=List_zap.list ; i > 0 ; --i, ++elist ) { + if ( strcmp( (*elist)->name, pathname ) == 0 ) + break; + } + if ( i > 0 ) + continue; + + entryp = new_entry( &List_file, pathname ); + if ( Reset_status ) { + message( MSSG_CREATED, entryp ); + } else { + entryp->mtime = sbuf.st_mtime; + entryp->size = sbuf.st_size; + } + + } + + (void) closedir(dirp); + return 0; + +} + + +/* + * Compare mtime of two entries. Used by the "qsort()" in "fixup_open_files()". + */ +static int ecmp(ep1,ep2) +register struct entry_descrip **ep1, **ep2; +{ + return ( (*ep2)->mtime - (*ep1)->mtime ); +} + +/* + * Manage the open files. + * A small number of entries in "List_file" are kept open to minimize + * the overhead in checking for changes. The strategy is to make sure + * the MAX_OPEN most recently modified files are all open. + */ +void fixup_open_files() +{ + register int i; + register struct entry_descrip **elist; + extern void qsort(); + + Dprintf(stderr, ">>> resorting file list\n"); + (void) qsort( + (char *) List_file.list, + List_file.num, + sizeof(struct entry_descrip *), + ecmp + ); + Sorted = TRUE; + + /* + * Start at the end of the list. + */ + i = List_file.num - 1; + elist = &List_file.list[i]; + + /* + * All the files at the end of the list should be closed. + */ + for ( ; i >= MAX_OPEN ; --i, --elist ) { + if ( (*elist)->fd > 0 ) { + (void) close( (*elist)->fd ); + (*elist)->fd = 0; + } + } + + /* + * The first MAX_OPEN files in the list should be open. + */ + for ( ; i >= 0 ; --i, --elist ) { + if ( (*elist)->fd <= 0 ) + (void) open_entry( &List_file, i ); + } + +} + + +/* + * Standard message interface. + * There are two reasons for this message interface. First, it provides + * consistent diagnostics for all the messages. Second, it manages the + * filename banner display whenever we switch to a different file. + * Warning - "errno" is used in some of the messages, so care must be + * taken not to step on it before message() can be called. + */ +void message(sel,e) +int sel; +struct entry_descrip *e; +{ + static char *ofile = NULL; + + /* + * Don't display the file banner if the file hasn't changed since last time. + */ + if ( sel == MSSG_BANNER && ofile != NULL && strcmp(ofile,e->name) == 0 ) + return; + + /* + * Make sure the message selector is within range. + */ + if ( sel < 0 || sel > MSSG_UNKNOWN ) + sel = MSSG_UNKNOWN; + + /* + * Display the message. + */ + if ( mssg_list[sel] != NULL ) + (void) printf(mssg_list[sel], e->name, sys_errlist[errno]); + + ofile = ( sel == MSSG_BANNER ? e->name : NULL ); +} + + +/* + * Display currently opened files. + */ +void show_status() +{ + int i, n; + struct tm *tp; + static char *monname[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + extern struct tm *localtime(); + + (void) printf("\n*** recently changed files ***\n"); + for ( i = 0, n = 0 ; i < List_file.num ; ++i ) { + if ( List_file.list[i]->fd > 0 ) { + tp = localtime(&List_file.list[i]->mtime); + (void) printf("%4d %2d-%3s-%02d %02d:%02d:%02d %s\n", + ++n, + tp->tm_mday, monname[tp->tm_mon], tp->tm_year, + tp->tm_hour, tp->tm_min, tp->tm_sec, + List_file.list[i]->name + ); + } + } + + (void) printf( + "currently watching: %d files %d dirs %d unknown entries\n", + List_file.num, List_dir.num, List_zap.num); + + message( MSSG_NONE, (struct entry_descrip *) NULL ); + +} + diff --git a/Tools/ntail/ntail.c b/Tools/ntail/ntail.c new file mode 100644 index 0000000..fab2ade --- /dev/null +++ b/Tools/ntail/ntail.c @@ -0,0 +1,401 @@ +/* ntail.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ntail/RCS/ntail.c,v 6.0 1991/12/18 20:32:10 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/ntail.c,v 6.0 1991/12/18 20:32:10 jpo Rel $ + * + * $Log: ntail.c,v $ + * Revision 6.0 1991/12/18 20:32:10 jpo + * Release 6.0 + * + */ + + + +/* + * @(#) ntail.c 2.1 89/07/26 19:15:42 + * + * Package: ntail version 2 + * File: ntail.c + * Description: main program + * + * Mon Jul 10 02:56:22 1989 - Chip Rosenthal + * Original composition. + */ + +#ifndef LINT +static char SCCSID[] = "@(#) ntail.c 2.1 89/07/26 19:15:42"; +#endif + +#include +#include +#include +#include +#define INTERN +#include "ntail.h" + +#ifdef M_XENIX +# undef NULL +# define NULL 0 +#endif + + +int sigcaught = 0; + +SIGTYPE sigcatcher(sig) +int sig; +{ +/* extern SIGTYPE (*signal)(); */ + if ( sig == SIGQUIT ) + (void) exit(0); + sigcaught = sig; +#ifdef STATUS_ENAB + (void) signal(SIGINT,sigcatcher); + (void) signal(SIGQUIT,sigcatcher); +#endif +} + + +main(argc,argv) +int argc; +char *argv[]; +{ + int open_files_only, already_open, iteration, i; + struct entry_descrip *entryp; + struct stat sbuf; + + /* + * Initialize. + */ + List_file.num = 0; + List_dir.num = 0; + List_zap.num = 0; + Sorted = FALSE; + Reset_status = FALSE; + Debug = FALSE; + sigcatcher(0); + + + /* + * Place all of the entries onto lists. + */ + for ( i = 1 ; i < argc ; ++i ) { + + if ( i == 1 && strcmp(argv[i],"-D") == 0 ) { + Debug = TRUE; + continue; + } + + /* + * Temporarily throw this entry onto the end of the zapped list. + */ + entryp = new_entry( &List_zap, argv[i] ); + + /* + * Stat the file and get it to its proper place. + */ + switch ( stat_entry( &List_zap, List_zap.num-1, &sbuf ) ) { + + case ENTRY_FILE: /* move entry to file list */ + move_entry( &List_file, &List_zap, List_zap.num-1 ); + entryp->size = sbuf.st_size; + entryp->mtime = sbuf.st_mtime; + break; + + case ENTRY_DIR: /* move entry to dir list */ + move_entry( &List_dir, &List_zap, List_zap.num-1 ); + entryp->size = sbuf.st_size; + entryp->mtime = sbuf.st_mtime; + if ( scan_directory( entryp->name ) != 0 ) { + message( MSSG_OPEN, entryp ); + rmv_entry( &List_dir, List_dir.num-1 ); + } + break; + + case ENTRY_ZAP: /* keep entry on zap list */ + break; + + case ENTRY_SPECIAL: /* entry is a special file */ + message( MSSG_NOTAFIL, entryp ); + rmv_entry( &List_zap, List_zap.num-1 ); + break; + + default: /* stat error */ + message( MSSG_STAT, entryp ); + rmv_entry( &List_zap, List_zap.num-1 ); + break; + + } + + } + + /* + * Make sure we are watching something reasonable. + */ + if ( List_file.num == 0 ) { + if ( List_dir.num == 0 && List_zap.num == 0 ) { + (void) fprintf(stderr, "%s: no valid entries specified\n", argv[0]); + (void) exit(1); + } + (void) puts("\n*** warning - no files are being watched ***"); + } + + + /* + * From this point on we want to reset the status of an entry any + * time we move it around to another list. + */ + Reset_status = TRUE; + + + /* + * Force a check of everything first time through the loop. + */ + iteration = CHECK_COUNT; + + + /* + * Loop forever. + */ + for (;;) { + + /* + * Once every CHECK_COUNT iterations check everything. + * All other times only look at the opened files. + */ + open_files_only = ( ++iteration < CHECK_COUNT ); + if ( !open_files_only ) + iteration = 0; + + + /* + * Make sure that the most recently modified files are open. + */ + if ( !Sorted ) + fixup_open_files(); + + + /* + * Display what we are watching if a SIGINT was caught. + */ + if ( sigcaught ) { + show_status(); + sigcatcher(0); + } + + + /* + * Go through all of the files looking for changes. + */ + Dprintf(stderr, ">>> checking files list (%s)\n", + ( open_files_only ? "open files only" : "all files" )); + for ( i = 0 ; i < List_file.num ; ++i ) { + + entryp = List_file.list[i]; + already_open = ( entryp->fd > 0 ) ; + + /* + * Ignore closed files except every CHECK_COUNT iterations. + */ + if ( !already_open && open_files_only ) + continue; + + /* + * Get the status of this file. + */ + switch ( stat_entry( &List_file, i, &sbuf ) ) { + case ENTRY_FILE: /* got status OK */ + break; + case ENTRY_DIR: /* huh??? it's now a dir */ + move_entry( &List_dir, &List_file, i-- ); + continue; + case ENTRY_ZAP: /* entry has been deleted */ + message( MSSG_ZAPPED, entryp ); + move_entry( &List_zap, &List_file, i-- ); + continue; + case ENTRY_SPECIAL: /* entry is a special file */ + message( MSSG_NOTAFIL, entryp ); + rmv_entry( &List_file, i-- ); + continue; + default: /* stat error */ + message( MSSG_STAT, entryp ); + rmv_entry( &List_file, i-- ); + continue; + } + + + /* + * See if an opened file has been deleted. + */ + if ( already_open && sbuf.st_nlink == 0 ) { + message( MSSG_ZAPPED, entryp ); + move_entry( &List_zap, &List_file, i-- ); + continue; + } + + /* + * If nothing has changed then continue on. + */ + if ( entryp->size==sbuf.st_size && entryp->mtime==sbuf.st_mtime ) + continue; + + /* + * If the file isn't already open, then do so. + * Note -- it is important that we call "fixup_open_files()" + * at the end of the loop to make sure too many files don't + * stay opened. + */ + if ( !already_open && open_entry( &List_file, i ) != 0 ) { + --i; + continue; + } + + /* + * See if the file has been truncated. + */ + if ( sbuf.st_size < entryp->size ) { + message( MSSG_TRUNC, entryp ); + entryp->size = 0; + } + + /* + * Seek to where the changes begin. + */ + { + extern long lseek(); + if ( lseek( entryp->fd, entryp->size, 0 ) < 0 ) { + message( MSSG_SEEK, entryp ); + rmv_entry( &List_file, i-- ); + continue; + } + } + + /* + * Dump the recently added info. + */ + { + int nb; + static char buf[BUFSIZ]; + message( MSSG_BANNER, entryp ); + while ( ( nb = read( entryp->fd, buf, sizeof(buf) ) ) > 0 ) { + (void) fwrite( buf, sizeof(char), (unsigned) nb, stdout ); + entryp->size += nb; + } + if ( nb < 0 ) { + message( MSSG_READ, entryp ); + rmv_entry( &List_file, i-- ); + continue; + } + } + + /* + * Update the modification time. + */ + entryp->mtime = sbuf.st_mtime; + + /* + * Since we've changed the mtime, the list might no longer be + * sorted. However if this entry is already at the top of the + * list then it's OK. + */ + if ( i != 0 ) + Sorted = FALSE; + + /* + * If we've just opened the file then force a resort now to + * prevent too many files from being opened. + */ + if ( !already_open ) + fixup_open_files(); + + } + + + /* + * Go through list of nonexistent entries to see if any have appeared. + * This is done only once every CHECK_COUNT iterations. + */ + if ( !open_files_only ) { + Dprintf(stderr, ">>> checking zapped list\n"); + for ( i = 0 ; i < List_zap.num ; ++i ) { + entryp = List_zap.list[i]; + switch ( stat_entry( &List_zap, i, &sbuf ) ) { + case ENTRY_FILE: /* entry has appeared as a file */ + message( MSSG_CREATED, entryp ); + move_entry( &List_file, &List_zap, i-- ); + break; + case ENTRY_DIR: /* entry has appeared as a dir */ + message( MSSG_CREATED, entryp ); + move_entry( &List_dir, &List_zap, i-- ); + break; + case ENTRY_ZAP: /* entry still doesn't exist */ + break; + case ENTRY_SPECIAL: /* entry is a special file */ + message( MSSG_NOTAFIL, entryp ); + rmv_entry( &List_zap, i-- ); + break; + default: /* error - entry removed */ + message( MSSG_STAT, entryp ); + rmv_entry( &List_zap, i-- ); + break; + } + } + } + + + /* + * Go through the list of dirs to see if any new files were created. + * This is done only once every CHECK_COUNT iterations. + */ + if ( !open_files_only ) { + Dprintf(stderr, ">>> checking directory list\n"); + for ( i = 0 ; !open_files_only && i < List_dir.num ; ++i ) { + entryp = List_dir.list[i]; + switch ( stat_entry( &List_dir, i, &sbuf ) ) { + case ENTRY_DIR: /* got status OK */ + break; + case ENTRY_FILE: /* huh??? it's now a reg file */ + move_entry( &List_file, &List_dir, i-- ); + continue; + case ENTRY_ZAP: /* entry has been deleted */ + message( MSSG_ZAPPED, entryp ); + move_entry( &List_zap, &List_dir, i-- ); + continue; + case ENTRY_SPECIAL: /* entry is a special file */ + message( MSSG_NOTAFIL, entryp ); + rmv_entry( &List_dir, i-- ); + continue; + default: /* stat error */ + message( MSSG_STAT, entryp ); + rmv_entry( &List_dir, i-- ); + continue; + } + if ( entryp->mtime == sbuf.st_mtime ) + continue; + if ( scan_directory( entryp->name ) != 0 ) { + message( MSSG_OPEN, entryp ); + rmv_entry( &List_dir, i-- ); + } + entryp->mtime = sbuf.st_mtime; + } + } + + + /* + * End of checking loop. + */ + { + extern unsigned sleep(); + (void) fflush(stdout); + (void) sleep(SLEEP_TIME); + } + + } + + /*NOTREACHED*/ + +} + diff --git a/Tools/ntail/ntail.h b/Tools/ntail/ntail.h new file mode 100644 index 0000000..c4284b4 --- /dev/null +++ b/Tools/ntail/ntail.h @@ -0,0 +1,248 @@ +/* ntail.h: */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Tools/ntail/RCS/ntail.h,v 6.0 1991/12/18 20:32:10 jpo Rel $ + * + * $Log: ntail.h,v $ + * Revision 6.0 1991/12/18 20:32:10 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_NTAIL +#define _H_NTAIL + +#include "util.h" /* to get system defn */ + +/* + * @(#) xtail.h 2.1 89/07/26 19:16:49 + * + * Package: xtail version 2 + * File: xtail.h + * Description: header definitions + * + * Mon Jul 10 02:56:22 1989 - Chip Rosenthal + * Original composition. + */ + + + +/***************************************************************************** + * + * Start of Site-Specific Customizations + * + *****************************************************************************/ + +/* + * Define one of the following. It says how to use your "directory" library. + */ +/*#define DIR_XENIX /* include , use "struct direct" */ +#define DIR_BSD /* include , use "struct direct" */ +/*#define DIR_SYSV /* include , use "struct dirent" */ + +/* + * Define one of the following. It specifies the return type of "signal()". + */ +/*#define SIGTYPE int /* declare as "int (*signal)()" */ +/*#define SIGTYPE void /* declare as "void (*signal)()" */ +#if !defined(SVR3) && !defined(SVR4) && !defined(SUNOS4) && !defined(BSD44) && !defined(ultrix) +#define SIGTYPE int +#else +#define SIGTYPE void +#endif + +/* + * STATUS_ENAB If defined, a SIGINT causes a summary of the opened files to + * be displayed, and a SIGQUIT terminates the program. If not + * defined, these signals act normally. + */ +#define STATUS_ENAB /**/ + +/* + * SLEEP_TIME An iteration through the checking loop is performed once + * per this many seconds. + */ +#define SLEEP_TIME 1 + +/* + * MAX_OPEN This number of most recently changed files is kept open, and + * they are checked every iteration through the checking loop. + * Keeping these files open improves the performance because we + * can use "fstat()" rather than "stat()". Keeping too many + * files open may overflow your open file table, and will reduce + * performance by checking more files more frequently. + */ +#define MAX_OPEN 6 + +/* + * CHECK_COUNT Everything besides open files are checked once per this + * many iterations through the checking loop. + */ +#define CHECK_COUNT 5 + +/* + * MAX_ENTRIES The maximum number of entries in any list. It can be fairly + * large -- each unused entry only eats 3*sizeof(char*) bytes. + */ +#define MAX_ENTRIES 512 + + +/***************************************************************************** + * + * End of Site-Specific Customizations + * + *****************************************************************************/ + + +#define TRUE 1 +#define FALSE 0 + +#define Dprintf if ( !Debug ) ; else (void) fprintf + + +/* + * Codes returned by the "stat_entry()" procedure. + */ +#define ENTRY_ERROR 0 /* stat error or permissions error */ +#define ENTRY_SPECIAL 1 /* entry is a special file */ +#define ENTRY_FILE 2 /* entry is a regular file */ +#define ENTRY_DIR 3 /* entry is a directory */ +#define ENTRY_ZAP 4 /* specified entry doesn't exist */ + + +/* + * Diagnostic message codes. + * The ordering of codes must correspond to the "mssg_list[]" defined below. + */ +#define MSSG_NONE 0 /* no message - just reset header */ +#define MSSG_BANNER 1 /* display banner for file output */ +#define MSSG_CREATED 2 /* file has been created */ +#define MSSG_ZAPPED 3 /* file has been deleted */ +#define MSSG_TRUNC 4 /* file has been truncated */ +#define MSSG_NOTAFIL 5 /* error - not a regular file or dir */ +#define MSSG_STAT 6 /* error - stat() failed */ +#define MSSG_OPEN 7 /* error - open() failed */ +#define MSSG_SEEK 8 /* error - lseek() failed */ +#define MSSG_READ 9 /* error - read() failed */ +#define MSSG_UNKNOWN 10 /* unknown error - must be last in list */ + + +#ifdef INTERN +# define EXTERN +#else +# define EXTERN extern +#endif + + +/* + * Each item we are watching is stored in a (struct entry_descrip). These + * entries are placed in lists, which are managed as (struct entry_list). + * + * There are three lists maintained: + * + * List_file All of the regular files we are watching. We will try to + * keep the MAX_OPEN most recently modified files open, and + * they will be checked more frequently. + * + * List_dir All of the directories we are watching. If a file is created + * in one of these directories, we will add it to "List_file". + * + * List_zap All the entries which don't exist. When something appears + * under one of these names, the entry will be moved to either + * "List_file" or "List_dir", as appropriate. + */ + +struct entry_descrip { + char *name; /* pathname to the entry */ + int fd; /* opened fd, or <= 0 if not opened */ + long size; /* size of entry last time checked */ + long mtime; /* modification time last time checked */ +}; + +struct entry_list { + struct entry_descrip *list[MAX_ENTRIES]; + int num; +}; + +/* + * The lists of entries being watched. + */ +EXTERN struct entry_list List_file; /* regular files */ +EXTERN struct entry_list List_dir; /* directories */ +EXTERN struct entry_list List_zap; /* nonexistent entries */ + + +/* + * List sorting status. + * This flag indicates that "List_file" is sorted, and the right entries + * are open. Anything which possibly effects this state (e.g. an entry + * is added to "List_file", the mtime of a file is changed, etc.) must set + * this flag FALSE. We will periodically check this flag and call the + * "fixup_open_files()" procedure to resort and organize the list. + */ +EXTERN int Sorted; + + +/* + * Entry status control flag. + * The procedures which manipulate entries will reset the status information + * if this flag is TRUE. When initializing the lists we want this FALSE. + * For example, consider the file size. When initializing we want to use + * the current file size, otherwise we would dump the file from the beginning. + * However, later when we notice things are created we want to reset the + * size to zero so that we do dump from the beginning. + */ +EXTERN int Reset_status; + + +/* + * Debugging output flag. + */ +EXTERN int Debug; + + +/* + * Diagnostic messages produced by the "message()" procedure. + * The first "%s" is the entry name. The second "%s" is the errno descrip. + */ +#ifdef INTERN + char *mssg_list[] = { + NULL, /*MSSG_NONE */ + "\n*** %s ***\n", /*MSSG_BANNER */ + "\n*** '%s' has been created ***\n", /*MSSG_CREATED*/ + "\n*** '%s' has been deleted ***\n", /*MSSG_ZAPPED */ + "\n*** '%s' has been truncated - rewinding ***\n", /*MSSG_TRUNC */ + "\n*** error - '%s' not a file or dir - removed ***\n", /*MSSG_NOTAFIL*/ + "\n*** error - couldn't stat '%s' (%s) - removed ***\n",/*MSSG_STAT */ + "\n*** error - couldn't open '%s' (%s) - removed ***\n",/*MSSG_OPEN */ + "\n*** error - couldn't seek '%s' (%s) - removed ***\n",/*MSSG_SEEK */ + "\n*** error - couldn't read '%s' (%s) - removed ***\n",/*MSSG_READ */ + "\n*** error - unknown error on file '%s' ***\n", /*MSSG_UNKNOWN*/ + }; +#else + extern char *mssg_list[]; +#endif + + +/* + * Entry managment procedures. + */ +struct entry_descrip *new_entry(); /* create a new entry and add to list */ +void move_entry(); /* move an entry between lists */ +void rmv_entry(); /* remove an entry from a list */ +int stat_entry(); /* get the inode status for an entry */ +int open_entry(); /* open an entry */ + +/* + * Miscelaneous procedures. + */ +void fixup_open_files(); /* manage the open files */ +int scan_directory(); /* scan a dir for files not on a list */ +void message(); /* standard message interface */ +void show_status(); /* display currently opened files */ + + +#endif diff --git a/Tools/ppbm/Makefile b/Tools/ppbm/Makefile new file mode 100644 index 0000000..afc7aa0 --- /dev/null +++ b/Tools/ppbm/Makefile @@ -0,0 +1,97 @@ +# pp benchamark Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/Makefile,v 6.0 1991/12/18 20:32:20 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:20 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ppbm.c +OBJS = ppbm.o + +LINT = lint +LINTFLAGS = -bhuz + +CC = cc +LDFLAGS = +CFLAGS = -O + +############################################################ +# +# Building Rules +# +############################################################ + +all: xppbm +lint: l-ppbm + +install:; + +results: text ps + +text: ppbm-raw.txt ppbm-sorted.txt + +ps: ppbm-sorted.ps ppbm-raw.ps + +ppbm-raw.txt: pp-benchmarks.tbl + tbl $? | nroff -ms | colcrt > $@ + +ppbm-sorted.txt: pp-benchmarks.tbl pp-bench.awk + pp-bench.awk pp-benchmarks.tbl | tbl | nroff -ms | colcrt > $@ + +ppbm-sorted.ps: pp-benchmarks.tbl pp-bench.awk + pp-bench.awk pp-benchmarks.tbl | tbl | psroff -ms -t > $@ + +ppbm-raw.ps: pp-benchmarks.tbl + tbl $? | psroff -ms -t > $@ + +ppbm: xppbp +xppbm: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) + +l-ppbm: $(SRCS) + $(LINT) $(LINTFLAGS) $(SRCS) + +shar: shar-src +shar-src: Makefile ppbm.c ppbm.8 + shar -cv Makefile ppbm.c ppbm.8 > $@ + +inst-ppbm: + echo "ppbm not for installation" + + +clean: tidy + rm -f $(OBJS) *.txt *.ps x* +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ppbm/make b/Tools/ppbm/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ppbm/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ppbm/pp-bench.awk b/Tools/ppbm/pp-bench.awk new file mode 100755 index 0000000..90ea680 --- /dev/null +++ b/Tools/ppbm/pp-bench.awk @@ -0,0 +1,52 @@ +#! /bin/sh + +nawk ' +BEGIN { FS = "@" } +NF > 1 { + if ($NF == "T{") { + for (i = 1; i < NF; i++) + printf "%s@", $i + + while (getline > 0) { + if ($1 == "T}") { + for (i = 2; i <= NF; i++) + printf "@%s", $i + break + } + else printf "%s ", $0 + } + printf "\n" + } + else + print $0 +} +' $* | +nawk ' +BEGIN { FS = "@"; OFS = "@" +} +NF == 1 { next } +/tab\(/ { next } +$1 == "Model" { next } + { + if ($1 == "\\^") $1 = last1 + if ($2 == "\\^") $2 = last2 + print $1, $2, $6, $7 + last1 = $1 + last2 = $2 + } +' | sort -t@ +2nr | +nawk ' +BEGIN { + print ".TS H" + print "tab(@);" + print "c s s s" + print "cfB cfB cfB cfB" + print "a a n l." + print "PP Benchmark Summary (sorted)" + print ".sp .5" + print "Model@Disc@M/s@Notes" + print ".TH" + print "=" +} + { print } +END { print ".TE" } diff --git a/Tools/ppbm/pp-benchmarks.tbl b/Tools/ppbm/pp-benchmarks.tbl new file mode 100644 index 0000000..887575b --- /dev/null +++ b/Tools/ppbm/pp-benchmarks.tbl @@ -0,0 +1,251 @@ +.TS H +tab(@); +c s s s s s s +cfB cfB cfB cfB cfB cfB cfB +l l n n n n a. +PP Throughtput Benchmark Test Results +.sp +Model@Disk@Time@User@System@M/S@Notes += +.TH +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Julian Onions, XTEL += +Sun SSII@ SCSI@105.96@0.22@7.28@1.42 +\^@\^@76.62@0.22@6.29@1.96@No fsync +\^@NFS to SCSI@76.6@0.22@6.29@1.14 +\^@TMPFS@2.62@0.25@2.23@57.04 +_ +IBM RS/6000@???@35.89@0.41@7.81@4.18 +\^@\^@30.50@0.50@6.69@4.92@No fsync +_ +ICL DRS6000@???@104@0.63@13.20@1.44 +\^@\^@93@0.67@11.23@1.61@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Andrew Findlay, Brunel += +Sun 4/460@T{ +IPI + Prestoserve +T}@15.21@0.19@11.57@9.86 +\^@\^@13.66@0.17@9.32@10.98@No fsync +\^@\^@15.73@0.25@11.53@9.53@No flock +\^@\^@9.76@0.22@8.63@15.37@No fsync/flock +\^@IPI@80.25@0.24@6.54@1.87 +\^@TMPFS@2.16@0.13@1.58@69.44 +_ +Sun SSII@SCSI@104.99@0.14@5.64@1.43 +\^@T{ +NFS to 4/470 with presto +T}@56.77@0.22@10.66@2.64 +_ +Sun 4/280@SMD + SMD4@95.99@0.46@12.25@1.56 +_ +Sun IPC@SCSI@127.29@0.47@8.94@1.18 +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Piete Brooks, Cambridge += +Sun 4/330@SMD@221.84@0.38@20.39@0.68@Load Avrg 7 +\^@SCSI@244.56@0.48@10.19@0.61@Load Avrg 7 +_ +Sun 4/280@SMD@127.75@0.54@16.3@1.17@Load Avrg 7 +\^@TMPFS@24.92@0.4@7.44@6.02@Load Avrg 7 +_ +DEC 5400@RA90@133.21@0.42@12.1@1.13@Load Avrg 5 +_ +DEC MV 3600@RA82@116.09@0.95@21.35@1.29@Load Avrg 2 +_ +HP 9000/370@??@402@0.4@14.58@0.37@Load Avrg 6 +_ +DEC MV-II@RVD@278.24@1.81@38.52@0.54@Load Avrg 3 +_ +Sun 3/60@SCSI@142.78@0.58@18.4@1.05@Load Avrg 1 +_ +Sun 4/390@IPI@96.55@0.37@9.79@1.55@Load Avrg 2 +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Valdis Kletnieks, Virginia Tech += +IBM RS/6000@???@52.022@0.14@3.66@2.88 +\^@\^@34.61@0.18@3.07@4.22@No fsync +\^@\^@51.43@0.22@3.51@2.92@No flock +\^@\^@36.32@0.15@3.28@4.13@No flock/fsync +_ +IBM 3090/300@???@82.41@0.21@3.17@1.82 +\^@\^@76.84@0.21@3.15@1.95@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Anthony Starks, Merk & Co += +Sun 386i@SCSI@237.38@0.66@18.9@0.63 +_ +Sony 3250@???@175@0.58@36.20@0.86@No flock +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +John Andrews, University College London += +Sun 4/330@SCSI@161.04@0.66@9.75@0.93@Busy machine +\^@\^@94.9@0.53@9.43@1.58@Idle Machine +\^@\^@162.46@0.46@10.29@0.92@Busy, no fsync +\^@\^@78.5@0.45@8.29@1.91@Idle, no fsync +\^@XD@137.03@0.61@11.33@1.09@Busy Machine +\^@\^@132.57@0.53@9.63@1.13@Busy, no fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +George Michealson, University of Queensland += +Dec ??@SCSI@109.60@0.14@6.33@1.37@ +\^@\^@138.39@0.17@5.97@1.08@No fsync +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Havard Eidnes, runit.sintef.no += +Sun 4/330@CDC Sabre@143.45@0.51@8.63@1.05@ +\^@\^@135.96@0.28@8.18@1.10@No fsync +_ +Dec 5500@RZ57@113.18@0.08@5.03@1.33 +\^@\^@97.07@0.12@4.82@1.55@No fsync +_ +Sun 4/490@SCSI@135.93@0.3@4.63@1.10 +\^@\^@128.81@0.23@4.58@1.16@No fsync +_ +Sun 4/490@IPI@113.21@0.25@4.98@1.32 +\^@\^@91.04@0.20@4.73@1.65@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Andi Karrer, ETH += +Sun 4/490@TMPFS@1.77@0.15@1.59@84.75 +\^@IPI@127.95@0.26@5.16@1.17 +_ +Dec 5500@T{ +RA90 + Prestoserve +T}@47.87@0.09@9.86@3.13 +_ +Dec 5000@RZ56@96.32@0.18@5.96@1.56 +_ +Convex C220@IPI@99.31@0.27@8.25@1.51 +_ +Sun 3/280@SMD@108.10@0.62@18.96@1.39 +_ +Dec 5849 (4cpu)@RA90@1.27@0.49@21.01@1.17 +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Chris Moore, sooner.palo-alto.ca.us += +Sun SLC@SCSI@133.08@0.54@11.22@1.13 +\^@\^@118.60@0.42@10.77@1.26@No fsync +\^@\^@130.23@0.47@11.35@1.15@No flock +\^@\^@115.51@0.40@10.26@1.30@No flock/fsync +_ + +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Per Andersson, Chalmers University += +Sun IPC@SCSI@186.58@0.37@12.79@0.80 +\^@\^@154.41@0.36@11.79@0.97@No fsync +_ +Sun 4/490@IPI@68.49@0.20@5.43@2.19 +\^@\^@54.18@0.20@4.87@2.77@No fsync +_ +Dec 5000@SCSI@128.48@0.34@7.86@1.17 +\^@\^@108.72@0.37@7.71@1.38@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Andrew Macpherson, BNR Europe += +Sun SLC@NFS to IPI@360.60@0.47@18.13@0.42 +\^@\^@485.21@0.36@19.61@0.31@No flock/fsync +HP 9000/720@???@150@0.25@3.18@1.00 +\^@\^@118@0.23@3.20@1.27@No fsync/flock +_ +Sun 3@XY@124.08@0.68@15.96@1.21 +\^@\^@110.02@0.54@15.18@1.36@No fsync +_ +Sun SS2@SCSI@69.23@0.32@5.19@2.17 +\^@\^@56.56@0.28@4.56@2.65@No fsync +_ +Sun 4/330@SCSI@128.34@0.42@9.93@1.17@ +\^@\^@113.46@0.40@9.10@1.32@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Paridaens Olivier, helios.iihe.rtt.be += +Unisys U6000@SCSI@118@0.65@41.25@1.27@No fsync +\^@\^@121@0.73@39.70@1.24 +_ +ICL DRS3000@SCSI@149@0.58@18.27@1.01 +\^@\^@127@0.75@18.07@1.18@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Bill Nowicki, Legato.com += +Sun SS2@T{ +SCSI + Presto +T}@42.177@0.29@9.31@3.56 +\^@\^@39.99@0.29@8.503.75@3.75@No fsync +\^@No presto@176.21@0.30@6.01@0.85 +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +Randy Grinstead, MIPS Computer Systems += +MIPS Magnum 3000/33@SCSI@@@1.84 +\^@\^@@@2.04@No fsync +_ +.sp .5 +.T& +cfB s s s s s s +a a n n n n a. +rick@uunet.uu.net (Rick Adams) += +Sun 4/470@IPI@14.6@0.14@11.66@10.27 +_ +Sequent S81 (20)@DCC@31.083@0.49@15.09@4.83 +\^@4way DCC@107.86@0.63@17.29@1.39 +_ +.TE diff --git a/Tools/ppbm/ppbm.8 b/Tools/ppbm/ppbm.8 new file mode 100644 index 0000000..458dd9e --- /dev/null +++ b/Tools/ppbm/ppbm.8 @@ -0,0 +1,63 @@ +.TH PPBM 8 "November 1991" +.\" @(#) $Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/ppbm.8,v 6.0 1991/12/18 20:32:20 jpo Rel $ +.\" +.\" $Log: ppbm.8,v $ +.\" Revision 6.0 1991/12/18 20:32:20 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ppbm \- PP throughput measurement tool +.SH SYNOPSIS +.in +.5i +.ti -.5i +ppbm +\%[\-c\ nchilden] \%[\-d\ base] \%[\-f] \%[\-F] \%[\-n\ nbatch] +\%[\-m\ nmessage] \%[\-s\ secs] \%[\-S\ nsubdirs] \%[\-v] +.in -.5i +.SH DESCRIPTION +.I Ppbm +is a utility to estimate the throughput that PP will achieve on a +given system. It does this by simulating the creation and deletion of +messages in a replica queue directory. +.PP +There are a number of flags that can be given to try different senarios. +.TP +\-c nchildren +Create this number of child processes to do the test. The default is 5. +.TP +\-d base +Use the given directory as the test basis. The default is the current +directory. +.TP +\-f +Do not use the fsync flag to flush data to disk. The default is to +flush data after writing the file. +.TP +\-F +Do not use the flock call when writing to files. +.TP +\-n batch +The number of cycles for each child to create and delete messages. The +default is to go through the cycle 3 times. +.TP +\-m messages +The number of messages to create and delete in each batch. +.TP +\-s secs +Sleep for given seconds between batches. +.TP +\-S count +Use this number of subdirectories as in the PP queue structure. +.TP +\-v +verbose flag. Prints messages about what is happening. Probably should +not be used for real runs. +.SH FILES +None specifically. +.SH "Author" +Alan Young, Concurrent Computer Corporation. +.br +Tweaked by Julian Onions, X-tel Services Ltd. + diff --git a/Tools/ppbm/ppbm.c b/Tools/ppbm/ppbm.c new file mode 100644 index 0000000..fa71859 --- /dev/null +++ b/Tools/ppbm/ppbm.c @@ -0,0 +1,417 @@ +/* ppbm.c - measures PP throughput on a filesystem */ + +static char Rcsid[] = "$Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/ppbm.c,v 6.0 1991/12/18 20:32:20 jpo Rel $"; + +/* + * $Header: /xtel/pp/pp-beta/Tools/ppbm/RCS/ppbm.c,v 6.0 1991/12/18 20:32:20 jpo Rel $ + * + * $Log: ppbm.c,v $ + * Revision 6.0 1991/12/18 20:32:20 jpo + * Release 6.0 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#ifndef SYS5 +#include +#include +#endif +#include + +#define NOTOK (-1) +#define MAXPATHLENGTH 1024 +#define hertz 60 /* the (times(2/3) manual page says this + is a constant but is it really ? */ + +#ifndef SYS5 +struct rusage rusage; +#endif +int addr_file_size = 600; /* how much to put in the address file */ +int create_message_sleep = 0; +int delete_message_sleep = 0; +int batch_sleep = 0; +int usesubdirs = 0; +#ifdef LOCK_EX +int do_flock = 1; /* should we flock things? */ +#else +int do_flock = 0; +#endif +int do_sync = 1; /* should files be fsync(2)ed ? */ +int n_batch = 3; /* # batches per child */ +int message_batch = 10; /* # messages per batch */ +int n_child = 5; +int verbose = 0; +int mypid, childno; + +char * base_dir = "."; /* where to create the test messages */ +char buf[60000]; + +/* serror */ +serror (routine, what) +char *routine, *what; +{ + extern int errno; + extern int sys_nerr; + extern char *sys_errlist[]; + char sbuf[BUFSIZ]; + char *p; + + if (errno > 0 && errno < sys_nerr) + p = sys_errlist[errno]; + else p = "Unknown error"; + (void) sprintf (sbuf, "%s %s %s\n", routine, what ? what : "", p); + (void) write (2, sbuf, strlen(sbuf)); +} + +/* main worker function */ +child(cno) +int cno; +{ + int i, j; + mypid = getpid (); + childno = cno; + + for (i = 0; i < n_batch; i++) { + for (j = 0; j < message_batch; j++) { + create_message(j); + if (create_message_sleep) sleep(create_message_sleep); + } + for (j = 0; j < message_batch; j++) { + delete_message(j); + if (delete_message_sleep) sleep(delete_message_sleep); + } + if (batch_sleep) sleep(batch_sleep); + } +} + +/* create a message with address file + 1 header + 1 body part */ +create_message(i) +int i; +{ + char msg[MAXPATHLENGTH]; + char base[MAXPATHLENGTH]; + char file[MAXPATHLENGTH]; + int adr, fd; + + if (usesubdirs) + (void) sprintf (msg, "%s/%d/msg.%d-%d", + base_dir, (childno+i) % usesubdirs, mypid, i); + else + (void) sprintf(msg, "%s/msg.%d-%d", base_dir, mypid, i); + if (mkdir(msg, 0777) == NOTOK) { + serror ("mkdir", msg); + return; + } + (void) sprintf(file, "%s/addr", msg); + if ((adr = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK) { + serror("open", file); + return; + } +#ifdef LOCK_EX + if (do_flock && flock (adr, LOCK_EX) == NOTOK) + serror ("flock", file); +#endif + if (write(adr, buf, addr_file_size) != addr_file_size) { + serror("write", file); + (void) close (adr); + return; + } + + (void) sprintf(base, "%s/base", msg); + if (mkdir(base, 0777) == NOTOK) { + serror ("mkdir", base); + return; + } + (void) sprintf(file, "%s/hdr.822", base); + if ((fd = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK) { + serror("open", file); + (void) close (adr); + return; + } + if (write(fd, buf, header_size(i)) != header_size(i)) { + serror ("write", file); + (void) close (fd); + (void) close (adr); + return; + } + + if (do_sync && fsync(fd) == NOTOK) + serror ("fsync", file); + if (close(fd) == NOTOK) + serror ("close", file); + (void) sprintf(file, "%s/1.ia5", base); + if ((fd = open(file, O_CREAT | O_WRONLY, 0666)) == NOTOK) + serror ("open", file); + else { + if (write(fd, buf, message_size(i)) != message_size(i)) + serror ("write", file); + if (do_sync && fsync(fd) == NOTOK) + serror ("fsync", file); + if (close(fd) == NOTOK) + serror ("close", file); + } + if (do_sync && fsync(adr) == NOTOK) + serror ("fsync", "addr"); + if (close(adr) == NOTOK) + serror ("close", "addr"); +} + +header_size(i) +int i; +{ + return(600); +} + +message_size(i) +int i; +{ + return(6875); /* average of a couple of days on slough */ +} + +delete_message(i) +int i; +{ + char msg[MAXPATHLENGTH]; + + if (usesubdirs) + (void) sprintf(msg, "%s/%d/msg.%d-%d", base_dir, + (childno + i) % usesubdirs, mypid, i); + else + (void) sprintf(msg, "%s/msg.%d-%d", base_dir, mypid, i); + rm_tree(msg); +} + +rm_tree(dir) +char * dir; +{ + char file[MAXPATHLENGTH]; + DIR *d = opendir(dir); + struct dirent * e; + struct stat st; + + if (d == NULL) { + serror ("opendir", dir); + return; + } + + while (e = readdir(d)) { + if (strcmp (e -> d_name, ".") == 0 || + strcmp (e -> d_name, "..") == 0) + continue; + (void) sprintf(file, "%s/%s", dir, e->d_name); + if (stat(file, &st) == NOTOK) { + serror ("stat", file); + continue; + } + if ((st.st_mode&S_IFMT) == S_IFREG) { + int fd; + if ((fd = open(file, O_RDONLY, 0)) != NOTOK) { + if (read (fd, buf, st.st_size) != st.st_size) + serror ("read", file); + (void) close(fd); + } + else + serror ("open", file); + if (verbose) + printf ("Unlink file %s\n", file); + if (unlink(file) == NOTOK) + serror ("unlink", file); + } else if ((st.st_mode & S_IFMT) == S_IFDIR) + rm_tree(file); + } + if (verbose) + printf ("rmdir %s\n", dir); + if (closedir(d) == NOTOK) + serror ("closedir", dir); + if (rmdir(dir) == NOTOK) + serror ("rmdir", dir); +} + +makesubdirs () +{ + char buf[BUFSIZ]; + int i; + + for (i = 0; i < usesubdirs; i++) { + (void) sprintf (buf, "%s/%d", base_dir, i); + if (mkdir (buf, 0777) == NOTOK && errno != EEXIST) + serror ("mkdir", buf); + } +} + +main(argc, argv) +int argc; +char *argv[]; +{ + extern char *optarg; + int i, c; + struct tms tms; +#ifndef SYS5 + struct timeval startt, endt, tdiff; + struct rusage rus; + double mps; +#else + time_t startt, endt; +#endif + union wait wt; + + while ((c = getopt(argc, argv, "c:d:fFn:m:s:S:v")) != EOF) { + switch (c) { + + case 'c': + n_child = atoi(optarg); + break; + + case 'd': + base_dir = optarg; + break; + + case 'f': + do_sync = 0; + break; + + case 'F': + do_flock = 0; + break; + + case 'n': + n_batch = atoi(optarg); + break; + + case 'm': + message_batch = atoi(optarg); + break; + + case 's': + batch_sleep = atoi(optarg); + break; + case 'S': + usesubdirs = atoi(optarg); + break; + case 'v': + verbose = 1; + break; + + case '?': + default: + fprintf(stderr, +"usage: %s [-vf] [-c children] [-n iterations] [-m messages-per-iterations] [-d base_dir]\n", + argv[0]); + exit(1); + } + } + + if (usesubdirs) + makesubdirs (); +#ifndef SYS5 + gettimeofday (&startt, (struct timezone *)0); +#else + startt = time((time_t *)0); +#endif + (void) fflush(stdout); + for (i = 0; i < n_child; i++) { + switch(fork()) { + + case 0: + child(i); + exit(0); + + case -1: + perror("fork"); + exit(1); + } + } +#ifndef SYS5 + while (wait3(&wt.w_status, 0, &rus) != -1) { + gettimeofday (&endt, (struct timezone *)0); + add_ru (&rus); + } +#else + while (wait(&wt.w_status) != -1) + ; + times(&tms); + endt = time((time_t *)0); +#endif + printf ("parameters: flock=%d, fsync=%d, verb=%d\n", + do_flock, do_sync, verbose); + printf(" children=%d, iterations=%d, msgs/iterations=%d = %d msgs\n", + n_child, n_batch, message_batch, + n_child * n_batch * message_batch); + +#define ELAPASED "elapsed time" +#define SYST "system time" +#define USERT "user time" +#ifndef SYS5 + tvsub (&tdiff, &endt, &startt); + printf ("%-14s %d.%06d\n", ELAPASED, tdiff.tv_sec, tdiff.tv_usec); + printf ("%-14s %d.%06d\n", USERT, rusage.ru_utime.tv_sec, + rusage.ru_utime.tv_usec); + printf ("%-14s %d.%06d\n", SYST, rusage.ru_stime.tv_sec, + rusage.ru_stime.tv_usec); + printf ("I/O blocks in=%d, blocks out=%d\n", rusage.ru_inblock, + rusage.ru_oublock); + mps = tdiff.tv_sec + (double)tdiff.tv_usec / 1000000.0; + mps = (n_child * n_batch * message_batch) / mps; + printf ("Gives messages/sec=%.2f\n", mps); +#else + printf("%-14s %d\n", ELAPASED, endt - startt); + printf ("%-14s %.2f\n", USERT, (float)tms.tms_cutime / hertz); + printf ("%-14s %.2f\n", SYST, (float)tms.tms_cstime / hertz); + printf ("Gives messages-per-sec=%.2f\n", + n_child * n_batch * message_batch / (float) (endt - startt)); +#endif +} + + +#ifndef SYS5 +add_ru (ru) +struct rusage *ru; +{ + tvadd(&rusage.ru_utime, &ru->ru_utime); + tvadd(&rusage.ru_stime, &ru->ru_stime); +#define addru(x) rusage.x += ru -> x; + addru(ru_maxrss); + addru(ru_ixrss); + addru(ru_idrss); + addru(ru_isrss); + addru(ru_minflt); + addru(ru_majflt); + addru(ru_nswap); + addru(ru_inblock); + addru(ru_oublock); + addru(ru_msgsnd); + addru(ru_msgrcv); + addru(ru_nsignals); + addru(ru_nvcsw); + addru(ru_nivcsw); +#undef addru +} + +tvsub (tdiff, t1, t0) +register struct timeval *tdiff, + *t1, + *t0; +{ + + tdiff -> tv_sec = t1 -> tv_sec - t0 -> tv_sec; + tdiff -> tv_usec = t1 -> tv_usec - t0 -> tv_usec; + if (tdiff -> tv_usec < 0) + tdiff -> tv_sec--, tdiff -> tv_usec += 1000000; +} + +tvadd (td, tplus) +struct timeval *td, *tplus; +{ + td -> tv_sec += tplus -> tv_sec; + td -> tv_usec += tplus -> tv_usec; + if (td -> tv_usec > 1000000) + td -> tv_usec -= 1000000, td -> tv_sec ++; +} + +#endif diff --git a/Tools/ppls/Makefile b/Tools/ppls/Makefile new file mode 100644 index 0000000..4297a4b --- /dev/null +++ b/Tools/ppls/Makefile @@ -0,0 +1,83 @@ +# ppls dummy Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/ppls/RCS/Makefile,v 6.0 1991/12/18 20:32:36 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:36 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = ppls.c +OBJS = ppls.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -DDEBUG -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xppls + +default: $(PROGS) +all: default +lint: l-ppls + +install: inst-dir inst-ppls +inst-dir: $(TOOLDIR) + + +ppls: xppls +xppls: ppls.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ ppls.o $(LIBPP) $(LIBSYS) + +l-ppls: ppls.c + $(LINT) $(LINTFLAGS) ppls.c $(LINTLIBS) + + +inst-ppls: + echo "ppls not for installation" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/ppls/make b/Tools/ppls/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/ppls/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/ppls/ppls.c b/Tools/ppls/ppls.c new file mode 100644 index 0000000..1c85290 --- /dev/null +++ b/Tools/ppls/ppls.c @@ -0,0 +1,151 @@ +/* ppls: pp version of ls to test directory routines */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ppls/RCS/ppls.c,v 6.0 1991/12/18 20:32:36 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/ppls/RCS/ppls.c,v 6.0 1991/12/18 20:32:36 jpo Rel $ + * + * $Log: ppls.c,v $ + * Revision 6.0 1991/12/18 20:32:36 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include +#include +#include + + +char *myname; +static int selection (); +static void adios (), advise (); +extern int alphasort (); + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + while((opt = getopt(argc, argv, "")) != EOF) + switch (opt) { + default: + fprintf (stderr, "Usage: %s", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc == 0) + dols ("."); + else while (argc-- > 0) { + dols(*argv++); + } + exit (0); +} + +dols (directory) +char *directory; +{ + struct stat st; + struct dirent **namelist, **dp; + int num, i; + + if (stat (directory, &st) == NOTOK) + adios (directory, "Can't stat "); + + if ((st.st_mode & S_IFMT) != S_IFDIR) + printf ("%s\n", directory); + + num = _scandir (directory, &namelist, selection, alphasort); + + if (num == 0) + return; + + for (i = 0, dp = namelist; i < num; i++, dp++) + printf ("%s\n", (*dp) -> d_name); + free ((char *)namelist); +} + +static int selection (dp) +struct dirent *dp; +{ + if (*dp -> d_name == '.') + return 0; + return 1; +} + +#ifndef lint +static void _advise (); + + +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +static void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Tools/probe/Makefile b/Tools/probe/Makefile new file mode 100644 index 0000000..37f7829 --- /dev/null +++ b/Tools/probe/Makefile @@ -0,0 +1,144 @@ +# Build the probe utility +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/probe/RCS/Makefile,v 6.0 1991/12/18 20:32:41 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:41 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = p_stdin.c p_ut.c probe.c +OBJS = p_stdin.o p_ut.o probe.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xprobe + +default: $(PROGS) + +probe: xprobe +xprobe: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + + +install: inst-dir inst-probe + +inst-probe: $(TOOLDIR)/probe +$(TOOLDIR)/probe: xprobe + -$(BACKUP) $@ zxprobe + rm -f $@ + $(INSTALL) xprobe $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "probe installed normally"; echo "" + +inst-dir: $(TOOLDIR) + +lint: + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core $(PROGS) zxprobe *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +p_stdin.o: p_stdin.c +p_stdin.o: ../../h/util.h +p_stdin.o: ../../h/config.h +p_stdin.o: ../../h/ll_log.h +p_stdin.o: ../../h/q.h +p_stdin.o: ../../h/adr.h +p_stdin.o: ../../h/list_rchan.h +p_stdin.o: ../../h/chan.h +p_stdin.o: ../../h/table.h +p_stdin.o: ../../h/list_bpt.h +p_stdin.o: ../../h/auth.h +p_stdin.o: ../../h/list_bpt.h +p_stdin.o: ../../h/extension.h +p_stdin.o: ../../h/mta.h +p_stdin.o: ../../h/adr.h +p_stdin.o: ../../h/list_bpt.h +p_stdin.o: ../../h/mta.h +p_stdin.o: ../../h/tb_q.h +p_ut.o: p_ut.c +p_ut.o: ../../h/util.h +p_ut.o: ../../h/config.h +p_ut.o: ../../h/ll_log.h +p_ut.o: ../../h/q.h +p_ut.o: ../../h/adr.h +p_ut.o: ../../h/list_rchan.h +p_ut.o: ../../h/chan.h +p_ut.o: ../../h/table.h +p_ut.o: ../../h/list_bpt.h +p_ut.o: ../../h/auth.h +p_ut.o: ../../h/list_bpt.h +p_ut.o: ../../h/extension.h +p_ut.o: ../../h/mta.h +p_ut.o: ../../h/adr.h +p_ut.o: ../../h/list_bpt.h +p_ut.o: ../../h/mta.h +p_ut.o: ../../h/tb_bpt84.h +p_ut.o: ../../h/tb_p1.h +p_ut.o: ../../h/retcode.h +probe.o: probe.c +probe.o: ../../h/head.h +probe.o: ../../h/util.h +probe.o: ../../h/config.h +probe.o: ../../h/ll_log.h +probe.o: ../../h/retcode.h +probe.o: ../../h/prm.h +probe.o: ../../h/q.h +probe.o: ../../h/adr.h +probe.o: ../../h/list_rchan.h +probe.o: ../../h/chan.h +probe.o: ../../h/table.h +probe.o: ../../h/list_bpt.h +probe.o: ../../h/auth.h +probe.o: ../../h/list_bpt.h +probe.o: ../../h/extension.h +probe.o: ../../h/mta.h +probe.o: ../../h/adr.h +probe.o: ../../h/list_bpt.h +probe.o: ../../h/mta.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/probe/make b/Tools/probe/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/probe/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/probe/p_stdin.c b/Tools/probe/p_stdin.c new file mode 100644 index 0000000..dfe4442 --- /dev/null +++ b/Tools/probe/p_stdin.c @@ -0,0 +1,148 @@ +/* p_stdin.c: Gets values for the probe via stdin */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/probe/RCS/p_stdin.c,v 6.0 1991/12/18 20:32:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/probe/RCS/p_stdin.c,v 6.0 1991/12/18 20:32:41 jpo Rel $ + * + * $Log: p_stdin.c,v $ + * Revision 6.0 1991/12/18 20:32:41 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "tb_q.h" +#include + + +#define GetStr(buf) (gets (buf) != NULL && isstr(buf)) + + +/* --- externals --- */ +extern CMD_TABLE qtbl_que[]; +extern Q_struct *QuePtr; +extern ADDR *make_adr_new(); + + +/* --- static routines --- */ +static void prompt_encoded(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +void prompt_probe_stdin() +{ + char buf[BUFSIZ]; + int found; + ADDR *ap; + + /* --- Print a message --- */ + printf ("\n\n"); + printf ( +"******************************************************************************"); + printf ("\n\n"); + printf ("This is a probe generation utility. Please note that the Recipient address \n"); + printf ("field is recursive, and that each address should be input, a line at a time\n\n"); + printf ( +"******************************************************************************"); + printf ("\n\n"); + + + /* --- Originator --- */ + printf ("From: "); + printf ("%s\n", QuePtr -> Oaddress -> ad_value); + + + /* --- Recipients --- */ + printf ("To: "); + for (found = FALSE; GetStr(buf);) { + ap = make_adr_new (buf, AD_RECIPIENT); + adr_add (&QuePtr -> Raddress, ap); + printf (" "); + found = TRUE; + } + if (found == FALSE) { + printf ("*** Error: No Recipients specified ***\n"); + exit (1); + } + + + /* --- Content Length --- */ + printf ("%s: ", rcmd_srch(Q_MSGSIZE, qtbl_que)); + GetStr(buf); + QuePtr -> msgsize = atoi(buf); + + + /* --- EncodedInformationTypes --- */ + (void) prompt_encoded(); + + + /* --- UA id --- */ + printf ("%s: ", rcmd_srch(Q_UA_ID, qtbl_que)); + GetStr(buf); + if (isstr(buf)) + QuePtr -> ua_id = strdup (buf); + + + /* --- Per Message Flag --- */ + QuePtr -> implicit_conversion_prohibited = + prompt_yn (rcmd_srch (Q_IMPLICIT_CONVERSION, qtbl_que)); + + QuePtr -> alternate_recip_allowed = + prompt_yn (rcmd_srch (Q_ALTERNATE_RECIP_ALLOWED, qtbl_que)); + + printf ("\n"); +} + + + +/* --------------------- Static Routines -------------------------------- */ + + + +static int prompt_yn (name) +char *name; +{ + char buf[BUFSIZ]; + int retval; + + if (name == NULLCP) { + printf ("*** Error: Internal error no key specified ***\n"); + exit (1); + } + + printf ("%s (y/n): ", name); + if (gets(buf) == NULL) + exit (1); + retval = set_yn(buf); + return retval; +} + + + +static void prompt_encoded() +{ + char buf[BUFSIZ]; + int retval; + + + for (;;) { + printf ("%s: ", rcmd_srch(Q_ENCODED_INFO, qtbl_que)); + if (gets(buf) == NULL) exit (1); + retval = set_encoded (buf); + if (retval == NOTOK) + continue; + return; + } +} diff --git a/Tools/probe/p_ut.c b/Tools/probe/p_ut.c new file mode 100644 index 0000000..12caa6b --- /dev/null +++ b/Tools/probe/p_ut.c @@ -0,0 +1,130 @@ +/* p_ut.c: Common Utilities for probe */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/probe/RCS/p_ut.c,v 6.0 1991/12/18 20:32:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/probe/RCS/p_ut.c,v 6.0 1991/12/18 20:32:41 jpo Rel $ + * + * $Log: p_ut.c,v $ + * Revision 6.0 1991/12/18 20:32:41 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "q.h" +#include "tb_bpt84.h" +#include "tb_p1.h" +#include "retcode.h" +#include +#include + + + +/* --- externals --- */ +extern CMD_TABLE bptbl_body_parts84[]; +extern CMD_TABLE p1tbl_encinfoset[]; +extern Q_struct *QuePtr; + + + +/* -- local routines -- */ +ADDR *make_adr_new(); +int set_encoded(); +int set_yn(); +void set_from(); + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +int set_encoded (values) +char *values; +{ + int argc; + char *argv[10]; + int retval; + + argv[0] = "="; + argv[1] = rcmd_srch (EI_BIT_STRING, p1tbl_encinfoset); + + if (!isstr (values)) + argv[2] = rcmd_srch(BPT_IA5, bptbl_body_parts84); + else + argv[2] = values; + + retval = txt2encodedinfo (&QuePtr->encodedinfo, argv, 3); + return retval; +} + + + + +int set_yn (value) +char *value; +{ + if (!isstr (value)) + return NO; + if (lexequ (value, "y") == 0) + return YES; + if (lexequ (value, "yes") == 0) + return YES; + return NO; +} + + + + +void set_from() +{ + RP_Buf rp; + struct passwd *pwd, + *getpwuid(); + + if ((pwd = getpwuid(getuid())) == NULL) { + printf("Cannot get your passwd entry\n"); + exit(0); + } + + QuePtr -> Oaddress = make_adr_new (pwd->pw_name, AD_ORIGINATOR); +} + + +ADDR *make_adr_new (value, flag) +char *value; +int flag; +{ + static int recipno = 0; + int type = 0; + ADDR *ap = NULLADDR; + + if (index (value, '@')) + type = AD_822_TYPE; + else if (value[0] == '/') + type = AD_X400_TYPE; + else + type = AD_822_TYPE; + + switch (flag) { + case AD_ORIGINATOR: + ap = adr_new (value, type, 0); + break; + case AD_RECIPIENT: + ap = adr_new (value, type, ++recipno); + break; + default: + printf ("make_adr_new/Unknown type '%d'\n", flag); + exit (1); + } + + return (ap); +} + diff --git a/Tools/probe/probe.c b/Tools/probe/probe.c new file mode 100644 index 0000000..c366efc --- /dev/null +++ b/Tools/probe/probe.c @@ -0,0 +1,311 @@ +/* probe.c: Generates a probe */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/probe/RCS/probe.c,v 6.0 1991/12/18 20:32:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/probe/RCS/probe.c,v 6.0 1991/12/18 20:32:41 jpo Rel $ + * + * $Log: probe.c,v $ + * Revision 6.0 1991/12/18 20:32:41 jpo + * Release 6.0 + * + */ + + + +#include "head.h" +#include "prm.h" +#include "q.h" +#include + + + +/* --- externals --- */ +extern char *loc_dom_site, + *local_822_chan, + *cont_822; +extern ADDR *make_adr_new(); + + +/* --- queue variables --- */ +static struct prm_vars PRMstruct; +static Q_struct Qstruct; +static struct prm_vars *PrmPtr = &PRMstruct; +Q_struct *QuePtr = &Qstruct; + + +/* --- other statics --- */ +static char *myname = NULLCP; + +#define OPT_TO 1 +#define OPT_SIZE 2 +#define OPT_EIT 3 +#define OPT_UAID 4 +#define OPT_IMPCONV 5 +#define OPT_ALTRECIP 6 +#define OPT_DEBUG 7 + +static int param = OPT_TO; + +CMD_TABLE probe_options[] = { /* probe commandline options */ + "-t", OPT_TO, + "-s", OPT_SIZE, + "-e", OPT_EIT, + "-u", OPT_UAID, + "-i", OPT_IMPCONV, + "-a", OPT_ALTRECIP, + 0, -1 + }; + + + +static void probe_set_rest(), probe_checks(), usage(); + + + + + +/* --------------------- Begin Routines -------------------------------- */ + + + + +main (argc, argv) +int argc; +char **argv; +{ + char *filename; + ADDR *ap; + int retval; + + + bzero ((char *)PrmPtr, sizeof(*PrmPtr)); + bzero ((char *)QuePtr, sizeof(*QuePtr)); + (void) set_from(); + + myname = argv[0]; + + if (argc > 16) + usage(); + + if (argc == 1) { + (void) prompt_probe_stdin(); + probe_process(); + } + + + while (--argc > 0) { + argv ++; + if (**argv == '-') + switch (param = cmd_srch (*argv, probe_options)) { + + case OPT_TO: + case OPT_SIZE: + case OPT_EIT: + case OPT_UAID: + break; + + case OPT_IMPCONV: + QuePtr -> implicit_conversion_prohibited = YES; + break; + case OPT_ALTRECIP: + QuePtr->alternate_recip_allowed = YES; + break; + default: + printf ("\n***Error: Unknown option '%s'\n", + *argv); + usage(); + } /* -- end of switch -- */ + + else { + switch (param) { + case OPT_TO: + ap = make_adr_new (*argv, AD_RECIPIENT); + adr_add (&QuePtr -> Raddress, ap); + break; + case OPT_SIZE: + QuePtr -> msgsize = atoi(*argv); + break; + case OPT_EIT: + retval = set_encoded (*argv); + if (retval == NOTOK) { + printf ("\n***Error: eits! '%s'\n", + *argv); + usage(); + } + break; + case OPT_UAID: + QuePtr -> ua_id = strdup (*argv); + break; + default: + printf ("\n***Error: Unknown option '%s'\n", + *argv); + usage(); + + } /* -- end of switch -- */ + + } /* -- end of else -- */ + + } /* -- end of while -- */ + + + probe_process(); +} + + + + + + +/* --------------------- Static Routines ------------------------------- */ + + + + + + +static void usage() +{ + printf ("\n\n"); + printf ("Usage: %s\n", myname); + printf (" [-t Recipient]\n"); + printf (" [-s MessageSize]\n"); + printf (" [-e EncodedInfoTypes]\n"); + printf (" [-u UAid]\n"); + printf (" [-i ImplicitConversion]\n"); + printf (" [-a AlternateRecipientAllowed]\n"); + printf ("\n\n"); + exit (1); +} + + + + + +static int probe_process() +{ + int retval; + + (void) probe_checks(); + + sys_init (myname); + if (or_init() == NOTOK) exit (1); + or_myinit(); + (void) probe_set_rest(); + + printf ("Processing ...\n"); + retval = probe_submit(); + + if (rp_isbad (retval)) { + printf ("*** Error: Unable to submit ***\n\n"); + exit (1); + } + + exit (0); +} + + + + +static void probe_set_rest() +{ + prm_init (PrmPtr); + PrmPtr->prm_opts = PRM_ACCEPTALL; + + QuePtr -> msgtype = MT_PMPDU; + QuePtr -> cont_type = strdup(cont_822); + QuePtr -> priority = PRIO_URGENT; + QuePtr -> inbound = list_rchan_new (loc_dom_site, local_822_chan); + + if (QuePtr -> msgsize == 0) + QuePtr -> msgsize = 500; + + if (QuePtr -> encodedinfo.eit_types == 0) + if (set_encoded (NULLCP) == NOTOK) { + printf ("\n***Error: Unable to set eit\n"); + exit (1); + } + (void) MPDUid_new (&QuePtr -> msgid); +} + + + + +static void probe_checks() +{ + + ADDR *ap; + int err = FALSE; + + if (isstr (QuePtr -> ua_id) && (int)strlen (QuePtr -> ua_id) > 16) { + printf ("*** Error: Invalid UA size (max 16) '%s' ***\n", + QuePtr -> ua_id); + exit (1); + } + + if (QuePtr -> msgsize < 0) { + printf ("*** Error: Invalid Message Size '%d' ***\n", + QuePtr -> msgsize); + exit (1); + } +} + + + + +static int probe_submit() +{ + RP_Buf rp; + ADDR *ap; + int submit_status = NOTOK; + + if (rp_isbad (io_init(rp))) { + printf ("*** Error: probe_submit: io_init\n"); + exit (1); + } + + if (rp_isbad (io_wprm (PrmPtr, &rp))) { + printf ("*** Error: probe_submit: io_wprm\n"); + goto probe_submit_end; + } + + if (rp_isbad (io_wrq (QuePtr, &rp))) { + printf ("*** Error: probe_submit: io_wrq\n"); + goto probe_submit_end; + } + + if (rp_isbad (io_wadr (QuePtr->Oaddress, AD_ORIGINATOR, &rp))) { + printf ("*** Error: probe_submit: io_wadr ('%s')\n", + QuePtr->Oaddress->ad_value); + goto probe_submit_end; + } + + + for (ap = QuePtr->Raddress; ap; ap = ap->ad_next) { + + /* -- Red Book X.411 Clause 4.3.2.2 -- */ + ap -> ad_mtarreq = AD_MTA_CONFIRM; + ap -> ad_usrreq = AD_USR_CONFIRM; + + if (rp_isbad (io_wadr (ap, AD_RECIPIENT, &rp))) { + printf ("*** Error: probe_submit: io_wadr ('%s')\n", + ap->ad_value); + goto probe_submit_end; + } + } + + + if (rp_isbad (io_adend (&rp))) { + printf ("*** Error: probe_submit: io_adend\n"); + goto probe_submit_end; + } + else printf ("%s\n", rp.rp_line); + + submit_status = OK; + +probe_submit_end: ; + io_end (submit_status); + return submit_status; +} diff --git a/Tools/splat/Makefile b/Tools/splat/Makefile new file mode 100644 index 0000000..b410fbd --- /dev/null +++ b/Tools/splat/Makefile @@ -0,0 +1,99 @@ +# splat Makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/splat/RCS/Makefile,v 6.0 1991/12/18 20:32:50 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:32:50 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = splat.c ps2pe.c +OBJS = splat.o ps2pe.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +LDFLAGS = $(LDOPTIONS) $(LLF) +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) -u +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + + +############################################################ +# +# Building Rules +# +############################################################ + +PROGS = xsplat + +default: $(PROGS) +all: default +lint: l-splat + +install: inst-dir inst-splat +inst-dir: $(TOOLDIR) + + +splat: xsplat +xsplat: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +l-splat: $(SRCS) + $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS) + + +inst-splat: $(TOOLDIR)/splat +$(TOOLDIR)/splat: xsplat + -$(BACKUP) $@ zxsplat + rm -f $@ + $(INSTALL) xsplat $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "splat tool installed normally"; echo "" + + +clean: tidy + rm -f $(OBJS) +tidy: + rm -f core.* $(PROGS) zx* *.old *.BAK + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +splat.o: splat.c +splat.o: ../../h/util.h +splat.o: ../../h/config.h +splat.o: ../../h/ll_log.h +splat.o: splat.c +splat.o: ../../h/util.h +splat.o: ../../h/config.h +splat.o: ../../h/ll_log.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/splat/make b/Tools/splat/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/splat/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/splat/ps2pe.c b/Tools/splat/ps2pe.c new file mode 100644 index 0000000..00effcf --- /dev/null +++ b/Tools/splat/ps2pe.c @@ -0,0 +1,264 @@ +/* ps2pe.c - presentation stream to presentation element */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + + + +/* + * NOTICE + * + * Acquisition, use, and distribution of this module and related + * materials are subject to the restrictions of a license agreement. + * Consult the Preface in the User's Manual for the full terms of + * this agreement. + * + */ + + +/* LINTLIBRARY */ + +#include +#include +#include + +/* */ + +PE ps2pe_aux (ps, top) +register PS ps; +int top; +{ + register PElementLen len; + PElementClass class; + PElementForm form; + PElementID id; + register PE pe; + + if (top && ps_prime (ps) == NOTOK) + return NULLPE; + + if (ps_read_id (ps, top, &class, &form, &id) == NOTOK) + return NULLPE; + if ((pe = pe_alloc (class, form, id)) == NULLPE) + return ps_seterr (ps, PS_ERR_NMEM, NULLPE); + if (ps_read_len (ps, &pe -> pe_len) == NOTOK) + goto you_lose; + + len = pe -> pe_len; + switch (pe -> pe_form) { + case PE_FORM_PRIM: + if (len == PE_LEN_INDF) { + (void) ps_seterr (ps, PS_ERR_INDF, NULLPE); + goto you_lose; + } + if (len > 0) { + if (ps -> ps_inline) { /* "ultra-efficiency"... */ + if (ps -> ps_base == NULLCP || ps -> ps_cnt < len) { + (void) ps_seterr (ps, PS_ERR_XXX, NULLPE); + goto you_lose; + } + pe -> pe_inline = 1; + pe -> pe_prim = (PElementData) ps -> ps_ptr; + ps -> ps_ptr += len, ps -> ps_cnt -= len; + ps -> ps_byteno += len; + } + else { + if ((pe -> pe_prim = PEDalloc (len)) == NULLPED) { + (void) ps_seterr (ps, PS_ERR_NMEM, NULLPE); + goto you_lose; + } + if (ps_read (ps, pe -> pe_prim, len) == NOTOK) { +#ifdef DEBUG + SLOG (psap_log, LLOG_DEBUG, NULLCP, + ("error reading primitive, %d bytes: %s", + len, ps_error (ps -> ps_errno))); +#endif + goto you_lose; + } + } + } + break; + + case PE_FORM_CONS: + if (len != 0 && ps_read_cons (ps, &pe -> pe_cons, len) == NOTOK) + goto you_lose; + break; + } + + return pe; + +you_lose: ; +#ifdef DEBUG + if (psap_log -> ll_events & LLOG_DEBUG) { + LLOG (psap_log, LLOG_PDUS, ("PE read thus far")); + pe2text (psap_log, pe, 1, NOTOK); + } +#endif + + pe_free (pe); + return NULLPE; +} + +/* */ + +static int pe_id_overshift = PE_ID_MASK << (PE_ID_BITS - (PE_ID_SHIFT + 1)); + + +int ps_read_id (ps, top, class, form, id) +register PS ps; +int top; +register PElementClass *class; +register PElementForm *form; +register PElementID *id; +{ + byte c, + d; + register PElementID j; + + if (ps_read (ps, &c, 1) == NOTOK) { + if (top && ps -> ps_errno == PS_ERR_EOF) + ps -> ps_errno = PS_ERR_NONE; + else { +#ifdef DEBUG + SLOG (psap_log, LLOG_DEBUG, NULLCP, + ("error reading initial octet: %s", ps_error (ps -> ps_errno))); +#endif + } + + return NOTOK; + } + + *class = (PElementClass)(c & PE_CLASS_MASK) >> PE_CLASS_SHIFT; + *form = (PElementForm)(c & PE_FORM_MASK) >> PE_FORM_SHIFT; + j = (c & PE_CODE_MASK); + + if (j == PE_ID_XTND) + for (j = 0;; j <<= PE_ID_SHIFT) { + if (ps_read (ps, &d, 1) == NOTOK) { + if (ps -> ps_errno == PS_ERR_EOF) + ps -> ps_errno = PS_ERR_EOFID; + return NOTOK; + } + + j |= d & PE_ID_MASK; + if (!(d & PE_ID_MORE)) + break; + if (j & pe_id_overshift) + return ps_seterr (ps, PS_ERR_OVERID, NOTOK); + } + *id = j; + DLOG (psap_log, LLOG_DEBUG, ("class=%d form=%d id=%d",*class, *form, *id)); + + return OK; +} + +/* */ + +int ps_read_len (ps, len) +register PS ps; +register PElementLen *len; +{ + register int i; + register PElementLen j; + byte c; + + if (ps_read (ps, &c, 1) == NOTOK) { +#ifdef DEBUG + SLOG (psap_log, LLOG_DEBUG, NULLCP, + ("error reading initial length octet: %s", + ps_error (ps -> ps_errno))); +#endif + + return NOTOK; + } + + if ((i = c) & PE_LEN_XTND) { + if ((i &= PE_LEN_MASK) > sizeof (PElementLen)) + return ps_seterr (ps, PS_ERR_OVERLEN, NOTOK); + + if (i) { + for (j = 0; i-- > 0;) { + if (ps_read (ps, &c, 1) == NOTOK) { + if (ps -> ps_errno == PS_ERR_EOF) + ps -> ps_errno = PS_ERR_EOFLEN; + return NOTOK; + } + + j = (j << 8) | (c & 0xff); + } + *len = j; + } + else + *len = PE_LEN_INDF; + } + else + *len = i; +#ifdef DEBUG + SLOG (psap_log, LLOG_DEBUG, NULLCP, ("len=%d", *len)); +#endif + + return OK; +} + +/* */ + +int ps_read_cons (ps, pe, len) +register PS ps; +register PE *pe; +register PElementLen len; +{ + register int cc; + register PE p, + q; + + cc = ps -> ps_byteno + len; + + if ((p = ps2pe_aux (ps, 0)) == NULLPE) { +no_cons: ; +#ifdef DEBUG + if (len == PE_LEN_INDF) + LLOG (psap_log, LLOG_DEBUG, + ("error building indefinite constructor, %s", + ps_error (ps -> ps_errno))); + else + LLOG (psap_log, LLOG_DEBUG, + ("error building constructor, stream at %d, wanted %d: %s", + ps -> ps_byteno, cc, ps_error (ps -> ps_errno))); +#endif + + return NOTOK; + } + *pe = p; + + if (len == PE_LEN_INDF) { + if (p -> pe_class == PE_CLASS_UNIV && p -> pe_id == PE_UNIV_EOC) { + pe_free (p); + *pe = NULLPE; + return OK; + } + for (q = p; p = ps2pe_aux (ps, 0); q = q -> pe_next = p) { + if (p -> pe_class == PE_CLASS_UNIV && p -> pe_id == PE_UNIV_EOC) { + pe_free (p); + return OK; + } + } + + goto no_cons; + } + + for (q = p;; q = q -> pe_next = p) { + if (cc < ps -> ps_byteno) + return ps_seterr (ps, PS_ERR_LEN, NOTOK); + if (cc == ps -> ps_byteno) + return OK; + if ((p = ps2pe_aux (ps, 0)) == NULLPE) + goto no_cons; + } +} diff --git a/Tools/splat/splat.c b/Tools/splat/splat.c new file mode 100644 index 0000000..02bff77 --- /dev/null +++ b/Tools/splat/splat.c @@ -0,0 +1,300 @@ +/* splat.c: produces a ASN.1 dump */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/splat/RCS/splat.c,v 6.0 1991/12/18 20:32:50 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/splat/RCS/splat.c,v 6.0 1991/12/18 20:32:50 jpo Rel $ + * + * $Log: splat.c,v $ + * Revision 6.0 1991/12/18 20:32:50 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include +void advise(); + + + + +/* --------------------- Begin Routines -------------------------------- */ +char *myname; +int process1 (), process2 (); + + +main (argc, argv, envp) +int argc; +char **argv, + **envp; +{ + extern char *optarg; + extern int optind; + int opt; + register char *cp; + register FILE * fp; + int status = 0; + IFP fnx = process1; + + myname = argv[0]; + while((opt = getopt(argc, argv, "d")) != EOF) + switch (opt) { + case 'd': + fnx = process2; + break; + default: + fprintf (stderr, "Usage: %s", myname); + break; + } + argc -= optind; + argv += optind; + + if (argc == 0) + status = (*fnx) ("(stdin)", stdin); + else + while (cp = *argv++) { + if ((fp = fopen (cp, "r")) == NULL) { + advise (cp, "unable to read"); + status++; + continue; + } + status += (*fnx) (cp, fp); + (void) fclose (fp); + } + + exit (status); +} + + + +/* --------------------- Static Routines ------------------------------- */ + + + +static int process1 (file, fp) +register char *file; +register FILE *fp; +{ + register PE pe; + register PS ps; + PS ps_out; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + advise ("process", "ps_alloc"); + return 1; + } + if (std_setup (ps, fp) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + if ((ps_out = ps_alloc (std_open)) == NULLPS) + printf ("failed on ps_alloc\n"); + if (std_setup (ps_out, stdout) != OK) + printf ("failed to asssign stdout\n"); + + for (;;) { + if ((pe = ps2pe (ps)) == NULLPE) + if (ps -> ps_errno) { + advise (NULLCP, "ps2pe: %s", ps_error(ps -> ps_errno)); + ps_free (ps); + return 1; + } + else { + ps_free (ps); + return 0; + } + + + pe2pl (ps_out, pe); + + pe_free (pe); + } +} + +#define ps_advise(ps, str) advise (NULLCP, "%s: %s", str, ps_error(ps -> ps_errno)); + +int process2 (file, fp) +char *file; +FILE *fp; +{ + register PE pe; + register PS ps; + PS ps_out; + + if ((ps = ps_alloc (std_open)) == NULLPS) { + advise ("process", "ps_alloc"); + return 1; + } + if (std_setup (ps, fp) == NOTOK) { + advise (NULLCP, "%s: std_setup loses", file); + return 1; + } + + for (;;) { + if (read_stuff (ps, 0) == NOTOK) + return 1; + } +} + + +read_stuff (ps, depth) +PS ps; +int depth; +{ + PElementClass class; + PElementForm form; + PElementID id; + int len; + + if (ps_read_id (ps, 1, &class, &form, &id) == NOTOK) { + ps_advise (ps, "ps_read_id"); + return NOTOK; + } + printf ("%*sClass %s, form %s, id %d ", depth * 2, "", + pe_classlist[class], + form == PE_FORM_PRIM ? "primitive" : "constructor", + id); + if (ps_read_len (ps, &len) == NOTOK) { + ps_advise (ps, "ps_read_len"); + return NOTOK; + } + printf (len == PE_LEN_INDF ? "length indefinite\n" : "length %d\n", len); + if (form == PE_FORM_PRIM) { + if (len == 0) { + if (class == PE_CLASS_UNIV && id == 0) + return DONE; + else return OK; + } + else { + char *str = malloc (len); + if (ps_read (ps, str, len) == NOTOK) { + ps_advise (ps, "ps_read"); + return NOTOK; + } + hexdump (str, len, depth); + free (str); + } + } + else { + if (len == PE_LEN_INDF) { + int res; + + for (;;) { + res = read_stuff (ps, depth + 1); + if (res == NOTOK) + return res; + if (res == DONE) + break; + } + } + else { + int cc = ps -> ps_byteno + len; + + for (;;) { + if (read_stuff (ps, depth + 1) == NOTOK) + return NOTOK; + if (ps -> ps_byteno >= cc) + break; + } + } + + } + + return OK; + +} + +hexdump (s, n, depth) +char *s; +int n; +{ + int i; + char *hexstr = "0123456789ABCDEF"; + + printf ("%*s", depth * 2, ""); + for (i = depth * 2; n > 0; n--, i+=2, s++) { + putchar (hexstr[(*s>>4) & 0xf]); + putchar (hexstr[(*s)&0xf]); + if (i > 70) { + putchar ('\n'); + i = depth; + printf ("%*s", depth * 2, ""); + } + } + putchar ('\n'); +} + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + diff --git a/Tools/statgen/Makefile b/Tools/statgen/Makefile new file mode 100644 index 0000000..ad3aa63 --- /dev/null +++ b/Tools/statgen/Makefile @@ -0,0 +1,83 @@ +# Stats generation stuff +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/statgen/RCS/Makefile,v 6.0 1991/12/18 20:33:14 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:33:14 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = statp.c +OBJS = statp.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +LIBS = $(LIBPP) $(LIBSYS) + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + + +default: xstatp line.awk + +statp: xstatp + @true +xstatp: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +install: inst-statp + +inst-statp: $(TOOLDIR)/statp +$(TOOLDIR)/statp: xstatp + -$(BACKUP) $@ zxstatp + rm -f $@ + $(INSTALL) xstatp $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "statp tool installed normally"; echo "" + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old xstatp line.awk + +lint: l-stat + +l-stat: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +lex.o: y.tab.h + +line.awk: line.nawk + sed -e '/^#BEGIN(nawk)/,/^#END(nawk)/d' \ + -e 's/nawk/awk/' \ + -e 's/bytes *(\([^)]*\))/\1/g' $? > $@ || rm $@ + chmod 755 $@ + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Tools/statgen/README b/Tools/statgen/README new file mode 100644 index 0000000..87802d6 --- /dev/null +++ b/Tools/statgen/README @@ -0,0 +1,2 @@ +This directory contains some sample scripts for processing the stat +log. New examples giving new formats are encouraged. diff --git a/Tools/statgen/line.nawk b/Tools/statgen/line.nawk new file mode 100755 index 0000000..ce36d50 --- /dev/null +++ b/Tools/statgen/line.nawk @@ -0,0 +1,188 @@ +#! /bin/sh + +# nawk script for producing summary listings of stats +# +# + +nawk ' +BEGIN { + FS = "|" +} +NF > 1 { + split ($1, parts, ":") + if (NR == 1) { + first_month = parts[1]; first_day = parts[2] + first_hour = parts[3] + first_min = parts[4] + 0 + first_sec = parts[5] + 0 + } + last_month = parts[1]; last_day = parts[2] + last_hour = parts[3] + last_min = parts[4] + last_sec = parts[5] +} +$2 == "Deliv" { +# Format +# date-time|Deliv|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# sub-time|queue-time +# 12 13 + next +} +$2 == "DR" { +# Format +# date-time|DR|type|msgid|p1id|size|inchan|dest|inhost|outchan|src|host| +# 1 2 3 4 5 6 7 8 9 10 11 12 +# cchan|reason|diag|mesg +# 13 14 15 16 +# OR for positive & transit +# cchan|submit-time|queued-time +# 13 14 15 + if (NF < 13 && NF > 15) { + print "Bad record line", NR, $0 | "cat 1>&2" + next + } + type = $3 + if (type == "positive") + good_drs ++ + else if (type == "negative") + bad_drs ++ + else if (type == "transit") + trans_drs ++ + else print "Unknown DR type", type, NR, $0 | "cat 1>&2" +} +$2 == "ok" { +# Format +# date-time|ok|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# msg|submit-time +# 12 13 + if (NF != 13) { + print "Bad record line NR", $0 | "cat 1>&2" + next + } + + total_addr ++ + msgid = $3 + inchan = $4 + outchan = $5 + size = $7 + inmta = $9 + outmta = $11 + if (im[msgid] == 0) { + total_msgs ++ + total_size += size + im[msgid] = 1 + inchan_size[inchan] += size + if (ih[inchan inmta] == 0) { + inchan_nhosts[inchan] ++ + ih[inchan inmta] = 1 + } + if (ih[inmta] == 0) { + total_inmta ++ + ih[inmta] = 1 + } + inchan_nmsgs[inchan] ++ + } + inchan_naddr[inchan] ++ + + if (om[msgid outchan] == 0) { + om[msgid outchan] = 1 + outchan_size[outchan] += size + if (oh[outchan outmta] == 0) { + outchan_nhosts[outchan] ++ + oh[outchan outmta] = 1 + } + if (oh[outmta] == 0) { + total_outmta ++ + oh[outmta] = 1 + } + outchan_nmsgs[outchan] ++ + } + outchan_naddr[outchan] ++; + + + cp = inchan " -> " outchan + chpair_naddr[cp] ++ + if (cm[msgid cp] == 0) { + cm[msgid cp] = 1 + chpair_size[cp] += size + chpair_nmsgs[cp] ++ + } +} +#BEGIN(nawk) +func bytes(n) { + if (n < 1000) + return sprintf ("%d", n) + if (n < 1000000) + return sprintf ("%.2fK", n / 1000.0) + else return sprintf ("%.2fM", n / 1000000.0) +} +#END(nawk) +END { + printf "SUMMARY for period %d/%d %d:%02d:%02d to %d/%d %d:%02d:%02d\n", \ + first_month, first_day, first_hour, first_min, first_sec, \ + last_month, last_day, last_hour, last_min, last_sec + + printf "%-20s: %s\n", "Messages", bytes(total_msgs) + printf "%-20s: %s\n", "Addresses", bytes(total_addr) + printf "%-20s: %s\n", "Bytes", bytes(total_size) + + printf "%-20s: %s\n", "Inbound MTAs", bytes(total_inmta) + printf "%-20s: %s\n", "Outbound MTAs", bytes(total_outmta) + if (good_drs) + printf "%-20s: %s\n", "Positive DRs", bytes(good_drs) + if (bad_drs) + printf "%-20s: %s\n", "Negative Drs", bytes(bad_drs) + if (trans_drs) + printf "%-20s: %s\n", "Transiting Drs", bytes(trans_drs) + print "\n" + + print "Inbound Channel Totals" + title = "Channel" + maxw = length(title) + for (i in inchan_naddr) + if (length(i) > maxw) + maxw = length(i) + format = "%-" maxw "s %8d %8d %8s %8s\n" + printf "%-" maxw "s %8s %8s %8s %8s\n", title, \ + "Msgs", "Addr", "Bytes", "MTAs" + for (i in inchan_naddr) + printf format, i, \ + inchan_nmsgs[i], inchan_naddr[i], \ + bytes(inchan_size[i]) , inchan_nhosts[i] + + print ""; print ""; + print "Outbound Channel Totals" + title = "Channel" + maxw = length(title) + if (length(i) > maxw) + maxw = length(i) + + for (i in outchan_naddr) + if (length(i) > maxw) + maxw = length(i) + printf "%-" maxw "s %8s %8s %8s %8s\n", title,\ + "Msgs", "Addr", "Bytes", "MTAs" + + for (i in outchan_naddr) + printf "%-" maxw "s %8d %8d %8s %8s\n", i, \ + outchan_nmsgs[i], outchan_naddr[i], \ + bytes(outchan_size[i]), outchan_nhosts[i] + + print ""; print "" + print "Channel Pair Totals" + title = "Channel" + maxw = length(title) + + for (i in chpair_naddr) + if (length(i) > maxw) + maxw = length(i) + printf "%-" maxw "s %8s %8s %8s\n", title, \ + "Msgs", "Addrs", "Bytes" + for (i in chpair_naddr) + printf "%-" maxw "s %8d %8d %8s\n", i, \ + chpair_nmsgs[i], chpair_naddr[i], \ + bytes(chpair_size[i]) + +}' $* diff --git a/Tools/statgen/make b/Tools/statgen/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/statgen/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/statgen/rare.nawk b/Tools/statgen/rare.nawk new file mode 100755 index 0000000..4faf9fe --- /dev/null +++ b/Tools/statgen/rare.nawk @@ -0,0 +1,220 @@ +#! /bin/sh + +nawk ' +BEGIN { FS = "|" + days[0] = 0 + days[1] = 31 + days[2] = days[1] + 28 + days[3] = days[2] + 31 + days[4] = days[3] + 30 + days[5] = days[4] + 31 + days[6] = days[5] + 30 + days[7] = days[6] + 31 + days[8] = days[7] + 31 + days[9] = days[8] + 30 + days[10] = days[9] + 31 + days[11] = days[10] + 30 + days[12] = days[11] + 31 +} + { ctime = $1 + if(!starttime) + starttime = ctime + } +$2 == "Deliv" { +# Format +# date-time|Deliv|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# sub-time|queue-time +# 12 13 + mtaout = $11 + size = $7 + msg = $3 + queuetime = $13 + storeit(mtaout, msg, queuetime, size) + next +} +$2 == "DR" { +# Format +# date-time|DR|type|msgid|p1id|size|inchan|dest|inhost|outchan|src|host| +# 1 2 3 4 5 6 7 8 9 10 11 12 +# cchan|reason|diag|mesg +# 13 14 15 16 +# cchan|submit-time|queued-time +# 13 14 15 + + msg = $4 + mtain = $8 + mtaout = $12 + type = $3 + queuetime = $15 + size = $6 + if (type == "negative") { + # storeit(mtaout, msg, queuetime,size) + drsnegative ++ + } else if (type == positive) { + storeit(mtaout, msg, queuetime, size) + drspositive ++ + } else if (type == "transit") { + drsin ++; + drsmta[mtain] ++ + } + next +} +$2 == "ok" { +# Format +# date-time|ok|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# msg|submit-time +# 12 13 + mtain = $9 + msg = $3 + size = $7 + mtaout = $11 + if(mtamsgin[mtain msg] == 0) { + mtamsgin[mtain msg] = 1 + if (mtainbytes[mtain] == 0) { + n = split(mtain, parts, ".") + if (n > 1) + domcom[mtain] = parts[n] + else domcom[mtain] = "local" + } + mtainbytes[mtain] += size + mtainnumb[mtain] ++ + } + next +} + { error( "ignore line " NR $0) } +func error(mesg) { + print mesg | "cat 1>&2" +} + +func storeit(mtaout, msg, queuetime,size) { + if (mtamsgout[mtaout msg] == 0){ + mtamsgout[mtaout msg] = 1 + if (mtaoutbytes[mtaout] == 0) { + n = split(mtaout, parts, ".") + if (n > 1) + domcom[mtaout] = parts[n] + else domcom[mtaout] = "local" + } + mtaoutbytes[mtaout] += size + mtaoutnumb[mtaout] ++ + + n = tdiff(queuetime, ctime) + for (i = n; i <= 5; i++) + elapsed[mtaout i] ++ + } +} +func line(c, n, i, str) { + for (i = 0; i < n; i++) + str = str c + print str +} +func percent(a,b) { + if (b == 0) return 0; + return a * 100 / b +} +func tdiff(t1,t2, diff,time1,time2) { + split(t1, t1pts, ":") + split(t2, t2pts, ":") + time1 = days[t1pts[1]-1] * 24 * 3600 + time1 += t1pts[2] * 24 * 3600 + time1 += t1pts[3] * 3600 + time1 += t1pts[4] * 60 + time1 += t1pts[5] + time2 = days[t2pts[1]-1] * 24 * 3600 + time2 += t2pts[2] * 24 * 3600 + time2 += t2pts[3] * 3600 + time2 += t2pts[4] * 60 + time2 += t2pts[5] + diff = time2 - time1 + if (diff < 60) + return 1 + else if (diff < 5 * 60) + return 2 + else if (diff < 3600) + return 3 + else if (diff < 3600*24) + return 4 + else return 5 +} +END { + line("=", 80) + split(starttime, part1, ":") + split(ctime, part2, ":") + msg = sprintf(\ + "Statistics from %s/%s %d:%02d:%02d to %s/%s %d:%02d:%02d",\ + part1[1], part1[2], part1[3], part1[4], part1[5],\ + part2[1], part2[2], part2[3], part2[4], part2[5]) + printf "%" (length(msg) - 80) / 2 "s%s\n", "", msg + line("=",80) + msg = "Inbound statistics" + print "\n\n" + print msg + line("-", length(msg)) + print "\n\nSource" + partner = "Partner" + MTA = "MTA" + wid = length(MTA) + for (i in mtainnumb) + if (length(i) > wid) + wid = length(i) + wid2 = length(partner) + for (i in domcom) + if (length(domcom[i]) > wid2) + wid2 = length(domcom[i]) + printf "%-" wid2 "s %-" wid "s %8s %10s\n", partner,\ + MTA, "#messg", "#kByte" + line("-", 80) + for (i in mtainnumb) { + printf "%-" wid2 "s %-" wid "s %8d %10.2f\n", domcom[i], i,\ + mtainnumb[i], mtainbytes[i]/1000 + totbytes += mtainbytes[i]/1000.0 + totmsgs += mtainnumb[i] + } + line("-", 80) + printf "%-" wid + wid2 "s %8d %10.2f\n", "Total", totmsgs, totbytes + + msg = "Outbound statistics" + print "\n\n" + print msg + line("-", length(msg)) + wid = length(MTA) + for (i in mtaoutnumb) + if (length(i) > wid) + wid = length(i) + + printf "\n\n%-" wid + wid2 + 28 "s %s\n", "", \ + "% of messages" + printf "%-" wid + wid2 + 27 "s %s\n", "Destination", "relayed within" + printf "%-" wid2 "s %-" wid "s %8s %10s %4s %4s %4s %4s\n", \ + partner, MTA, "#messg", "#kByte", "1m", "5m", "1h", "1d" + totbytes = totmsgs = 0 + line("-", 80) + for (i in mtaoutnumb) { + printf "%-" wid2 "s %-" wid "s %8d %10.2f %4d %4d %4d %4d\n",\ + domcom[i], i, mtaoutnumb[i], mtaoutbytes[i]/1000,\ + percent(elapsed[i 1], mtaoutnumb[i]), \ + percent(elapsed[i 2], mtaoutnumb[i]), \ + percent(elapsed[i 3], mtaoutnumb[i]), \ + percent(elapsed[i 4], mtaoutnumb[i]) + for (j = 1; j < 5; j++) + telapsed[j] += elapsed[i j] + totbytes += mtaoutbytes[i]/1000 + totmsgs += mtaoutnumb[i] + } + line("-", 80) + printf "%-" wid + wid2 "s %8d %10.2f %4d %4d %4d %4d\n\n", \ + "Total", totmsgs, totbytes, \ + percent(telapsed[1], totmsgs), \ + percent(telapsed[2], totmsgs), \ + percent(telapsed[3], totmsgs), \ + percent(telapsed[4], totmsgs) + + if (drspositive || drsnegative) + printf "Delivery reports generated: %d positive, %d negative\n", \ + drspositive, drsnegative + if (drsin) + printf "Delivery reports relayed: %d\n", drsin +} +' $* diff --git a/Tools/statgen/slowhosts.awk b/Tools/statgen/slowhosts.awk new file mode 100755 index 0000000..4d85dc6 --- /dev/null +++ b/Tools/statgen/slowhosts.awk @@ -0,0 +1,143 @@ +#! /bin/sh + +# +# Find who is the slowest of the slow... +# +# +nawk ' +BEGIN { FS = "|" + days[0] = 0 + days[1] = 31 + days[2] = days[1] + 28 + days[3] = days[2] + 31 + days[4] = days[3] + 30 + days[5] = days[4] + 31 + days[6] = days[5] + 30 + days[7] = days[6] + 31 + days[8] = days[7] + 31 + days[9] = days[8] + 30 + days[10] = days[9] + 31 + days[11] = days[10] + 30 + days[12] = days[11] + 31 +} + { ctime = $1 + if(!starttime) + starttime = ctime + } +$2 == "Deliv" { +# Format +# date-time|Deliv|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# sub-time|queue-time +# 12 13 + next +} +$2 == "DR" { +# Format +# date-time|DR|type|msgid|p1id|size|inchan|dest|inhost|outchan|src|host| +# 1 2 3 4 5 6 7 8 9 10 11 12 +# cchan|reason|diag|mesg +# 13 14 15 16 +# cchan|submit-time|queued-time +# 13 14 15 + + next +} +$2 == "ok" { +# Format +# date-time|ok|msgid|inchan|outchan|p1id|size|sender|inmta|recip|outmta| +# 1 2 3 4 5 6 7 8 9 10 11 +# msg|submit-time +# 12 13 + inmta = $9 + msgid= $3 + subtime = $13 + if (inmtamsg[inmta msgid] == 0) { + inmtamsg[inmta msg] = 1 + t1 = tdiff(subtime, ctime) + if (! (inmta in mintime)) { + mintime[inmta] = 999999999 + if (length(inmta) > maxmtalen) + maxmtalen = length(inmta) + } + if (t1 < mintime[inmta]) + mintime[inmta] = t1 + if (t1 > maxtime[inmta]) + maxtime[inmta] = t1 + countmta[inmta] ++ + avrgtime[inmta] = \ + (avrgtime[inmta] * (countmta[inmta]-1) / countmta[inmta])\ + + t1/countmta[inmta] + } + next +} + { error( "ignore line " NR $0) } +func error(mesg) { + print mesg | "cat 1>&2" +} + +func line(c, n, i, str) { + for (i = 0; i < n; i++) + str = str c + print str +} +func tdiff(t1,t2, time1,time2) { + split(t1, t1pts, ":") + split(t2, t2pts, ":") + time1 = days[t1pts[1]-1] * 24 * 3600 + time1 += t1pts[2] * 24 * 3600 + time1 += t1pts[3] * 3600 + time1 += t1pts[4] * 60 + time1 += t1pts[5] + time2 = days[t2pts[1]-1] * 24 * 3600 + time2 += t2pts[2] * 24 * 3600 + time2 += t2pts[3] * 3600 + time2 += t2pts[4] * 60 + time2 += t2pts[5] + return time2 - time1 +} +func totime(secs, strtime) { + if (secs < 0) { + strtime = "-" + secs = -secs + } + else strtime = "" + if (secs > 60*60*24) { + strtime = strtime sprintf("%2d ", secs/(60*60*24)) + secs %= 60*60*24 + } + if (secs > 60*60) { + strtime = strtime sprintf("%2d:", secs/(60*60)) + secs %= 60*60 + } + if (secs > 60) { + strtime = strtime sprintf(strtime ? "%02d:" : "%2d:", secs/60) + secs %= 60 + } + strtime = strtime sprintf(strtime ? "%02d" : "%2d", secs) + return strtime +} +END { + line("=", 80) + split(starttime, part1, ":") + split(ctime, part2, ":") + msg = sprintf(\ + "Statistics from %s/%s %d:%02d:%02d to %s/%s %d:%02d:%02d",\ + part1[1], part1[2], part1[3], part1[4], part1[5],\ + part2[1], part2[2], part2[3], part2[4], part2[5]) + printf "%" (length(msg) - 80) / 2 "s%s\n", "", msg + line("=",80) + + printf "\n\t\tDelay time in receiving messages" + + printf "\n\n%-" maxmtalen "s %5s %12s %12s %12s\n",\ + "MTA", "Msgs", "Min", "Max", "Avrg" + line("-", 80) + for (i in countmta) + printf "%-" maxmtalen "s %5d %12s %12s %12s\n", \ + i, countmta[i], \ + totime(mintime[i]), \ + totime(maxtime[i]), \ + totime(avrgtime[i]) +} +' $* diff --git a/Tools/statgen/statp.c b/Tools/statgen/statp.c new file mode 100644 index 0000000..14b0211 --- /dev/null +++ b/Tools/statgen/statp.c @@ -0,0 +1,406 @@ +/* statp.c: produce awk-able stats */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/statgen/RCS/statp.c,v 6.0 1991/12/18 20:33:14 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/statgen/RCS/statp.c,v 6.0 1991/12/18 20:33:14 jpo Rel $ + * + * $Log: statp.c,v $ + * Revision 6.0 1991/12/18 20:33:14 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +char *myname; +int lineno; +static char *curfile; + +static void process (); +static int parseline (); +static void adios (), advise (); + +main (argc, argv) +int argc; +char **argv; +{ + extern char *optarg; + extern int optind; + int opt; + + myname = argv[0]; + while((opt = getopt(argc, argv, "")) != EOF) + switch (opt) { + default: + fprintf (stderr, "Usage: %s\n", myname); + break; + } + argc -= optind; + argv += optind; + if (argc > 0) { + while (argc > 0) { + FILE *fp; + + if ((fp =fopen (*argv, "r")) == NULL) + adios (*argv, "Can't open file"); + process (fp, *argv); + fclose (fp); + argv ++; argc --; + } + } + else + process (stdin, "standard input"); + exit (0); +} + +static void process (fp, name) +FILE *fp; +char *name; +{ + char linebuf[BUFSIZ*4]; + + curfile = name; + lineno = 1; + while (fgets (linebuf, sizeof linebuf, fp)) { + parseline (linebuf); + lineno ++; + } +} + +static int parseline (line) +char *line; +{ + int month, day; + int hour, mins, sec; + char *cp, *p; + char *argv[100]; + int argc, n; + + month = atoi (line); + if ((cp = index(line, '/')) == NULL) + return badline (line, "No / date separator"); + + day = atoi (++cp); + + while (*cp && isspace (*cp)) + cp ++; + while (*cp && isdigit(*cp)) + cp ++; + while (*cp && isspace (*cp)) + cp ++; + + if (sscanf (cp, "%d:%d:%d", &hour, &mins, &sec) != 3) + return badline (cp, "No hour:min:sec field"); + + if ((cp = index (line, ')')) == NULL) + return badline (line, "No ')' in line"); + + cp ++; + if (index (cp, '|')) + return badline (cp, "Line contains a '|'"); + + + printf ("%d:%d:%d:%02d:%02d|", month, day, hour, mins, sec); + + + if ((p = index (cp, '>')) != NULL && p[-1] == '-') + p[-1] = *p = ' '; + argc = sstr2arg (cp, 100, argv, " \t\n="); + + if (lexequ (argv[0], "DR") == 0 ) + return do_dr (argc, argv); + else if (lexequ (argv[0], "ok") == 0) + return do_basic (argc, argv); + else if (lexequ (argv[0], "deliv") == 0) + return do_deliv (argc, argv); + else + return badline (argv[0], "unknown key"); +} + +do_basic (argc, argv) +int argc; +char **argv; +{ + int n; + +#define NF_NORM 18 + if (argc != NF_NORM) { + char buf[BUFSIZ]; + (void) sprintf (buf, + "Incorrect number of fields %d, expecting %d", + argc, NF_NORM); + return badline (argv[0], buf); + } + + printf ("%s|%s|%s|%s|", + argv[0], argv[1], argv[2], argv[3]); + + n = 4; + if (lexequ (argv[n], "p1msgid")) + return badline (argv[n], "p1msgid missing"); + printf ("%s|", argv[++n]); + n ++; + + if (lexequ(argv[n], "size")) + return badline(argv[n], "size missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ (argv[n], "sender")) + return badline (argv[n], "sender missing"); + printf ("%s|%s|", argv[n+1], argv[n+2]); + n += 3; + + if (lexnequ (argv[n], "recip", 5)) + return badline (argv[n], "recip missing"); + printf ("%s|%s|%s|", argv[n+1], argv[n+2], argv[n+3]); + n += 4; + + if (lexequ (argv[n], "submit-time")) + return badline (argv[n], "submit-time missing"); + printf ("%s\n", argv[n+1]); + + return OK; +} + +do_dr (argc, argv) +int argc; +char **argv; +{ + int n; + int noneg; + char *p; + +#define NF_DROK 22 + if (argc < NF_DROK) { + char buf[BUFSIZ]; + (void) sprintf (buf, + "Incorrect number of fields %d, expecting at kleast %d", + argc, NF_DROK); + return badline (argv[0], buf); + } + + printf ("%s|%s|%s|", + argv[0], argv[1], argv[2]); + + noneg = lexequ (argv[1], "negative") != 0; + + n = 3; + if (lexequ (argv[n], "p1msgid")) + return badline (argv[n], "p1msgid missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ(argv[n], "size")) + return badline (argv[n], "size missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ(argv[n], "inchan")) + return badline(argv[n], "inchan missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ (argv[n], "dr_dest")) + return badline (argv[n], "recip missing"); + printf ("%s|%s|", argv[n+1], argv[n+2]); + n += 3; + + if (lexequ (argv[n], "outchan")) + return badline (argv[n], "outchan missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ (argv[n], "dr-src")) + return badline (argv[n], "dr-src missing"); + printf ("%s|%s|", argv[n+1], argv[n+2]); + n += 3; + + if (lexequ (argv[n], "cur-channel")) + return badline (argv[n], "cur-channel missing"); + printf ("%s", argv[++n]); + n ++; + + if (noneg) { + if (lexequ (argv[n], "submit-time")) + return badline(argv[n], "submit-time missing"); + printf ("|%s", argv[n+1]); + n += 2; + + if (lexequ (argv[n], "queued-time")) + return badline(argv[n], "queued-time missing"); + printf ("|%s", argv[n+1]); + n += 2; + + } + + if (n + 2 >= argc) { + putchar ('\n'); + return OK; + } + else + putchar ('|'); + + if (lexequ (argv[n], "reason")) + return badline (argv[n], "reason missing"); + printf ("%s|", argv[++n]); + n ++; + + if (lexequ (argv[n], "diag")) + return badline (argv[n], "diag missing"); + printf ("%s", argv[++n]); + n ++; + + if (n >= argc) { + putchar ('\n'); + return OK; + } + else + putchar ('|'); + + for (p = argv[n]; *p; p++) + if (*p == '\n') + *p = ' '; + printf ("%s\n", argv[n]); + return OK; +} + +do_deliv (argc, argv) +int argc; +char **argv; +{ + int n; + +#define NF_DELIV 19 + if (argc != NF_DELIV) { + char buf[BUFSIZ]; + (void) sprintf (buf, + "Incorrect number of fields %d, expecting %d", + argc, NF_DELIV); + return badline (argv[0], buf); + } + + printf ("%s|%s|%s|%s|", argv[0], argv[1], argv[2], argv[3]); + + n = 4; + if (lexequ (argv[n], "p1msgid")) + return badline (argv[n], "p1msgid missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ (argv[n], "size")) + return badline (argv[n], "size missing"); + printf ("%s|", argv[++n]); + n++; + + if (lexequ(argv[n], "sender")) + return badline(argv[n], "sender missing"); + printf ("%s|", argv[++n]); + n++; + + printf ("%s|", argv[n]); + n++; + + if (lexequ (argv[n], "recip")) + return badline (argv[n], "recip missing"); + printf ("%s|", argv[++n]); + n++; + + printf ("%s|", argv[n]); + n++; + + if (lexequ(argv[n], "submit-time")) + return badline(argv[n], "submit-time missing"); + printf ("%s|", argv[++n]); + n ++; + + if (lexequ(argv[n], "queued-time")) + return badline (argv[n], "queued-time missing"); + printf ("%s\n", argv[++n]); + + return OK; +} + +int badline (line, mesg) +char *line, *mesg; +{ + putchar ('\n'); + advise (NULLCP, "Bad stat line '%s' line %d in %s: %s", + line, lineno, curfile, mesg); + return NOTOK; +} + +#ifndef lint +static void _advise (); + + +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +static void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); +} +#else +/* VARARGS */ + +static void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif diff --git a/Tools/tables/Makefile b/Tools/tables/Makefile new file mode 100644 index 0000000..fa61251 --- /dev/null +++ b/Tools/tables/Makefile @@ -0,0 +1,45 @@ +# tables programs master makefile +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/RCS/Makefile,v 6.0 1991/12/18 20:35:38 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:35:38 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = abbrev tjoin +ALLDIRS = $(SUBDIRS) domain compat + +############################################################ +# +# Building Rules +# +############################################################ + +target: + for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +install: + for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +tidy define depend clean lint: + for i in ${ALLDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Tools/tables/abbrev/Makefile b/Tools/tables/abbrev/Makefile new file mode 100644 index 0000000..8bab4f5 --- /dev/null +++ b/Tools/tables/abbrev/Makefile @@ -0,0 +1,90 @@ +# abbrev - extend domain table to include abbreviations +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/abbrev/RCS/Makefile,v 6.0 1991/12/18 20:33:28 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:33:28 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = abbrev.c +OBJS = abbrev.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = xabbrev + +default: all +progs: $(PROGS) +all: $(PROGS) +abbrev: $(PROGS) + +xabbrev: abbrev.o + $(CC) $(LDFLAGS) abbrev.o -o $@ $(LIBSYS) + + +install: inst-dir inst-abbrev +inst-dir: $(TOOLDIR) +inst-abbrev: $(TOOLDIR)/abbrev +$(TOOLDIR)/abbrev: xabbrev + -$(BACKUP) $@ zxabbrev + rm -f $@ + $(INSTALL) xabbrev $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "abbrev tool installed normally"; echo "" + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f *.old *.BAK *.OUT $(PROGS) zx* + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + +lint: l-abbrev +l-abbrev: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +abbrev.o: abbrev.c +abbrev.o: abbrev.c + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/tables/abbrev/abbrev.c b/Tools/tables/abbrev/abbrev.c new file mode 100644 index 0000000..87d4752 --- /dev/null +++ b/Tools/tables/abbrev/abbrev.c @@ -0,0 +1,226 @@ +/* abbrev.c: abbreviates domains */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/tables/abbrev/RCS/abbrev.c,v 6.0 1991/12/18 20:33:28 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/tables/abbrev/RCS/abbrev.c,v 6.0 1991/12/18 20:33:28 jpo Rel $ + * + * $Log: abbrev.c,v $ + * Revision 6.0 1991/12/18 20:33:28 jpo + * Release 6.0 + * + */ + + + +#include "util.h" + +extern char *strdup (), *index(); +static int LineCount; +static char *myname; +static char *aliases[100]; +static int maxalias = 0; +static int bitmap; + +static void do_alias (); +/* --------------------- Begin Routines -------------------------------- */ + + +main (ac,av) +int ac; +char *av []; +{ + char buffer [BUFSIZ], *entries[10]; + register char *alias, *name, *nonwildcard; + register int i, NumEntries, use; + char rhs[BUFSIZ], entry[BUFSIZ]; + + myname = av [0]; + if (ac < 2) { + fprintf (stderr, "Usage: %s Domain...\n", myname); + exit (1); + } + + + for (i = 1; i < ac; i++) { + (void) sprintf (buffer, "X.%s", av[i]); + aliases[maxalias++] = strdup (buffer); + } + LineCount = 0; + + while (fgets (buffer, sizeof buffer, stdin) != NULL) { + LineCount++; + alias = &buffer [0]; + printf ("%s", alias); + if (*alias == '#' || *alias == '\n') + continue; + + alias [strlen (alias) - 1] = '\0'; + for (name = alias; *name != '\0'; name++) + if (*name == ':' || *name == '#') + break; + if (*name == '#') + continue; + + if (*name == '\0') { + fprintf (stderr, "%s: Syntax Error [%s] ", + myname, alias); + fprintf (stderr, "at line %d - Ignored\n", LineCount); + continue; + } + *name++ = '\0'; + + if (alias[0] == '*' + && alias[1] == '.') + nonwildcard = &(alias[2]); + else + nonwildcard = &(alias[0]); + + if ((NumEntries = sstr2arg (name, 10, entries, "|")) < 1) { + fprintf(stderr, "%s: Syntax Error [%s] ", + myname, alias); + fprintf(stderr, "at line %d - Ignored\n", LineCount); + continue; + } + rhs[0] = '\0'; + use = 1; + for (i = 0; i < NumEntries && use == 1; i++) { + use = do_entry(entries[i], nonwildcard, entry, alias); + if (rhs[0] != '\0') + strcat (rhs, "|"); + strcat (rhs, entry); + } + if (use == 1) + for (i = 0; i < maxalias; i++) + do_alias (alias, rhs, aliases[i]); + } + exit (0); +} + +do_entry(name, nonwildcard, rhs, alias) +char *name; +char *nonwildcard; +char *rhs; +char *alias; +{ + char *vec[10]; + int vecp, i; + int use = 0; + int gotnorm; + int mtaislhs; + if ((vecp = sstr2arg (name, 10, vec, " \t")) < 1) { + fprintf(stderr, "%s: Syntax Error [%s] ", + myname, alias); + fprintf(stderr, "at line %d - Ignored\n", LineCount); + return use; + } + + rhs[0] = '\0'; + gotnorm = 0; + mtaislhs = 0; + for (i = 0; i < vecp; i++) { + char *p; + + if (lexnequ (vec[i], "norm+mta", 8) == 0 + || lexnequ (vec[i], "mta+norm", 8) == 0) { + use = 1; + gotnorm = 1; + if (rhs[0] != '\0') + strcat(rhs, " "); + if ((p = index(vec[i], '=')) != (char *) 0 + && *(p+1) != NULL) + strcat(rhs, vec[i]); + else { + /* construct norm+mta= */ + strcat(rhs, "norm+mta="); + strcat(rhs, nonwildcard); + } + } else if (lexnequ (vec[i], "norm", 3) == 0) { + use = 1; + gotnorm = 1; + if (rhs[0] != '\0') + strcat(rhs, " "); + if ((p = index(vec[i], '=')) != (char *) 0 + && *(p+1) != NULL) + strcat(rhs, vec[i]); + else { + /* construct norm= */ + strcat(rhs, "norm="); + strcat(rhs, nonwildcard); + } + } else if (lexnequ (vec[i], "synonym", 7) == 0) { + gotnorm = 1; + use = 1; + if (rhs[0] != '\0') + strcat(rhs, " "); + strcat(rhs, vec[i]); + } else if (lexnequ (vec[i], "local", 5) == 0) { + use = 1; + if (rhs[0] != '\0') + strcat(rhs, " "); + strcat(rhs, vec[i]); + } else if (lexnequ (vec[i], "mta", 3) == 0) { + use = 1; + if (rhs[0] != '\0') + strcat(rhs, " "); + if ((p = index(vec[i], '=')) != (char *) 0 + && *(p+1) != NULL) + strcat(rhs, vec[i]); + else + /* construct norm= */ + mtaislhs = 1; + } else { + if (rhs[0] != '\0') + strcat(rhs, " "); + strcat(rhs, vec[i]); + } + } + bitmap = 0; + + if (gotnorm == 0) { + char *key; + /* add norm=lhs */ + if (mtaislhs == 1) + key = "norm+mta="; + else + key = "norm="; + if (rhs[0] != '\0') + strcat(rhs, " "); + strcat(rhs, key); + strcat(rhs, nonwildcard); + } else if (mtaislhs == 1) { + if (rhs[0] != '\0') + strcat(rhs, " mta="); + else + strcat(rhs, "mta="); + strcat(rhs, nonwildcard); + } + return use; +} + +/* --------------------- Static Routines ------------------------------- */ + + + +static void do_alias (alias, name, domain) +register char *alias, *name, *domain; +{ + register char *a, *d; + int dn = -1; + + a = &alias [strlen (alias) - 1]; + d = &domain [strlen (domain) - 1]; + for (; a != alias && *a == *d; a--, d--) + if (*a == '.') { + dn ++; + if (bitmap & (1 << dn)) + continue; + bitmap |= (1 << dn); + *a = '\00'; + if (strcmp (alias, "*") != 0) + printf ("%s:%s\n", alias, name); + *a = '.'; + } +} diff --git a/Tools/tables/abbrev/make b/Tools/tables/abbrev/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/abbrev/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/compat/Makefile b/Tools/tables/compat/Makefile new file mode 100644 index 0000000..13e2559 --- /dev/null +++ b/Tools/tables/compat/Makefile @@ -0,0 +1,66 @@ +# PP compatability routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/compat/RCS/Makefile,v 6.0 1991/12/18 20:33:35 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:33:35 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = +OBJS = +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + + + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = + +default: all + +all: ${PROGS} + +install: ; + +clean: tidy + rm -f *.temp $(OBJS) $(PROGS) + +tidy: + rm -f *.old *.BAK *.OUT + +depend: ; +define: ; + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/tables/compat/ali_o2n b/Tools/tables/compat/ali_o2n new file mode 100755 index 0000000..655b29f --- /dev/null +++ b/Tools/tables/compat/ali_o2n @@ -0,0 +1,38 @@ +#! /bin/sh + +# +# convert old style alias table to new style +# + +sed 's/:[ ]*/:/' $* | +awk ' +BEGIN { OFS = " " } +/^#/ || NF == 0 { print; next } +{ + n = split ($1, parts, ":") + if (n != 2) { + print "Bad line ", $0, "at", $NR | "cat 1>&2" + next + } + key = parts[1] + val1 = parts[2] + $1 = "" + if (val1 == "alias") + printf "%s:%s %s\n", key, val1, $0 + else if (val1 == "synonym") + printf "%s:%s %s\n", key, val1, $0 + else if (val1 == "822") + printf "%s:alias %s 822\n", key, $0 + else if (val1 == "x400") + printf "%s:alias %s x400\n", key, $0 + else if (val1 == "822-synonym") + printf "%s:synonym %s 822\n", key, $0 + else if (val1 == "x400-synonym") + printf "%s:synonym %s x400\n", key, $0 + else if (val1 == "x400-alias") + printf "%s:alias %s\n", key, $0 + else if (val1 == "822-synonym") + printf "%s:alias %s 822\n", key, $0 + else print "Unknown key", val1, "at", NR | "cat 1>&2" +} +' diff --git a/Tools/tables/compat/dom_o2n b/Tools/tables/compat/dom_o2n new file mode 100755 index 0000000..00e68aa --- /dev/null +++ b/Tools/tables/compat/dom_o2n @@ -0,0 +1,46 @@ +#! /bin/sh + +# +# convert old style domain table to new style +# + +sed 's/[ ]*:[ ]*/:/' $* | awk ' +/^#/ || NF == 0 { print; next } + { + star = minmax = "" + n = split($1, parts, ":") + if (n != 2) { + print "Illegal key/value", $1 | "cat 1>&2" + next + } + key = parts[1]; value = parts[2] + type = "mta=" + if (key != value) type= "synonym=" + if (NF >= 2) { + star = "*." + rstar = star + if ($2 != "1:*") { + n = split($2, parts, ":") + if (n == 1 && parts[1] == "*") + minmax = "" + else if (n == 1) { + if (parts[1] == 0) + rstar = star = "" + else + minmax = " max=" parts[1] + } + else { + minmax=" max=" parts[2] + if (parts[1] != 1) + minmax = minmax " min=" parts[1] + } + } + } + if (NF == 3) + type = "local " type + else if (NF == 4) + type = "local=" $4 " " type + if (key == value) rstar = "" + print star key ":" type rstar value minmax +} +' diff --git a/Tools/tables/compat/make b/Tools/tables/compat/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/compat/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/compat/que_o2n b/Tools/tables/compat/que_o2n new file mode 100755 index 0000000..3fba80d --- /dev/null +++ b/Tools/tables/compat/que_o2n @@ -0,0 +1,31 @@ +#! /bin/sh + +# +# que_o2n - change queue format from old to new format. +# +# Usage: que_o2n queue-directory +# + +#echo=echo +case $# in + 1) ;; + *) echo "Usage: $0 directory" >&2; exit 1;; +esac + +if [ ! -d "$1" ] +then + echo "$1 is not a directory" >&2; exit 1 +fi + +cd $1 +if [ ! -d addr -o ! -d msg -o ! -d tmp ] +then echo "$1 does not look like a PP directory" >&2; exit 1 +fi +$echo mv tmp tmp.old +for i in `cd addr; find . -name 'msg.*' -print` +do + $echo mv addr/$i msg/$i/addr + $echo mv msg/$i $i +done +$echo rm -rf tmp.old +$echo rmdir msg addr diff --git a/Tools/tables/domain/Makefile b/Tools/tables/domain/Makefile new file mode 100644 index 0000000..50e741f --- /dev/null +++ b/Tools/tables/domain/Makefile @@ -0,0 +1,61 @@ +# t-getdomain = test getdomain +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/domain/RCS/Makefile,v 6.0 1991/12/18 20:33:42 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:33:42 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = t-getdomain.c +OBJS = t-getdomain.o + +HEADERS = ../../../h +LIBPP = ../../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xt-getdomain + +xt-getdomain: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) \ + $(LIBPP) $(LIBSYS) + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old xt-getdomain + +lint: l-targets + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Tools/tables/domain/make b/Tools/tables/domain/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/domain/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/domain/t-getdomain.c b/Tools/tables/domain/t-getdomain.c new file mode 100644 index 0000000..516d40b --- /dev/null +++ b/Tools/tables/domain/t-getdomain.c @@ -0,0 +1,108 @@ +/* t-getdomain.c: test results of tb_getdomain */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/tables/domain/RCS/t-getdomain.c,v 6.0 1991/12/18 20:33:42 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/tables/domain/RCS/t-getdomain.c,v 6.0 1991/12/18 20:33:42 jpo Rel $ + * + * $Log: t-getdomain.c,v $ + * Revision 6.0 1991/12/18 20:33:42 jpo + * Release 6.0 + * + */ + +#include "util.h" +#include "chan.h" +#include "table.h" + +main (argc, argv) +int argc; +char *argv[]; +{ + char buf[BUFSIZ]; + extern int optind; + int opt, dmnorder = CH_USA_ONLY; + char *table = NULLCP; + extern char *optarg; + + sys_init(argv[0]); + while ((opt = getopt (argc, argv, "bl0123t:T:")) != EOF) + switch (opt) { + case 'l': + dmnorder = CH_USA_PREF; + break; + case 'b': + dmnorder = CH_UK_PREF; + break; + case '0': + case '1': + case '2': + case '3': + dmnorder = opt - '0'; + break; + case 't': + case 'T': + table = optarg; + break; + default: + printf("usage: %s [-b] [-l] [-0] [-1] [-2] [-3]\n", + argv[0]); + exit(1); + break; + } + + argc -= optind; + argv += optind; + + if (table != NULLCP) { + Table *Domain; + if ((Domain = tb_nm2struct("domain")) == NULLTBL) { + printf("No table 'domain' defined\n"); + exit(1); + } + Domain->tb_flags = TB_LINEAR; + Domain->tb_file = table; + } + if (argc == 0) + while (gets(buf) != NULL) { + char *ix = &(buf[0]); + while (ix != NULLCP && + *ix != '\0' + && isspace(*ix)) ix++; + if (ix != NULLCP && *ix != '\0') + get_domain(buf, dmnorder); + } + else + while (argc--) + get_domain(*argv++, dmnorder); + exit(0); +} + +get_domain(dom, order) +char *dom; +int order; +{ + char norm[BUFSIZ], chan[BUFSIZ], *subdom; + + if (tb_getdomain(dom, chan, norm, order, &subdom) != OK) + printf("Domain '%s' unknown\n", + dom); + else { + printf("Input '%s'\nNormalised '%s'\n", + dom, norm); + if (subdom != NULLCP) { + printf("Local sub hub '%s'\n", + subdom); + free(subdom); + } + if (chan[0] != '\0') + printf("Channel key '%s'\n", + chan); + else + printf("No channel key\n"); + } + printf("\n"); +} + diff --git a/Tools/tables/make b/Tools/tables/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Tools/tables/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/pp-rfc987/Makefile b/Tools/tables/pp-rfc987/Makefile new file mode 100644 index 0000000..5d7cfb2 --- /dev/null +++ b/Tools/tables/pp-rfc987/Makefile @@ -0,0 +1,71 @@ +# PP specific routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/pp-rfc987/RCS/Makefile,v 6.0 1991/12/18 20:34:52 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:34:52 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = +OBJS = +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + + + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = + +default: all + +progs: ${PROGS} + +all: ${PROGS} + +rfc2or: awk.rfc2or +or2rfc: awk.or2rfc + +install: ; + +clean: tidy + rm -f *.temp $(OBJS) $(PROGS) + +tidy: + rm -f *.old *.BAK *.OUT + +depend: ; +define: ; + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/tables/pp-rfc987/awk.or2rfc b/Tools/tables/pp-rfc987/awk.or2rfc new file mode 100755 index 0000000..a8128c5 --- /dev/null +++ b/Tools/tables/pp-rfc987/awk.or2rfc @@ -0,0 +1,62 @@ +#!/bin/sh +# +# +# awk.or2rfc - is an awk program that reformats the +# the PP tables into the RFC-987 International ones. +# +# +# syntax : awk.or2rfc {first | multi} input-table +# +###################################################################### + +AWK=/usr/bin/awk + +FILEIN=$1 +FILETEMP=or2rfc.temp + +if [ -z "$FILEIN" ] +then + echo " " + echo "Usage: awk.or2rfc input-table" + echo " " + exit 1 +fi + +grep "^C" $FILEIN >$FILETEMP +grep "^ADMD" $FILEIN >>$FILETEMP +grep "^PRMD" $FILEIN >>$FILETEMP +grep "^O" $FILEIN | sort -u >>$FILETEMP + + + +#---------------------- Start of the awk routines --------------------------# + + + +$AWK <$FILETEMP ' +BEGIN { + + print("#") + print("#=============================================================================") + print("#======================================================= United Kingdom ======") + print("# Last update: 90.02.01") + print("# Responsible: John Seymour ") + print("#") + print("# Beware of the quoted dots in this table!") + print("#") + FS =":" + } + +/^#.*/ { + continue + } + { + printf("%s#%s#\n", $1, $2) + continue + } + +END {} + +' + +rm $FILETEMP diff --git a/Tools/tables/pp-rfc987/awk.rfc2or b/Tools/tables/pp-rfc987/awk.rfc2or new file mode 100755 index 0000000..87bb783 --- /dev/null +++ b/Tools/tables/pp-rfc987/awk.rfc2or @@ -0,0 +1,57 @@ +#!/bin/sh +# +# +# awk.rfc2or - is an awk program that reformats the +# PP tables into the RFC-987 International ones. +# +# +# syntax : awk.rfc2or { first | multi } input-table +# +###################################################################### + + +AWK=/usr/bin/awk + +FILEIN=$1 +FILEOUT=rfc2or.temp + +if [ -z "$FILEIN" ] +then + echo " " + echo "Usage: awk.rfc2or input-table" + echo " " + exit 1 +fi + + +grep ":C" $FILEIN > $FILEOUT +grep ":ADMD" $FILEIN >> $FILEOUT +grep ":PRMD" $FILEIN >> $FILEOUT +grep ":O" $FILEIN | sort -u >> $FILEOUT + + + +#---------------------- Start of the awk routines --------------------------# + + +$AWK < $FILEOUT ' +BEGIN { + print("#") + print("#=============================================================================") + print("#======================================================= United Kingdom ======") + print("# Last update: 90.02.01") + print("# Responsible: John Seymour ") + print("#") + print("# Beware of the quoted dots in this table!") + print("#") + FS =":" + } +/^#.*/ { + continue + } + { + printf("%s#%s#\n", $1, $2) + continue + } +END {} +' diff --git a/Tools/tables/pp-rfc987/make b/Tools/tables/pp-rfc987/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/pp-rfc987/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/rfc987-pp/Makefile b/Tools/tables/rfc987-pp/Makefile new file mode 100644 index 0000000..be65df2 --- /dev/null +++ b/Tools/tables/rfc987-pp/Makefile @@ -0,0 +1,78 @@ +# PP specific routines +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/rfc987-pp/RCS/Makefile,v 6.0 1991/12/18 20:35:14 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:35:14 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = +OBJS = +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + + + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = + +default: all + +progs: ${PROGS} + +all: ${PROGS} + +rfc987: awk.rfc987 + +install: inst-rfc987 +inst-rfc987: $(TBLDIR)/awk.rfc987 +$(TBLDIR)/awk.rfc987: awk.rfc987 + -$(BACKUP) $@ zawk.rfc987 + rm -f $@ + $(INSTALL) awk.rfc987 $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + @echo "awk.rfc987 script installed normally"; echo "" + +clean: tidy +# -rm -f $(OBJS) $(PROGS) + +tidy: + rm -f *.old *.BAK *.OUT + +depend: ; +define: ; + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/tables/rfc987-pp/awk.rfc987.pac b/Tools/tables/rfc987-pp/awk.rfc987.pac new file mode 100755 index 0000000..f18c094 --- /dev/null +++ b/Tools/tables/rfc987-pp/awk.rfc987.pac @@ -0,0 +1,57 @@ +#!/bin/sh +# +# +# awk.rfc987 - is an awk program that reformats the +# RFC-987 International tables into PP ones. +# +# +# syntax : awk.rfc987 input-table +# +###################################################################### + + +AWK=/usr/bin/awk + +FILE=$1 + +if [ -z "$FILE" ] +then + echo " " + echo "Usage: awk.rfc987 input-table" + echo " " + exit 1 +fi + + + + + +#---------------------- Start of the awk routines --------------------------# + + +$AWK <$FILE ' +BEGIN { + FS ="#" + } +/^#.*/ { + print $0 + next + } + { + if ((n = split($1, array, ":")) > 1) { + for (i = 1; i < n; i++) + printf("%s\:",array[i]) + printf("%s", array[n]); + } else + printf("%s", $1) + + printf(":"); + + printf("%s", $2) + for (i = 3; i < NF; i++) + printf("#%s", $i); + printf("\n"); + next + } +END {} +' diff --git a/Tools/tables/rfc987-pp/make b/Tools/tables/rfc987-pp/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/rfc987-pp/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/tjoin/Makefile b/Tools/tables/tjoin/Makefile new file mode 100644 index 0000000..2877de6 --- /dev/null +++ b/Tools/tables/tjoin/Makefile @@ -0,0 +1,99 @@ +# tjoin - table join 11/04/89 jct +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/Makefile,v 6.0 1991/12/18 20:35:29 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:35:29 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = tjoin1.c tjoin2.c tjoin3.c lex.c tjoin.c +OBJS = tjoin1.o tjoin2.o tjoin3.o lex.o tjoin.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../../h +INCLUDE = -I$(HEADERS) +CFLAGS = $(CCOPTIONS) $(LCF) $(INCLUDE) +LDFLAGS = $(LDOPTIONS) $(LLF) +YFLAGS = -d +LLFLAGS = $(LINTFLAGS) $(INCLUDE) +LINTLIBS = ../../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + + +PROGS = xtjoin + +default: all +progs: ${PROGS} +all: ${PROGS} + +tjoin: xtjoin +xtjoin: $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -ll -o $@ $(LIBSYS) + +lex.o: tjoin.c y.tab.h + +y.tab.h: tjoin.y; + +lint: l-tjoin +l-tjoin: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +install: inst-dir inst-tjoin +inst-dir: $(TOOLDIR) +inst-tjoin: $(TOOLDIR)/tjoin +$(TOOLDIR)/tjoin: xtjoin + -$(BACKUP) $@ zxtjoin + rm -f $@ + $(INSTALL) xtjoin $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "tjoin tool installed normally"; echo "" + + +clean: tidy + rm -f $(OBJS) lex.c tjoin.c y.tab.h +tidy: + rm -f core *.old *.BAK *.OUT $(PROGS) zx* + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +define: + $(DEFINE) Makefile + + +############################################################ +# +# End of building rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +tjoin1.o: tjoin1.c +tjoin1.o: ../../../h/tjoin.h +tjoin2.o: tjoin2.c +tjoin2.o: ../../../h/tjoin.h +tjoin3.o: tjoin3.c +tjoin3.o: ../../../h/tjoin.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Tools/tables/tjoin/lex.l b/Tools/tables/tjoin/lex.l new file mode 100644 index 0000000..58ec7fe --- /dev/null +++ b/Tools/tables/tjoin/lex.l @@ -0,0 +1,79 @@ +%{ + + +#include "y.tab.h" + +#ifdef input +#undef input +#endif +# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):bwgetc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) + +#define HEAP 30 /* cleans the heap after a YACC err */ +#define NULL 0 + +extern YYSTYPE yylval; +extern int Debug; +extern char *av0; +extern char *strdup(); + +static char buffer [1000]; +static char *buffptr = 0; + +char **memptr, *heapstore [HEAP]; + +%} + +%% + +#.*\n ; +[-a-zA-Z0-9\.]* { + yylval.str = strdup (yytext); + return (STRING); + } + +\n { + return ('\n'); + } + +[,:()] { + return (yytext [0]); + } + +. ; + +%% + + + +bwgetc (fp) +FILE *fp; +{ + if (buffptr == 0 || *buffptr == '\00') { + if (fgets (&buffer [0], 999, fp) == NULL) + return (EOF); + buffptr = &buffer[0]; + memptr = &heapstore[0]; + *memptr = NULL; + } + return (*buffptr++); +} + +crapline() +{ + char **p; + int len; + + len = strlen (&buffer[0]); + if (len < 0) + --len; + + buffer [len] = '\00'; + + for (p = &heapstore[0]; *p != NULL; p++) { + if ((Debug & 1) != 0) + printf ("Free %s - CrapLine\n", p); + free (*p); + p = NULL; + } + fprintf (stderr, "*** Error [%s] line %d\n", &buffer [0], yylineno - 1); +} diff --git a/Tools/tables/tjoin/make b/Tools/tables/tjoin/make new file mode 100755 index 0000000..c63ff19 --- /dev/null +++ b/Tools/tables/tjoin/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../../Make.defs -f Makefile ${1+"$@"} diff --git a/Tools/tables/tjoin/tjoin.y b/Tools/tables/tjoin/tjoin.y new file mode 100644 index 0000000..b7694c3 --- /dev/null +++ b/Tools/tables/tjoin/tjoin.y @@ -0,0 +1,115 @@ +%union { + char *str; +} + +%token STRING + +%type host +%% +file : line + | file line + ; + +line : '\n' + | STRING ':' hostlist '\n' { + /* Direct Connet or AR hosts */ + if (CheckHost ($1) != 0) + StoreHost ($1); + else + FreeHostInfo (HostList); + free ($1); + HostList = NULL; + } + | STRING ':' '(' chanlist ')' '\n' { + if (CheckChan (ChanList) != 0) + StoreChans ($1); + else + FreeChanInfo (ChanList); + free ($1); + ChanList = NULL; + } + | error '\n' { + crapline (); + HostList = NULL; + ChanList = NULL; + } + ; + +hostlist : host { + StartHostList ($1); + ChanList = NULL; + } + | hostlist ',' host { + AddToHostList ($3); + ChanList = NULL; + } + ; + +host : STRING '(' ')' { + /* This is an Application Relay */ + $$ = $1; + } + | STRING '(' chanlist ')' { + /* This is a Direct Connect */ + $$ = $1; + } + ; + +chanlist : STRING { + StartChanList ($1); + } + | chanlist ',' STRING { + AddToChanList ($3); + } + ; + +%% + +#include +#include "tjoin.h" + +extern int yylineno; + +int PrintNode (), CheckARs (); +SBUFF *InitStringStore (); + +char *av0, *MyName; +HOST *HostList = NULL; /* Stores Host info on input line basis */ +CHAN *ChanList = NULL; /* Stores Chan info on input host basis */ +CHAN *ValidChanList = NULL; +MTA *MtaTree = NULL; /* Root of in core database */ +SBUFF *ARStringStore, *HostStringStore; +int Debug = 0, PrintRoute = 0, DirectFirst = 0, ComplexOutput = 0; + +main (argc, argv) +int argc; +char *argv []; +{ + register int i; + + av0 = argv [0]; + MyName = NULL; + for (i = 1; i < argc; i++) { + if (*argv [i] == '-') + DoFlag (&argv [i][1]); + else + if (MyName == NULL) + MyName = argv [i]; + else + DefineChan (argv [i]); + } + if (ValidChanList == NULL) + Usage (); + ARStringStore = InitStringStore (); + HostStringStore = InitStringStore (); + yyparse (); + WalkTree (MtaTree, CheckARs); + /* + * Now that all AR names point to MTA structs - Zap space used + * to store names. + */ + FreeStringStore (ARStringStore); + if (Debug == 2) DebugTree (MtaTree, 0); + WalkTree (MtaTree, PrintNode); + exit (0); +} diff --git a/Tools/tables/tjoin/tjoin1.c b/Tools/tables/tjoin/tjoin1.c new file mode 100644 index 0000000..d8413bd --- /dev/null +++ b/Tools/tables/tjoin/tjoin1.c @@ -0,0 +1,200 @@ +/* tjoin1.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin1.c,v 6.0 1991/12/18 20:35:29 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin1.c,v 6.0 1991/12/18 20:35:29 jpo Rel $ + * + * $Log: tjoin1.c,v $ + * Revision 6.0 1991/12/18 20:35:29 jpo + * Release 6.0 + * + */ + + + +#include +#include "tjoin.h" + +extern char *av0; +extern int yylineno, Debug; +extern HOST *HostList; +extern CHAN *ChanList; +extern char *FastInChanList(); + + + +FreeChanInfo (list) +register CHAN *list; +{ + register CHAN *startlist = list, + *chptr; + + for (; list != NULL; list = chptr) { + chptr = list -> ch_next; + if (Debug == 1) + printf ("FreeChanInfo %s\n", list->ch.name); + if (list) + free ((char *)list); + } + + startlist = NULL; +} + + + +RejectHost (host) +register HOST *host; +{ + register CHAN *c1; + + fprintf (stderr, +"%s: Channel present, but LHS & RHS hosts differ at line %d\n", + av0, yylineno - 1); + + for (c1 = host -> hst_chan; c1 != NULL; c1 = c1 -> ch_next) { + if (Debug == 1) + printf ("Free %x - RejectHost ChanName\n", c1->ch.name); + + if (c1 -> ch.name) { + free (c1 -> ch.name); + c1 -> ch.name = NULL; + } + } + + if (Debug == 1) + printf ("Free %x - RejectHost HostName\n", host -> hst_name); + + if (host -> hst_name) { + free (host -> hst_name); + host -> hst_name = NULL; + } +} + + +StartChanList (str) +char *str; +{ + if (ChanList != NULL) { + fprintf (stderr, "%s: StartChanList - ChanList not NULL\n", + av0); + exit (1); + } + + if ((ChanList = (CHAN *) malloc (sizeof (CHAN))) == NULL) { + fprintf (stderr, "%s: StartChanList - No Memory\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("StartChanList - %s\n", str ? str : "null"); + + bzero ((char *)ChanList, sizeof(*ChanList)); + ChanList -> ch.name = str; +} + + +AddToChanList (str) +char *str; +{ + register CHAN *chan; + + if ((chan = (CHAN *) malloc (sizeof (CHAN))) == NULL) { + fprintf (stderr, "%s: AddToChanList - No Memory\n"); + exit (1); + } + + if (Debug == 1) + printf ("AddToChanList - %s\n", str ? str : "null"); + + bzero ((char *)chan, sizeof(*chan)); + chan -> ch_next = ChanList; + ChanList = chan; + chan -> ch.name = str; +} + + +StartHostList (str) +char *str; +{ + if (HostList != NULL) { + fprintf (stderr, "%s: StartHostList - HostList not NULL\n", + av0); + exit (1); + } + + if ((HostList = (HOST *) malloc (sizeof (HOST))) == NULL) { + fprintf (stderr, "%s: StartHostList - No Memory\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("StartHostList - %s\n", str ? str : "null"); + + bzero ((char *)HostList, sizeof(*HostList)); + HostList -> hst_name = str; + HostList -> hst_chan = ChanList; +} + + +AddToHostList (str) +char *str; +{ + register HOST *host; + + if ((host = (HOST *) malloc (sizeof (HOST))) == NULL) { + fprintf (stderr, "%s: AddToHostList - No Memory\n"); + exit (1); + } + + if (Debug == 1) + printf ("AddToHostList - %s\n", str ? str : "null"); + + bzero ((char *)host, sizeof(*host)); + host -> hst_next = HostList; + HostList = host; + host -> hst_name = str; + host -> hst_chan = ChanList; +} + + +char *FastInChanList (list, name) +register CHAN *list; +char *name; +{ + if (name == NULL) + return (NULL); + for (; list != NULL; list = list -> ch_next) + if (list -> ch.name == name) + return (list -> ch.name); + return (NULL); +} + + +char *InChanList (list, name) +register CHAN *list; +char *name; +{ + if (name == NULL) + return (NULL); + for (; list != NULL; list = list -> ch_next) + if (strcmp (list -> ch.name, name) == 0) + return (list -> ch.name); + return (NULL); +} + + +CHAN *InsertChan (list, item) +register CHAN *list, *item; +{ + register CHAN *c1; + + if (list == NULL) + return (item); + for (c1 = list; c1 -> ch_next != NULL; c1 = c1 -> ch_next) + continue; + c1 -> ch_next = item; + return (list); +} diff --git a/Tools/tables/tjoin/tjoin2.c b/Tools/tables/tjoin/tjoin2.c new file mode 100644 index 0000000..1099b5a --- /dev/null +++ b/Tools/tables/tjoin/tjoin2.c @@ -0,0 +1,599 @@ +/* tjoin2.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin2.c,v 6.0 1991/12/18 20:35:29 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin2.c,v 6.0 1991/12/18 20:35:29 jpo Rel $ + * + * $Log: tjoin2.c,v $ + * Revision 6.0 1991/12/18 20:35:29 jpo + * Release 6.0 + * + */ + + + +#include +#include "tjoin.h" + +extern char *av0; +extern int Debug, PrintRoute, DirectFirst, ComplexOutput; +extern MTA *MtaTree; +extern CHAN *ValidChanList; +extern char *FastInChanList(); + +static MTST *MtaStore = NULL; +static CHST *ChanStore = NULL; + +static char *MailRoute(); +static void DoDomainOutput(), PrintOutList(), PrintThing(), + FreePrintList(); +static int HighestCost(), CountAts(); + +PRINT *DoChanOrder(), *InsertPrint(), *DeleteItem(); + + +/* ------------------------ Begin Routines ------------------------------- */ + + +WalkTree (tree, func) +register MTA *tree; +int (*func)(); +{ + if (tree == NULL) + return; + if (tree -> mta_left != NULL) + WalkTree (tree -> mta_left, func); + + (*func) (tree); + + if (tree -> mta_right != NULL) + WalkTree (tree -> mta_right, func); +} + + +DebugTree (tree, indent) +register MTA *tree; +int indent; +{ + int i; + + if (tree == NULL) + return; + + if (tree -> mta_left != NULL) + DebugTree (tree -> mta_left, indent - 3); + + for (i=0; i < indent; i++) printf (" "); + printf ("%s\n", tree -> mta_name ? tree -> mta_name : "null"); + fflush (stdout); + + if (tree -> mta_right != NULL) + DebugTree (tree -> mta_right, indent + 3); +} + + + +PrintNode (node) +register MTA *node; +{ + register PRINT *print, *list2, *p2, *p3; + register int cost, i; + + if (node == NULL) + return; + + if (Debug == 1) + printf ("PrintNode - %s\n", + node -> mta_name ? node -> mta_name : "null"); + + if (node -> mta_domain != NULL) { + DoDomainOutput (node); + return; + } + + if ((print = DoChanOrder (node)) == NULL) + return; + + if (DirectFirst != 0) { + /* Sort List2 by cost (Hop Count) */ + list2 = NULL; + cost = HighestCost (print); + for (i = 0; i <= cost; i++) + for (p2 = print; p2 != NULL; p2 = p3) { + p3 = p2 -> pr_next; + if (p2 -> pr_cost == i) { + print = DeleteItem (print, p2); + list2 = InsertPrint (list2, p2); + } + } + print = list2; + } + + PrintOutList (print, node -> mta_name); + FreePrintList (print); +} + +MTA *InsertMta (tree, mta) +register MTA *tree, *mta; +{ + register int x; + + if (tree == NULL) + return (mta); + + if (Debug == 1) + printf ("InsertMTA - %s %s\n", + tree -> mta_name ? tree -> mta_name : "null", + mta -> mta_name ? mta -> mta_name : "null"); + + if ((x = strcmp (mta -> mta_name, tree -> mta_name)) == 0) { + /* --- Found the same node - should not happen --- */ + fprintf (stderr, "%s: InsertMta - Fatal Error\n", av0); + exit (1); + } + if (x < 0) + tree -> mta_left = InsertMta (tree -> mta_left, mta); + else + tree -> mta_right = InsertMta (tree -> mta_right, mta); + return (tree); +} + + + +MTA *NameToMta (name) +char *name; +{ + register MTA *mta; + register int x; + + if (Debug == 1) + printf ("NameToMTA - %s\n", name ? name : "null"); + + mta = MtaTree; + + while (mta != NULL) { + if ((x = strcmp (name, mta -> mta_name)) == 0) + break; + if (x < 0) + mta = mta -> mta_left; + else + mta = mta -> mta_right; + } + return (mta); +} + + +CHAN *GetChan() +{ + register CHST *chst; + register CHAN *chan; + + if (ChanStore == NULL) { + /* Starting up */ + if ((ChanStore = (CHST *) malloc (sizeof (CHST))) == NULL) { + fprintf (stderr, "%s: GetChan - No Memory [1]\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("GetChan Start - Malloc %x\n", ChanStore); + + bzero ((char *)ChanStore, sizeof(*ChanStore)); + } + + + if (ChanStore -> chs_index >= CHANSTORESIZE) { + /* Get another bunch */ + if ((chst = (CHST *) malloc (sizeof (CHST))) == NULL) { + fprintf (stderr, "%s: GetChan - No Memory [2]\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("GetChan GetBuff - Malloc %x\n", chst); + + bzero ((char *)chst, sizeof(*chst)); + chst -> chs_next = ChanStore; + ChanStore = chst; + } + + chan = &ChanStore -> chs_buffer [ChanStore -> chs_index++]; + chan -> ch_next = NULL; + chan -> ch.name = NULL; + return (chan); +} + + +SBUFF *InitStringStore() +{ + register SBUFF *str; + + if ((str = (SBUFF *) malloc (sizeof (SBUFF))) == NULL) { + fprintf (stderr, "%s: InitStringStore - No Memory\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("InitStringStore - Malloc %x\n", str); + + bzero ((char *)str, sizeof(*str)); + return (str); +} + + + +char *StoreStr (store, string) +register SBUFF *store; +char *string; +{ + register int length; + char *ptr; + + if (Debug == 1) + printf ("StoreStr - %s\n", string ? string : "null"); + + if (string == NULL || *string == '\0') + return ((char *)0); + + length = strlen (string) + 1; + + if (length > STRINGSTORESIZE) { + /* This is FATAL */ + fprintf (stderr, "%s: StoreStr - Can't store %s - Ignored\n", + av0, string); + exit (1); + } + + while (length > STRINGSTORESIZE - store -> str_index) { + if (store -> str_next != NULL) { + store = store -> str_next; + continue; + } + + store -> str_next = (SBUFF *) malloc (sizeof (SBUFF)); + + if (store -> str_next == NULL) { + fprintf (stderr, "%s: StoreStr - No Memory\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("Malloc %x - StoreStr\n", store -> str_next); + + store = store -> str_next; + bzero ((char *)store, sizeof(*store)); + break; + } + + ptr = &store -> str_buffer [store -> str_index]; + (void) strcpy (ptr, string); + store -> str_index += length; + return (ptr); +} + + + +MTA *GetMta() +{ + register MTST *mtst; + register MTA *mta; + + if (MtaStore == NULL) { + /* Starting up */ + if ((MtaStore = (MTST *) malloc (sizeof (MTST))) == NULL) { + fprintf (stderr, "%s: GetMta - No Memory [1]\n", av0); + exit (1); + } + + if (Debug == 1) + printf ("GetMta Start - Malloc %x \n", MtaStore); + + bzero ((char *)MtaStore, sizeof(*MtaStore)); + } + + if (MtaStore -> mts_index >= MTASTORESIZE) { + /* Get another bunch */ + if ((mtst = (MTST *) malloc (sizeof (MTST))) == NULL) { + fprintf (stderr, "%s: GetMta - No Memory [2]\n", av0); + exit (1); + } + if (Debug == 1) + printf ("GetMta GetBuffer - Malloc %x \n", mtst); + + bzero ((char *)mtst, sizeof(*mtst)); + mtst -> mts_next = MtaStore; + MtaStore = mtst; + } + + mta = &MtaStore -> mts_buffer [MtaStore -> mts_index++]; + mta -> mta_left = NULL; + mta -> mta_right = NULL; + mta -> mta_chan = NULL; + mta -> mta_arlist = NULL; + mta -> mta_domain = NULL; + mta -> mta_name = NULL; + return (mta); +} + + + +FreeStringStore (str) +register SBUFF *str; +{ + register SBUFF *startstr = str, + *s2; + + if (Debug == 1) + printf ("FreeStringStore - %x\n", str); + + for (; str != NULL; str = s2) { + s2 = str -> str_next; + if (str) free ((char *)str); + } + + startstr = NULL; +} + + + +/* ------------------------ Static Routines ------------------------------- */ + + + + + +static void DoDomainOutput (node) +register MTA *node; +{ + register CHAN *chan; + register int flag = 0; + + if (Debug == 1) + printf ("DoDomainOutput - %s\n", + node -> mta_name ? node -> mta_name : "null"); + + printf ("%s:", node -> mta_name); + + if (ComplexOutput != 0) + printf ("("); + + for (chan = ValidChanList; chan != NULL; chan = chan -> ch_next) + if (FastInChanList (node->mta_domain, chan->ch.name) != NULL) { + if (flag == 1) + printf (","); + if (ComplexOutput == 0) + printf ("(%s)", chan -> ch.name); + else + printf ("%s", chan -> ch.name); + flag = 1; + } + + if (ComplexOutput != 0) + printf (")"); + + printf ("\n"); +} + + +static int HighestCost (print) +register PRINT *print; +{ + register int cost; + + cost = 0; + for (; print != NULL; print = print -> pr_next) + if (print -> pr_cost > cost) + cost = print -> pr_cost; + return (cost); +} + + +static void PrintOutList (print, mtaname) +register PRINT *print; +register char *mtaname; +{ + register char *last; + + if (Debug == 1) + printf ("PrintOutList - %s\n", mtaname ? mtaname : "null"); + + printf ("%s:", mtaname); + + last = ""; + + for (; print != NULL; print = print -> pr_next) { + + if (PrintRoute == 0) { + PrintThing (print -> pr_nexthop, last); + if (ComplexOutput != 0) + last = print -> pr_nexthop; + } + else { + PrintThing (&print -> pr_relay [0], last); + if (ComplexOutput != 0) + last = &print -> pr_relay [0]; + } + + printf ("%s", print -> pr_chan); + + if (print -> pr_next == NULL) + if (ComplexOutput == 0) + printf (")\n"); + else + printf (")\n"); + else + if (ComplexOutput == 0) + printf ("),"); + } +} + + + +static void PrintThing (host, last) +register char *host, *last; +{ + if (Debug == 1) + printf ("PrintThing - %s\n", host ? host : "null"); + + if (ComplexOutput == 0) + printf ("%s(", host); + else + if (*last == '\00') + printf ("%s(", host); + else + if (strcmp (last, host) != 0) + printf ("),%s(", host); + else + printf (","); +} + + +static void FreePrintList (print) +register PRINT *print; +{ + register PRINT *startprint = print, + *p2; + + for (; print != NULL; print = p2) { + p2 = print -> pr_next; + if (print) free ((char *)print); + } + + startprint = NULL; +} + + +static PRINT *DoChanOrder (node) +register MTA *node; +{ + register CHAN *chan; + char *ptr, buff [LOADS]; + PRINT *print, *p2; + int space; + if (Debug == 1) + printf ("DoChanOrder - %s\n", + node -> mta_name ? node -> mta_name : "null"); + + print = NULL; + + for (chan = ValidChanList; chan != NULL; chan = chan -> ch_next) { + space = sizeof(buff); + if ((ptr = MailRoute (node, chan, &buff [0], &space)) != NULL) { + if ((p2 = (PRINT *) malloc (sizeof (PRINT))) == NULL) { + fprintf (stderr, "%s: DoChanOrder - No ", av0); + fprintf (stderr, "memory\n"); + exit (1); + } + + bzero ((char *)p2, sizeof(*p2)); + (void) strcpy (&p2 -> pr_relay [0], &buff [1]); + p2 -> pr_nexthop = ptr; + p2 -> pr_chan = chan -> ch.name; + p2 -> pr_cost = CountAts (&buff [1]); + print = InsertPrint (print, p2); + } + } + return (print); +} + + +static int CountAts (str) +register char *str; +{ + register int count; + + if (str == NULL) + return (0); + count = 0; + for (; *str != '\00'; str++) + if (*str == '@') + count++; + return (count); +} + + + +static PRINT *DeleteItem (list, item) +register PRINT *list, *item; +{ + register PRINT *p1; + + if (Debug == 1) printf ("DeleteItem\n"); + + if (list == NULL) { + fprintf (stderr, "%s: DeleteItem - List is NULL\n", av0); + return (NULL); + } + + if (list == item) { + p1 = list -> pr_next; + list -> pr_next = NULL; + return (p1); + } + + for (p1 = list; p1 -> pr_next != NULL; p1 = p1 -> pr_next) + if (item == p1 -> pr_next) { + p1 -> pr_next = item -> pr_next; + item -> pr_next = NULL; + return (list); + } + + fprintf (stderr, "%s: DeleteItem - Item not in List\n", av0); + return (list); +} + + +static PRINT *InsertPrint (list, item) +register PRINT *list, *item; +{ + register PRINT *p1; + + if (Debug == 1) printf ("InsertPrint\n"); + + if (list == NULL) + return (item); + for (p1 = list; p1 -> pr_next != NULL; p1 = p1 -> pr_next) + continue; + p1 -> pr_next = item; + return (list); +} + + + +static char *MailRoute (mta, chan, str, space) +register MTA *mta; +register CHAN *chan; +register char *str; +int *space; +{ + register CHAN *c1; + register MTA *m1; + register char *ptr; + + if (Debug == 1) printf ("MailRoute\n"); + + if ((*space -= ((int)strlen(mta -> mta_name) + 1)) < 1) { + fprintf(stderr, + "Possible AR loop detected containing mta '%s' (buffer overrun)\n", + mta->mta_name); + return (NULL); + } + + (void) sprintf (str, "@%s", mta -> mta_name); + + if (FastInChanList (mta -> mta_chan, chan -> ch.name) != NULL) + return (mta -> mta_name); + + for (c1 = mta -> mta_arlist; c1 != NULL; c1 = c1 -> ch_next) { + if ((m1 = c1 -> ch.mta) == NULL) + continue; + if ((ptr = MailRoute (m1, chan, &str [strlen (str)], space)) != NULL) + return (ptr); + } + return (NULL); +} + + diff --git a/Tools/tables/tjoin/tjoin3.c b/Tools/tables/tjoin/tjoin3.c new file mode 100644 index 0000000..aa6f708 --- /dev/null +++ b/Tools/tables/tjoin/tjoin3.c @@ -0,0 +1,498 @@ +/* tjoin3.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin3.c,v 6.0 1991/12/18 20:35:29 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Tools/tables/tjoin/RCS/tjoin3.c,v 6.0 1991/12/18 20:35:29 jpo Rel $ + * + * $Log: tjoin3.c,v $ + * Revision 6.0 1991/12/18 20:35:29 jpo + * Release 6.0 + * + */ + + + +#include +#include "tjoin.h" + +extern int yylineno; + +int PrintNode(), CheckARs(); +SBUFF *InitStringStore(); +MTA *NameToMta(), *InsertMta(), *GetMta(); +CHAN *InsertChan(), *GetChan(); +char *StoreStr(), *InChanList(); + +extern char *av0, *MyName; +extern HOST *HostList; +extern CHAN *ChanList; +extern CHAN *ValidChanList; +extern MTA *MtaTree; +extern SBUFF *ARStringStore, *HostStringStore; +extern int Debug, PrintRoute, DirectFirst, ComplexOutput; + + + + +/* ---------------------- Begin Routines --------------------------------- */ + + + +Usage() +{ + fprintf (stderr, "Usage: %s [flags] Hostname ChannelList\n", av0); + fprintf (stderr, "\t-r\tPrint Routes\n"); + fprintf (stderr, "\t-d\tMost Direct Route First\n"); + fprintf (stderr, "\t-c\tComplex Output\n"); + fprintf (stderr, "\t-h\tThis Message\n"); + exit (1); +} + + + +DoFlag (str) +register char *str; +{ + for (; *str != '\00'; str++) { + + if (*str == 'h') + Usage(); + + if (*str == 'd') { + DirectFirst = 1; + continue; + } + + if (*str == 'c') { + ComplexOutput = 1; + continue; + } + + if (*str == 'r') { + PrintRoute = 1; + continue; + } + + fprintf (stderr, "%s: Unknown flag %c\n", av0, *str); + exit (1); + } +} + + + +CheckARs (mta) +register MTA *mta; +{ + register CHAN *chan; + int lineno; + char buff [500]; /* --- Lex Buffer Size --- */ + + + /* --- Go along the list of AR names. --- */ + /* --- These are of form "Name Lineno" --- */ + + for (chan = mta->mta_arlist; chan != NULL; chan = chan->ch_next) { + if (sscanf (chan->ch.name, "%s %d", &buff [0], &lineno) != 2) { + /* --- Internal error - Horrible --- */ + fprintf (stderr, "%s: CheckARs - AAARGH!!\n", av0); + exit (1); + } + + if ((chan->ch.mta = NameToMta (&buff [0])) == NULL) { + fprintf (stderr, "%s: AR %s ", av0, &buff [0]); + fprintf (stderr, "does not exist at line %d\n", lineno); + } + } +} + + + +DefineChan (str) +char *str; +{ + register CHAN *chan; + + chan = GetChan(); + chan->ch.name = str; /* --- Leave this data where it is --- */ + chan->ch_next = NULL; + ValidChanList = InsertChan (ValidChanList, chan); +} + + +/* --- *** --- +This routine does all checking Possible. It can not check for +validity of AR hosts, but can check that channels exist. If there are +any problems with the channels, the line is discarded. This routine +also start to modify the data structures and free the memory used by +the LEX part of the program. +--- *** --- */ + +int CheckHost (hostname) +char *hostname; +{ + register CHAN *c1; + register char *ptr; + register HOST *host; + int valid; + + valid = 0; + + for (host = HostList; host != NULL; host = host->hst_next) { + + /* --- Check name against hostname --- */ + + if (host->hst_chan != NULL) + if (strcmp (hostname, host->hst_name) != 0) { + RejectHost (host); + continue; + } + else { + if (Debug == 1) + printf ("CheckHost HostName - Free %s\n", + host->hst_name ? + host->hst_name : "null"); + + if (host -> hst_name) { + free (host->hst_name); + host->hst_name = NULL; + } + } + else { + /* --- *** --- + Check That I am not the AR here. If I am + then just zap it and say nothing + --- *** --- */ + if (strcmp (MyName, host->hst_name) == 0) { + if (Debug == 1) + printf ("CheckHost AR HostName\n", + host->hst_name ? + host->hst_name : "null"); + + if (host->hst_name) { + free (host->hst_name); + host->hst_name = NULL; + } + + continue; + } + + /* --- Check the MTA does not have AR of itself --- */ + if (strcmp (hostname, host->hst_name) == 0) { + /* --- What a dummy --- */ + fprintf (stderr, "%s: CheckHost - Line ", av0); + fprintf (stderr, "%d has AR of ", yylineno - 1); + fprintf (stderr, "itself - Ignored\n"); + + if (Debug == 1) + printf ("CheckHost AR HostName - Free %s\n", + host->hst_name ? + host->hst_name : "null"); + + if (host->hst_name) { + free (host->hst_name); + host->hst_name = NULL; + } + continue; + } + + valid = 1; /* --- Application Relay --- */ + continue; + } + + for (c1 = host->hst_chan; c1 != NULL; c1 = c1->ch_next) { + /* --- c1->ch.name points at a LEX buffer --- */ + ptr = InChanList (ValidChanList, c1->ch.name); + if (ptr == NULL) { + if (Debug == 2) { + fprintf (stderr, "%s: Invalid Channel ", av0); + fprintf (stderr, "%s at line ", c1->ch.name); + fprintf (stderr, "%d - ", yylineno - 1); + fprintf (stderr, "Ignored\n"); + } + } + else + valid = 1; + + if (Debug == 1) + printf ("CheckHost - ChanName Free %s\n", + c1->ch.name ? c1->ch.name : "null"); + + if (c1->ch.name) + free (c1->ch.name); + + c1->ch.name = ptr; + } + } + + return (valid); +} + + + +/* --- Check that Channels exist --- */ + +CheckChan (c1) +register CHAN *c1; + { + int valid; + char *ptr; + + for (valid = 0; c1 != NULL; c1 = c1->ch_next) { + + /* --- c1->ch.name points at a LEX buffer --- */ + ptr = InChanList (ValidChanList, c1->ch.name); + if (ptr == NULL) { + if (Debug == 2) { + fprintf (stderr, "%s: Invalid Channel ", av0); + fprintf (stderr, "%s at line ", c1->ch.name); + fprintf (stderr, "%d - Ignored\n", yylineno- 1); + } + } + else + valid = 1; + + + if (Debug == 1) + printf ("CheckChan - ChanName Free %s\n", + c1->ch.name ? c1->ch.name : "null"); + + if (c1->ch.name) + free (c1->ch.name); + + c1->ch.name = ptr; + } + + return (valid); +} + + + + +/* --- *** --- +This routine takes the valid data in the input line structure +and merges it into the internal database format. It also frees up all +storeage used by the line input routines. +--- *** --- */ + + +StoreHost (hostname) +char *hostname; +{ + register MTA *mta; + + if ((mta = NameToMta (hostname)) == NULL) { + mta = GetMta(); + mta->mta_name = StoreStr (HostStringStore, hostname); + MtaTree = InsertMta (MtaTree, mta); + } + + if (mta->mta_domain != NULL) { + /* --- Very Serious - Don't know what to do --- */ + fprintf (stderr, "%s: StoreHost - Line %d ", av0, yylineno - 1); + fprintf (stderr, "uses mixed types - Ignored\n"); + FreeHostInfo (HostList); + return; + } + + MergeData (mta, HostList); +} + + + +StoreChans (name) +char *name; +{ + register MTA *mta; + + if ((mta = NameToMta (name)) == NULL) { + mta = GetMta(); + mta->mta_name = StoreStr (HostStringStore, name); + MtaTree = InsertMta (MtaTree, mta); + } + + if (mta->mta_arlist != NULL || mta->mta_chan != NULL) { + /* --- Very Serious - Don't know what to do --- */ + fprintf (stderr, "%s: StoreHost - Line %d ", av0, yylineno - 1); + fprintf (stderr, "uses mixed types - Ignored\n"); + FreeChanInfo (ChanList); + return; + } + + MergeChanData (mta, ChanList); +} + + + +FreeHostInfo (host) +register HOST *host; +{ + register HOST *h2; + register CHAN *c1, *c2; + + for (; host != NULL; host = h2) { + h2 = host->hst_next; + + for (c1 = host->hst_chan ; c1 != NULL; c1 = c2) { + + c2 = c1->ch_next; + + if (Debug == 1) + printf ("FreeHostInfo - Chan Free %s\n", + c1->ch.name ? c1->ch.name : "null"); + + free ((char *)c1); + c1 = NULL; + } + + if (host->hst_name != NULL) { + if (Debug == 1) + printf ("FreeHostInfo - HostName Free %s\n", + host->hst_name ? host->hst_name : "null"); + free (host->hst_name); + host->hst_name = NULL; + } + + if (Debug == 1) + printf ("FreeHostInfo - Host Free %x\n", host); + + if (host) { + free ((char *)host); + host = NULL; + } + } +} + + +yyerror (str) +char *str; +{ + fprintf (stderr, "%s at line number %d\n", str, yylineno); +} + + + + +/* ---------------------- Static Routines --------------------------------- */ + + + + +/* --- *** --- +This routine adds the new data to existing data. It is also +responsible for freeing the space used by AR lines and HOST and +CHAN buffers. +--- *** --- */ + +static MergeData (mta, host) +register MTA *mta; +register HOST *host; +{ + register HOST *h2; + register CHAN *c1; + + for (; host != NULL; host = h2) { + h2 = host->hst_next; + if ((c1 = host->hst_chan) != NULL) + DoDirectChans (mta, c1); + else + ProcessAR (mta, host->hst_name); + + if (Debug == 1) + printf ("MergeData - Host Free %s\n", + host->hst_name ? host -> hst_name : "null"); + + if (host) { + free ((char *)host); + host = NULL; + } + + } +} + + +static ProcessAR (mta, hostname) +register MTA *mta; +register char *hostname; +{ + register CHAN *chan; + char localHost[BUFSIZ]; /* --- To SPRINTF a number into --- */ + + if (hostname == NULL) /* --- I was the AR --- */ + return; + + if (InChanList (mta->mta_arlist, hostname) == NULL) { + + chan = GetChan(); + + /* --- Store the Line number with AR in case of errors --- */ + (void) sprintf (localHost, "%s %d", hostname, yylineno - 1); + + chan->ch.name = StoreStr (ARStringStore, localHost); + + if (Debug == 1) + printf ("ProcessAR - HostName Free %s\n", + hostname ? hostname : "null"); + + if (hostname) { + free (hostname); + hostname = NULL; + } + + mta->mta_arlist = InsertChan (mta->mta_arlist, chan); + } +} + + + +static MergeChanData (mta, c1) +register MTA *mta; +register CHAN *c1; +{ + register CHAN *c2, *chan; + + for (; c1 != NULL; c1 = c2) { + c2 = c1->ch_next; + if (c1->ch.name != NULL) + if (InChanList (mta->mta_domain, c1->ch.name) == NULL) { + chan = GetChan(); + chan->ch.name = c1->ch.name; + mta->mta_domain = InsertChan (mta->mta_domain, + chan); + } + + if (Debug == 1) + printf ("MergeChanData - Chan Free %s\n", + c1->ch.name ? c1->ch.name : "null"); + + free ((char *)c1); + c1 = NULL; + } +} + + +static DoDirectChans (mta, c1) +register MTA *mta; +register CHAN *c1; +{ + register CHAN *c2, *chan; + + for (; c1 != NULL; c1 = c2) { + c2 = c1->ch_next; + if (c1->ch.name != NULL) + if (InChanList (mta->mta_chan, c1->ch.name) == NULL) { + chan = GetChan(); + chan->ch.name = c1->ch.name; + mta->mta_chan = InsertChan (mta->mta_chan,chan); + } + + if (Debug == 1) + printf ("DoDirectChans - Chan Free %s\n", + c1->ch.name ? c1->ch.name : "null"); + + free ((char *)c1); + c1 = NULL; + } +} diff --git a/Uip/Makefile b/Uip/Makefile new file mode 100644 index 0000000..d3b8111 --- /dev/null +++ b/Uip/Makefile @@ -0,0 +1,40 @@ +# User interface programs +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/RCS/Makefile,v 6.0 1991/12/18 20:42:20 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:42:20 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = mail rcvalert rcvtrip sendmail resend misc + +############################################################ +# +# Building Rules +# +############################################################ + +target: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +lint tidy install define depend clean: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/Uip/mail/Makefile b/Uip/mail/Makefile new file mode 100644 index 0000000..70040c6 --- /dev/null +++ b/Uip/mail/Makefile @@ -0,0 +1,97 @@ +# Dummmm v6-like mail interface +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/mail/RCS/Makefile,v 6.0 1991/12/18 20:35:57 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:35:57 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = mail.c +OBJS = mail.o +# DO NOT DELETE THIS LINE MAKE DEFINE NEEDS IT + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +all: xmail + +mail: xmail + @true +xmail: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +clean: tidy + rm -f $(OBJS) + +tidy: + rm -f zxmail xmail core* a.out *.old *.BAK + + +install: inst-dir inst-mail + +inst-dir: $(CMDDIR) + +inst-mail: $(CMDDIR)/mail +$(CMDDIR)/mail: xmail + -$(BACKUP) $@ zxmail + rm -f $@ + $(INSTALL) xmail $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Mail installed normally"; echo "" + +lint: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + + +define: + $(DEFINE) Makefile + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + + +############################################################ +# +# End of Building Rules +# +############################################################ + +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +mail.o: mail.c +mail.o: ../../h/util.h +mail.o: ../../h/config.h +mail.o: ../../h/ll_log.h +mail.o: ../../h/retcode.h +mail.o: mail.c +mail.o: ../../h/util.h +mail.o: ../../h/config.h +mail.o: ../../h/ll_log.h +mail.o: ../../h/retcode.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/mail/mail.c b/Uip/mail/mail.c new file mode 100644 index 0000000..54cad8c --- /dev/null +++ b/Uip/mail/mail.c @@ -0,0 +1,230 @@ +/* mail: very dumb mail interface */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/mail/RCS/mail.c,v 6.0 1991/12/18 20:35:57 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/mail/RCS/mail.c,v 6.0 1991/12/18 20:35:57 jpo Rel $ + * + * $Log: mail.c,v $ + * Revision 6.0 1991/12/18 20:35:57 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include + +#define TO 1 +#define CC 2 +#define SUBJECT 3 + +#define MAX_TO 100 +#define MAX_CC 100 + + + +static char *to[MAX_TO], + *cc[MAX_CC], + subject[BUFSIZ], + *invo_name; + +static int param = TO, /* initial state */ + lastparam = TO, + toptr, + ccptr; + +static RP_Buf rps, *rp = &rps; + +static void do_text (); +static void mail_init (); +static void do_addrs (); + +/* --------------------- Start Routines -------------------------------- */ + + +main (argc, argv) +int argc; +char **argv; +{ + uip_init (invo_name = argv[0]); + + if (argc <= 1 ) + user_err (1, + "Usage: %s to [-c cc] [-s subject] [-t to]\n", + argv[0]); + + while (--argc > 0) { + argv ++; + if (**argv == '-') + switch (argv[0][1]) { + case 't': + lastparam = param = TO; + break; + case 'c': + lastparam = param = CC; + break; + case 's': + param = SUBJECT; + break; + default: + user_err (1, "Unknown switch %s\n", *argv); + break; + + } /* -- end of switch -- */ + + else { + switch (param) { + case TO: + if (toptr >= MAX_TO) + user_err (1, + "Too many 'to' addresses\n"); + to[toptr++] = *argv; + break; + case CC: + if (ccptr >= MAX_TO) + user_err (1, + "Too many 'cc' addresses\n"); + cc[ccptr++] = *argv; + break; + case SUBJECT: + (void) strcat (subject, *argv); + (void) strcat (subject, " "); + param = lastparam; + break; + + } /* -- end of switch -- */ + + } /* -- end of else -- */ + + } /* -- end of while -- */ + + + if (toptr == 0 && ccptr == 0) + user_err (1, "No recipients given\n"); + + mail_init(); + do_addrs(); + do_text(); + exit (0); +} + + + + +/* --------------------- Start Routines -------------------------------- */ + +static void mail_init() +{ + if (pps_init (subject, rp) == NOTOK) + sys_err (1, "pps_init", rp, "Initialisation failed"); +} + + + + +static void do_addrs() +{ + int i; + + for (i = 0; i < toptr; i++) + if (pps_adr (to[i], rp) == NOTOK) + sys_err (1, "pps_adr", rp, "Address %s failed", to[i]); + + if (pps_cc(rp) == NOTOK) + sys_err (1, "pps_cc", rp, "CC list failed"); + + for (i = 0; i < ccptr; i++) + if (pps_adr (cc[i], rp) == NOTOK) + sys_err (1, "pps_adr", rp, "Address %s failed", cc[i]); + + if (pps_aend(rp) == NOTOK) + sys_err (1, "pps_adend", rp, "Address end failed"); +} + + + + +static void do_text() +{ + if (pps_tinit(rp) == NOTOK) + sys_err (1, "pps_tinit", rp, "Can't initalise for text"); + + if (pps_file (stdin, rp) == NOTOK) + sys_err (1, "pps_file", rp, "Text copy failed"); + + if (pps_end (OK, rp) == NOTOK) + sys_err (1, "pps_end", rp, "Termination phase failed"); + +} + + + + +/* --------------------- Error Routines -------------------------------- */ + + + + +#ifdef lint +/*VARARGS2*/ +user_err (n, fmt) +int n; +char *fmt; +{ + user_err (n, fmt); +} +#else +user_err (va_alist) +va_dcl +{ + char buf[BUFSIZ]; + va_list ap; + int n; + + va_start (ap); + n = va_arg (ap, int); + + _asprintf (buf, NULLCP, ap); + fprintf (stderr, "%s: %s\n", invo_name, buf); + va_end (ap); + + exit (n); +} +#endif + +#ifdef lint +/*VARARGS4*/ +sys_err (n, proc, rp, fmt) +int n; +RP_Buf *rp; +char *proc, *fmt; +{ + sys_err (n, proc, rp, fmt); +} +#else +sys_err (va_alist) +va_dcl +{ + int n; + char buf[BUFSIZ]; + RP_Buf *rp; + char *proc; + va_list ap; + + va_start (ap); + n = va_arg (ap, int); + proc = va_arg (ap, char *); + rp = va_arg (ap, RP_Buf *); + + _asprintf (buf, NULLCP, ap); + fprintf (stderr, "%s: %s %s [%s]\n", invo_name, proc, + buf, rp -> rp_line); + va_end (ap); + exit (n); +} +#endif diff --git a/Uip/mail/make b/Uip/mail/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/mail/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/make b/Uip/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/Uip/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/misc/Makefile b/Uip/misc/Makefile new file mode 100644 index 0000000..d877740 --- /dev/null +++ b/Uip/misc/Makefile @@ -0,0 +1,157 @@ +# misc utilities +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/misc/RCS/Makefile,v 6.0 1991/12/18 20:39:34 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:39:34 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = strip_addr.c flock.c X400_addr.c +OBJS = + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xstrip_addr xflock xX400_addr + +strip_addr: xstrip_addr + @true + +xstrip_addr: strip_addr.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ strip_addr.o $(LIBPP) $(LIBSYS) + +install: inst-strip_addr + +inst-strip_addr: $(USRBINDIR)/strip_addr +$(USRBINDIR)/strip_addr: xstrip_addr + -$(BACKUP) $@ zxstrip_addr + rm -f $@ + $(INSTALL) xstrip_addr $@ + -@$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Strip_Addr installed normally"; echo "" + +flock: xflock + @true + +xflock: flock.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ flock.o $(LIBPP) $(LIBSYS) + +install: inst-flock + +inst-flock: $(USRBINDIR)/flock +$(USRBINDIR)/flock: xflock + -$(BACKUP) $@ zxflock + rm -f $@ + $(INSTALL) xflock $@ + -@$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Flock installed normally"; echo "" + +X400_addr: xX400_addr + @true + +xX400_addr: X400_addr.o $(LIBPP) + $(CC) $(LDFLAGS) -o $@ X400_addr.o $(LIBPP) $(LIBSYS) + +install: inst-X400_addr + +inst-X400_addr: $(USRBINDIR)/X400_addr +$(USRBINDIR)/X400_addr: xX400_addr + -$(BACKUP) $@ zxX400_addr + rm -f $@ + $(INSTALL) xX400_addr $@ + -@$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X400_addr installed normally"; echo "" + +clean: tidy +tidy: + rm -f *.o core a.out Makefile.old x* z* + +lint: l-strip_addr l-flock + +l-strip_addr: strip_addr.c + $(LINT) $(LLFLAGS) strip_addr.c $(LINTLIBS) + + +l-flock: flock.c + $(LINT) $(LLFLAGS) flock.c $(LINTLIBS) + +l-X400_addr: X400_addr.c + $(LINT) $(LLFLAGS) X400_addr.c $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +strip_addr.o: strip_addr.c +strip_addr.o: ../../h/util.h +strip_addr.o: ../../h/config.h +strip_addr.o: ../../h/ll_log.h +strip_addr.o: ../../h/ap.h +strip_addr.o: ../../h/util.h +flock.o: flock.c +flock.o: ../../h/util.h +flock.o: ../../h/config.h +flock.o: ../../h/ll_log.h +X400_addr.o: X400_addr.c +X400_addr.o: ../../h/util.h +X400_addr.o: ../../h/config.h +X400_addr.o: ../../h/ll_log.h +X400_addr.o: ../../h/adr.h +X400_addr.o: ../../h/list_rchan.h +X400_addr.o: ../../h/chan.h +X400_addr.o: ../../h/table.h +X400_addr.o: ../../h/list_bpt.h +X400_addr.o: ../../h/auth.h +X400_addr.o: ../../h/list_bpt.h +X400_addr.o: ../../h/extension.h +X400_addr.o: ../../h/mta.h +X400_addr.o: ../../h/adr.h +X400_addr.o: ../../h/list_bpt.h +X400_addr.o: ../../h/aparse.h +X400_addr.o: ../../h/ap.h +X400_addr.o: ../../h/util.h +X400_addr.o: ../../h/or.h +X400_addr.o: ../../h/chan.h +X400_addr.o: ../../h/auth.h +X400_addr.o: ../../h/list_rchan.h +X400_addr.o: ../../h/retcode.h +X400_addr.o: ../../h/list_rchan.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/misc/X400_addr.c b/Uip/misc/X400_addr.c new file mode 100644 index 0000000..a9ae5a7 --- /dev/null +++ b/Uip/misc/X400_addr.c @@ -0,0 +1,78 @@ +/* x400_adr.c: basically ckadr but stripped */ +/* returns the x400 form of the given addresses */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/misc/RCS/X400_addr.c,v 6.0 1991/12/18 20:39:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/misc/RCS/X400_addr.c,v 6.0 1991/12/18 20:39:34 jpo Rel $ + * + * $Log: X400_addr.c,v $ + * Revision 6.0 1991/12/18 20:39:34 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "adr.h" +#include "retcode.h" +#include "list_rchan.h" + + +static int responsibility = NO; +static int parse= CH_UK_PREF; +static void parse_address(); + + +/* --------------------- Begin Routines ---------------------------------- */ + +main(argc, argv) +int argc; +char **argv; +{ + char buf[BUFSIZ]; + int i = 1; + int opt; + + sys_init(argv[0]); + + argc--; + argv++; + + if (argc == 0) + while (gets(buf) != NULL) + parse_address(buf); + else + while (argc--) + parse_address(*argv++); +} + +static void parse_address(str) +char *str; +{ + ADDR *ad; + RP_Buf rp; + int origType; + int type, first; + LIST_RCHAN *ix; + + + if (index (str, '@')) + type = AD_822_TYPE; + else if (str[0] == '/') + type = AD_X400_TYPE; + else + type = AD_822_TYPE; + + ad = adr_new(str, type, 0); + ad -> ad_resp = responsibility; + origType = ad->ad_type; + + if (rp_isbad(ad_parse(ad, &rp, parse))) + printf("Address parsing failed:\nReason: %s\nParsing gave this:\n\n", ad->ad_parse_message); + if (isstr(ad->ad_r400adr)) + printf("%s\n", ad->ad_r400adr); +} diff --git a/Uip/misc/flock.c b/Uip/misc/flock.c new file mode 100644 index 0000000..1584a94 --- /dev/null +++ b/Uip/misc/flock.c @@ -0,0 +1,83 @@ +/* flock.c: lock a file and execute a command */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/misc/RCS/flock.c,v 6.0 1991/12/18 20:39:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/misc/RCS/flock.c,v 6.0 1991/12/18 20:39:34 jpo Rel $ + * + * $Log: flock.c,v $ + * Revision 6.0 1991/12/18 20:39:34 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include + +#ifndef WEXITSTATUS +#define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode) +#endif +#ifndef WTERMSIG +#define WTERMSIG(x) (((union wait *)&(x)) -> w_termsig) +#endif + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp; + extern int errno; + int pid, cpid; +#ifdef SYS5 + int status; +#else + union wait status; +#endif + + uip_init (argv[0]); + if (argc < 3) { + fprintf (stderr, "Usage: %s file commands...\n", argv[0]); + exit (1); + } + + if ((fp = flckopen (argv[1], "a")) == NULL) { + fprintf (stderr, "%s: Can't open file %s: %s\n", + argv[0], argv[1], sys_errname (errno)); + exit (1); + } + + if ((pid = tryfork () ) == NOTOK) { + fprintf (stderr, "%s: can't fork: %s\n", argv[0], + sys_errname (errno)); + exit (1); + } + + if (pid == 0) { + fclose (fp); + + execvp (argv[2], &argv[2]); + _exit (1); + } + +#ifdef SYS5 + while ((cpid = wait( &status)) != pid && cpid != NOTOK) +#else + while ((cpid = wait( &status.w_status)) != pid && cpid != NOTOK) +#endif + continue; + + if (cpid == NOTOK) /* ??? */ + exit (1); + + if (WIFSIGNALED(status)) + exit (1); + + if (WIFEXITED(status)) + exit (WEXITSTATUS(status)); + + exit (1); +} diff --git a/Uip/misc/make b/Uip/misc/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/misc/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/misc/strip_addr.c b/Uip/misc/strip_addr.c new file mode 100644 index 0000000..b43597d --- /dev/null +++ b/Uip/misc/strip_addr.c @@ -0,0 +1,79 @@ +/* strip_addr.c: simpify addresses */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/misc/RCS/strip_addr.c,v 6.0 1991/12/18 20:39:34 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/misc/RCS/strip_addr.c,v 6.0 1991/12/18 20:39:34 jpo Rel $ + * + * $Log: strip_addr.c,v $ + * Revision 6.0 1991/12/18 20:39:34 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "ap.h" + +static int no_routes = 0; + +main (argc, argv) +int argc; +char **argv; +{ + int opt; + extern int optind; + + while ((opt = getopt (argc, argv, "rp")) != EOF) + switch (opt) { + case 'r': + no_routes ++; + break; + case 'p': + ap_use_percent (); + break; + default: + break; + } + + argc -= optind; argv += optind; + + + if (argc <= 0) { + char buf[BUFSIZ]; + + while (fgets (buf, sizeof buf, stdin) ) + do_addr (buf); + } + else + while (argc-- > 0) + do_addr (*argv++); + exit (0); +} + + +do_addr (str) +char *str; +{ + char *cp; + AP_ptr local, domain, route, tree; + + tree = ap_s2t (str); + + switch ((int)tree) { + case NOTOK: + case 0: + printf ("%s\n", str); + return; + } + (void) ap_t2p (tree, (AP_ptr *)0, (AP_ptr *)0, + &local, &domain, &route); + cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, + no_routes ? NULLAP : route); + printf ("%s\n", cp); + + free (cp); +} diff --git a/Uip/rcvalert/Makefile b/Uip/rcvalert/Makefile new file mode 100644 index 0000000..e48796d --- /dev/null +++ b/Uip/rcvalert/Makefile @@ -0,0 +1,225 @@ +# Rcvalert program +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/Makefile,v 6.0 1991/12/18 20:39:41 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:39:41 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) +SRCS = flagmail.c parsesbr.c ttyalert.c \ + ttybiff.c ttysbr.c udpsbr.c xalert.c + +############################################################ +# +# Building Rules +# +############################################################ + +default: xalert-$(X11) flagmail # ttyalert ttybiff + +install: inst-flagmail inst-xalert-$(X11) # inst-ttyalert ttybiff + +############################################################ +# +# Xclient +# +############################################################ + +FLAGSRC = flagmail.c ttysbr.c parsesbr.c +FLAGOBJ = flagmail.o ttysbr.o parsesbr.o + +inst-flagmail: $(USRBINDIR)/flagmail + +$(USRBINDIR)/flagmail: xflagmail + -$(BACKUP) $@ zflagmail + rm -f $@ + $(INSTALL) xflagmail $@ + -$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X alert client program install normally"; echo "" + +flagmail: xflagmail + @true + +xflagmail: $(FLAGOBJ) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(FLAGOBJ) $(LIBPP) $(LIBSYS) + +l-flagmail: flagmail.c + $(LINT) $(LLFLAGS) $(FLAGSRC) $(LINTLIBS) + +############################################################ +# +# ttyalert +# +############################################################ + +TTYSRC = ttyalert.c ttysbr.c parsesbr.c +TTYOBJ = ttyalert.o ttysbr.o parsesbr.o + +inst-ttyalert: $(USRBINDIR)/ttyalert + +$(USRBINDIR)/ttyalert: xttyalert + -$(BACKUP) $@ zttyalert + rm -f $@ + $(INSTALL) xttyalert $@ + -$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "tty alert program installed normally"; echo "" + +ttyalert: xttyalert +xttyalert: $(TTYOBJ) + $(CC) $(LDFLAGS) -o $@ $(TTYOBJ) $(LIBPP) $(LIBSYS) + +l-ttyalert: $(TTYSRC) + $(LINT) $(LLFLAGS) $(TTYSRC) $(LINTLIBS) + +############################################################ +# +# xalert +# +############################################################ + +XALERTSRC = dirsbr.c xalert.c ttysbr.c udpsbr.c +XALERTOBJ = dirsbr.o xalert.o ttysbr.o udpsbr.o +# uncomment the next line to switch off photo lookup code. +#NOPHOTO = -DNOPHOTOS + +inst-xalert-true: inst-xalert inst-xalert-appdef + @true + +inst-xalert- inst-xalert-false: + @echo "X11 not defined so not installing xalert" + +inst-xalert: $(USRBINDIR)/xalert +$(USRBINDIR)/xalert: xxalert + -$(BACKUP) $@ zxalert + rm -f $@ + $(INSTALL) xxalert $@ + $(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "X photo alert program installed normally" + +inst-xalert-appdef: $(APPDEFAULTS)/XAlert +$(APPDEFAULTS)/XAlert: XAlert.ad + -$(BACKUP) $@ zXAlert.ad + rm -rf $@ + $(INSTALL) XAlert.ad $@ + -$(CHMOD) 444 $@ + -$(CHOWN) $(ROOTUSER) $@ + -@ls -ls $@ + -@echo "XAlert application defaults installed normally"; echo "" + +xalert-true: xalert + @true +xalert-false xalert-:; @echo "X11 not defined so not builing xalert" + +xalert:xxalert + @true +xxalert: $(XALERTOBJ) + $(CC) $(LDFLAGS) -o $@ $(XALERTOBJ) $(LIBPHOTO) $(LIBSYS) $(LIBX) + +xalert.o: xalert.c + $(CC) $(CFLAGS) -c $(NOPHOTO) xalert.c + +l-xalert: $(XALERTSRC) + $(LINT) $(LLFLAGS) $(XALERTSRC) $(LINTLIBS) \ + /usr/local/lib/lint/llib-ldsap.ln \ + /usr/local/lib/lint/llib-lisode.ln + +saber_xalert: $(XALERTSRC) + #load -C $(CFLAGS) $(XALERTSRC) $(LIBPHOTO) $(LIBSYS) + +############################################################ +# +# TtyBiff +# +############################################################ + +TTYBSRC = ttybiff.c ttysbr.c udpsbr.c +TTYBOBJ = ttybiff.o ttysbr.o udpsbr.o + +inst-ttybiff: $(USRBINDIR)/ttybiff + +$(USRBINDIR)/ttybiff: xttybiff + -$(BACKUP) $@ zttybiff + rm -f $@ + $(INSTALL) xttybiff $@ + -$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "tty alert program installed normally"; echo "" + +ttybiff: xttybiff +xttybiff: $(TTYBOBJ) + $(CC) $(LDFLAGS) -o $@ $(TTYBOBJ) $(LIBSYS) + +l-ttybiff: $(TTYSRC) + $(LINT) $(LLFLAGS) $(TTYBSRC) $(LINTLIBS) + +############################################################ +# +# Misc stuff +# +############################################################ + +clean: tidy +tidy: + rm -f *.o core a.out Makefile.old z* \ + xxalert xttyalert xflagmail xttybiff + +lint: l-xalert l-flagmail l-ttyalert + + + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +flagmail.o: flagmail.c +flagmail.o: ./data.h +parsesbr.o: parsesbr.c +parsesbr.o: ../../h/util.h +parsesbr.o: ../../h/config.h +parsesbr.o: ../../h/ll_log.h +ttyalert.o: ttyalert.c +ttyalert.o: ./data.h +ttybiff.o: ttybiff.c +ttybiff.o: ./data.h +ttysbr.o: ttysbr.c +ttysbr.o: ../../h/config.h +udpsbr.o: udpsbr.c +udpsbr.o: ./data.h +xalert.o: xalert.c +xalert.o: ./data.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/rcvalert/README b/Uip/rcvalert/README new file mode 100644 index 0000000..86f71a5 --- /dev/null +++ b/Uip/rcvalert/README @@ -0,0 +1,14 @@ +flagmail + +Runs on the machine mail is delivered on, attempts to connect to a +xalert process running there and display its message. +If it can't, it writes to the users logged in ttys (if any). + +xalert + +The alert program - beeps and displays a scan line. +If an X screen can be found, use that, else use all the user's ttys, +else use stdout + +Will make use of photographs stored in the directory unless configured with +-DNOPHOTOS. If photos are desired, the libphoto.a library is required. diff --git a/Uip/rcvalert/XAlert.ad b/Uip/rcvalert/XAlert.ad new file mode 100644 index 0000000..69fbe97 --- /dev/null +++ b/Uip/rcvalert/XAlert.ad @@ -0,0 +1,134 @@ +! X defaults for Xalert and XAlert with Photos +! +! + +! +! xalert +! +! +! xalert toppane topform box Quit prompt dialog +! ok +! Clear cancel +! Options Options Reset +! Bell +! AutoRaise +! Photo +! +! text +! +! pbox photolabel +! photo +! + +! colours + +*foreground: DarkSlateGrey +*background: LightSkyBlue1 + +*topform*Command.background: gainsboro +*topform*Toggle.background: gainsboro +*topform*MenuButton.background: gainsboro +*topform*SimpleMenu.background: gainsboro + +! shapes + +*Command.shapeStyle: oval +*Toggle.shapeStyle: oval +*MenuButton.shapeStyle: oval + +! fonts + +*Command.font: -adobe-new century schoolbook-bold-r-normal--12-* +*Toggle.font: -adobe-new century schoolbook-bold-r-normal--12-* +*MenuButton.font: -adobe-new century schoolbook-bold-r-normal--12-* +*SimpleMenu*font: -adobe-new century schoolbook-bold-r-normal--12-* + +*Form.defaultDistance: 1 + +*toppane.orientation: horizontal + +*topform.borderWidth: 0 +*topform.top: ChainTop + +*topform.box.top: ChainTop +*topform.box.bottom: ChainTop +*topform.box.left: ChainLeft +*topform.box.right: ChainLeft +*topform.box.borderWidth: 0 + +*topform.box.Clear.fromVert: Quit +*topform.box.Options.fromVert: Clear + +*topform.text.scrollVertical: whenNeeded +*topform.text.scrollHorizontal: whenNeeded +*topform.text.width: 400 +*topform.text.fromHoriz: box +*topform.text.top: ChainTop +*topform.text.bottom: ChainBottom +*topform.text.left: ChainLeft +*topform.text.right: ChainRight +*topform.text*editType: append +*topform.text.height: 75 + +!*text*font: -adobe-new century schoolbook-medium-r-normal--12-* + +*toppane.pbox*resizable: True +*toppane.pbox.allowResize: True +*toppane.pbox.skipAdjust: True +*toppane.pbox.max: 250 + +*toppane.pbox.photolabel.label: +*toppane.pbox.photolabel.top: ChainTop +*toppane.pbox.photolabel.left: ChainLeft +*toppane.pbox.photolabel.right: ChainLeft +*toppane.pbox.photolabel.borderWidth: 0 +*toppane.pbox.photolabel.resizable: true +*toppane.pbox.photolabel.resize: true +*toppane.pbox.photolabel.justify: left + +*toppane.pbox.photo.height: 150 +*toppane.pbox.photo.width: 150 +*toppane.pbox.photo.fromVert: photolabel +*toppane.pbox.photo.top: rubber +*toppane.pbox.photo.bottom: ChainBottom +*toppane.pbox.photo.left: ChainLeft +*toppane.pbox.photo.right: ChainLeft +*toppane.pbox.photo.resize: True +!*toppane.pbox.photo.resize: False +*toppane.pbox.photo.resizable: True +*toppane.pbox.photo.borderWidth: 0 + +*toppane.pbox.photo.shapeStyle: rectangle +!*toppane.pbox.photo.background: white +!*toppane.pbox.photo.foreground: black + +*Dialog.label: Really Quit? +*ok.label: OK +*cancel.label: Cancel +*dialog.Label.font: -adobe-new century schoolbook-medium-r-normal--12-* + +! accelerators + +*Reset.accelerators: #override\n\ +MetaR: set() notify() unset() + +*Bell.accelerators: #override\n\ +MetaB: set() notify() unset() + +*AutoRaise.accelerators:#override\n\ +MetaA: set() notify() unset() + +*Photo.accelerators: #override\n\ +MetaP: set() notify() unset() + +*Clear.accelerators: #override\n\ +MetaC: set() notify() unset() + +*Quit.accelerators: #override\n\ +CtrlC: set() notify() unset() + +*cancel.accelerators: #override\n\ +Return: set() notify() unset() + +*ok.accelerators: #override\n\ +CtrlC: set() notify() unset() diff --git a/Uip/rcvalert/data.h b/Uip/rcvalert/data.h new file mode 100644 index 0000000..579d254 --- /dev/null +++ b/Uip/rcvalert/data.h @@ -0,0 +1,29 @@ +/* data.h: data excahnge between rcvalert client/server */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/data.h,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: data.h,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_RCVALERT_DATA +#define _H_RCVALERT_DATA + +struct data { + long refid; /* network order */ + char user[40]; /* username */ + char data[512]; /* null terminated */ + char from[64]; /* who its really from */ +}; + +#define PORT 2345 +#define N_RETRYS 3 + + +#endif diff --git a/Uip/rcvalert/dirsbr.c b/Uip/rcvalert/dirsbr.c new file mode 100644 index 0000000..46224f6 --- /dev/null +++ b/Uip/rcvalert/dirsbr.c @@ -0,0 +1,1136 @@ +/* imagesbr.c - image subroutines */ + +#ifndef lint +static char *Rcsid = "$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/dirsbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +#endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/dirsbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * + * $Log: dirsbr.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + * + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "image.h" + +#ifndef NOPHOTOS +/* GENERAL */ +#if ISODE < 69 +#define s_filter filter +#endif + +static char *myname = "image"; +extern int debug; +int errsw = OK; + +static LLog _pgm_log = { + "-", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, + LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER | LLOGTTY, NOTOK +}; +LLog *pgm_log = &_pgm_log; +void adios (); + +#define DEF_TIMELIMIT 20 +/* IMAGE */ + + +struct image *fetch_image (); + +/* AKA */ + +struct aka { + struct aka *ak_forw; + struct aka *ak_back; + + time_t ak_notfound; + char *ak_domain; + char *ak_local; + + struct dn_seq *ak_bases; + struct image *ak_image; +}; +static struct aka akas; +static struct aka *AHead = &akas; + +void init_aka (); + +static int stay_bound = 0; + +DN local_dn; + + +struct dn_seq *dm2dn_seq (); + + +extern char *local_dit; +struct dn_seq *dn_seq_push (); +int dn_seq_print (); +PE grab_pe (); + +#ifdef TESTVERSION +main (argc, argv) +int argc; +char **argv; +{ + struct image *myim; + + if (argc != 3) { + fprintf (stderr, "Usdage: %s host name\n", argv[0]); + exit (1); + } + + init_aka (myname = argv[0], 1, NULLCP); + myim = fetch_image (argv[1], argv[2]); + + if (myim) { + printf ("Retrieved photo of size %dx%d\n", myim -> width, + myim -> height); + } + else + printf ("No photo found\n"); + exit (0); +} +#endif + +/* */ + +void init_aka (pgm, stayopen, dit) +char *pgm, + *dit; +int stayopen; +{ + char *cp; + register struct aka *ak; + static int once_only = 0; + static char *username, *password; + + if (once_only == 0) { + int argp; + char *arg[2], + **argptr; + + quipu_syntaxes (); + + argp = 0; + arg[argp++] = myname; + arg[argp] = NULLCP; + + dsap_init (&argp, (argptr = arg, &argptr)); + quipurc (&username, &password); + once_only = 1; + } + stay_bound = stayopen; + myname = pgm; + + AHead -> ak_forw = AHead -> ak_back = AHead; + if ((ak = (struct aka *) calloc (1, sizeof *ak)) == NULL) + adios (NULLCP, "out of memory"); + + ak -> ak_domain = ak -> ak_local = ""; + + insque (ak, AHead -> ak_back); + + if ((local_dn = str2dn (cp = (dit ? dit + : *local_dit != '@' ? local_dit + : local_dit + 1))) + == NULLDN) + adios (NULLCP, "local_dit invalid: \"%s\"", cp); + do_bind (username, password); +} + +quipurc (username, password) +char **username, **password; +{ + char *home; + FILE *file; + extern char *local_dit; + char *p; + char Dish_Home[BUFSIZ]; + char Read_in_Stuff[BUFSIZ]; + extern char *TidyString (); + + *username = *password = NULLCP; + + if (home = getenv ("QUIPURC")) + (void) strcpy (Dish_Home, home); + else if (home = getenv ("HOME")) + (void) sprintf (Dish_Home, "%s/.quipurc", home); + else + (void) strcpy (Dish_Home, "./.quipurc"); + + if ((file = fopen (Dish_Home, "r")) == 0) + return; + + while (fgets (Read_in_Stuff, sizeof Read_in_Stuff, file) != 0) { + char *part1, *part2; + + p = SkipSpace (Read_in_Stuff); + if (( *p == '#') || (*p == '\0')) + continue; /* ignore comments and blanks */ + + part1 = p; + if ((part2 = index (p,':')) == NULLCP) + continue; + + *part2++ = '\0'; + part2 = TidyString (part2); + + if (lexequ (part1, "username") == 0) + *username = strdup(*part2 != '@' ? part2 : part2 + 1); + + else if (lexequ (part1, "password") == 0) { + *password = strdup(part2); + } else if (lexequ (part1, "dsap") == 0) + (void) tai_string (part2); + else if (lexequ (part1, "isode") == 0) { + char * split; + if ((split = index (part2,' ')) != NULLCP) { + *split++ = 0; + (void)isodesetvar (part2,strdup(split),0); + } + } + } + (void) fclose (file); + +} +/* */ + +static struct aka *mbox2ak (local, domain) +char *local, + *domain; +{ + register struct aka *ak, *am, *adm= NULL; + + if (domain == NULL) + domain = ""; + if (local == NULL) + local = ""; + + for (ak = AHead -> ak_forw; ak != AHead; ak = ak -> ak_forw) { + if (lexequ (domain, ak -> ak_domain) != 0) + continue; + adm = ak; + if (lexequ (local, ak -> ak_local) == 0) { + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("hit \"%s\" \"%s\"", domain, local)); + + return ak; + } + } + if (adm) { + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("partial hit \"%s\"", domain)); + if ((am = (struct aka *) calloc (1, sizeof *am)) == NULL + || (am -> ak_domain = strdup (domain)) == NULL + || (am -> ak_local = strdup (local)) == NULL) + adios (NULLCP, "out of memory"); + am -> ak_bases = adm -> ak_bases; + insque (ak = am, AHead); + + return ak; + } + + if ((am = (struct aka *) calloc (1, sizeof *am)) == NULL + || (am -> ak_domain = strdup (domain)) == NULL + || (am -> ak_local = strdup (local)) == NULL) + adios (NULLCP, "out of memory"); + + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("miss \"%s\" \"%s\"", domain, local)); + + if (index (domain, '.')) + am -> ak_bases = dm2dn_seq (domain); + else + am -> ak_bases = dn_seq_push (local_dn, NULLDNSEQ); + + insque (ak = am, AHead); + + return ak; +} + +/* DIRECTORY */ + +#define ADOMAIN "associatedDomain" +#define PHOTO "photo" +#define USERID "userid" +#define MAILBOX "rfc822Mailbox" +#define OTHERMAILBOX "otherMailbox" +#define COMMONNAME "commonname" +#define SURNAME "surname" + +static int bound = 0; +static int dlevel = 0; +static AttributeType adomain_t; + +struct dn_seq *dm2dn_seq_aux (); + + +static struct dn_seq *dm2dn_seq (dm) +char *dm; +{ + register char *dp; + char *av[100]; + int count; + + for (dp = dm, av[count = 0] = dm; *dp; dp++) { + if (isupper (*dp)) + *dp = tolower (*dp); + if (*dp == '.') + av[++count] = dp+1; + } + av[++count] = NULL; + + if ((adomain_t = AttrT_new (ADOMAIN)) == NULL) + adios ("invalid attribute type \"%s\"", ADOMAIN); + + dlevel = 0; + + if (!bound && do_bind (NULLCP, NULLCP) == NOTOK) + return NULLDNSEQ; + + return dm2dn_seq_aux (dm, count, 0, av, NULLDN, NULLDNSEQ); +} + +/* */ + +static int find_best_match (atv, maxdmn, av) +AV_Sequence atv; +int maxdmn; +char *av[]; +{ + int best = maxdmn + 1; + int i; + char buffer[BUFSIZ]; + PS ps; + + if ((ps = ps_alloc (str_open)) == NULLPS + || str_setup (ps, buffer, sizeof buffer, 1) == NOTOK) + adios ("can't set up PS stream"); + + for (; atv; atv = atv -> avseq_next) { + AttrV_print (ps, &atv -> avseq_av, EDBOUT); + *ps->ps_ptr = NULL; + for (i = 0; i < maxdmn; i++) + if (lexequ (buffer, av[i]) == 0) + if (i < best) { + best = i; + break; + } + if (str_setup (ps, buffer, sizeof buffer, 1) == NOTOK) + adios ("can't reset PS stream"); + } + ps_free (ps); + if (best > maxdmn) + return best; + return maxdmn - best; +} + +static struct dn_seq *dm2dn_seq_aux (dm, maxdmn, ndmn, av, dn, dlist) +char *dm; +DN dn; +int maxdmn, ndmn; +char *av[]; +struct dn_seq *dlist; +{ + char buffer[BUFSIZ]; + struct ds_search_arg search_arg; + register struct ds_search_arg *sa = &search_arg; + struct ds_search_result search_result; + register CommonArgs *ca; + register struct ds_search_result *sr = &search_result; + struct DSError error; + register struct DSError *se = &error; + PS ps; + + if ((ps = ps_alloc (str_open)) + && str_setup (ps, buffer, sizeof buffer, 1) != NOTOK) { + dn_print (ps, dn, EDBOUT); + ps_print (ps, " "); + *--ps -> ps_ptr = NULL, ps -> ps_cnt ++; + } + else + buffer[0] = NULL; + if (ps) + (void) ps_free (ps); + + if (debug) + fprintf (stderr, "dlevel=%d maxlevel=%d dm=%s dn=%s\n", + ndmn, maxdmn, dm, buffer); + + bzero ((char *) sa, sizeof *sa); + + ca = &sa -> sra_common; + ca -> ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; + ca -> ca_servicecontrol.svc_timelimit = DEF_TIMELIMIT; + ca -> ca_servicecontrol.svc_sizelimit = SVC_NOSIZELIMIT; + + sa -> sra_baseobject = dn; + sa -> sra_subset = SRA_ONELEVEL; + sa -> sra_searchaliases = FALSE; + + sa -> sra_eis.eis_allattributes = FALSE; + sa -> sra_eis.eis_select = as_comp_new (str2AttrT (ADOMAIN), NULLAV, + NULLACL_INFO); + sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + + for (;;) { + int i; + EntryInfo *ptr; + register s_filter *fi; + + if (debug) + fprintf (stderr, + "-- dlevel=%d maxlevel=%d, domain=%s dn=%s\n", + ndmn, maxdmn, dm, buffer); + + if (ndmn >= maxdmn) + break; + + sa -> sra_filter = fi = filter_alloc (); + + bzero ((char *) fi, sizeof *fi); + fi -> flt_type = FILTER_OR; + + for (i = 0; i < maxdmn - ndmn; i++) { + s_filter *f; + + f = filter_alloc (); + bzero ((char *)f, sizeof *f); + f -> flt_type = FILTER_ITEM; + f -> FUITEM.fi_type = FILTERITEM_EQUALITY; + f -> FUITEM.UNAVA.ava_type = AttrT_cpy(adomain_t); + f -> FUITEM.UNAVA.ava_value = + str2AttrV (av[i], adomain_t -> oa_syntax); + + f -> flt_next = fi -> FUFILT; + fi -> FUFILT = f; + } + + if (ds_search (sa, se, sr) != DS_OK) { + if (debug) + LLOG (pgm_log, LLOG_EXCEPTIONS, + ("search operation failed (%d)", + se -> dse_type)); + + if (se -> dse_type == DSE_REMOTEERROR) { + (void) ds_unbind (); + bound = 0; + } + + goto free_filter; + } + + if (sr -> srr_correlated != TRUE) + correlate_search_results (sr); + + if (sr -> CSR_entries == NULLENTRYINFO) { + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("search for %s \"%s\" at baseobject \"%s\" failed", + ADOMAIN, dm, buffer)); + goto free_filter; + } + + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("search for %s \"%s\" at baseobject \"%s\" succeeded", + ADOMAIN, dm, buffer)); + + for (ptr = sr -> CSR_entries; ptr; ptr = ptr -> ent_next) { + struct dn_seq *dprev = dlist; + Attr_Sequence as; + int best = maxdmn + 1; + + for (as = ptr -> ent_attr; as; as = as -> attr_link) { + if (AttrT_cmp (as -> attr_type, + adomain_t) == 0) { + i = find_best_match (as -> attr_value, + maxdmn, av); + if (i < best) + best = i; + } + } + if (best < maxdmn) /* ok match */ + ndmn = best; + else if (best == maxdmn) { /* perfect match */ + dlist = dn_seq_push (ptr -> ent_dn, dlist); + continue; + } + else + continue; + + dlist = dm2dn_seq_aux (dm, maxdmn, ndmn, av, + ptr -> ent_dn, dlist); + + if (dprev == dlist) /* nothing better in recursion? */ + dlist = dn_seq_push (ptr -> ent_dn, dlist); + } + + dn_free (sr -> CSR_object); + entryinfo_free (sr -> CSR_entries, 0); + crefs_free (sr -> CSR_cr); + free_filter: ; + filter_free (sa -> sra_filter); + break; + } + + return dlist; +} + +/* */ +typedef struct SearchKeys { + char *type; + char *value; +} SearchKeys; + +static int image_search (ak, imp) +register struct aka *ak; +struct image *imp; +{ + register struct dn_seq *dlist; + SearchKeys sk[10]; + int retval; + char buf[BUFSIZ]; + char *cp; + int n; + + if (debug) { + LLOG (pgm_log, LLOG_NOTICE, ("searching for %s %s", + ak -> ak_domain, ak -> ak_local)); + pslog (pgm_log, LLOG_NOTICE, " using baseobjects ", + dn_seq_print, (caddr_t) ak -> ak_bases); + } + + sk[0].type = MAILBOX; + (void) sprintf (buf, "%s@%s", ak -> ak_local, ak -> ak_domain); + sk[0].value = strdup(buf); + sk[1].type = USERID; + sk[1].value = strdup(ak -> ak_local); + sk[2].type = OTHERMAILBOX; + (void) sprintf (buf, "internet$%s@%s", + ak -> ak_local, ak -> ak_domain); + sk[2].value = strdup(buf); + sk[3].type = sk[3].value = NULLCP; + + retval = NOTOK; + for (dlist = ak -> ak_bases; dlist; dlist = dlist -> dns_next) { + if ((retval = do_search (dlist -> dns_dn, + sk, imp)) != DONE) + break; + } + for (n = 0; sk[n].type; n++) + free (sk[n].value); + + if (retval != DONE) + return retval; + + /* OK - try some more heuristics */ + n = 0; + sk[n].type = COMMONNAME; + sk[n++].value = strdup(ak -> ak_local); + + if ((cp = rindex(ak -> ak_local, '.')) != NULL) { + (void) strcpy (buf, ak -> ak_local); /* try replacing '.'->' ' */ + for (cp = buf; *cp; cp++) + if (*cp == '.') + *cp = ' '; + sk[n].type = COMMONNAME; + sk[n++].value = strdup(buf); + } + sk[n].type = sk[n].value = NULLCP; + + retval = NOTOK; + + for (dlist = ak -> ak_bases; dlist; dlist = dlist -> dns_next) { + if ((retval = do_search (dlist -> dns_dn, + sk, imp)) != DONE) + break; + } + if (retval != DONE) + return retval; + + n = 0; + sk[n].type = SURNAME; + sk[n++].value = strdup(ak -> ak_local); + if ((cp = rindex(ak -> ak_local, '.')) != NULL) { + sk[n].type = SURNAME; /* try last component as surname */ + sk[n++].value = cp + 1; + } + sk[n].type = sk[n].value = NULLCP; + + retval = NOTOK; + + for (dlist = ak -> ak_bases; dlist; dlist = dlist -> dns_next) { + if ((retval = do_search (dlist -> dns_dn, + sk, imp)) != DONE) + break; + } + return retval; +} + +static AttributeType t_photo, t_phone, t_address, t_description, t_info; + +struct pairs { + char *p_name; + AttributeType *p_at; +} pairs[] = { + PHOTO, &t_photo, + "telephoneNumber", &t_phone, + "postalAddress", &t_address, + "description", &t_description, + "info", &t_info, + NULL, +}; + +static char *as2str (as) +Attr_Sequence as; +{ + static PS ps; + char buffer[BUFSIZ]; + + if (ps == NULLPS) { + if ((ps = ps_alloc (str_open)) == NULLPS) + adios (NULLCP, "Out of memory"); + } + if (str_setup (ps, buffer, sizeof buffer, 1) == NOTOK) + adios (NULLCP, "Can't setup PS"); + + avs_print (ps, as -> attr_value, READOUT); + ps_print (ps, " "); + *--ps -> ps_ptr = NULL, ps -> ps_cnt ++; + + return strdup (buffer); +} + +static Attr_Sequence get_select () +{ + static Attr_Sequence as = NULL; + + if (!as) { + struct pairs *p; + AttributeType at; + + for (p = pairs; p -> p_name; p++) { + at = *p -> p_at = AttrT_new (p -> p_name); + + if (at) + as = as_merge (as, + as_comp_new (AttrT_cpy(at), + NULLAV, + NULLACL_INFO)); + } + } + + return as; +} + +decode_result (imp, eptr) +struct image *imp; +Attr_Sequence eptr; +{ + + for (; eptr; eptr = eptr -> attr_link) { + if (AttrT_cmp (eptr -> attr_type, t_photo) == 0) + imp -> pe = + pe_cpy (grab_pe (eptr -> attr_value + -> avseq_av)); + else if (AttrT_cmp (eptr -> attr_type, t_info) == 0) + imp -> info = as2str (eptr); + else if (AttrT_cmp (eptr -> attr_type, t_description) == 0) + imp -> description = as2str (eptr); + else if (AttrT_cmp (eptr -> attr_type, t_address) == 0) + imp -> address = as2str (eptr); + else if (AttrT_cmp (eptr -> attr_type, t_phone) == 0) + imp -> phone = as2str (eptr); + } +} + +static int do_search (dn, sk, imp) +DN dn; +SearchKeys sk[]; +struct image *imp; +{ + struct ds_search_arg search_arg; + register struct ds_search_arg *sa = &search_arg; + struct ds_search_result search_result; + register CommonArgs *ca; + register struct ds_search_result *sr = &search_result; + struct DSError error; + register struct DSError *se = &error; + extern int dn_print(); + extern char *dn2ufn (); + SearchKeys *skp; + s_filter *fi; + + bzero ((char *) sa, sizeof *sa); + + ca = &sa -> sra_common; + ca -> ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN; + ca -> ca_servicecontrol.svc_timelimit = DEF_TIMELIMIT; + ca -> ca_servicecontrol.svc_sizelimit = 1; + + sa -> sra_subset = SRA_WHOLESUBTREE; + sa -> sra_searchaliases = TRUE; + + if ((sa -> sra_baseobject = dn) == NULL) + return DONE; + + sa -> sra_filter = fi = filter_alloc (); + + bzero ((char *) fi, sizeof *fi); + fi -> flt_type = FILTER_OR; + + for (skp = sk; skp -> type; skp ++) { + s_filter *f; + AttributeType at; + + f = filter_alloc (); + bzero ((char *) f, sizeof *f); + + f -> flt_type = FILTER_ITEM; + f -> FUITEM.fi_type = FILTERITEM_EQUALITY; + if ((f -> FUITEM.UNAVA.ava_type = at = + AttrT_new (skp -> type)) == NULL) + adios ("invalid attribute type \"%s\"", USERID); + f -> FUITEM.UNAVA.ava_value = + str2AttrV (skp -> value, at -> oa_syntax); + f -> flt_next = fi -> FUFILT; + fi -> FUFILT = f; + } + + sa -> sra_eis.eis_allattributes = FALSE; + sa -> sra_eis.eis_select = get_select (); + sa -> sra_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES; + + if (debug) { + extern int fi_print (); + + pslog (pgm_log, LLOG_NOTICE, "Searching for ", + fi_print, (caddr_t)fi); + pslog (pgm_log, LLOG_NOTICE, " from ", + dn_print, (caddr_t) dn); + } + if (ds_search (sa, se, sr) != DS_OK) { + if (debug) + LLOG (pgm_log, LLOG_EXCEPTIONS, + ("search operation failed (%d)", + se -> dse_type)); + + switch (se -> dse_type) { + case DSE_REMOTEERROR: + (void) ds_unbind (); + bound = 0; + break; + default: + break; + } + + filter_free (sa -> sra_filter); + return bound == 0 ? NOTOK : DONE; + } + + if (sr -> srr_correlated != TRUE) + correlate_search_results (sr); + + switch (sr -> CSR_limitproblem) { + case LSR_NOLIMITPROBLEM: + break; + case LSR_TIMELIMITEXCEEDED: + if (debug) + LLOG (pgm_log, LLOG_NOTICE, + ("took tooo long")); + /* fall */ + case LSR_ADMINSIZEEXCEEDED: + filter_free (sa -> sra_filter); + return NOTOK; + + case LSR_SIZELIMITEXCEEDED: + if (debug) + pslog (pgm_log, LLOG_NOTICE, + "search: hit too many targets at ", + dn_print, (caddr_t)dn); + break; /* carry on anyway */ + } + + if (sr -> CSR_entries == NULLENTRYINFO) { + if (debug) + pslog (pgm_log, LLOG_NOTICE, + "search failed at baseobject ", + dn_print, (caddr_t) dn); + filter_free (sa -> sra_filter); + return DONE; + } + + if (sr -> CSR_entries -> ent_attr == NULLATTR) { + if (debug) + pslog (pgm_log, LLOG_NOTICE, + "search succeeded (but no attribute) at ", + dn_print, (caddr_t) dn); + } + else { + if (debug) + pslog (pgm_log, LLOG_NOTICE, + "search succeeded at ", + dn_print, (caddr_t) dn); + decode_result (imp, sr -> CSR_entries -> ent_attr); + } + + imp -> ufnname = dn2ufn (sr ->CSR_entries -> ent_dn, -1); + + dn_free (sr -> CSR_object); + entryinfo_free (sr -> CSR_entries, 0); + crefs_free (sr -> CSR_cr); + filter_free (sa -> sra_filter); + return OK; + +} +/* */ + +static int do_bind (dn, passwd) +char *dn; +char *passwd; +{ + struct ds_bind_arg bind_arg, + bind_result; + register struct ds_bind_arg *ba = &bind_arg, + *br = &bind_result; + struct ds_bind_error bind_error; + register struct ds_bind_error *be = &bind_error; + static char *savedn, *savepasswd; + + bzero ((char *) ba, sizeof *ba); + ba -> dba_version = DBA_VERSION_V1988; + ba -> dba_auth_type = DBA_AUTH_NONE; + if (dn || (dn = savedn) != NULLCP) { + if (savedn == NULLCP) + savedn = strdup (dn); + ba -> dba_dn = str2dn (dn); + if (passwd || (passwd=savepasswd) != NULLCP) { + if (savepasswd == NULLCP) + savepasswd = strdup (passwd); + (void) strcpy (ba -> dba_passwd, passwd); + ba -> dba_auth_type = DBA_AUTH_SIMPLE; + } + } + + + if (ds_bind (ba, be, br) != DS_OK) { + if (debug) + LLOG (pgm_log, LLOG_EXCEPTIONS, + ("directory bind failed: %s", + be -> dbe_type == DBE_TYPE_SECURITY ? "security error" + : "DSA unavailable")); + + return NOTOK; + } + + bound = 1; + + return OK; +} + +/* IMAGE */ + +static int passno; +static int x, y, maxx; + +static struct image *the_image = NULL; + +/* */ +void image_free (imp) +struct image *imp; +{ + if (imp -> data) qb_free(imp ->data); + if (imp -> ufnname) free (imp->ufnname); + if (imp -> phone) free (imp -> phone); + if (imp -> description) free (imp -> description); + if (imp -> info) free (imp -> info); + if (imp -> address) free (imp -> address); + if (imp -> pe) pe_free (imp->pe); + free ((char *)imp); +} + +struct image *fetch_image (local, domain) +char *local, + *domain; +{ + register struct aka *ak; + time_t now; + + (void) time(&now); + + if ((ak = mbox2ak (local, domain)) == NULL) + return NULL; + + if (ak -> ak_image) + return ak -> ak_image; + if (ak -> ak_notfound > now - 30*60) { + if (debug) + LLOG (pgm_log, LLOG_NOTICE, ("Hit negative cache!")); + return NULL; /* neg cache */ + } + if (!bound && do_bind (NULLCP, NULLCP) == NOTOK) + return NULL; + + if ((the_image = (struct image *) calloc (1, sizeof *the_image)) == NULL) { + if (debug) + fprintf (stderr, "calloc fails"); + return NULL; + } + if (image_search (ak, the_image) == NOTOK) { + ak -> ak_notfound = now; + return NULL; + } + + if (!stay_bound) { + (void) ds_unbind (); + bound = 0; + } + + if (the_image -> pe) + dec_photo (the_image); + return (ak -> ak_image = the_image); +} + + +dec_photo (imp) +struct image *imp; +{ + PS ps; + PE pe = imp -> pe; + + imp -> pe = NULLPE; + + if ((ps = ps_alloc (str_open)) == NULLPS) { + if (debug) + fprintf (stderr, "ps_alloc: failed\n"); + + goto out; + } + if (str_setup (ps, NULLCP, 0, 0) == NOTOK) { + if (debug) + fprintf (stderr, "ps_alloc: %s\n", + ps_error (ps -> ps_errno)); + + goto out; + } + + if (pe2ps (ps, pe) == NOTOK) { + if (debug) + fprintf (stderr, "pe2ps: %s\n", + pe_error (pe -> pe_errno)); + + goto out; + } + + for (passno = 1; passno < 3; passno++) + if (decode_t4 (ps -> ps_base, PHOTO, + ps -> ps_ptr - ps -> ps_base) + == NOTOK) { + fprintf (stderr, "\n"); + if (imp -> data) { + qb_free (imp -> data); + imp -> data = NULL; + } + break; + } + + out: ; + if (ps) + ps_free (ps); + pe_free (pe); +} +/* */ + +/* ARGSUSED */ + +photo_start (name) +char *name; +{ + if (passno == 1) + maxx = 0; + x = y = 0; + + return OK; +} + + +/* ARGSUSED */ + +photo_end (name) +char *name; +{ + int len; + register struct qbuf *qb, + *pb; + + if (passno == 1) { + x = maxx, y--; + + if (debug) + fprintf (stderr, "ending pass one for \"%s\", %dx%d\n", + name, x, y); + + the_image -> width = x, the_image -> height = y; + + len = ((the_image -> width + 7) / 8) * the_image -> height; + if ((the_image -> data = qb = (struct qbuf *) malloc (sizeof *qb)) == NULL) { + if (debug) + fprintf (stderr, "unable to allocate qbuf"); + return NOTOK; + } + qb -> qb_forw = qb -> qb_back = qb; + qb -> qb_data = NULL, qb -> qb_len = len; + + if ((pb = (struct qbuf *) calloc ((unsigned) (sizeof *pb + len), 1)) + == NULL) { + if (debug) + fprintf (stderr, "unable to allocate qbuf (%d+%d)", + sizeof *qb, len); + return NOTOK; + } + pb -> qb_data = pb -> qb_base, pb -> qb_len = len; + insque (pb, qb); + return OK; + } + return OK; +} + + +photo_black (length) +int length; +{ + if (passno == 2) { + register int i, + j; + register unsigned char *cp; + + cp = (unsigned char *) the_image -> data -> qb_forw -> qb_data + + ((the_image -> width + 7) / 8) * y + x / 8; + i = x % 8; + for (j = length; j > 0; j--) { + *cp |= 1 << i; + if (++i == 8) + cp++, i = 0; + } + + } + + x += length; + + return OK; +} + + +photo_white (length) +int length; +{ + x += length; + + return OK; +} + + +/* ARGSUSED */ + +photo_line_end (line) +caddr_t line; +{ + if (passno == 1 && x > maxx) + maxx = x; + x = 0, y++; + + return OK; +} + +/* ERRORS */ + +#ifndef lint +void _advise (); + + +void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS */ + +void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + + +#ifndef lint +void advise (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _advise (ap); + + va_end (ap); +} + + +static void _advise (ap) +va_list ap; +{ + char buffer[BUFSIZ]; + + asprintf (buffer, ap); + + (void) fflush (stdout); + + if (errsw != NOTOK) { + fprintf (stderr, "%s: ", myname); + (void) fputs (buffer, stderr); + (void) fputc ('\n', stderr); + + (void) fflush (stderr); + } +} +#else +/* VARARGS */ + +void advise (what, fmt) +char *what, + *fmt; +{ + advise (what, fmt); +} +#endif + +#endif diff --git a/Uip/rcvalert/flagmail.c b/Uip/rcvalert/flagmail.c new file mode 100644 index 0000000..c776f60 --- /dev/null +++ b/Uip/rcvalert/flagmail.c @@ -0,0 +1,255 @@ +/* client.c: client for alert program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/flagmail.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/flagmail.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: flagmail.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include +#include +#include +#include +#include + +#include "data.h" + +char displayline[BUFSIZ]; +char from[BUFSIZ]; +char username[40]; +char hostname[BUFSIZ]; +char homedir[512]; +char *filename = ".alert"; +char *extra = "NEW: "; +char *format = "%extra(%size) %20from %subject << %80body"; +int width = 80; +int debug = 0; +int theport = 0; + +char *myname; + +extern char *index (); + +main (argc, argv) +int argc; +char *argv[]; +{ + extern char *optarg; + extern int optind; + int opt; + int size = 0; + int use_tty = 0; + int use_x = 0; + + myname = argv[0]; + pp_initialise (myname, 0); + while((opt = getopt(argc, argv, "de:f:h:p:s:txw:")) != EOF) + switch (opt) { + case 'e': + extra = optarg; + break; + + case 'f': + format = optarg; + break; + + case 'd': + debug = 1; + break; + + case 'h': + filename = optarg; + break; + + case 's': + size = atoi (optarg); + break; + + case 'p': + theport = atoi (optarg); + break; + + case 't': + use_tty = 1; + break; + + case 'w': + width = atoi (optarg); + break; + + case 'x': + use_x = 1; + break; + + default: + fprintf (stderr, "Usage: %s [options]\n", + myname); + break; + } + argc -= optind; + argv += optind; + + init_stuff (); + + parse_msg (displayline, from, format, BUFSIZ-1, size, extra); + chop(displayline); + + if (debug == 0 && fork () > 0) + exit (1); + if (use_tty || (notify_x () == 0 && ! use_x)) + { if (width > 0 && width < sizeof displayline) + displayline[width] = 0; + chop(displayline); + (void) notify_normal (displayline, username); + } + exit (1); +} + +init_stuff () +{ + struct passwd *pwd; + char *cp, *getenv (); + + if ((pwd = getpwuid (getuid())) == NULL) { + fprintf (stderr, "No user name\n"); + exit(-1); + } + + (void) strcpy (username, pwd -> pw_name); + if ((cp = getenv ("HOME")) != NULL && *cp) + (void) strcpy (homedir, cp); + else + (void) strcpy (homedir, pwd -> pw_dir); +} + + +notify_x () +{ + struct data data; + struct sockaddr_in sin; + struct hostent *hp; + int i; + int sd; + + if (!findhost(hostname)) + return 0; + + if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + perror ("socket"); + exit (1); + } + + bzero ((char *)&sin, sizeof sin); + + sin.sin_family = AF_INET; + sin.sin_port = htons (theport); + + bzero ((char *)&data, sizeof data); + data.refid = htonl(getpid ()); + (void) strcpy (data.user, username); + (void) strncpy (data.data, displayline, sizeof (data.data) - 1); + data.data[sizeof data.data - 1] = 0; + (void) strncpy (data.from, from, sizeof(data.from) - 1); + data.from[sizeof data.from - 1] = 0; + + if ((hp = gethostbyname (hostname)) == NULL) { + fprintf (stderr, "No such host %s\n", hostname); + return 0; + } + bcopy (hp -> h_addr, (char *)&sin.sin_addr, hp -> h_length); + for (i = 0; i < N_RETRYS; i++) { + if (debug) printf("Send to %s.%d\n", hostname, theport); + if (sendto (sd, (char *)&data, sizeof data, 0, + (struct sockaddr *)&sin, sizeof sin) < 0) + perror ("sendto"); + + if (replys (sd)) + return 1; + } + if (debug) printf("No reply from %s.%d\n", hostname, theport); + return 0; +} + +replys (sd) +int sd; +{ + fd_set rfds; + char buffer[20]; + struct timeval timer; + struct sockaddr_in nsin; + int len; + + timer.tv_usec = 0; + timer.tv_sec = 10; + FD_ZERO (&rfds); + FD_SET (sd, &rfds); + + if (select (sd + 1, &rfds, NULLFD, NULLFD, &timer) <= 0) + return 0; + + if (FD_ISSET (sd, &rfds)) { + len = sizeof nsin; + + if (recvfrom (sd, buffer, 3, 0, + (struct sockaddr *)&nsin, &len) < 0) + perror ("recvfrom"); + return 1; + } + if (debug) printf("No reply from %s.%d\n", hostname, theport); + return 0; +} + +findhost (host) +char *host; +{ + FILE *fp; + char *cp; + char buf[BUFSIZ]; + + if (*filename == '/' || strncmp (filename, "./", 2) == 0 || + strncmp (filename, "../", 3) == 0) + (void) strcpy (buf, filename); + else + (void) sprintf (buf, "%s/%s", homedir, filename); + + if ((fp = fopen (buf, "r")) == NULL && + (fp = fopen (filename, "r")) == NULL) + return 0; + + if (fgets (host, BUFSIZ, fp) == NULL) { + (void) fclose (fp); + return 0; + } + (void) fclose (fp); + if (cp = index (hostname, '\n')) + *cp = '\0'; + if (cp = index (hostname, ' ')) { + *cp++ = '\0'; + if (theport == 0) + theport = atoi (cp); + } + + if (theport == 0) { + fprintf (stderr, "No port!\n"); + return 0; + } + + return 1; +} + +chop(string) +char *string; +{ char *end = string + strlen(string) -1; + while (end != string && (*end == ' ' || *end == '\t')) *end-- = 0; +} diff --git a/Uip/rcvalert/image.h b/Uip/rcvalert/image.h new file mode 100644 index 0000000..7d4660d --- /dev/null +++ b/Uip/rcvalert/image.h @@ -0,0 +1,24 @@ +/* image.h: image definition */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/image.h,v 6.0 1991/12/18 20:40:03 jpo Rel $ + * + * $Log: image.h,v $ + * Revision 6.0 1991/12/18 20:40:03 jpo + * Release 6.0 + * + * + */ + +struct image { + int width, height; + struct qbuf *data; + char *ufnname; + char *phone; + char *description; + char *info; + char *address; + PE pe; +}; + +extern struct image *fetch_image (); diff --git a/Uip/rcvalert/make b/Uip/rcvalert/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/rcvalert/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/rcvalert/parsesbr.c b/Uip/rcvalert/parsesbr.c new file mode 100644 index 0000000..688233a --- /dev/null +++ b/Uip/rcvalert/parsesbr.c @@ -0,0 +1,220 @@ +/* parsebr.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/parsesbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/parsesbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: parsesbr.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "ap.h" +#include "chan.h" + +#define MAXFIELDS 100 + +struct fields { + char *name; + int nlen; + int len; + int start; + int finish; + int flags; +#define PARSE_FROM 1 +#define PARSE_BODY 2 +#define PARSE_SIZE 3 +#define PARSE_EXTRA 4 + char *value; +} fields[MAXFIELDS]; + +int nfields = 0; + +parse_msg (displayline, from, format, maxlen, msgsize, extra) +char *displayline; +char *from; +char *format; +int maxlen; +int msgsize; +char *extra; +{ + char buf[BUFSIZ], buf2[BUFSIZ], *cp; + struct fields *fp; + int n; + + break_fields (format); + + while (fgets (buf, sizeof buf, stdin) != NULL) { + if (buf[0] == '\n') + break; + if (lexnequ (buf, "from:", 5) == 0) + fillin_from (from, buf); + for (fp = fields; fp < &fields[nfields]; fp++) + if (lexnequ (buf, fp -> name, fp -> nlen) == 0) { + compress (buf + fp -> nlen + 1, buf2); + fp -> value = strdup (buf2); + break; + } + } + + buf[0] = NULL; + n = fread (buf, 1, sizeof buf, stdin); + buf[n] = NULL; + for (cp = buf; *cp; cp++) { + if (*cp == '\n') + *cp = ' '; + } + compress (buf, buf); + + for (fp = fields; fp < &fields[nfields]; fp++) { + if (fp -> value == NULLCP) + fp -> value = ""; + if (fp -> flags == PARSE_FROM) { + if ((cp = index (fp -> value, '<'))) { + *cp = '\0'; + compress (fp -> value, fp -> value); + } + } + else if (fp -> flags == PARSE_BODY) + fp -> value = strdup (buf); + else if (fp -> flags == PARSE_SIZE) { + (void) sprintf (buf2, "%d", msgsize); + fp -> value = strdup (buf2); + } + else if (fp -> flags == PARSE_EXTRA) + fp -> value = extra; + } + + build_string (format, displayline); + displayline[maxlen] = 0; +} + +break_fields (str) +char *str; +{ + char *cp, *p; + struct fields *fp; + char buf[BUFSIZ]; + + if (str == NULL) + return; + for (cp = str; *cp; ) { + if (*cp++ != '%') + continue; + if (*cp == '%') { + cp ++; + continue; + } + fp = &fields[nfields++]; + if (nfields >= MAXFIELDS) + nfields --; + fp -> start = cp - str - 1; + if (isdigit (*cp)) { + int n = 0; + while (isdigit (*cp)) + n = n * 10 + *cp++ - '0'; + fp -> len = n; + } + + for (p = cp; isalpha(*p) || *p == '-'; p++) + continue; + if (cp == p) { + nfields --; + continue; + } + (void) strncpy (buf, cp, p -cp); + buf[p - cp] = 0; + fp -> name = strdup (buf); + fp -> nlen = strlen (buf); + + if(lexequ (buf, "from") == 0) + fp -> flags = PARSE_FROM; + else if (lexequ (buf, "body") == 0) + fp -> flags = PARSE_BODY; + else if (lexequ (buf, "size") == 0) + fp -> flags = PARSE_SIZE; + else if (lexequ (buf, "extra") == 0) + fp -> flags = PARSE_EXTRA; + cp = p; + fp -> finish = cp - str; + } +} + +build_string (format, dest) +char *format; +char *dest; +{ + char *cp; + int last; + struct fields *fp; + + if (nfields == 0) { + (void) strcpy (dest, format); + return; + } + cp = dest; + last = 0; + for (fp = fields; fp < &fields[nfields]; fp ++) { + (void) strncpy (cp, format + last, fp -> start - last); + cp += fp -> start - last; + + if (fp -> len) { + int mlen; + + mlen = strlen (fp -> value); + if (fp -> len < mlen) + mlen = fp -> len; + + (void) sprintf (cp, "%-*.*s", fp -> len, + mlen, fp -> value); + + cp += strlen (cp); + } + else if (fp -> value) { + (void) strcpy (cp, fp -> value); + cp += strlen (fp -> value); + } + last = fp -> finish; + } + (void) strcpy (cp, format + last); + *cp = NULL; +} + +fillin_from (dest, line) +char *dest, *line; +{ + char *dp; + char *cp = line + 5; /* skip over from: */ + AP_ptr mbox, domain, tree; + + + dest[0] = 0; + + if (ap_s2p (cp, &tree, NULLAPP, NULLAPP, + &mbox, &domain, NULLAPP) == (char *)NOTOK) + return; +#ifdef UKORDER + if (ap_dmnormalize (domain, CH_UK_PREF) != OK) { +#else + if (ap_dmnormalize (domain, CH_USA_PREF) != OK) { +#endif + ap_sqdelete (tree, NULLAP); + ap_free (tree); + return; + } + + dp = ap_p2s_nc (NULLAP, NULLAP, mbox, domain, NULLAP); + if (dp != (char *)NOTOK && isstr(dp)) + (void) strcpy (dest, dp); + ap_sqdelete (tree, NULLAP); + ap_free (tree); + free (dp); +} diff --git a/Uip/rcvalert/rttyalert b/Uip/rcvalert/rttyalert new file mode 100755 index 0000000..88f7700 --- /dev/null +++ b/Uip/rcvalert/rttyalert @@ -0,0 +1,40 @@ +#! /bin/sh + +CMDLINE="/usr/local/bin/ttyalert" +#CMDLINE="echo" +HOST="" + +TMP=/tmp/rttyalert.pp.$$ + +trap "rm $TMP" 0 1 2 3 15 + +/bin/awk ' +BEGIN { eoh = 50 } # at most 50 lines +$0 ~ /^$/ { eoh = NR + 3} +NR == eoh { print $0 ; exit } +{ print $0 } +' > $TMP + +while [ $# -gt 0 ] +do + case "$1" in + -d) if [ $# -gt 0 ] + then shift + fi;; + -f|-e|-s|-w) CMDLINE="$CMDLINE $1 $2" + case $# in + 0) ;; + 1) shift ;; + *) shift; shift ;; + esac ;; + *) HOST="$HOST$1 "; + if [ $# -gt 0 ] + then shift + fi;; + esac +done + +for i in $HOST +do + rsh $i "$CMDLINE" < $TMP& +done diff --git a/Uip/rcvalert/ttyalert.c b/Uip/rcvalert/ttyalert.c new file mode 100644 index 0000000..933bf1f --- /dev/null +++ b/Uip/rcvalert/ttyalert.c @@ -0,0 +1,113 @@ +/* ttyalert.c: simple tty alert program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttyalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttyalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: ttyalert.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "sys.file.h" +#include +#include +#include +#include +#include + +#include "data.h" + +#ifndef UTMP_FILE +#define UTMP_FILE "/etc/utmp" +#endif + +#define OKTONOTIFY 020 /* group write perm */ + +char displayline[BUFSIZ]; +char from[BUFSIZ]; +char username[40]; +char homedir[512]; +char *extra = "NEW: "; +char *format = "%extra(%size) %20from %subject << %50body"; +int width = 80; +int debug = 0; + +char *myname; + +extern char *index (); + +main (argc, argv) +int argc; +char *argv[]; +{ + extern char *optarg; + extern int optind; + int opt; + int size = 0; + + myname = argv[0]; + while((opt = getopt(argc, argv, "de:f:s:w:")) != EOF) + switch (opt) { + case 'd': + debug = 1; + break; + + case 'e': + extra = optarg; + break; + + case 's': + size = atoi (optarg); + break; + + case 'f': + format = optarg; + break; + + case 'w': + width = atoi (optarg); + break; + + default: + fprintf (stderr, "Usage: %s [-f string] hosts..", + myname); + break; + } + argc -= optind; + argv += optind; + + init_stuff (); + + parse_msg (displayline, from, format, width, size, extra); + + if (debug == 0 && fork () > 0) + exit (0); + notify_normal (displayline, username); + exit (0); +} + +init_stuff () +{ + struct passwd *pwd; + char *cp, *getenv (); + + if ((pwd = getpwuid (getuid())) == NULL) { + fprintf (stderr, "No user name\n"); + exit(-1); + } + + (void) strcpy (username, pwd -> pw_name); + if ((cp = getenv ("HOME")) != NULL && *cp) + (void) strcpy (homedir, cp); + else + (void) strcpy (homedir, pwd -> pw_dir); +} diff --git a/Uip/rcvalert/ttybiff.c b/Uip/rcvalert/ttybiff.c new file mode 100644 index 0000000..d2b7cbd --- /dev/null +++ b/Uip/rcvalert/ttybiff.c @@ -0,0 +1,122 @@ +/* ttybiff.c: tty alert program using the UDP syntax stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttybiff.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttybiff.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: ttybiff.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "sys.file.h" +#include +#include +#include +#include +#include + +#include "data.h" + +char username[40]; +char hostname[128]; +char homedir[512]; +char *filename = ".alert"; +short port = 0; +char *extra = "NEW: "; +char *format = "%extra(%size) %20from %subject << %50body"; +int width = 80; +int debug = 0; +int stdoutonly = 0; + +char *myname; + +extern char *index (); + +main (argc, argv) +int argc; +char *argv[]; +{ + extern char *optarg; + extern int optind; + int opt; + int sd; + + myname = argv[0]; + while((opt = getopt(argc, argv, "f:p:u:s")) != EOF) + switch (opt) { + case 's': + stdoutonly = 1; + break; + case 'f': + filename = optarg; + break; + case 'p': + port = atoi(optarg); + break; + case 'u': + (void) strcpy (username, optarg); + break; + default: + fprintf (stderr, + "Usage: %s [-f file] [-p port] [-u user]", + myname); + break; + } + argc -= optind; + argv += optind; + + init_stuff (); + + sd = udp_start (port, filename, homedir); + + for (;;) { + fd_set rfds; + char buffer[BUFSIZ]; + char from[BUFSIZ]; + int n; + + FD_ZERO (&rfds); + FD_SET (sd, &rfds); + if(select (sd + 1, &rfds, NULLFD, NULLFD, + (struct timeval *)0) <= 0) + continue; + + n = sizeof (buffer) - 1; + if (FD_ISSET (sd, &rfds) && + getdata (sd, buffer, &n, username, from)) { + buffer[n] = 0; + if (stdoutonly || + (notify_normal (buffer, username) == NOTOK && + isatty (1))) + printf ("\n\r%s%c\n\r", + buffer, '\007'); + } + } +} + +init_stuff () +{ + struct passwd *pwd; + char *cp, *getenv (); + + if ((pwd = getpwuid (getuid())) == NULL) { + fprintf (stderr, "No user name\n"); + exit(-1); + } + if (username[0] == NULL) + (void) strcpy (username, pwd -> pw_name); + + if ((cp = getenv ("HOME")) != NULL && *cp) + (void) strcpy (homedir, cp); + else + (void) strcpy (homedir, pwd -> pw_dir); +} diff --git a/Uip/rcvalert/ttysbr.c b/Uip/rcvalert/ttysbr.c new file mode 100644 index 0000000..4260589 --- /dev/null +++ b/Uip/rcvalert/ttysbr.c @@ -0,0 +1,113 @@ +/* ttysbr.c: */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttysbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/ttysbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: ttysbr.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include +#include +#include +#include + +#ifndef UTMP_FILE +#define UTMP_FILE "/etc/utmp" +#endif +#ifdef XOS_2 +struct utmp *getutent(); +#endif + +#define OKTONOTIFY 020 /* group write perm */ + +#ifdef nonuser +#define NONUSER(x) nonuser(x) +#else +#ifdef XOS_2 +#define NONUSER(x) ((x)->ut_user[0] == 0) +#else +#define NONUSER(x) ((x).ut_name[0] == 0) +#endif +#endif + +int notify_normal (str, username) +char *str; +char *username; +{ + FILE *fp; + int done = NOTOK; +#ifdef XOS_2 + struct utmp *utmp; +#else + struct utmp utmp; +#endif + +#ifdef XOS_2 + while ((utmp = getutent ()) != (struct utmp *)NULL) { + if (NONUSER (utmp)) + continue; + if (strncmp (utmp->ut_user, username, + sizeof (utmp->ut_user)) == 0) + if (notify_user (utmp, str) == OK) + done = OK; + } +#else + if ((fp = fopen (UTMP_FILE, "r")) == NULL) + return NOTOK; + + while ((int)fread ((char *)&utmp, sizeof utmp, 1, fp) > 0) { + if (NONUSER (utmp)) + continue; + if (strncmp (utmp.ut_name, username, + sizeof (utmp.ut_name)) == 0) + if (notify_user (&utmp, str) == OK) + done = OK; + } + (void) fclose (fp); +#endif + return done; +} + +notify_user (ut, str) +struct utmp *ut; +char *str; +{ + char device[BUFSIZ]; + struct stat st; + int pid; + int fd; + + (void) sprintf (device, "/dev/%.*s", sizeof (ut -> ut_line), + ut -> ut_line); + + if (stat (device, &st) == NOTOK) + return NOTOK; + if ((st.st_mode & OKTONOTIFY) == 0) + return NOTOK; + + if ((pid = fork ()) == NOTOK) + return NOTOK; + + if (pid) + return OK; + + if ((fd = open (device, O_WRONLY, 0)) == NOTOK) + _exit(1); + (void) write (fd, "\r\n\007", 3); + (void) write (fd, str, strlen (str)); + (void) write (fd, "\r\n\007", 3); + (void) close (fd); + _exit (0); + return NOTOK; +} diff --git a/Uip/rcvalert/udpsbr.c b/Uip/rcvalert/udpsbr.c new file mode 100644 index 0000000..2b81a98 --- /dev/null +++ b/Uip/rcvalert/udpsbr.c @@ -0,0 +1,170 @@ +/* udpsbr.c: support routines for the UDP protocol notification stuff */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/udpsbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/udpsbr.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: udpsbr.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include + +#include "data.h" + +int getdata (fd, buf, len, user, from) +int fd; +char *buf; +int *len; +char *user; +char *from; +{ + struct data thedata; + struct data *ds = &thedata; + struct sockaddr_in sin; + int slen = sizeof sin; + int retval = 0; + int n; + + if((n = recvfrom (fd, (char *)ds, sizeof *ds, 0, + (struct sockaddr *)&sin, &slen)) <= 0 || + n != sizeof *ds) + return retval; + if ((*len = strlen(ds->data)) > (sizeof ds -> data) ) + *len = sizeof (ds -> data); + bcopy (ds -> data, buf, *len); + buf[*len] = 0; + if ((n = strlen (ds->from)) > (sizeof ds -> from)) + n = sizeof (ds -> from); + bcopy (ds -> from, from, n); + from[n] = 0; + if (checkid (ds, &sin, user)) + retval = 1; + ack (&sin); + return retval; +} + + +struct ref { + long refid; + u_long addr; +}; +#define MAXREFS 10 + +checkid (ds, sp, user) +struct data *ds; +struct sockaddr_in *sp; +char *user; +{ + static struct ref refs[MAXREFS]; + static int cur; + struct ref *rp; + int refid = (int) ntohl(ds->refid); + + if (strcmp (user, ds -> user) != 0) + return 0; + + for (rp = refs; rp < &refs[MAXREFS]; rp ++) + if (rp -> refid == refid && + sp -> sin_addr.s_addr == rp -> addr) + return 0; + + rp = &refs[cur]; + rp -> refid = refid; + rp -> addr = sp -> sin_addr.s_addr; + cur = (cur + 1) % MAXREFS; + return 1; +} + +static short theport; +static int replysock; +char alertfilename[BUFSIZ]; + +ack (sp) +struct sockaddr_in *sp; +{ + if( sendto (replysock, "ok", 2, 0, + (struct sockaddr *)sp, sizeof *sp) < 0) + perror ("sendto"); +} + +udp_start (port, file, home) +short port; +char *file, *home; +{ + int s; + struct sockaddr_in sin; + int len; + + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + perror ("socket failed"); + exit (1); + } + bzero ((char *)&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + + if (bind (s, (struct sockaddr *)&sin, sizeof sin) < 0) { + perror ("bind failed"); + exit (1); + } + + if ((replysock = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + perror ("socket failed"); + exit (1); + } + len = sizeof sin; + if (getsockname (s, (struct sockaddr *)&sin, &len) == -1) { + perror ("getsockname"); + exit (1); + } + theport = ntohs (sin.sin_port); + makeredirfile (file, home); + return s; +} + + +makeredirfile (file, home) +char *file; +char *home; +{ + FILE *fp; + char hostname[128]; + + if (gethostname (hostname, sizeof hostname) == -1) { + perror ("Can't fetch hostname"); + return; + } + if (*file == '/' || strncmp (file, "./", 2) == 0 || + strncmp (file, "../", 3) == 0) + (void) strcpy (alertfilename, file); + else { + (void) sprintf (alertfilename, "%s/%s", + home, file); + } + + + if ((fp = fopen (alertfilename, "w")) == NULL) { + perror (alertfilename); + return; + } + fprintf (fp, "%s %d\n", hostname, theport); + (void) fclose (fp); +} + +udp_cleanup () +{ + if (alertfilename[0]) + (void) unlink (alertfilename); + if (replysock) + (void) close (replysock); +} diff --git a/Uip/rcvalert/xalert.c b/Uip/rcvalert/xalert.c new file mode 100644 index 0000000..98b1799 --- /dev/null +++ b/Uip/rcvalert/xalert.c @@ -0,0 +1,731 @@ +/* xalert.c: X based alert program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/xalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvalert/RCS/xalert.c,v 6.0 1991/12/18 20:39:41 jpo Rel $ + * + * $Log: xalert.c,v $ + * Revision 6.0 1991/12/18 20:39:41 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "sys.file.h" +#include +#include +#include +#include +#include + +#include "data.h" +#include "image.h" + +#define check_width 9 +#define check_height 8 +static char check_bits[] = { + 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, + 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 +}; + +#define BASIC_WIDTH 400 + +static struct _app_resources { + char *filename; + char *user; + int port; + Boolean bell; + Boolean autoraise; + Boolean photos; +} app_resource; + +static int defaultPort = 0; +char homedir[BUFSIZ]; +char filename[] = ".alert"; + +char a_filename[]="-filename"; +char a_user[] = "-user"; +char a_port[] = "-port"; +char a_d[] = "-d"; +char a_f[] = "-f"; +char a_u[] = "-u"; +char a_p[] = "-p"; +char a_s[] = "-s"; +char a_t[] = "-t"; +char a_w[] = "-w"; +char a_x[] = "-x"; + +#define offset(x) XtOffset (struct _app_resources *, x) +static XtResource resources[] = { +{"fileName", "FileName", XtRString, sizeof (String), + offset(filename), XtRString, (caddr_t) filename }, +{"userName", "UserName", XtRString, sizeof (String), + offset(user), XtRString, (caddr_t) NULL }, +{"port", "Port", XtRInt, sizeof (int), + offset(port), XtRInt, (caddr_t) &defaultPort }, +{"bell", "Bell", XtRBoolean, sizeof(Boolean), + offset(bell), XtRImmediate, (caddr_t)1}, +{"autoRaise", "AutoRaise", XtRBoolean, sizeof(Boolean), + offset(autoraise), XtRImmediate, (caddr_t)0}, +#ifndef NOPHOTOS +{"photos", "Photos", XtRBoolean, sizeof(Boolean), + offset(photos), XtRImmediate, (caddr_t)1}, +#endif +}; + +static XrmOptionDescRec table[] = { +{a_filename, "fileName", XrmoptionSepArg, (caddr_t) NULL}, +{a_user, "userName", XrmoptionSepArg, (caddr_t) NULL}, +{a_port, "port", XrmoptionSepArg, (caddr_t) NULL}, +{"-nobell", "Bell", XrmoptionNoArg, (caddr_t)"False"}, +{"-bell", "Bell", XrmoptionNoArg, (caddr_t)"True"}, +{"-autoraise", "AutoRaise", XrmoptionNoArg, (caddr_t)"True"}, +{"-noautoraise","AutoRaise", XrmoptionNoArg, (caddr_t)"False"}, +#ifndef NOPHOTOS +{"-nophotos", "Photos", XrmoptionNoArg, (caddr_t)"False"}, +{"-photos", "Photos", XrmoptionNoArg, (caddr_t)"True"}, +#endif +}; + +XtAppContext context; +Display *dpy; +Screen *scrn; +Widget toplevel, pane, box, qb, topform, txt, photow, photolbl, db, optionw, pbox; +static Pixmap check; + +char username[128]; +int replysock; +char twfilename[BUFSIZ]; +char hostname[128]; +char *extra = "NEW: "; +char *format = "%extra(%size) %20from %subject << %50body"; +static char *myname; +int width = 80; +int debug = 0; +int stdoutonly = 0; +int no_x = 0; +int termwidth=80; + +static void Quit (); +static void QuitCancel (); +static void Delete (); +static void TextIn (); +static void catch_exit (); +static int EQuit (); +static int EQuit2 (); +static void Cancel (); +static void Ok (); +static void create_menu (); +#ifndef NOPHOTOS +static void lookup_photo (); +static void PhotoClr (); +static void photo_clr (); + +#endif + +XtActionsRec actionTable[] = { +{"Ok", Ok}, +{"Cancel", Cancel} +}; + +XrmDatabase fred; + +main (argc, argv) +int argc; +char *argv[]; +{ + int sd; + struct passwd *pwd; + char *cp, *getenv (); + long ptr; + XrmValue value; + + value.size=sizeof(ptr); + value.addr= (caddr_t) (&ptr); + + myname = argv[0]; + if ((pwd = getpwuid (getuid ())) == NULL) { + fprintf (stderr, "Unknown user"); + } + else { + (void) strcpy (username, pwd -> pw_name); + if ((cp = getenv ("HOME")) && *cp) + (void) strcpy (homedir, cp); + else + (void) strcpy (homedir, pwd -> pw_dir); + } + + pre_scan(argc, argv); + + if (! no_x) { + XtToolkitInitialize(); + context = XtCreateApplicationContext(); + dpy = XtOpenDisplay(context, (String)NULL, "xalert", "XAlert", + table, XtNumber(table), &argc, argv); + if (dpy == (Display *)0) { + fprintf (stderr, "Unable to open display, so using tty\n"); + no_x++; + } + } + + if (no_x) { + if (!app_resource.filename) app_resource.filename = filename; + if (!app_resource.user) app_resource.user = username; + signal(SIGHUP, catch_exit); + signal(SIGTERM, catch_exit); + signal(SIGINT, catch_exit); + sd = udp_start (app_resource.port, app_resource.filename, homedir); + for (;;) { + fd_set rfds; + char buffer[BUFSIZ]; + char from[BUFSIZ]; + int n; + + FD_ZERO (&rfds); + FD_SET (sd, &rfds); + if(select (sd + 1, &rfds, NULLFD, NULLFD, + (struct timeval *)0) <= 0) + continue; + + n = sizeof (buffer) - 1; + if (FD_ISSET (sd, &rfds) && + getdata (sd, buffer, &n, app_resource.user, + from)) { + buffer[n] = 0; + if (termwidth < n) buffer[termwidth] = 0; + if (stdoutonly || (notify_normal (buffer, app_resource.user) == NOTOK && + isatty (1))) + printf ("\n\r%s%c\n\r", + buffer, '\007'); + } + } + } + + scrn = DefaultScreenOfDisplay(dpy); + + XtAppAddActions(context, actionTable, XtNumber(actionTable)); + + toplevel = XtAppCreateShell("xalert", "XAlert", + applicationShellWidgetClass, dpy, NULL,0); + + XtGetApplicationResources (toplevel, (caddr_t)&app_resource, resources, + XtNumber(resources), NULL, 0); + + if (app_resource.user == NULL) + app_resource.user = username; + + sd = udp_start (app_resource.port, app_resource.filename, homedir); + + pane = XtVaCreateManagedWidget ("toppane", + panedWidgetClass, + toplevel, + NULL); + + topform = XtVaCreateManagedWidget("topform", + formWidgetClass, + pane, + NULL); + box = XtVaCreateManagedWidget ("box", + formWidgetClass, + topform, + NULL); + + qb = XtVaCreateManagedWidget ("Quit", + commandWidgetClass, + box, + NULL); + XtAddCallback(qb, XtNcallback, QuitCancel, NULL); + + db = XtVaCreateManagedWidget ("Clear", + commandWidgetClass, + box, + NULL); + XtAddCallback (db, XtNcallback, Delete, NULL); + + optionw = XtVaCreateManagedWidget ("Options", + menuButtonWidgetClass, + box, + XtNmenuName, "Options", + NULL); + + create_menu (toplevel, "Options", optionw); + + txt = XtVaCreateManagedWidget("text", + asciiTextWidgetClass, + topform, + NULL); +#ifndef NOPHOTOS + pbox = XtVaCreateWidget ("pbox", + formWidgetClass, + pane, + NULL); + + photolbl = XtVaCreateManagedWidget ("photolabel", + labelWidgetClass, + pbox, + NULL); + + photow = XtVaCreateManagedWidget ("photo", + commandWidgetClass, + pbox, + XtNlabel, "", + 0); + XtAddCallback (photow, XtNcallback, PhotoClr, NULL); + + if(app_resource.photos) { + XtManageChild(pbox); + } + +#endif + + XSetErrorHandler (EQuit); + XSetIOErrorHandler (EQuit2); + + (void) XtAppAddInput (context, sd, XtInputReadMask, TextIn, NULL); + + XtInstallAllAccelerators(txt, toplevel); + + XtRealizeWidget(toplevel); + + XtSetKeyboardFocus(toplevel, txt); + + XtAppMainLoop (context); +} + +static void Reset (); +static void ToggleBell (); +static void AutoRaise (); +#ifndef NOPHOTOS +static void TogglePhotos (); +#endif + +struct MenuEntries { + char *name; + void (*fnx)(); + Boolean *state; +}; + +struct MenuEntries menus[] = { + "Reset", Reset, NULL, + "Bell", ToggleBell, &app_resource.bell, + "AutoRaise", AutoRaise, &app_resource.autoraise, +#ifndef NOPHOTOS + "Photos", TogglePhotos, &app_resource.photos, +#endif + NULLCP, NULL, NULL, + }; + +static void create_menu (top, name, button) +Widget top; +char *name; +Widget button; +{ + Widget mw, bsb; + struct MenuEntries *mp; + + check = XCreateBitmapFromData (dpy, + RootWindowOfScreen(XtScreen(top)), + check_bits, + check_width, + check_height); + mw = XtVaCreatePopupShell (name, + simpleMenuWidgetClass, + button, + NULL); + + for (mp = menus; mp -> name; mp ++) { + bsb = XtVaCreateManagedWidget (mp -> name, + smeBSBObjectClass, + mw, + XtNleftMargin, check_width + 5, + NULL); + XtAddCallback (bsb, XtNcallback, mp -> fnx, button); + if (mp -> state && *mp ->state) + XtVaSetValues (bsb, + XtNleftBitmap, check, + NULL); + } +} + +/* ARGSUSED */ +static void TextIn (cdata, fdp, iid) +caddr_t cdata; +int *fdp; +XtInputId *iid; +{ + char buffer[BUFSIZ]; + char from[BUFSIZ]; + int n; + + if (*fdp == 0) { + if ((n = read (*fdp, buffer, sizeof buffer)) <= 0) + Quit (toplevel, (caddr_t)0, (caddr_t)0); + buffer[n] = 0; + AddText (buffer, n); + } + else { + if (getdata (*fdp, buffer, &n, app_resource.user, from)) { + AddText (buffer, n); +#ifndef NOPHOTOS + lookup_photo(from); +#endif + } + + } +} + +/* ARGSUSED */ +static int EQuit (disp, error) +Display *disp; +XErrorEvent *error; +{ + Quit (toplevel, (caddr_t)0, (caddr_t)0); +} + +/* ARGSUSED */ +static int EQuit2 (disp) +Display *disp; +{ + Quit (toplevel, (caddr_t)0, (caddr_t)0); +} + +/* ARGSUSED */ +static void Quit(widget, closure, callData) +Widget widget; +caddr_t closure; +caddr_t callData; +{ + XtDestroyWidget(toplevel); + catch_exit(); +} + +static void catch_exit() +{ + if (twfilename[0]) + (void) unlink (twfilename); + udp_cleanup (); + + exit(0); +} + +AddText (s, n) +char *s; +int n; +{ + XawTextPosition last; + XawTextBlock text; + + XawTextSetInsertionPoint (txt, (XawTextPosition)9999999); + last = XawTextGetInsertionPoint (txt); + + text.ptr = s; + text.firstPos = 0; + text.length = n; + text.format = FMT8BIT; + + if (XawTextReplace (txt, last, last, &text) != XawEditDone) + XBell (XtDisplay (txt), 0); + else { + XawTextPosition newend; + + XawTextSetInsertionPoint(txt, last + text.length); + newend = XawTextGetInsertionPoint(txt); + if (text.ptr[text.length-1] != '\n') { + text.ptr = "\n"; + text.length = 1; + XawTextReplace(txt, newend, newend, &text); + XawTextSetInsertionPoint(txt, newend += 1); + } + } + if (app_resource.bell) + XBell (XtDisplay (toplevel), 50); + if (app_resource.autoraise) + XMapRaised (dpy, XtWindow(toplevel)); +} + +/* ARGSUSED */ +static void Reset (widget, closure, callData) +Widget widget; +caddr_t closure; +caddr_t callData; +{ + makeredirfile (app_resource.filename, homedir); +} + +/* ARGSUSED */ +static void ToggleBell (widget, closure, callData) +Widget widget; +caddr_t closure; +caddr_t callData; +{ + app_resource.bell = !app_resource.bell; + if (app_resource.bell) + XtVaSetValues (widget, XtNleftBitmap, check, NULL); + else XtVaSetValues (widget, XtNleftBitmap, None, NULL); +} + +/* ARGSUSED */ +static void AutoRaise (widget, closure, callData) +Widget widget; +caddr_t closure; +caddr_t callData; +{ + app_resource.autoraise = !app_resource.autoraise; + if (app_resource.autoraise) + XtVaSetValues (widget, XtNleftBitmap, check, NULL); + else XtVaSetValues (widget, XtNleftBitmap, None, NULL); +} + +/* ARGSUSED */ +static void Delete (widget, closure, callData) +Widget widget; +caddr_t closure; +caddr_t callData; +{ + XtVaSetValues (txt, XtNstring, "", NULL); +#ifndef NOPHOTOS + photo_clr (); +#endif +} + + +/* YUCK ! This should use XrmParseCommand etc ... */ +pre_scan (argc, argv) +int argc; +char *argv[]; +{ + int i; + + for (i=1; i data) { + pix = XCreateBitmapFromData (dpy, XtWindow (photow), + image -> data -> qb_forw -> qb_data, + image -> width, image -> height); + if (pix == None) + return; + XtVaSetValues (photow, + XtNbitmap, pix, + 0); + } + else { + char lbuf[BUFSIZ*2]; + + lbuf[0] = 0; + if (image -> phone) + (void) strcat (lbuf, image -> phone); + if (image -> address) + (void) strcat (lbuf, image -> address); + if (image -> info) + (void) strcat (lbuf, image -> info); + if (image -> description) + (void) strcat (lbuf, image -> description); + XtVaSetValues (photow, + XtNlabel, lbuf, + NULL); + } + if (image -> ufnname) + XtVaSetValues (photolbl, + XtNlabel, image -> ufnname, + NULL); +} + +#endif + + + +static void DestroyPopupPrompt(); /* the callback of the popup cancel button */ +static void Ok(); /* an action proc calling ColorTheButton */ + + +/*ARGSUSED*/ +static void +QuitCancel(button, client_data, call_data) +Widget button; +XtPointer client_data, call_data; +{ + Arg args[5]; + Widget popup, dialog; + Position x, y; + Dimension width, height; + Cardinal n; + + n = 0; + XtSetArg(args[0], XtNwidth, &width); n++; + XtSetArg(args[1], XtNheight, &height); n++; + XtGetValues(button, args, n); + XtTranslateCoords(button, (Position) (width / 2), (Position) (height / 2), + &x, &y); + + n = 0; + XtSetArg(args[n], XtNx, x); n++; + XtSetArg(args[n], XtNy, y); n++; + + popup = XtCreatePopupShell("prompt", transientShellWidgetClass, button, + args, n); + + dialog = XtVaCreateManagedWidget("dialog", + dialogWidgetClass, + popup, + NULL); + + /* + * The prompting message's size is dynamic; allow it to request resize. + */ + + XawDialogAddButton(dialog, "ok", Quit, (XtPointer) dialog); + XawDialogAddButton(dialog, "cancel", DestroyPopupPrompt,(XtPointer)dialog); + + XtInstallAllAccelerators(dialog, dialog); + + XtPopup(popup, XtGrabExclusive); + + XtSetKeyboardFocus(toplevel, dialog); +} +/*ARGSUSED*/ +static void +DestroyPopupPrompt(widget, client_data, call_data) +Widget widget; +XtPointer client_data, call_data; +{ + Widget popup = XtParent( (Widget) client_data); + XtDestroyWidget(popup); +} + +/*ARGSUSED*/ +static void +Ok(widget, event, params, num_params) +Widget widget; +XEvent *event; +String *params; +Cardinal *num_params; +{ + catch_exit (); +} + +/*ARGSUSED*/ +static void +Cancel(widget, event, params, num_params) +Widget widget; +XEvent *event; +String *params; +Cardinal *num_params; +{ + Widget dialog = XtParent(widget); + + DestroyPopupPrompt(widget, (XtPointer) dialog, (XtPointer) NULL); +} diff --git a/Uip/rcvtrip/Makefile b/Uip/rcvtrip/Makefile new file mode 100644 index 0000000..4b04a06 --- /dev/null +++ b/Uip/rcvtrip/Makefile @@ -0,0 +1,106 @@ +# Rcvtrip program +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/rcvtrip/RCS/Makefile,v 6.0 1991/12/18 20:42:02 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:42:02 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = rcvtrip.c +OBJS = rcvtrip.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) $(LCF) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) $(LLF) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xrcvtrip + +install: inst-rcvtrip + +inst-rcvtrip: $(USRBINDIR)/rcvtrip + +$(USRBINDIR)/rcvtrip: xrcvtrip + -$(BACKUP) $@ zrcvtrip + rm -f $@ + $(INSTALL) xrcvtrip $@ + -$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "rcvtrip program installed normally"; echo "" + +rcvtrip: xrcvtrip + @true +xrcvtrip: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old xrcvtrip + +lint: l-rcvtrip + +l-rcvtrip: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +rcvtrip.o: rcvtrip.c +rcvtrip.o: ../../h/util.h +rcvtrip.o: ../../h/config.h +rcvtrip.o: ../../h/ll_log.h +rcvtrip.o: ../../h/retcode.h +rcvtrip.o: ../../h/adr.h +rcvtrip.o: ../../h/list_rchan.h +rcvtrip.o: ../../h/chan.h +rcvtrip.o: ../../h/table.h +rcvtrip.o: ../../h/list_bpt.h +rcvtrip.o: ../../h/auth.h +rcvtrip.o: ../../h/list_bpt.h +rcvtrip.o: ../../h/extension.h +rcvtrip.o: ../../h/mta.h +rcvtrip.o: ../../h/adr.h +rcvtrip.o: ../../h/list_bpt.h +rcvtrip.o: ../../h/aparse.h +rcvtrip.o: ../../h/ap.h +rcvtrip.o: ../../h/util.h +rcvtrip.o: ../../h/or.h +rcvtrip.o: ../../h/chan.h +rcvtrip.o: ../../h/auth.h +rcvtrip.o: ../../h/list_rchan.h +rcvtrip.o: ../../h/ap.h +rcvtrip.o: ../../h/chan.h +rcvtrip.o: ../../h/alias.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/rcvtrip/make b/Uip/rcvtrip/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/rcvtrip/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/rcvtrip/rcvtrip.c b/Uip/rcvtrip/rcvtrip.c new file mode 100644 index 0000000..de9e845 --- /dev/null +++ b/Uip/rcvtrip/rcvtrip.c @@ -0,0 +1,749 @@ +/* rcvtrip.c: trip reporting program */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/rcvtrip/RCS/rcvtrip.c,v 6.0 1991/12/18 20:42:02 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/rcvtrip/RCS/rcvtrip.c,v 6.0 1991/12/18 20:42:02 jpo Rel $ + * + * $Log: rcvtrip.c,v $ + * Revision 6.0 1991/12/18 20:42:02 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "retcode.h" +#include "adr.h" +#include "ap.h" +#include "chan.h" +#include "alias.h" +#include + +#define NONFATAL 0 /* Nonfatal reports */ +#define FATAL 1 /* Fatal reports (exit) */ +#define TRACE 2 /* General info for debug */ + +#define EX_SENT 1 +#define EX_DUP 2 +#define EX_NOT_DIR 3 +#define EX_PARSE_ERR 4 +#define EX_ERR 99 + +#define SENT 0 /* Sent out a reply */ +#define UNSENT 1 /* No reply sent - just + * note */ + +#define REPLIED '+' /* A reply was sent */ +#define NOT_REPLIED '-' /* A reply wasn't sent */ + +#define HDR_NAM 1 +#define HDR_EOH 2 +#define HDR_MOR 3 +#define HDR_NEW 4 + +#define DAYS * (60 * 60 * 24) + +#ifndef MAX_HEAD_LINES +#define MAX_HEAD_LINES 10 +#endif /* MAX_HEAD_LINES */ + +extern int ap_outtype; + +extern char *compress (); + +int debug = FALSE; /* output trace messages? */ +int repeat_interval = 14 DAYS; /* repeat after this interval */ +int found_1 = FALSE; /* true if message was sent to */ +int head_lines = 0; +int exit_alg = -1; /* algorithm to deiced on the exit code */ +int exit_code = 1; + + /* directly to recipient */ +char subj_field[LINESIZE]; /* contents of subject field */ +char _username[LINESIZE]; /* space for the users username */ +char *username = (char *) 0; /* the users username */ +char *msg_note = "tripnote";/* where to get reply message from */ +char *wholoc = "triplog"; /* where to note incoming messages */ +char *sigloc = ".signature";/* where to find user's name */ +char *tripsig = "MESSAGE AGENT"; + +/* signature of the returned message */ + +AP_ptr from_adr = NULLAP; /* address tree for from address */ +AP_ptr sndr_adr = NULLAP; /* - " - sender */ +AP_ptr repl_adr = NULLAP; /* - " - reply-to */ + +ADDR *user_adr; + +char *find_sig (); +static int exit_rc(); + +struct passwd *getpwuid (); + +/* + * This message is output before the users file message + */ +char *text_message[MAX_HEAD_LINES+1] = { + "\tThis is an automatic reply. Feel free to send additional", + "mail, as only this one notice will be generated. The following", + "is a prerecorded message, sent for ", 0 +}; + +/* + * This message is output if the users file is not readable or doesn't + * exist. (This is where you can have some fun!) + */ +char *error_txt[] = { + "\tIt appears that the person in question hasn't left a\n", + "message file, so the purpose of this message is unknown.\n", + "However it is assumed that as I, a daemon process,\n", + "have been called into existance that the person in question\n", + "is probably away for some time and won't be replying to your\n", + "message straight away.\n\nCheers,\n\tThe Mail System\n", 0 +}; + +main (argc, argv) +int argc; +char **argv; +{ + init (argc, argv); + parsemsg (); + doreplies (); +#ifdef PP_DEBUG + report (TRACE, 0, "exit with %d -> %d", exit_code, exit_rc(exit_code)); +#endif + exit (exit_rc(exit_code)); +} + +/* + * Initialisation - get user, setup flags etc. + */ + +init (argc, argv) +int argc; +char **argv; +{ + register struct passwd *pwdptr; + int opt; + extern int optind; + extern char *optarg; + RP_Buf rp; + + uip_init (argv[0]); + + ap_outtype = AP_PARSE_822; /* standardise on 822 */ + + while ((opt = getopt (argc, argv, "de:Ff:l:n:s:t:u:")) != EOF) + switch (opt) { + case 'd': debug = 1; break; + case 'e': exit_alg = atoi(optarg); break; + case 'F': found_1 = 1; break; + case 'f': tripsig = optarg; break; + case 'l': wholoc = optarg; break; + case 'n': msg_note = optarg; break; + /* This is disapbled for the momet ... */ + case 'r': opt = atoi(optarg); + if (!opt && *optarg != '0') break; + repeat_interval = opt DAYS; break; + case 's': sigloc = optarg; break; + case 't': if (head_lines < MAX_HEAD_LINES) + text_message[head_lines++] = optarg; break; + case 'u': username = optarg; break; + } +#ifdef PP_DEBUG + report (TRACE, 0, "argc=%d, optind=%d, argv='%s' ... '%s'", + argc, optind, argv[0], argv[argc-1]); +#endif + argv += optind; + argc -= optind; + + if (argc > 0) /* we have a command line sender + * address */ + { +#ifdef PP_DEBUG + report (TRACE, 0, "argc=%d, *argv=%x=`%s'", + argc, *argv, *argv); +#endif + if (*argv) parse_addr (*argv, &sndr_adr); + else report (TRACE, 0, "*argv was null !"); +#ifdef PP_DEBUG + report (TRACE, 0, "*argv parsed"); +#endif + } + + if (username) + ; + else if ((pwdptr = getpwuid (getuid ())) == (struct passwd *) 0) + report (FATAL, EX_ERR, "Can't Identify user"); + else + strcpy (username = _username, pwdptr->pw_name); + + if (head_lines) error_txt[head_lines] = (char *) 0; + + user_adr = adr_new (username, AD_ANY_TYPE, 0); +#ifdef UKORDER + if (rp_isbad (ad_parse (user_adr, &rp, CH_UK_PREF))) +#else + if (rp_isbad (ad_parse (user_adr, &rp, CH_USA_PREF))) +#endif + report (FATAL, EX_PARSE_ERR, "Can't parse you as a mail user"); +} + +/* + * parse message - just a front end to the real parser + */ + +parsemsg () +{ + if (rp_isbad (hdr_fil (stdin))) + report (FATAL, EX_PARSE_ERR, "parse of message failed"); +} + +/*************** Routines to despatch messages ***************/ + +/* + * Send replies to reply-to address if specified else + * from and sender address. + */ + +doreplies () +{ + if (found_1 != TRUE) + report (FATAL, EX_NOT_DIR, "Not sent directly to %s", username); + + if (repl_adr == NULLAP && from_adr == NULLAP && sndr_adr == NULLAP) + report (FATAL, EX_PARSE_ERR, "No parsable from or sender lines"); + +/* + * If there were any reply-to lines, use those in preference. + */ + if (repl_adr != NULLAP) + replyto (repl_adr); + else if (from_adr != NULLAP) + replyto (from_adr); + else if (sndr_adr != NULLAP) + replyto (sndr_adr); +} + +/* + * Actually do the work of sending the reply. + */ + +replyto (aptr) +AP_ptr aptr; +{ + register char *cp; + register char **cpp; + AP_ptr user, local, domain; + AP_ptr norm; + char *addr; + char *ref; + char *person; + char buffer[LINESIZE]; + FILE *fp; + RP_Buf rps, *rp = &rps; + +#ifdef PP_DEBUG + report (TRACE, 0, "replyto()"); +#endif + +#ifdef UKORDER + norm = ap_normalize (aptr, CH_UK_PREF); +#else + norm = ap_normalize (aptr, CH_USA_PREF); +#endif + ap_t2p (norm, (AP_ptr *) 0, &user, &local, &domain, (AP_ptr *) 0); + ref = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP); + +#ifdef PP_DEBUG + report (TRACE, 0, "normed addr = '%s'", ref); +#endif + + if (user != NULLAP) + person = user->ap_obvalue; + else + person = NULLCP; + + if (checkuser (ref)) { + +#ifdef PP_DEBUG + report (TRACE, 0, "Seen %s before", ref); +#endif + + noteuser (ref, UNSENT); + free (ref); + return; + } + if (ap_t2s (norm, &addr) == (AP_ptr) NOTOK) { + report (NONFATAL, 0, "Parse error for %s", addr); + noteuser (ref, UNSENT); + free (ref); + return; + } + buffer[0] = '\0'; + if (!prefix ("re:", subj_field)) + strcpy (buffer, "Re: "); + + strcat (buffer, subj_field); + +#ifdef PP_DEBUG + report (TRACE, 0, "pps_1adr ('%s' %s)", + buffer, addr); +#endif + + pps_1adr (buffer, addr, rp); + + if (person != NULLCP) { + compress (person, person); + sprintf (buffer, "\nDear %s,\n", person); + +#ifdef PP_DEBUG + report (TRACE, 0, "1st line %s", buffer); +#endif + + pps_txt (buffer, rp); + } + +#ifdef PP_DEBUG + report (TRACE, 0, "start builtin message"); +#endif + + for (cpp = text_message; *cpp != NULLCP; cpp++) + { if (cpp != text_message) pps_txt ("\n", rp); + pps_txt (*cpp, rp); + } + if ((cp = find_sig ()) != NULLCP) + pps_txt (cp, rp); + else if (user_adr && user_adr -> ad_r822adr) + pps_txt (user_adr -> ad_r822adr); + else + pps_txt (username, rp); + pps_txt ("\n\n\n", rp); + + if ((fp = fopen (msg_note, "r")) != (FILE *) 0) { + +#ifdef PP_DEBUG + report (TRACE, 0, "processing file %s", msg_note); +#endif + + pps_file (fp, rp); + fclose (fp); + } + else { + +#ifdef PP_DEBUG + report (TRACE, 0, "Sending built in error message"); +#endif + + for (cpp = error_txt; *cpp != NULLCP; cpp++) + pps_txt (*cpp, rp); + } + +#ifdef PP_DEBUG + report (TRACE, 0, "ml_end(OK)"); +#endif + + if (pps_end (OK, rp) == OK) + noteuser (ref, SENT); + else + noteuser (ref, UNSENT); + free (ref); + free (addr); +} + +/*************** Routines to pick apart the message ***************/ + +/* + * The actual picking out of headers + */ + +hdr_fil (msg) +FILE *msg; /* The message file */ +{ + char line[LINESIZE]; /* temp buffer */ + char name[LINESIZE]; /* Name of header field */ + char contents[LINESIZE]; /* Contents of header field */ + +#ifdef PP_DEBUG + report (TRACE, 0, "hdr_fil()"); +#endif + + if (msg == (FILE *) NULL) { + report (FATAL, EX_PARSE_ERR, "NULL file pointer"); + return (RP_NO); /* not much point doing anything + * else */ + } +/* process the file */ + + for (;;) { + if (fgets (line, sizeof line, msg) == NULL) { + report (NONFATAL, 0, "read error on message"); + return (RP_NO); /* skip and go home */ + } + + switch (hdr_parse (line, name, contents)) { + case HDR_NAM: /* No name so contine + * through header */ + continue; + + case HDR_EOH: /* End of header - lets go + * home */ + return (RP_OK); + + case HDR_NEW: + case HDR_MOR: /* We have a valid field */ + if (lexequ (name, "to") == 0 || + lexequ (name, "cc") == 0|| + lexequ (name, "resent-to") == 0 || + lexequ (name, "resent-cc") == 0) { + find_user (contents); + break; + } + else if (lexequ (name, "resent-from") == 0) { + if (from_adr) + ap_free (from_adr); + from_adr = AP_NIL; + parse_addr (contents, &from_adr); + break; + } else if (lexequ (name, "from") == 0) { + parse_addr (contents, &from_adr); + break; + } + else if (lexequ (name, "reply-to") == 0) { + parse_addr (contents, &repl_adr); + break; + } + else if (lexequ (name, "sender") == 0) { + parse_addr (contents, &sndr_adr); + break; + } + else if (lexequ (name, "subject") == 0) { + strncpy (subj_field, contents, + sizeof contents - 1); + break; + } + else + continue; + } + } +} + +/* + * The real parser + */ + +hdr_parse (src, name, contents) /* parse one header line */ +register char *src; /* a line of header text */ +char *name, /* where to put field's name */ + *contents; /* where to put field's contents */ +{ + extern char *compress (); + char linetype; + register char *dest; + +#ifdef PP_DEBUG + report (TRACE, 0, "hdr_parse('%*.*s')", strlen(src)-1, strlen(src)-1, src); +#endif + + if (isspace (*src)) { /* continuation text */ + +#ifdef PP_DEBUG + report (TRACE, 0, "hrd_parse -> cmpnt more"); +#endif + + if (*src == '\n') + return (HDR_EOH); + linetype = HDR_MOR; + } + else { /* copy the name */ + linetype = HDR_NEW; + for (dest = name; *dest = *src++; dest++) { + if (*dest == ':') + break; /* end of the name */ + if (*dest == '\n') { /* oops, end of the +line */ + *dest = '\0'; + return (HDR_NAM); + } + } + *dest = '\0'; + compress (name, name); /* strip extra & trailing + * spaces */ + +#ifdef PP_DEBUG + report (TRACE, 0, "hdr_parse -> cmpnt name '%s'", name); +#endif + } + + for (dest = contents; isspace (*src);) + if (*src++ == '\n') { /* skip leading white space + *//* u + * nfulfilled promise, no + * contents */ + *dest = '\0'; + return ((linetype == HDR_MOR) ? HDR_EOH : linetype); + } /* hack to fix up illegal spaces */ + + while ((*dest = *src) != '\n' && *src != 0) + src++, dest++; /* copy contents and then, backup */ + while (isspace (*--dest)); /* to eliminate trailing + * spaces */ + *++dest = '\0'; + + return (linetype); +} + +/*************** Parsing of addresses got from message ***************/ + +/* + * See if user is in this field. parse address first and + * compare mbox's. + */ + +find_user (str) +char *str; +{ + AP_ptr tree, local, domain; + ADDR *ad; + RP_Buf rp; + char *p; + +#ifdef PP_DEBUG + report (TRACE, 0, "find_user('%s')", str); +#endif + + if (found_1 == TRUE) { + +#ifdef PP_DEBUG + report (TRACE, 0, "find_user() name already found\n"); +#endif + + return; + } + + while ((str = ap_s2p (str, &tree, (AP_ptr *) 0, (AP_ptr *) 0, &local, + (AP_ptr *) &domain, (AP_ptr *) 0)) != (char *) DONE + && str != (char *) NOTOK) { + p = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP); + + ad = adr_new (p, AD_822_TYPE, 0); + ap_sqdelete (tree, NULLAP); + ap_free (tree); + +#ifdef UKORDER + if (rp_isbad (ad_parse (ad, &rp, CH_UK_PREF))) { +#else + if (rp_isbad (ad_parse (ad, &rp, CH_USA_PREF))) { +#endif + adr_free (ad); + continue; + } + found_1 = (lexequ (ad -> ad_r822adr, user_adr -> ad_r822adr) == 0 || + lexequ (p, username) == 0); +#ifdef PP_DEBUG + report (TRACE, 0, "find_user() -> found mbox %s (%s) ->%d", + p, user_adr -> ad_r822adr, found_1); +#endif + free (p); + if (found_1 == TRUE) + return; + } +} + +/* + * Attempt to parse a field into an address tree for later use. + */ + +parse_addr (str, aptr) +char *str; +AP_ptr *aptr; +{ + +#ifdef PP_DEBUG + report (TRACE, 0, "parse_addr('%s')", str); +#endif + + if (*aptr != NULLAP) { + +#ifdef PP_DEBUG + report (TRACE, 0, "field '%s' rejected, already seen one"); +#endif + + return; + } + + if ((*aptr = ap_s2t (str)) == (AP_ptr) NOTOK) + { *aptr = NULLAP; + report (NONFATAL, 0, "Can't parse address '%s'", str); + } +} + +/*************** User Data Base Routines ***************/ + +/* + * Note the fact we did/didnot reply to a given person + * and include the subject line for good measure. + */ + +noteuser (addr, mode) +char *addr; +int mode; +{ + FILE *fp; + time_t now; + char *ctime (); + int result = NOTOK; + +#ifdef PP_DEBUG + report (TRACE, 0, "noteuser(%s,%d)", addr, mode); +#endif + + time (&now); + + if ((fp = fopen (wholoc, "a")) != NULL) { + (void) chmod (wholoc, 0600); + fprintf (fp, "%c %-30s %19.19s >> %.20s\n", + mode == SENT ? REPLIED : NOT_REPLIED, + addr, ctime (&now), subj_field); + (void) fflush (fp); + result = ferror (fp) ? NOTOK : OK; + fclose (fp); + if (result == OK && mode == SENT) exit_code = 0; + } + return result; +} + +/* + * Have we replied to this person before? + */ +checkuser (addr) +char *addr; +{ + FILE *fp; + char buffer[LINESIZE]; + char compaddr[LINESIZE]; + + if (repeat_interval == 0) return FALSE; + + if ((fp = fopen (wholoc, "r")) == NULL) + return FALSE; + while (fgets (buffer, sizeof buffer, fp) != NULL) { + if (buffer[0] == NOT_REPLIED) + continue; + /* SHOULD parse the date to see whether to repeat */ + getaddress (buffer, compaddr); + +#ifdef PP_DEBUG + report (TRACE, 0, "checkuser, = '%s' & '%s'?", compaddr, addr); +#endif + + if (lexequ (compaddr, addr) == 0) { + fclose (fp); + return TRUE; + } + } + fclose (fp); + return FALSE; +} + + +/*************** Some Utility Routines ***************/ + + +/* + * Dig out a signature for the user + */ + +char *find_sig () +{ + FILE *fp; + static char buf[LINESIZE]; + static int been_here = FALSE; + char *p; + +#ifdef PP_DEBUG + report (TRACE, 0, "find_sig()"); +#endif + + if (been_here == TRUE) /* cuts off at least 1/4 + * micro-second */ + return buf; + + if ((fp = fopen (sigloc, "r")) == NULL) + return NULLCP; + if (fgets (buf, sizeof (buf), fp) == NULLCP) { + fclose (fp); + return NULLCP; + } + if ((p = index (buf, '\n')) != NULLCP) + *p = '\0'; + fclose (fp); + return buf; +} + +getaddress (source, dest) +char *source, *dest; +{ + register char *p; + int depth = 0; + + p = source + 2; /* skip over reply indicator */ + while (*p) { + switch (*p) { + case '"': /* in quoted part ? */ + depth = !depth; + break; + case ' ': + case '\t': + if (depth == 0) { + *dest = '\0'; + return; + } + break; + case '\\': /* gobble up next char */ + *dest++ = *p++; + break; + } + *dest++ = *p++; + } + *dest = '\0'; +} + +/*VARARGS2*/ +report (mode, rc, fmt, a1, a2, a3, a4) +int mode; +int rc; +char *fmt, *a1, *a2, *a3, *a4; +{ + static FILE *log; + + if (debug == FALSE && mode == TRACE) + return; + + if (debug == TRUE) { + fprintf (stderr, "%s\t", mode == TRACE ? "TRACE" : + (mode == FATAL ? "FATAL" : "!FATAL")); + fprintf (stderr, fmt, a1, a2, a3, a4); + putc ('\n', stderr); + fflush (stderr); + } + + if (mode == FATAL) + exit (exit_rc(rc)); /* die a horrible death */ +} + +static int exit_rc(num) +int num; +{ + switch (exit_alg) + { + case 0: return RP_MECH; + case 1: return 0; + case 2: return num; + default:return 0; + } +} diff --git a/Uip/resend/Makefile b/Uip/resend/Makefile new file mode 100644 index 0000000..f241840 --- /dev/null +++ b/Uip/resend/Makefile @@ -0,0 +1,107 @@ +# resend utility +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/resend/RCS/Makefile,v 6.0 1991/12/18 20:42:09 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:42:09 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = resend.c +OBJS = resend.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xresend + +resend: xresend + @true + +xresend: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-resend + +inst-resend: $(USRBINDIR)/resend +$(USRBINDIR)/resend: xresend + -$(BACKUP) $@ zxresend + rm -f $@ + $(INSTALL) xresend $@ + -$(CHMOD) $(PGMPROT) $@ + -$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Resend installed normally"; echo "" + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old x* z* + +lint: l-resend + +l-resend: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +resend.o: resend.c +resend.o: ../../h/util.h +resend.o: ../../h/config.h +resend.o: ../../h/ll_log.h +resend.o: ../../h/prm.h +resend.o: ../../h/q.h +resend.o: ../../h/adr.h +resend.o: ../../h/list_rchan.h +resend.o: ../../h/chan.h +resend.o: ../../h/table.h +resend.o: ../../h/list_bpt.h +resend.o: ../../h/auth.h +resend.o: ../../h/list_bpt.h +resend.o: ../../h/extension.h +resend.o: ../../h/mta.h +resend.o: ../../h/adr.h +resend.o: ../../h/list_bpt.h +resend.o: ../../h/aparse.h +resend.o: ../../h/ap.h +resend.o: ../../h/util.h +resend.o: ../../h/or.h +resend.o: ../../h/chan.h +resend.o: ../../h/auth.h +resend.o: ../../h/list_rchan.h +resend.o: ../../h/mta.h +resend.o: ../../h/adr.h +resend.o: ../../h/retcode.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/resend/make b/Uip/resend/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/resend/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/resend/resend.c b/Uip/resend/resend.c new file mode 100644 index 0000000..353162b --- /dev/null +++ b/Uip/resend/resend.c @@ -0,0 +1,261 @@ +/* resend.c: resend a message onwards */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/resend/RCS/resend.c,v 6.0 1991/12/18 20:42:09 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/resend/RCS/resend.c,v 6.0 1991/12/18 20:42:09 jpo Rel $ + * + * $Log: resend.c,v $ + * Revision 6.0 1991/12/18 20:42:09 jpo + * Release 6.0 + * + */ + + + +#include "util.h" +#include "prm.h" +#include "q.h" +#include "adr.h" +#include "retcode.h" +#include +#include +#include +#include + +extern char *strdup(); +extern UTC utclocalise(); + +extern char *loc_dom_site; +extern char *local_822_chan; +extern char *hdr_822_bp; +extern char *ia5_bp; + +static char *username = (char *) 0; + +#define ADR_TO 1 +#define ADR_CC 2 +static int list = ADR_TO; + +#define MAXADRS 100 +static char *toadrs[MAXADRS]; +static int tocnt = 0; +static char *ccadrs[MAXADRS]; +static int cccnt = 0; + +static RP_Buf rps; +static RP_Buf *rp = &rps; +static struct prm_vars prm; +static Q_struct qs; + +static void adios (); + +#define prefix(a,b) (lexnequ ((a), (b), strlen(a)) == 0) + +main (argc, argv) +int argc; +char *argv[]; +{ + char *cp; + + uip_init (argv[0]); + + pgminit (); + + if (argc <= 1) + adios (NULLCP, "No addresses given"); + + while (--argc > 0) { + cp = *++argv; + if (*cp == '-') + switch (cp[1]) { + case 't': + list = ADR_TO; + break; + case 'c': + list = ADR_CC; + break; + case 'u': + username = cp+2; + if (!*username) { username = *++argv; argc--; } + username = strdup(username); + fprintf(stderr, "Username = `%s'\n", username); + break; + default: + adios (NULLCP, "Bad switch %s", cp); + } + else if (list == ADR_TO) + toadrs[tocnt++] = cp; + else ccadrs[cccnt++] = cp; + } + fprintf(stderr, "Now send mail\n"); + sendmail (); + exit (0); +} + +pgminit () +{ + extern struct passwd *getpwuid (); + extern char *getmailid (); + struct passwd *pwdptr; + int realid; + + if (!username) + { realid = getuid (); + + if ((pwdptr = getpwuid (realid)) == (struct passwd *) NULL) + err_abrt (RP_PARM, "Unable to locate user's name"); + + username = strdup (pwdptr -> pw_name); + } +} + +sendmail () +{ + ADDR *adr; + int i; + + prm_init (&prm); + q_init (&qs); + + qs.inbound = list_rchan_new (loc_dom_site, local_822_chan); + qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp); + list_bpt_add (&qs.encodedinfo.eit_types, list_bpt_new (ia5_bp)); + + if (rp_isbad (io_init (rp)) || + rp_isbad (io_wprm (&prm, rp)) || + rp_isbad (io_wrq (&qs, rp))) + adios (NULLCP, "Unable to start submit: %s", rp -> rp_line); + + adr = adr_new (username, AD_822_TYPE, 0); + adr -> ad_status = AD_STAT_DONE; + adr -> ad_resp = NO; + if (rp_isbad (io_wadr (adr, AD_ORIGINATOR, rp))) + adios (NULLCP, "Bad sender %s: %s", + username, rp -> rp_line); + adr_tfree (adr); + + for ( i = 0; i < tocnt; i++) { + adr = adr_new (toadrs[i], AD_822_TYPE, 0); + if (rp_isbad (io_wadr (adr, AD_RECIPIENT, rp))) + adios (NULLCP, "Bad recipeint %s: %s", + toadrs[i], rp -> rp_line); + adr_tfree (adr); + } + for ( i = 0; i < cccnt; i++) { + adr = adr_new (ccadrs[i], AD_822_TYPE, 0); + if (rp_isbad (io_wadr (adr, AD_RECIPIENT, rp))) + adios (NULLCP, "Bad recipeint %s: %s", + ccadrs[i], rp -> rp_line); + adr_tfree (adr); + } + + if (rp_isbad (io_adend (rp)) || + rp_isbad (io_tinit (rp)) || + rp_isbad (io_tpart (hdr_822_bp, 0, rp))) + adios (NULLCP, "Can't initialise for text submission: %s", + rp -> rp_line); + + dumpheader(); + doresent(); + + dobody (); +} + +dumpheader() +{ + char line[LINESIZE]; + + while (fgets (line, LINESIZE, stdin) != NULL) { + if (line[0] == '\n') + break; + if (prefix ("resent-", line) || + prefix ("received:", line) || + prefix ("x400-received", line) || + prefix ("via:", line)) + if (rp_isbad (io_tdata ("Old-", 4))) + adios (NULLCP, "Data Copy failed"); + if (rp_isbad (io_tdata (line, strlen (line)))) + adios (NULLCP, "Data copy failed"); + } +} + +doresent() +{ + char datbuf[64]; + UTC now, lut; + now = utcnow(); + lut = utclocalise(now); + UTC2rfc(lut, datbuf); /* rfc822 format date */ + free ((char *) lut); + sndhdr ("Resent-Date: ", datbuf); + sndhdr ("Resent-From:", username); + doto (); + (void) sprintf (datbuf, "1.%s", ia5_bp); + if ( rp_isbad (io_tdend (rp)) || rp_isbad (io_tpart (datbuf, 0, rp))) + adios (NULLCP, "Can't setup for body part: %s", rp -> rp_line); +} + +sndhdr (name, contents) +char name[], + contents[]; +{ + char linebuf[LINESIZE]; + + (void) sprintf (linebuf, "%-10s%s\n", name, contents); + if (rp_isbad (io_tdata (linebuf, strlen (linebuf)))) + adios (NULLCP, "Data Copy failed"); +} + +doto () +{ + register int i; + + for (i = 0; i < tocnt; i++) + sndhdr ("Resent-To:", toadrs[i]); + for (i = 0; i < cccnt; i++) + sndhdr ("Resent-Cc:", ccadrs[i]); +} + +dobody () +{ + char buffer[BUFSIZ]; + register int i; + + while (!feof (stdin) && !ferror (stdin) && + (i = fread (buffer, sizeof (char), sizeof (buffer), stdin)) > 0) + if (rp_isbad (io_tdata (buffer, i))) + adios (NULLCP, "Problem writing body"); + + if (ferror (stdin)) + adios (NULLCP, "Problem reading body"); + if (rp_isbad (io_tdend (rp)) || rp_isbad (io_tend (rp))) + adios (NULLCP, "Error terminating: %s", rp -> rp_line); +} + +#ifndef lint +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif diff --git a/Uip/sendmail/Makefile b/Uip/sendmail/Makefile new file mode 100644 index 0000000..7543078 --- /dev/null +++ b/Uip/sendmail/Makefile @@ -0,0 +1,108 @@ +# Sendmail Fake +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/Uip/sendmail/RCS/Makefile,v 6.0 1991/12/18 20:42:15 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:42:15 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SRCS = sendmail.c +OBJS = sendmail.o + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: xsendmail + +sendmail: xsendmail + @true + +xsendmail: $(OBJS) $(LIBPP) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPP) $(LIBSYS) + +install: inst-sendmail + +inst-sendmail: $(CMDDIR)/sendmail +$(CMDDIR)/sendmail: xsendmail + -$(BACKUP) $@ zxsendmail + rm -f $@ + $(INSTALL) xsendmail $@ + -@$(CHMOD) $(PGMPROT) $@ + -@$(CHOWN) $(PPUSER) $@ + -@ls -ls $@ + -@echo "Sendmail fake installed normally"; echo "" + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old x* z* + +lint: l-sendmail + +l-sendmail: $(SRCS) + $(LINT) $(LLFLAGS) $(SRCS) $(LINTLIBS) + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ +# DO NOT DELETE THIS LINE MAKE DEPEND NEEDS IT +# Dependencies follow +sendmail.o: sendmail.c +sendmail.o: ../../h/util.h +sendmail.o: ../../h/config.h +sendmail.o: ../../h/ll_log.h +sendmail.o: ../../h/prm.h +sendmail.o: ../../h/q.h +sendmail.o: ../../h/adr.h +sendmail.o: ../../h/list_rchan.h +sendmail.o: ../../h/chan.h +sendmail.o: ../../h/table.h +sendmail.o: ../../h/list_bpt.h +sendmail.o: ../../h/auth.h +sendmail.o: ../../h/list_bpt.h +sendmail.o: ../../h/extension.h +sendmail.o: ../../h/mta.h +sendmail.o: ../../h/adr.h +sendmail.o: ../../h/list_bpt.h +sendmail.o: ../../h/aparse.h +sendmail.o: ../../h/ap.h +sendmail.o: ../../h/util.h +sendmail.o: ../../h/or.h +sendmail.o: ../../h/chan.h +sendmail.o: ../../h/auth.h +sendmail.o: ../../h/list_rchan.h +sendmail.o: ../../h/mta.h +sendmail.o: ../../h/adr.h +sendmail.o: ../../h/retcode.h +sendmail.o: ../../h/ap.h + +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/Uip/sendmail/make b/Uip/sendmail/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/Uip/sendmail/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/Uip/sendmail/sendmail.c b/Uip/sendmail/sendmail.c new file mode 100644 index 0000000..6f3ac61 --- /dev/null +++ b/Uip/sendmail/sendmail.c @@ -0,0 +1,520 @@ +/* sendmail.c: A fake sendmail for those that really need it */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Uip/sendmail/RCS/sendmail.c,v 6.0 1991/12/18 20:42:15 jpo Rel $"; +# endif + +/* + * $Header: /xtel/pp/pp-beta/Uip/sendmail/RCS/sendmail.c,v 6.0 1991/12/18 20:42:15 jpo Rel $ + * + * $Log: sendmail.c,v $ + * Revision 6.0 1991/12/18 20:42:15 jpo + * Release 6.0 + * + */ + + + +#include +#include +#include "util.h" +#include "prm.h" +#include "q.h" +#include "adr.h" +#include "retcode.h" +#include "ap.h" +#include + +extern char *loc_dom_site; +extern char *chndfldir; +extern char *hdr_822_bp; +extern char *ia5_bp; +extern char *local_822_chan; +extern UTC utclocalise(); + +extern struct passwd *getpwuid (); +extern char *getenv(); +extern char *dupfpath(); + +static char *SMTPSRVR = "smtpsrvr"; + +static char *fullname; /* sender's full name */ +static char *from; /* sender's mail address */ +static int verify; +static int badaddrs; +static int rewritefrom; +static int watch; +static int extract_mode; +static char *eaddr[1024]; +static int neaddr; +static char firstline[BUFSIZ]; + +static struct prm_vars prm; +static Q_struct qs; +static RP_Buf rps; +static RP_Buf *rp = &rps; + +static SFD die(); +static void adios (); + +static char tbuf[BUFSIZ]; + +/*ARGSUSED*/ +main(argc, argv) +int argc; +char **argv; +{ + struct passwd *pwdptr; + register char *p; + register char **av; + char **oobto = NULL; + ADDR *adr; + + uip_init(argv[0]); + pp_log_norm -> ll_stat |= LLOGTTY; + + if ((pwdptr = getpwuid (getuid())) == (struct passwd *) NULL) + adios (NULLCP, "Unable to locate user's name"); + + (void) sprintf (tbuf, "%s@%s", pwdptr -> pw_name, loc_dom_site); + from = strdup (tbuf); + + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + (void) signal(SIGINT, die); + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + (void) signal(SIGHUP, die); + (void) signal(SIGTERM, die); + (void) signal(SIGPIPE, die); + + fullname = getenv("NAME"); + /* nobody is going to use this anyway */ + if (p = index(pwdptr->pw_gecos,',')) + *p = 0; + if (!fullname) + fullname = strdup(pwdptr->pw_gecos); + + + av = argv; + while ((p = *++av) != NULL && p[0] == '-') { + switch (p[1]) { + case 'b': /* operations mode */ + switch (p[2]) { + case 'a': /* smtp on stdin */ + case 's': /* smtp on stdin */ + smtp(); + exit(98); /* should never happen */ + case 'm': /* just send mail */ + continue; + case 'v': /* verify mode */ + verify++; + continue; + default: + adios (NULLCP, "Invalid operation mode %c", p[2]); + } + continue; + + case 'f': /* from address */ + case 'r': /* obsolete -f flag */ + p += 2; + if (*p == '\0' && ((p = *++av) == NULL || *p == '-')) + { + p = *++av; + if (p == NULL || *p == '-') { + adios (NULLCP, "No \"from\" person"); + av--; + continue; + } + } + if (rewritefrom) { + adios (NULLCP, "More than one \"from\" person"); + continue; + } + from = p; + rewritefrom++; + continue; + + case 'F': /* set full name */ + p += 2; + if (*p == '\0' && ((p = *++av) == NULL || *p == '-')) + { + adios (NULLCP, "Bad -F flag"); + av--; + continue; + } + fullname = p; + continue; + + case 'h': /* hop count */ + p += 2; + if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p))) + { + adios (NULLCP, "Bad hop count (%s)", p); + av--; + continue; + } + continue; /* Ignore */ + + case 't': /* read recipients from message */ + extract_mode = 1; + continue; + + + case 'v': /* give blow-by-blow description */ + watch++; + continue; + + case 'T': /* set timeout interval */ + case 'C': /* select configuration file (already done) */ + case 'c': /* connect to non-local mailers */ + case 'd': /* debug */ + case 'e': /* error message disposition */ + case 'i': /* don't let dot stop me */ + case 'm': /* send to me too */ + case 'n': /* don't alias */ + case 'o': /* set option, handled in line */ + case 's': /* save From lines in headers */ + continue; + } +} + + setuid(getuid()); + + prm_init (&prm); + prm.prm_opts = PRM_ACCEPTALL; + q_init (&qs); + qs.inbound = list_rchan_new (loc_dom_site, local_822_chan); + qs.encodedinfo.eit_types = list_bpt_new (hdr_822_bp); + list_bpt_add (&qs.encodedinfo.eit_types, list_bpt_new (ia5_bp)); + + if (rp_isbad (io_init (rp)) || + rp_isbad (io_wprm (&prm, rp)) || + rp_isbad (io_wrq (&qs, rp))) + adios (NULLCP, "Unable to submit mail at this time: %s", + rp -> rp_line); + + adr = adr_new (from, AD_822_TYPE, 0); + adr -> ad_status = AD_STAT_DONE; + adr -> ad_resp = NO; + if (rp_isbad (io_wadr (adr, AD_ORIGINATOR, rp))) + adios (NULLCP, "Unable to submit mail from %s: %s", + from, rp -> rp_line); + adr_tfree (adr); + + if (*av == NULL && !extract_mode) { + adios (NULLCP, "Usage: /usr/lib/sendmail [flags] addr..."); + } + read_header (); + oobto = av; + while (*av) + send_address(*av++); + if (extract_mode) { + int i; + + for (i = 0; i < neaddr; i++) + send_address (eaddr[i]); + } + if (rp_isbad (io_adend (rp))) + adios (NULLCP, "Problem with address list."); + if (verify) { + io_end(NOTOK); + exit(badaddrs ? 1 : 0); + } + if (rp_isbad (io_tinit (rp)) || rp_isbad (io_tpart (hdr_822_bp, 0, rp))) + adios (NULLCP, "Problem initialising for text: %s", rp -> rp_line); + + doheader(oobto); + + exit(dobody()); +} + +static struct qbuf *Header; +static struct qbuf *qbase; +static int nleft; +static char *qbptr; + +static void qb_read_init (qp) +struct qbuf *qp; +{ + char *cp; + qbase = qp; + + cp = index (qp -> qb_data, ':'); + if (cp == NULL) + adios (NULLCP, "Internal error - missing ':'"); + cp ++; + nleft = qp -> qb_len - (cp - qp -> qb_data); + qbptr = cp; +} + +int getqbchar () +{ + if (nleft > 0) { + nleft --; + return *qbptr++; + } + qbase = qbase -> qb_forw; + if (qbase == Header) + return EOF; + if (qbase -> qb_data[0] != ' ' && qbase -> qb_data[0] != '\t') + return EOF; + nleft = qbase -> qb_len; + qbptr = qbase -> qb_data; + return getqbchar (); +} + +read_header () +{ + struct qbuf *qp; + char buffer[BUFSIZ]; + AP_ptr ap; + + Header = (struct qbuf *)malloc (sizeof *Header); + Header -> qb_forw = Header -> qb_back = Header; + + while (fgets (buffer, sizeof buffer, stdin) != NULL) { + if (isheader(buffer)) { /* end of header ? */ + qp = str2qb (buffer, strlen (buffer), 0); + insque (qp, Header -> qb_back); + } + else { + strcpy (firstline, buffer); + break; + } + } + + if (!extract_mode) + return; + + for (qp = Header -> qb_forw; qp != Header; qp = qp -> qb_forw) { + if (lexnequ (qp -> qb_data, "to:", 3) == 0 || + lexnequ (qp -> qb_data, "cc:", 3) == 0 || + lexnequ (qp -> qb_data, "bcc:", 4) == 0) { + qb_read_init (qp); + for (;;) { + ap_pinit (getqbchar); + switch (ap_1adr ()) { + case DONE: + break; + + case NOTOK: + adios (NULLCP, "error in address"); + break; + + default: + ap = ap_t2s (ap_pstrt, &eaddr[neaddr++]); + ap_free (ap); + continue; + } + break; + } + } + } +} + + +send_address (addr) +char *addr; +{ + int retval; + ADDR *adr; + + if (watch) { + printf ("%s: ", addr); + (void) fflush (stdout); + } + + adr = adr_new (addr, AD_822_TYPE, 0); + if (rp_isbad (retval = io_wadr (adr, AD_RECIPIENT, rp))) + adios (NULLCP, "Problem in send_address: [%s] %s.", + rp_valstr (retval), + rps.rp_line); + + adr_tfree (adr); + + switch (rp_gval (rp -> rp_val)) { + case RP_AOK: + if(watch) printf ("address ok\n"); + break; + + case RP_NO: + if(watch) printf ("not deliverable; unknown problem\n"); + badaddrs = TRUE; + break; + + case RP_USER: + if(watch) printf ("not deliverable; unknown address.\n"); + badaddrs = TRUE; + break; + + case RP_NDEL: + if(watch) printf ("not deliverable; permanent error.\n"); + badaddrs = TRUE; + break; + + case RP_AGN: + if(watch) printf ("failed, this attempt; try later\n"); + badaddrs = TRUE; + break; + + case RP_NOOP: + if(watch) printf ("not attempted, this time; perhaps try later.\n"); + badaddrs = TRUE; + break; + + default: + adios (NULLCP, "Unexpected address response: %s", rp -> rp_line); + } + (void) fflush (stdout); +} + +doheader(oobto) +char **oobto; +{ + int gotfrom, gotsender, gotdate, gotrecipient; + char line[LINESIZE]; + char buf[LINESIZE]; + struct qbuf *qp; + + gotfrom = gotsender = gotdate = gotrecipient = 0; + for (qp = Header -> qb_forw; qp != Header; qp = qp -> qb_forw) { + if (qp -> qb_data[0] == '\n') + break; + if (prefix ("Date:", qp -> qb_data)) + gotdate++; + if (prefix ("From:", qp -> qb_data)) { + gotfrom++; + if (rewritefrom) { + dofrom(); + continue; + } + } + if (prefix ("Sender:", qp -> qb_data)) + gotsender++; + if (prefix ("To:", qp -> qb_data) + || prefix ("Cc:", qp -> qb_data) + || prefix ("Bcc:", qp -> qb_data) + || prefix ("Apparently-To:", qp -> qb_data) ) + gotrecipient++; + + if (rp_isbad (io_tdata (qp -> qb_data, qp -> qb_len))) + adios (NULLCP, "Data copy error"); + } + + if (!gotrecipient && oobto) { + while (*oobto) { + (void) sprintf (buf, "Apparently-To: %s\n", *oobto++); + if (rp_isbad (io_tdata (buf, strlen(buf)))) + adios (NULLCP, "Data copy error"); + } + } + if (!gotdate) { + UTC now, lut; + (void) strcpy (buf, "Date: "); + now = utcnow(); + lut = utclocalise(now); + UTC2rfc (lut, buf + 6); + free ((char *) lut); + (void) strcat (buf, "\n"); + if (rp_isbad (io_tdata (buf, strlen(buf)))) + adios (NULLCP, "Data copy error"); + } + if (!gotfrom) + dofrom(); + if (!gotsender) { + (void) sprintf(buf, "Sender: %s\n", from); + if (rp_isbad (io_tdata (buf, strlen(buf)))) + adios (NULLCP, "data copy error"); + } + + (void) sprintf (tbuf, "1.%s", ia5_bp); + if (rp_isbad (io_tdend (rp)) || rp_isbad (io_tpart (tbuf, 0, rp))) + adios (NULLCP, "Error seting up for body part: %s", + rp -> rp_line); + if (firstline[0] != '\n') + io_tdata (firstline, strlen(firstline)); + +} + +/* + * Could this be an RFC822 header line? + */ +isheader(line) +char *line; +{ + register char *cp = line; + + while (*cp == ' ' || *cp == '\t') + cp++; + return *cp == '\n' ? 0 : 1; +} + +dofrom() +{ + char line[128]; + + if (isstr(fullname)) + (void) sprintf(line, "From: %s <%s>\n", fullname, from); + else + (void) sprintf(line, "From: %s\n", from); + io_tdata (line, strlen(line)); +} + +dobody() +{ + char buffer[BUFSIZ]; + register int i; + + while (!feof (stdin) && !ferror (stdin) && + (i = fread (buffer, sizeof (char), sizeof (buffer), stdin)) > 0) + if (rp_isbad (i = io_tdata (buffer, i))) + adios (NULLCP, "Problem writing body"); + + if (ferror (stdin)) + adios (NULLCP, "Problem reading body"); + + if (rp_isbad (io_tdend (rp)) || rp_isbad (io_tend (rp))) + adios (NULLCP, "problem ending submission: %s", rp -> rp_line); + + return(0); /* eventually the program exit value */ +} + +smtp() +{ + char *smtpd = dupfpath(chndfldir, SMTPSRVR); + + setuid(geteuid()); + execl (smtpd, "sendmail-smtp", "smtp", (char *)0); + adios ("failed", "execl of %s", smtpd); +} + +#ifndef lint +static void adios (va_alist) +va_dcl +{ + va_list ap; + + va_start (ap); + + _ll_log (pp_log_norm, LLOG_FATAL, ap); + + va_end (ap); + + _exit (1); +} +#else +/* VARARGS2 */ + +static void adios (what, fmt) +char *what, + *fmt; +{ + adios (what, fmt); +} +#endif + +static SFD die(sig) +int sig; +{ + io_end(NOTOK); + adios (NULLCP, "sendmail: dying from signal %d", sig); +} diff --git a/config/OPTIONS.h b/config/OPTIONS.h new file mode 100644 index 0000000..4aa4558 --- /dev/null +++ b/config/OPTIONS.h @@ -0,0 +1,22 @@ +Options for the config.h file are amongst the following. + +define NDBM or DBM depening on what database you have/want. + NDBM - new database stuff - 4.2/3 and sunos. If you have it, use it. + DBM - old dbm needs -ldbm for file access etc. + +Logging for PP + PP_DEBUG - this is a number, set to 0 for no debugging, 1 for some + and 2 for all tracing. + +Nameserver access +#define NAMESERVER if you wish to make use of the BIND domain nameserver. + [Note: This will require proper configuration of the LIBRESOLV + make variable] + +#define HAS_FSYNC define this if your system has the fsync(2) call. + This is defined for you if on a BSD or SVR4 based system. + +#define UKORDER defines that user tools (mlist etc) should use uk rfc-822 + domain ordering by default + +#define VAT define this for some cute special cases. diff --git a/config/OPTIONS.make b/config/OPTIONS.make new file mode 100644 index 0000000..fa86270 --- /dev/null +++ b/config/OPTIONS.make @@ -0,0 +1,153 @@ +This file describes the various macros you will need to define for Make.defs +See volume 1 of the PP user guide for more details. + +BINDIR = /usr/lib/pp/bin +administrator binaries - no user program found here. + +CMDDIR = /usr/lib/pp/cmds +PP main programs + +CHANDIR = $(CMDDIR)/chans +PP channel programs + +FORMDIR = $(CMDDIR)/format +PP formatting channels run under fcontrol + +TOOLDIR = $(CMDDIR)/tools +misc tools + +LOGDIR = /usr/lib/pp/logs +Where the log files should be placed + +MANDIR = /usr/local/man +where the manual pages should go +MANOPTS = -bsd42 +Manual page installation options + +TAILOR = /usr/lib/pp/tailor +The tailor file. This file is critical. + +QUEDIR = /usr/lib/pp/spool/queues +Where the PP disc queue is kept - needs plenty of headroom + +TBLDIR = /usr/lib/pp/tables +Where the routing tables etc go. + +USRBINDIR = /usr/local/bin +Where user visible binaries should be placed. + +# Other Libraries and programs +LIBSYS = -ldsap -lisode +System installed libraries. -ldbm may be useful + +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a +The quipu photo library - required for xalert + +OPTIONALCHANS = lists local shell smtp uucp x40084 +The particular channels that you require building. + +FAXDRIVERS = dexNet200 # or ps250 ... +The particular fax modem you have (need fax in OPTIONALCHANS) + +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +OPTIONALFILTERS = +Other filters you may require + +PEPY = pepy +PYFLAGS = +ISODE pepy program and any global flags + +ROSY = rosy +RYFLAGS = +ISODE rosy program and any global flags + +POSY = posy +POFLAGS = +ISODE posy program and any global flags + +PEPSY = pepsy +ISODE pepsy program +PEPSYHDRS = /usr/local/include/isode/pepsy + +LINTISODE = -lisode +The ISODE lint library if needed. Only useful if you wish to lint the +PP sources + +X11 = true +Set to "true" if you have X11, leave empty otherwise + +LIBX = -lXaw -lXmu -lXt -lX11 +The X11 libraries you will need. + +APPDEFAULTS = /usr/lib/X11/app-defaults +The X11 application defaults directory. + +LIBRESOLV = +The name of the BIND resolver library. You will need to define +NAMESERVER if you want to use this. + +CC = cc +The C compiler +OLDCC = $(CC) +System CC - used to work round gcc (1.37-1.??) bug on sparcs + +CCOPTIONS = -O +Compiler options + +LIBCCOPTIONS = -O +Compiler options for just the libraries. + +LDOPTIONS = +Any loader options needed + +AR = ar +The archiver program + +ARFLAGS = +Archiver flags + +RANLIB = ranlib +The ranlib program if you need it + +LINT = lint +The lint program + +LINTFLAGS = -haxbc +The lint flags in force + +PGMPROT = 755 +The mode for general binaries to be installed with + +PPUSER = pp +The User which will own the PP system + +ROOTUSER = root +The root user - needed for setuid channels + +CHOWN = chown +man 8 chown command + +CHMOD = chmod +man 1 chmod command + +BACKUP = cp +What to use to save backup copies - set to : if you don't want any + +INSTALL = cp +# what to use to install new binaries etc. install(1) is also suitable + + +# Various documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = + diff --git a/config/README b/config/README new file mode 100644 index 0000000..a4ad177 --- /dev/null +++ b/config/README @@ -0,0 +1,7 @@ +Description of the files and directories found in the directory (config/) + +OPTIONS.h - brief description of the .h defines +OPTIONS.make - brief description of the .make macros + +*.h - sample .h files +*.make - sample .make files diff --git a/config/drs6000.h b/config/drs6000.h new file mode 100644 index 0000000..e681e9f --- /dev/null +++ b/config/drs6000.h @@ -0,0 +1,29 @@ +#ifndef _H_CONFIG +#define _H_CONFIG + +#ifndef SYS5 +#define SYS5 /* System 5 */ +#ifndef SVR4 +#define SVR4 /* Release 4 */ +#endif +#endif + +#define GDBM + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 + +#define PP_DEBUG PP_DEBUG_ALL + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ +#define UNICORN + +#endif diff --git a/config/drs6000.make b/config/drs6000.make new file mode 100644 index 0000000..807262b --- /dev/null +++ b/config/drs6000.make @@ -0,0 +1,175 @@ +# Default Configuration values for other Makefiles +# +# You should look through all of them, but in particular lines the first +# too sections. +# Tailor this May need to be tailored to your system +# Check this Ensure that this is OK +# +# NOTE: SUN MAKE AND SOME NEWER MAKES TOO TAKE OF TRAILING SPACES IN A +# MACRO DEFINITION. HENCE YOU SHOULD EITHER REMOVE THE TRAILING COMMENTS +# OR MAKE SURE THE COMMENT STARTS DIRECTLY AFTER THE DEFINITION FOR THOSE +# MACROS WHERE THIS IS IMPORTANT (e.g pathnames). +# +############################################################ +# +# +############################################################ +# + +############################################################ +# +# Things you really should tailor +# +############################################################ + +# List of channels that you may require. Choose from those in the +# Chans/ directory. Each should be a directory name within Chans. +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 +# If fax defined - give type +#FAXDRIVERS = dexNet200 # or ps250 ... +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +# Optional filters +OPTIONALFILTERS = + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -ldbm +# For SYS5 also need -lsocket -lgen + + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # gcc +# suns cc if using gcc on sparc +OLDCC = $(CC) +CCOPTIONS = -O # -g +LIBCCOPTIONS = $(CCOPTIONS) +LDOPTIONS = -s # -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /usr/lib/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /usr/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -bsd42 + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do you have X11 installed? Leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +# The applications default directory +APPDEFAULTS = /usr/lib/X11/app-defaults + + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = + +# Photo support +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a + + +# These commands have a habit of moving around +CHOWN = chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /usr/src/local/niftp +# The niftp interface in use. +NIFTPINTERFACE = sun + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = ranlib +# SYS5 has no ranlib - replace with echo + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = cp +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = diff --git a/config/hpux.h b/config/hpux.h new file mode 100644 index 0000000..049f51f --- /dev/null +++ b/config/hpux.h @@ -0,0 +1,29 @@ +/* config.h: compile time configuration parameters */ + + +#ifndef _H_CONFIG +#define _H_CONFIG + +#define NDBM + + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 +/* turning off all debugging causes the make to fail with lots of + * missing routines . This needs some work. + */ +#define PP_DEBUG PP_DEBUG_SOME + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ + +#define HPUX +#define SYS5 +#endif diff --git a/config/hpux.make b/config/hpux.make new file mode 100644 index 0000000..e69110b --- /dev/null +++ b/config/hpux.make @@ -0,0 +1,145 @@ +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 x40088 fax + +# If fax defined - give type +#FAXDRIVERS = dexNet200 # or ps250 ... + +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -ldbm -lc -lPW -lbsdipc + + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # gcc +OLDCC = $(CC) +# preprocessor symbols space needs expanding, even more than ISODE requires. +CCOPTIONS = -O -W p,-H384000 $(OPTIONS) +LIBCCOPTIONS = $(CCOPTIONS) +LDOPTIONS = -s # -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /usr/lib/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /usr/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -hpux + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do you have X11 installed? Leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +# The applications default directory +APPDEFAULTS = /usr/lib/X11/app-defaults + + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = + +# photo library +LIBPHOTO = /usr/etc/g3fax/libphoto.a + +# These commands have a habit of moving around +CHOWN = chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /usr/src/local/niftp +# The niftp interface in use. +NIFTPINTERFACE = hpux + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = echo + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = cp +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = diff --git a/config/pp.start b/config/pp.start new file mode 100755 index 0000000..6948f77 --- /dev/null +++ b/config/pp.start @@ -0,0 +1,8 @@ +#! /bin/sh + +# +# Start up PP - assume we are PP. +# +cd /usr/pp/cmds +pptsapd > /dev/null 2>&1 +qmgr > /dev/null 2>&1 diff --git a/config/pp.startaspp b/config/pp.startaspp new file mode 100755 index 0000000..3e37c78 --- /dev/null +++ b/config/pp.startaspp @@ -0,0 +1,15 @@ +#! /bin/sh + +# +# Start PP running - assumes we are root. +# This is suitable for running from /etc/rc.local or similar. +# +cd /usr/pp/cmds + +# +# SMTP usually run from inetd +# chans/smtpd smtpsrvr > /dev/null 2>&1 +# + +su pp -c ./pptsapd > /dev/null 2>&1 +su pp -c ./qmgr > /dev/null 2>&1 diff --git a/config/s5r4.h b/config/s5r4.h new file mode 100644 index 0000000..1dac776 --- /dev/null +++ b/config/s5r4.h @@ -0,0 +1,28 @@ +#ifndef _H_CONFIG +#define _H_CONFIG + +#ifndef SYS5 +#define SYS5 /* System 5 */ +#ifndef SVR4 +#define SVR4 /* Release 4 */ +#endif +#endif + +#define GDBM + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 + +#define PP_DEBUG PP_DEBUG_ALL + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ + +#endif diff --git a/config/s5r4.make b/config/s5r4.make new file mode 100644 index 0000000..73d3889 --- /dev/null +++ b/config/s5r4.make @@ -0,0 +1,181 @@ +# Default Configuration values for other Makefiles +# +# You should look through all of them, but in particular lines the first +# too sections. +# Tailor this May need to be tailored to your system +# Check this Ensure that this is OK +# +# NOTE: SUN MAKE AND SOME NEWER MAKES TOO TAKE OF TRAILING SPACES IN A +# MACRO DEFINITION. HENCE YOU SHOULD EITHER REMOVE THE TRAILING COMMENTS +# OR MAKE SURE THE COMMENT STARTS DIRECTLY AFTER THE DEFINITION FOR THOSE +# MACROS WHERE THIS IS IMPORTANT (e.g pathnames). +# +############################################################ +# +# @(#) $Header: /cs/research/pp/hubris/pp-beta/config/RCS/Make.defs.dist,v 5.0 90/09/20 16:35:18 pp Exp Locker: pp $ +# +# $Log: Make.defs.dist,v $ +# Revision 5.0 90/09/20 16:35:18 pp +# rcsforce : 5.0 public release +# +# +############################################################ +# + +############################################################ +# +# Things you really should tailor +# +############################################################ + +# List of channels that you may require. Choose from those in the +# Chans/ directory. Each should be a directory name within Chans. +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 +# If fax defined - give type +#FAXDRIVERS = dexNet200 # or ps250 ... +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +# Optional filters +OPTIONALFILTERS = + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -ldbm +# For SYS5 also need -lsocket -lnsl -lgen + + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # gcc +# suns cc if using gcc on sparc +OLDCC = $(CC) +CCOPTIONS = -O # -g +LIBCCOPTIONS = $(CCOPTIONS) +LDOPTIONS = -s # -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /usr/lib/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /usr/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -bsd42 + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do you have X11 installed? Leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +# The applications default directory +APPDEFAULTS = /usr/lib/X11/app-defaults + + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = + +# Photo support +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a + + +# These commands have a habit of moving around +CHOWN = chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /usr/src/local/niftp +# The niftp interface in use. +NIFTPINTERFACE = sun + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = ranlib +# SYS5 has no ranlib - replace with echo + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = cp +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = diff --git a/config/sun.h b/config/sun.h new file mode 100644 index 0000000..67d0909 --- /dev/null +++ b/config/sun.h @@ -0,0 +1,35 @@ +/* config.h: compile time configuration parameters */ + +/* + * @(#) $Header$ + * + * $Log$ + * + */ + + + +#ifndef _H_CONFIG +#define _H_CONFIG + +#define NDBM + + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 + +#define PP_DEBUG PP_DEBUG_ALL + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ + +/* Add after this anything specific to your host. */ + +#endif diff --git a/config/sun.make b/config/sun.make new file mode 100644 index 0000000..684c30a --- /dev/null +++ b/config/sun.make @@ -0,0 +1,182 @@ +# Default Configuration values for other Makefiles +# +# You should look through all of them, but in particular lines the first +# too sections. +# Tailor this May need to be tailored to your system +# Check this Ensure that this is OK +# +# NOTE: SUN MAKE AND SOME NEWER MAKES TOO TAKE OF TRAILING SPACES IN A +# MACRO DEFINITION. HENCE YOU SHOULD EITHER REMOVE THE TRAILING COMMENTS +# OR MAKE SURE THE COMMENT STARTS DIRECTLY AFTER THE DEFINITION FOR THOSE +# MACROS WHERE THIS IS IMPORTANT (e.g pathnames). +# +############################################################ +# +# @(#) $Header: /cs/research/pp/hubris/pp-beta/config/RCS/Make.defs.dist,v 5.0 90/09/20 16:35:18 pp Exp Locker: pp $ +# +# $Log: Make.defs.dist,v $ +# Revision 5.0 90/09/20 16:35:18 pp +# rcsforce : 5.0 public release +# +# +############################################################ +# + +############################################################ +# +# Things you really should tailor +# +############################################################ + +# List of channels that you may require. Choose from those in the +# Chans/ directory. Each should be a directory name within Chans. +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 +# If fax defined - give type +#FAXDRIVERS = dexNet200 # or ps250 ... + +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +# Optional filters +OPTIONALFILTERS = + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -ldbm +# For SYS5 also need -lsocket -lnsl -lgen + + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # gcc +# suns cc if using gcc on sparc +OLDCC = $(CC) +CCOPTIONS = -O # -g +LIBCCOPTIONS = $(CCOPTIONS) +LDOPTIONS = -s # -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /usr/lib/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /usr/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -bsd42 + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do you have X11 installed? Leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +# The applications default directory +APPDEFAULTS = /usr/lib/X11/app-defaults + + + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = + +# Photo support +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a + +# These commands have a habit of moving around +CHOWN = chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /usr/src/local/niftp +# The niftp interface in use. +NIFTPINTERFACE = sun + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = ranlib +# SYS5 has no ranlib - replace with echo + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = cp +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = diff --git a/config/vax.h b/config/vax.h new file mode 100644 index 0000000..a92384b --- /dev/null +++ b/config/vax.h @@ -0,0 +1,36 @@ +/* config.h: compile time configuration parameters */ + +/* + * @(#) $Header$ + * + * $Log$ + * + */ + + + +#ifndef _H_CONFIG +#define _H_CONFIG + +#define NDBM + + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 + +#define PP_DEBUG PP_DEBUG_ALL + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ + +/* Add after this anything specific to your host. */ + +#endif + diff --git a/config/vax.make b/config/vax.make new file mode 100644 index 0000000..ab0d289 --- /dev/null +++ b/config/vax.make @@ -0,0 +1,181 @@ +# Default Configuration values for other Makefiles +# +# You should look through all of them, but in particular lines the first +# too sections. +# Tailor this May need to be tailored to your system +# Check this Ensure that this is OK +# +# NOTE: SUN MAKE AND SOME NEWER MAKES TOO TAKE OF TRAILING SPACES IN A +# MACRO DEFINITION. HENCE YOU SHOULD EITHER REMOVE THE TRAILING COMMENTS +# OR MAKE SURE THE COMMENT STARTS DIRECTLY AFTER THE DEFINITION FOR THOSE +# MACROS WHERE THIS IS IMPORTANT (e.g pathnames). +# +############################################################ +# +# @(#) $Header: /cs/research/pp/hubris/pp-beta/config/RCS/Make.defs.dist,v 5.0 90/09/20 16:35:18 pp Exp Locker: pp $ +# +# $Log: Make.defs.dist,v $ +# Revision 5.0 90/09/20 16:35:18 pp +# rcsforce : 5.0 public release +# +# +############################################################ +# + +############################################################ +# +# Things you really should tailor +# +############################################################ + +# List of channels that you may require. Choose from those in the +# Chans/ directory. Each should be a directory name within Chans. +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 +# If fax defined - give type +#FAXDRIVERS = dexNet200 # or ps250 ... + +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +#FAXPAGESIZE = -DA4 + +# Optional filters +OPTIONALFILTERS = + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -ldbm +# For SYS5 also need -lsocket -lnsl -lgen + + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # gcc +# suns cc if using gcc on sparc +OLDCC = $(CC) +CCOPTIONS = -O # -g +LIBCCOPTIONS = $(CCOPTIONS) +LDOPTIONS = -s # -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /usr/lib/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /usr/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -bsd42 + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do you have X11 installed? Leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +# The applications default directory +APPDEFAULTS = /usr/lib/X11/app-defaults + + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = + +# PHOTO support +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a + +# These commands have a habit of moving around +CHOWN = chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /usr/src/local/niftp +# The niftp interface in use. +NIFTPINTERFACE = sun + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = ranlib +# SYS5 has no ranlib - replace with echo + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = cp +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..1438828 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,51 @@ +# Document construction +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = manual +ALLDIRS = $(SUBDIRS) ifip6.5-88 tailor funet91 nordunet sun-89 \ + uknet90 unix-niftp + + +############################################################ +# +# Building Rules +# +############################################################ + +default: + @for i in $(SUBDIRS); \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE) );\ + done + +install: + @for i in $(SUBDIRS); \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@);\ + done + + +clean tidy: + @for i in $(ALLDIRS); \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@);\ + done +lint:; + +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..424ae5b --- /dev/null +++ b/doc/README @@ -0,0 +1,37 @@ +[ PP documentation directory ] + +The PP documentaion, such as it is. This consists of the following +directories at present. + +funet91/ + A talk given at the FUNET meeting in spring 91. It contains + a paper, some slides and some ISODE/PP/QUIPU status notes. + +ifip6.5-88/ + The PP talk given at the IFIP-6.5 meeting in October 1988 by + Steve Kille. There is a directory containing the paper in latex + and the slides of the presentation in slitex. + +manual/ + The PP User manual. Subdirectories:- + volume0/ + Introduction and credits + volume1/ + Installation and Operation + volume2/ + Programmers Manual. + volume3/ + PP user manual + +nordunet/ + A talk given at the nordunet conference in autumn 1990. + +sun-89/ + A talk given at the sun users group in 1989 + +tailor/ + Document describing the yet to be introduced tailoring system. + +uknet90/ + A talk given at the uknet meeting in 1990 + diff --git a/doc/funet91/Makefile b/doc/funet91/Makefile new file mode 100644 index 0000000..3514dec --- /dev/null +++ b/doc/funet91/Makefile @@ -0,0 +1,96 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps \ + .ry .py .grap .chem + +.ry.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grap.tex:; grap $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.chem.tex:; chem $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.b.tex:; itbit $< + +.xb.tex:; xtbit $< + +.xwd.tex:; xtwd $< + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grf.tex:; sh -c 'if graph < $< | plot -TeX > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.pct.pic:; pct2pic $< + +.pic.tex:; tpic $< + +.plt.tex:; sh -c 'if plot -TeX < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if tgrind -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if latex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if dvialw $(DFLAGS) $< ; \ + then exit 0; else rm $@; exit 1; fi' + mv $*.alw $@ + + +############################################################# +# Here it is... +############################################################# + + + +############################################################# +# pp +############################################################# + +all: pp.dvi pp-slides.dvi bof-slides.dvi + +print: pp.ps pp-slides.ps bof-slides.ps + +# customization files, et. al., not included below +pp.dvi: pp.vrsn + +pp.vrsn: pp.tex pp.bbl version.sh figure1.tex figure2.tex + @version.sh pp + +pp-slides.dvi: pp-slides.tex + sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +bof-slides.dvi: bof-slides.tex + sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +biblio:; bibtex pp + +preview: pp.dvi true + xtex pp.dvi + +index:; idx2ind -l pp + +clean:; rm -f *.ps *.dvi *.log \ + *.blg _* + +true:; diff --git a/doc/funet91/bcustom.bib b/doc/funet91/bcustom.bib new file mode 100644 index 0000000..2c10b96 --- /dev/null +++ b/doc/funet91/bcustom.bib @@ -0,0 +1,39 @@ +% BibTeX customization + +% people +@string{mtr = "Marshall T. Rose"} +@string{jpo = "Julian P. Onions"} + +% places +@string{bbn = "Bolt, Beranek, and Newman, Inc."} +@string{ccitt = "International Telegraph and Telephone Consultative Committee"} +@string{cis = "Department of Computer and Information Sciences"} +@string{ee = "Department of Electrical Engineering"} +@string{ics = "Department of Information and Computer Science"} +@string{iso/iec = "International Organization for Standardization/International Electrotechnical Institute"} +@string{nic = "DDN Network Information Center"} +@string{nrtc = "Northrop Research and Technology Center"} +@string{rand = "The Rand Corporation"} +@string{sri = "SRI International"} +@string{twg = "The Wollongong Group"} +@string{uci = "University of California, Irvine"} +@string{ucl = "University College London"} +@string{udel = "University of Delaware"} +@string{unott = "University of Nottingham"} + +% journals +@string{connexions = "ConneXions"} +@string{cn/isdn = "Computer Networks and ISDN Systems"} +@string{ccr = "Computer Communication Review"} +@string{ieeecom = "IEEE Transactions on Communications"} +@string{ieeecm = "IEEE Communications Magazine"} +@string{jsac = "IEEE Journal on Selected Areas in Communications"} + +% handbooks +@string{ddn = "DDN Protocol Handbook, + Volume One: \dod/ Military Standard Protocols, + DDN Network Information Center, SRI International"} + +% types +@string{idea = "IDEA"} +@string{rfc = "Request for Comments"} diff --git a/doc/funet91/bof-slides.tex b/doc/funet91/bof-slides.tex new file mode 100644 index 0000000..94fb8c5 --- /dev/null +++ b/doc/funet91/bof-slides.tex @@ -0,0 +1,139 @@ +% -*- LaTeX -* Although it's slitex really + +\documentstyle[blackandwhite,pagenumbers,small,oval,psfig,tgrind]{NRslides} + +\raggedright + +\begin{document} +\title {ISODE/PP/QUIPU BOF} + +\author{Julian P.~Onions\\ +j.onions@xtel.co.uk\\[.5in] +X-Tel Services Ltd.\\ +Nottingham University\\ +Nottingham NG7 2RD\\ +ENGLAND} + +\date {March 19th, 1991} + +\maketitle + +\begin{bwslide} +\ctitle{CONTENTS} +\begin{nrtc} +\item Where are we now? + \begin{itemize} + \item Current state of ISODE + \item Current state of QUIPU + \item Current state of PP + \end{itemize} + +\item Whats coming up next? + \begin{itemize} + \item What is happening to ISODE + \item Where is QUIPU going + \item what are the plans for PP + \end{itemize} +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Where are we now -- ISODE} +\begin{nrtc} +\item 6.0 is the official released version - released Jan 1990 +\item 6.8 is an interim version. Released March 1991. +\item 7.0 is the next official release - when? (Anybodys guess) +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Changes in ISODE up to 6.8} +\begin{nrtc} +\item New ASN.1 compiler (PEPSY) + \begin{itemize} + \item Smaller code. + \item faster? + \item Harder to debug! + \end{itemize} +\item Many many bug fixes +\item Some changes to smnp +\item Has shared libraries under SUN OS 4.1 +\item DS can be used for bootstrapping now - DASED and IAED. +\item Application lookup using DS. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Changes in Quipu up to 6.8} +\begin{nrtc} +\item Changed to make use of pepsy (smaller binaries) +\item Internal data structures now stored as an AVL tree. +\item Indexing ability on sub-trees. +\item Spot shadowing of entries -- including a DSA mastering its own entry. +\item Attribute inheritance down the tree +\item DSA relaying +\item User friendly naming in the directory (UFN) +\item T.61 string handling +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Current state of PP} +\begin{nrtc} +\item Current version is an interim 5.2 release. +\item Reasonably stable +\item Supports many protocols. + \begin{itemize} + \item X.400 -- 1898 and 1988 + \item SMTP with DNS + \item UUCP + \item Local delivery + \item Greybook + \item Reformatting and interworking between all the above + \end{itemize} +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{ISODE -- things planned} +\begin{nrtc} +\item Basically not very much. +\item Profiling and speeding up high on the agenda +\item TLI transport interface. +\item Maybe look at other ASN.1 encodings. +\item Bug fixing (as ever!) +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Changes to QUIPU planned} +\begin{nrtc} +\item Alignment to Internet DSP (as per emerging RFC) +\item Management controls and Authorisation for operations. +\item DIT counting +\item DS for all lookups of ISODE applications +\item Strong authentication of operations +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Changes to PP planned} +\begin{nrtc} +\item For 6.0 release + \begin{itemize} + \item FAX gateway -- subject to the whims of manufacturers + \item More robust, faster etc. + \item Better support of deliver reports + \item Channel pairing. + \end{itemize} +\item For 7.0 release + \begin{itemize} + \item Integration with the directory for routing and name +lookup. + \item Most tables then optional. + \item A P7/P7+/P3 message store available + \item An X based X.400 user agent available with the release. + \end{itemize} +\end{nrtc} +\end{bwslide} +\end{document} diff --git a/doc/funet91/captcont.sty b/doc/funet91/captcont.sty new file mode 100644 index 0000000..70f662e --- /dev/null +++ b/doc/funet91/captcont.sty @@ -0,0 +1,16 @@ +% SubStyle file to permit the use of captions in continuations of floats. +% +% \captcont is like \caption, except that it doesn't update the counter, and +% it doesn't make an entry in the list of figures or list of tables. + +\def\captcont{\@dblarg{\@captcont\@captype}} + +\long\def\@captcont#1[#2]#3{ +% \addcontentsline{\csname ext@#1\endcsname}{#1}{\protect\numberline{\csname +% the#1\endcsname}{\ignorespaces #2}} + \par + \begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} diff --git a/doc/funet91/figure1.pic b/doc/funet91/figure1.pic new file mode 100644 index 0000000..f03143f --- /dev/null +++ b/doc/funet91/figure1.pic @@ -0,0 +1,52 @@ +.PS 5 +eighth = 1/8 +boxwid = 0.5 +boxht = 0.25 +arrowhead = 7 +arrowht = eighth/2 +define user X box "User" X +define ua X box "UA" wid 7/16 X +define mta X box "MTA" X +MHE: box dotted ht 4 + eighth wid 6.25 + "Message Handling Environment" at MHE.nw + (eighth, -eighth) ljust +MHS: box ht 3.25 wid 4.5 with .s at MHE.s + (0,eighth) + "MHS" ljust at MHS.nw + (0.25, -0.25) +MTS: box dashed ht 2.5 wid 3 - eighth with .s at MHS.s + (0,eighth) + "MTS" ljust at MTS.nw + (0.25, -0.25) + + user with .e at MHS.sw + (-eighth, 1) +Ua1: ua with .w at MHS.sw + (eighth, 1) + line <-> from 2nd last box.e to last box.w + + user with .e at MHS.sw + (-eighth, 2) +Ua2: ua with .w at MHS.sw + (eighth, 2) + line <-> from 2nd last box.e to last box.w + + user with .s at MHS.n + (0, eighth) +Ua3: ua with .n at MHS.n - (0,eighth) + line <-> from 2nd last box.s to last box.n + + user with .w at MHS.se + (eighth,0.5) +Ua4: ua with .e at MHS.se + (-eighth, 0.5) + line <-> from 2nd last box.w to last box.e + +Mta1: mta with .w at MTS.sw + (eighth, 1.25) + line <-> from Ua1.e to Mta1.sw + line <-> from Ua2.e to Mta1.nw + +Mta2: mta with .n at MTS.n + (0, -eighth) + line <-> from Mta1.n to Mta2.w + line <-> from Mta2.n to Ua3.s + +Mta3: mta with .e at MTS.se + (-eighth, 1.25) + line <-> from Mta2.e to Mta3.n + line <-> from Mta1.e to Mta3.w + +Mta4: mta with .e at Ua4.w - (0.5,0) + line <-> from Mta4.e to Ua4.w + line <-> from Mta3.s to Mta4.n + +Mta5: mta with .e at Mta4.w - (0.5,0) + line <-> from Mta4.w to Mta5.e + line <-> from Mta5.n to Mta1.s +.PE diff --git a/doc/funet91/figure1.tex b/doc/funet91/figure1.tex new file mode 100644 index 0000000..7e127a6 --- /dev/null +++ b/doc/funet91/figure1.tex @@ -0,0 +1,317 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{pa 0 3300}% + \special{pa 5000 3300}% + \special{dt 0.050}% + \special{pa 5000 3300}% + \special{pa 5000 0}% + \special{dt 0.050}% + \special{pa 5000 0}% + \special{pa 0 0}% + \special{dt 0.050}% + \special{pa 0 0}% + \special{pa 0 3300}% + \special{dt 0.050}% + \rlap{\kern 0.100in\lower 0.141in\hbox to0pt{Message Handling Environment\hss}}% + \special{pa 700 3200}% + \special{pa 700 600}% + \special{pa 4300 600}% + \special{pa 4300 3200}% + \special{pa 700 3200}% + \special{fp}% + \rlap{\kern 0.900in\lower 0.841in\hbox to0pt{MHS\hss}}% + \special{pa 1350 3100}% + \special{pa 3650 3100}% + \special{da 0.050}% + \special{pa 3650 3100}% + \special{pa 3650 1100}% + \special{da 0.050}% + \special{pa 3650 1100}% + \special{pa 1350 1100}% + \special{da 0.050}% + \special{pa 1350 1100}% + \special{pa 1350 3100}% + \special{da 0.050}% + \rlap{\kern 1.550in\lower 1.341in\hbox to0pt{MTS\hss}}% + \special{pa 200 2500}% + \special{pa 200 2300}% + \special{pa 600 2300}% + \special{pa 600 2500}% + \special{pa 200 2500}% + \special{fp}% + \rlap{\kern 0.400in\lower 2.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 2500}% + \special{pa 800 2300}% + \special{pa 1150 2300}% + \special{pa 1150 2500}% + \special{pa 800 2500}% + \special{fp}% + \rlap{\kern 0.975in\lower 2.441in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 2380}% + \special{pa 600 2400}% + \special{fp}% + \special{pa 650 2420}% + \special{pa 600 2400}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2420}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2380}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 200 1700}% + \special{pa 200 1500}% + \special{pa 600 1500}% + \special{pa 600 1700}% + \special{pa 200 1700}% + \special{fp}% + \rlap{\kern 0.400in\lower 1.641in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 1700}% + \special{pa 800 1500}% + \special{pa 1150 1500}% + \special{pa 1150 1700}% + \special{pa 800 1700}% + \special{fp}% + \rlap{\kern 0.975in\lower 1.641in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 1580}% + \special{pa 600 1600}% + \special{fp}% + \special{pa 650 1620}% + \special{pa 600 1600}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1620}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1580}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 2300 500}% + \special{pa 2300 300}% + \special{pa 2700 300}% + \special{pa 2700 500}% + \special{pa 2300 500}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 2325 900}% + \special{pa 2325 700}% + \special{pa 2675 700}% + \special{pa 2675 900}% + \special{pa 2325 900}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 2520 550}% + \special{pa 2500 500}% + \special{fp}% + \special{pa 2480 550}% + \special{pa 2500 500}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2480 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2520 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 4400 2900}% + \special{pa 4400 2700}% + \special{pa 4800 2700}% + \special{pa 4800 2900}% + \special{pa 4400 2900}% + \special{fp}% + \rlap{\kern 4.600in\lower 2.841in\hbox to 0pt{\hss User\hss}}% + \special{pa 3850 2900}% + \special{pa 3850 2700}% + \special{pa 4200 2700}% + \special{pa 4200 2900}% + \special{pa 3850 2900}% + \special{fp}% + \rlap{\kern 4.025in\lower 2.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 4350 2820}% + \special{pa 4400 2800}% + \special{fp}% + \special{pa 4350 2780}% + \special{pa 4400 2800}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2780}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2820}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 1450 2200}% + \special{pa 1450 2000}% + \special{pa 1850 2000}% + \special{pa 1850 2200}% + \special{pa 1450 2200}% + \special{fp}% + \rlap{\kern 1.650in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1181 2356}% + \special{pa 1150 2400}% + \special{fp}% + \special{pa 1203 2389}% + \special{pa 1150 2400}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1419 2244}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1397 2211}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1196 1628}% + \special{pa 1150 1600}% + \special{fp}% + \special{pa 1164 1652}% + \special{pa 1150 1600}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1404 1972}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1436 1948}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 2300 1400}% + \special{pa 2300 1200}% + \special{pa 2700 1200}% + \special{pa 2700 1400}% + \special{pa 2300 1400}% + \special{fp}% + \rlap{\kern 2.500in\lower 1.341in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1669 1950}% + \special{pa 1650 2000}% + \special{fp}% + \special{pa 1699 1977}% + \special{pa 1650 2000}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2281 1350}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2251 1323}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2480 1150}% + \special{pa 2500 1200}% + \special{fp}% + \special{pa 2520 1150}% + \special{pa 2500 1200}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2520 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2480 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 3150 2200}% + \special{pa 3150 2000}% + \special{pa 3550 2000}% + \special{pa 3550 2200}% + \special{pa 3150 2200}% + \special{fp}% + \rlap{\kern 3.350in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 2749 1323}% + \special{pa 2700 1300}% + \special{fp}% + \special{pa 2719 1350}% + \special{pa 2700 1300}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3301 1977}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3331 1950}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 1900 2080}% + \special{pa 1850 2100}% + \special{fp}% + \special{pa 1900 2120}% + \special{pa 1850 2100}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2120}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2080}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3050 2900}% + \special{pa 3050 2700}% + \special{pa 3450 2700}% + \special{pa 3450 2900}% + \special{pa 3050 2900}% + \special{fp}% + \rlap{\kern 3.250in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3500 2780}% + \special{pa 3450 2800}% + \special{fp}% + \special{pa 3500 2820}% + \special{pa 3450 2800}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2820}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2780}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3360 2253}% + \special{pa 3350 2200}% + \special{fp}% + \special{pa 3321 2245}% + \special{pa 3350 2200}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3240 2647}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3279 2655}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 2250 2900}% + \special{pa 2250 2700}% + \special{pa 2650 2700}% + \special{pa 2650 2900}% + \special{pa 2250 2900}% + \special{fp}% + \rlap{\kern 2.450in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3000 2820}% + \special{pa 3050 2800}% + \special{fp}% + \special{pa 3000 2780}% + \special{pa 3050 2800}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2780}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2820}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2397 2690}% + \special{pa 2450 2700}% + \special{fp}% + \special{pa 2418 2657}% + \special{pa 2450 2700}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1703 2210}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1682 2243}% + \special{pa 1650 2200}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 3.301in +} diff --git a/doc/funet91/figure2.pic b/doc/funet91/figure2.pic new file mode 100644 index 0000000..0e8dbf9 --- /dev/null +++ b/doc/funet91/figure2.pic @@ -0,0 +1,15 @@ +.PS 5 +Inb: ellipse "Inbound" "Channel" + line <-> down right from Inb.se +Submit: ellipse "Submit" with .nw at last line .end + line <-> up right from Submit.ne + ellipse "UA" with .sw at last line .end + line <-> down left from Submit.sw +Qmgr: ellipse "QMGR" with .ne at last line .end + line <-> down right from Qmgr.se +Out: ellipse "Outbound" "Channel" with .nw at last line .end + line <-> down right from Submit.se +Que: box "Queue" with .nw at last line .end + (0, boxht/4) + line <-> dashed from Qmgr.e to Que.w + line <-> from 3/4 to Out.ne +.PE diff --git a/doc/funet91/figure2.tex b/doc/funet91/figure2.tex new file mode 100644 index 0000000..e5898bc --- /dev/null +++ b/doc/funet91/figure2.tex @@ -0,0 +1,123 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{ar 642 428 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 0.386in\hbox to 0pt{\hss Inbound\hss}}% + \rlap{\kern 0.642in\lower 0.552in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 1247 821}% + \special{pa 1096 731}% + \special{fp}% + \special{pa 1187 882}% + \special{pa 1096 731}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1801 1496}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1861 1435}% + \special{pa 1952 1587}% + \special{fp}% + \special{ar 2406 1889 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 1.930in\hbox to 0pt{\hss Submit\hss}}% + \special{pa 2951 1435}% + \special{pa 2860 1587}% + \special{fp}% + \special{pa 3011 1496}% + \special{pa 2860 1587}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3625 882}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3565 821}% + \special{pa 3716 731}% + \special{fp}% + \special{ar 4170 428 642 427 0.000 6.283}% + \rlap{\kern 4.170in\lower 0.469in\hbox to 0pt{\hss UA\hss}}% + \special{pa 1861 2343}% + \special{pa 1952 2192}% + \special{fp}% + \special{pa 1801 2283}% + \special{pa 1952 2192}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1187 2897}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1247 2957}% + \special{pa 1096 3048}% + \special{fp}% + \special{ar 642 3351 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 3.392in\hbox to 0pt{\hss QMGR\hss}}% + \special{pa 1247 3744}% + \special{pa 1096 3653}% + \special{fp}% + \special{pa 1187 3805}% + \special{pa 1096 3653}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1801 4418}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1861 4358}% + \special{pa 1952 4509}% + \special{fp}% + \special{ar 2406 4812 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 4.770in\hbox to 0pt{\hss Outbound\hss}}% + \rlap{\kern 2.406in\lower 4.936in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 3011 2283}% + \special{pa 2860 2192}% + \special{fp}% + \special{pa 2951 2343}% + \special{pa 2860 2192}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3565 2957}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3625 2897}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3716 3690}% + \special{pa 3716 2834}% + \special{pa 5000 2834}% + \special{pa 5000 3690}% + \special{pa 3716 3690}% + \special{fp}% + \rlap{\kern 4.358in\lower 3.303in\hbox to 0pt{\hss Queue\hss}}% + \special{pa 1454 3302}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1457 3387}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1284 3351}% + \special{pa 3716 3262}% + \special{da 0.050}% + \special{pa 3546 3311}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3543 3225}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3640 3635}% + \special{pa 3716 3476}% + \special{fp}% + \special{pa 3574 3581}% + \special{pa 3716 3476}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 2936 4350}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 3002 4405}% + \special{pa 2860 4509}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 5.240in +} diff --git a/doc/funet91/jpo.bib b/doc/funet91/jpo.bib new file mode 100644 index 0000000..26455fe --- /dev/null +++ b/doc/funet91/jpo.bib @@ -0,0 +1,65 @@ +% ``jpo'' bibliography database + + +@techreport{TP0.bridge, + author = "Julian P. Onions and Marshall T. Rose", + title = "{ISO-TP0 bridge between TCP and X.25}", + type = rfc, + number = 1086, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@inproceedings{Amigo.DL, + author = "Steve Benford and Julian Onions", + title = "{Pilot Distribution Lists -- Agents and Directories}", + booktitle= "{Proceedings, Third International Symposium on + Computer Message Systems}", + publisher= {North Holland}, + month = apr, + year = 1987, + note = {Munich, Germany}, +} + +@inproceedings{Amigo.DL.IMP, + author = "Steve Benford and Julian Onions and Manfred Bogen and + Bernd Wagner", + title = "{The Implementation of Amigo Distribution Lists}", + publisher= {North Holland}, + year = 1988, + month = apr, + booktitle= {Proceedings of the EUTECO Conference} +} + +@book{Amigo.MHSbook, + title = "{Distributed Group Communication -- The AMIGO + Information Model.}", + author = "Hugh Smith and Julian Onions and Steve Benford", + year = 1989, + publisher= "Ellis Horwood", + address = "Chichester, England" +} + +@inproceedings{Applications.Cookbook, + author = "Julian P. Onions and Marshall T. Rose", + title = "{The Application Cookbook}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{X400.Tutorial, + author = jpo, + title = "{Components of OSI: X.400}", + journal = connexions, + volume = 3, + number = 5, + month = may, + year = 1989, + pages = {2--8} +} diff --git a/doc/funet91/lcustom.tex b/doc/funet91/lcustom.tex new file mode 100644 index 0000000..5ae23b3 --- /dev/null +++ b/doc/funet91/lcustom.tex @@ -0,0 +1,350 @@ +% LaTeX customization + + +\makeatletter % for a little while + + +% plain TeX compatibility + +\def\oldstyle{\xdef\@oldstyle{\the\textfont\@ne}\mit\@oldstyle} + + +% PhD-TeX compatibility + +\def\showsummary{% + \begingroup + \def\note##1{% + \ifcase\value{##1}no ##1s\or + 1 ##1\else + \the\value{##1} ##1s\fi + }% + \typeout{LaTeX summary: \note{figure}, \note{table}, \note{footnote}.}% + \endgroup +} + +\def\smaller{\footnotesize} + + +% Float Support + +\def\topfraction{0.85} +\def\textfraction{0.20} +\def\floatpagefraction{0.85} +\def\dbltopfraction{0.85} +\def\dblfloatpagefraction{0.85} + +\def\@tagskipcommand{\vskip .5\baselineskip} + +% \tagfigure*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads TPIC output in file figureFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagfigure{\@ifstar{\@stagfigure}{\@tagfigure}} +\def\@tagfigure{\@ifnextchar[{\@@tagfigure}{\@@tagfigure[t]}} +\def\@stagfigure{\@ifnextchar[{\@@stagfigure}{\@@stagfigure[t]}} + +\def\@@tagfigure[#1]#2{% + \@@@tagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} +\def\@@stagfigure[#1]#2{% + \@@@stagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} + + +% \tagdiagram*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeX input in file diagramFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagdiagram{\@ifstar{\@stagdiagram}{\@tagdiagram}} +\def\@tagdiagram{\@ifnextchar[{\@@tagdiagram}{\@@tagdiagram[t]}} +\def\@stagdiagram{\@ifnextchar[{\@@stagdiagram}{\@@stagdiagram[t]}} + +\def\@@tagdiagram[#1]#2{\@@@tagfigure[#1]{\input diagram#2\relax}} +\def\@@stagdiagram[#1]#2{\@@@stagfigure[#1]{\input diagram#2\relax}} + +\def\@@@tagfigure[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@@stagfigure[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +% \tagtable*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FILE read LaTeX input in file tableFILE +% FLOAT float options +% CAPTION for list of tables +% LABEL for \ref and \pageref +\def\tagtable{\@ifstar{\@stagtable}{\@tagtable}} +\def\@tagtable{\@ifnextchar[{\@@tagtable}{\@@tagtable[t]}} +\def\@stagtable{\@ifnextchar[{\@@stagtable}{\@@stagtable[t]}} + +\def\@@tagtable[#1]#2#3#4{% + \begin{table}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table} +} + +\def\@@stagtable[#1]#2#3#4{% + \begin{table*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table*} +} + + +% Environments: + +% DESCRIBE - similar to DESCRIPTION, but indents extra on left margin of +% outer list + +\def\describe{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \ifnum\@listdepth=1 \advance\leftmargin by2em\fi + \let\makelabel\descriptionlabel}} +\let\enddescribe=\endlist + + +% Document style options: +% 10pt - Makes ten-point type the normal (default) type size +% draftnote - Customized draft option + +\@namedef{ds@10pt}{\def\@ptsize{0}} %%% for orthogonality + + +\newif\ifdraft \draftfalse + +\def\draftstring{{\ifdraft \tt Draft\fi}} + +\def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today\ with \fmtname\ v\fmtversion + \else + Draft \versiontag/ of \versiondate/ + \fi + \endgroup + \fi +} + +\def\versiontag/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}%6 + \versiontag/% +} +\def\versiondate/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}% + \versiondate/% +} + +\def\ds@draftnote{% + \drafttrue + \@ifundefined{ds@draft}{}{\ds@draft}% + \def\ps@plain{% + \let\@mkboth=\@gobbletwo + \def\@oddhead{\draftext\hfil}% + \def\@oddfoot{\draftstring\hfil\rm\thepage\hfil\draftstring}% + \def\@evenhead{\hfil\draftext}% + \let\@evenfoot=\@oddfoot + }% + \let\ps@@headings=\ps@headings + \def\ps@headings{% + \ps@@headings + \def\@oddfoot{\draftext\hfil}% + \def\@evenfoot{\hfil\draftext}% + }% +} + + +% Page Styles + +% \pagestyle{myfootings} similar to the myheadings command but also permits +% the user to define foot information as well as head information +% \markleftfoot{left_foot} specifies the foot for odd-numbered +% pages +% \markrightfoot{right_foot} specifies the foot for even-numbered +% pages +% N.B. DOES NOT USE MARKS TO ACCOMPLISH THIS, OWING TO CONFLICT WITH HEADING +% ROUTINES + +\def\ps@myfootings{\ps@myheadings} + +\def\markleftfoot#1{\def\@evenfoot{\hbox{}\sl#1\hfil}} +\def\markrightfoot#1{\def\@oddfoot{\hfil\sl#1\hbox{}}} + + +% \pagestyle{reprint} similar to plain page style in draft mode + +\let\reprintext=\draftext +\let\reprintstring=\draftstring + +\def\ps@reprint{% + \def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today + \else + Draft \versiontag/ + \fi + \endgroup + \fi + }% + \def\@oddhead{\reprintext\hfil\draftext}% + \def\@oddfoot{\reprintstring\hfil\rm\thepage}% + \def\@evenhead{\draftext\hfil\reprintext}% + \def\@evenfoot{\rm\thepage\hfil\reprintstring}% +} + + +% The Title + +\def\title#1{% + \gdef\@title{#1}% + \gdef\banner{% + \newpage\setcounter{page}{1}% + \begin{center}\Large#1\end{center}% + }% +} + + +% Miscellany + +\def\implies{\quad\supset\ } + +\def\tdots{\ldots\thinspace} + +\def\boxit#1{\fbox{\sc#1}} + +\def\note#1{\ifdraft\marginpar{\tt#1}\fi} + + +% Fractions (from The TUGboat v6 n1, 1985) + +\def\myfrac#1/#2{% + \leavevmode\kern.1em + \raise.5ex\mbox{\the\scriptfont\z@ #1}\kern-.1em + /\kern-.15em\lower.25ex\mbox{\the\scriptfont\z@ #2}% +} + + +% Trademarks... + +\input trademark + + +% Continuation Captions... + +\input captcont.sty + + +% Startup + +\xdef\today{% + \ifcase\month + \number\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\else + \number\month\fi + \space\number\day, {\noexpand\mit\number\year}% +} + +\begingroup + \count0=\time + \count1=\count0 + \divide\count0 by 60 + \count2=\count0 + \multiply\count0 by 60 + \advance\count1 by -\count0 + \ifnum\count2>11 + \ifnum\count2>12 \advance\count2 by -12\fi + \def\ampm{pm}% + \else + \ifnum\count2=0 \advance\count2 by 12\fi + \def\ampm{am}% + \fi + \xdef\daytime{% + \ifnum\count2<10 0\fi \the\count2:% + \ifnum\count1<10 0\fi \the\count1 + \ampm + }% +\endgroup + + +\makeatother % back to normal diff --git a/doc/funet91/make b/doc/funet91/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/funet91/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/funet91/networking.bib b/doc/funet91/networking.bib new file mode 100644 index 0000000..22fbe33 --- /dev/null +++ b/doc/funet91/networking.bib @@ -0,0 +1,1768 @@ +% ``Networking'' bibliography database for BiB-TeX + + +@techreport{ARP, + author = "David C. Plummer", + title = "{An Ethernet Address Resolution Protocol}", + type = rfc, + number = 825, + institution= nic, + address = sri, + month = sep, + year = 1982 +} + +@techreport{ARPA.MHS, + author = "Stephen E. Kille", + title = "{Mapping between X.400 and RFC822}", + type = rfc, + number = 987, + institution= nic, + address = sri, + month = jun, + year = 1986, + note = {Also available as UCL Technical Report number~120 + and Mailgroup Note number~19} +} + +@techreport{ARPA.mapping.MHS, + author = mtr, + title = "{Mapping Service Elements between ARPA and MHS}", + institution= nrtc, + month = nov, + year = 1985, + note = {Unpublished (superceded by IFIP WG6.5 report)} +} + +@techreport{Assigned.Numbers, + author = "Joyce K. Reynolds", + title = "{Assigned Numbers}", + type = rfc, + number = 1010, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@incollection{ARM, + author = "Michael A. Padlipksy", + title = "{A Perspective on the ARPANET Reference Model}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 5, + pages = {89--115}, + publisher= {Prentice-hall}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as Internet Request for Comments 871} +} + +@inproceedings{ASDC.DIPS, + author = "Jaime Delgado and Manuel Medina", + title = "{Use of the Abstract Service Definition + Conventions for Distributed Information + Processing Systems Specification}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {217--231}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{Building.Applications, + author = mtr, + title = "{Building Distributed Applications in an OSI + Framework}", + journal = connexions, + volume = 2, + number = 3, + month = mar, + year = 1988, + pages = {2--7}, + note = {ISSN 0894-5926} +} + +@inproceedings{Applications.Cookbook, + author = "Julian P. Onions and Marshall T. Rose", + title = "{The Application Cookbook}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {247--265}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@book{Carl.Faberge, + author = "Alexander von Solodkoff", + title = "{The Art of Carl Faberg\'{e}}", + publisher= {Crown Publishers, Inc.}, + address = {New York}, + year = 1988, + note = {ISBN 0--517--571242} +} + +@book{Masterpieces.Faberge, + author = "Alexander von Solodkoff", + editor = "Chrisopher Forbes", + title = "{Masterpieces from the House of Faberg\'{e}}", + publisher= {Harry N.~Abrams, Inc.}, + address = {New York}, + year = 1989, + note = {ISBN 0--8109--8089--4} +} + +@misc{CCITT.ACS.Service, + key = {CCITT}, + title = "{Association Control Service Definition for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.217} +} + +@misc{CCITT.ACS.Protocol, + key = {CCITT}, + title = "{Association Control Protocol Specification for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.227} +} + +@misc{CCITT.Directory, + key = {CCITT}, + title = "{The Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.500} +} + +@misc{CCITT.MHS, + key = {CCITT}, + title = "{Message Handling: System and Service Overview}", + year = 1988, + howpublished= ccitt, + note = {Recommendation X.400} +} + +@misc{CCITT.TP.Service, + key = {CCITT}, + title = "{Transport Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.214} +} + +@misc{CCITT.TP.Protocol, + key = {CCITT}, + title = "{Transport Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Service, + key = {CCITT}, + title = "{Session Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Protocol, + key = {CCITT}, + title = "{Session Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.225} +} + +@misc{CCITT.PP.Service, + key = {CCITT}, + title = "{Presentation Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.216} +} + +@misc{CCITT.PP.Protocol, + key = {CCITT}, + title = "{Presentation Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.226} +} + +@misc{CCITT.PP.Syntax, + key = {CCITT}, + title = "{Specification of Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.208} +} + +@misc{CCITT.PP.Encoding, + key = {CCITT}, + title = "{Specification of Basic Encoding + Rules for Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.209} +} + +@misc{CCITT.ROS.Service, + key = {CCITT}, + title = "{Remote Operations: Model, Notation and Service + Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.219} +} + +@misc{CCITT.ROS.Protocol, + key = {CCITT}, + title = "{Remote Operations: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.229} +} + +@misc{CCITT.RTS.Service, + key = {CCITT}, + title = "{Reliable Transfer: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.218} +} + +@misc{CCITT.RTS.Protocol, + key = {CCITT}, + title = "{Reliable Transfer: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.228} +} + +@techreport{CMOT, + author = "Unni Warrier and Larry Besaw", + title = "{Common Management Information Services and + Protocol over TCP/IP (CMOT)}", + type = rfc, + number = 1095, + institution= nic, + address = sri, + month = apr, + year = 1989 +} + +@book{Computer.Networks, + author = "Andrew S. Tanenbaum", + title = "{Computer Networks}", + publisher= {Prentice-hall}, + series = {Prentice Hall Software Series}, + year = 1988, + note = {ISBN 0--13--162959--X} +} + +@inproceedings{Congestion.Control, + author = "Van Jacobson", + title = "{Congestion Avoidance and Control}", + booktitle= "{Proceedings, SIGCOMM '88 Workshop}", + pages = {314--329}, + organization= {ACM SIGCOMM}, + publisher= {ACM Press}, + month = aug, + year = 1988, + note = {Stanford, CA} +} + +@techreport{Courier.BSD, + author = "Eric C. Cooper", + title = "{Writing Distributed Programs with Courier}", + institution= {Computer Science Division~---~EECS}, + address = {University of California, Berkeley}, + month = mar, + year = 1982 +} + +@techreport{DNS, + author = "Paul V. Mockapetris", + title = "{Domain Names --- Concepts and Facilities}", + type = rfc, + number = 1033, + institution= nic, + address = sri, + month = Nov, + year = 1987 +} + +@misc{DoD.OSI, + key = {DDN}, + title = "{The Department of Defense Open Systems + Interconnection (OSI) Implementation Strategy}", + month = may, + year = 1988, + note = {The MITRE Corporation} +} + +@misc{ECMA.ROS, + key = {ECMA}, + title = "{Remote Operations: Concepts, Notation and + Connection-Oriented Mappings}", + month = dec, + year = 1985, + note = {ECMA TR/31} +} + +@techreport{EON, + author = "Robert A. Hagens and Nancy E. Hall and + Marshall T. Rose", + title = "{Use of the DARPA/NSF Internet as a Subnet for + Experimentation with the OSI Network Layer}", + type = rfc, + number = 1070, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@techreport{EON.addressing, + author = "Ross Callon and Hans-Werner Braun", + title = "{Guidelines for the use of Internet-IP + addresses in the ISO Connectionless-Mode Network + Protocol}", + type = rfc, + number = 1069, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@article{Fletcher.Checksum, + author = "John G. Fletcher", + title = "{An Arithmetic Checksum for Serial Transmissions}", + journal = ieeecom, + volume = {COM--30}, + number = 1, + month = jan, + year = 1982 +} + +@article{Fletcher.Pitfalls, + author = "Anastase Nakassis", + title = "{Fletcher's Error Detection Algorithm: How to + implement it efficiently and how to avoid the most + common pitfalls}", + journal = ccr, + volume = 18, + number = 5, + month = oct, + year = 1988, + pages = {63--68} +} + +@techreport{FTP, + key = {FTP}, + author = {Jon B. Postel}, + title = "{File Transfer Protocol}", + type = rfc, + number = 959, + institution= nic, + address = sri, + month = oct, + year = 1985, + note = {See also \milstd/ 1780} +} + +@incollection{Gateways.Heffalumps, + author = "Michael A. Padlipksy", + title = "{Gateways, Architectures, and Heffalumps}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 10, + pages = {167--176}, + publisher= {Prentice-hall}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as Internet Request for Comments 875} +} + +@misc{US.GOSIP, + key = {USGOSIP}, + title = "{U.S.~Government Open Systems Interconnection + Profile (GOSIP)}", + month = aug, + year = 1988, + note = {U.S.~Federal Information Processing Standards + Publication~146} +} + +@misc{UK.GOSIP, + key = {UKGOSIP}, + title = "{U.K.~Government OSI Profile}", + month = jan, + year = 1988, + note = {Version~3.0} +} + +@techreport{HEMS, + author = "Craig Partridge and Glenn Trewit", + title = "{The High-Level Entity Management System}", + type = rfc, + number = {1021--1024}, + institution= nic, + address = sri, + month = oct, + year = 1987 +} + +@article{Host.Multicasting, + author = "Stephen E. Deering", + title = "{Multicast Routing in Internetworks and + Extended LANs}", + journal = ccr, + volume = 18, + number = 4, + month = aug, + year = 1988, + pages = {55--64} +} + +@techreport{Interim.Addresses, + author = "Stephen E. Kille", + title = "{An interim approach to use of Network Addresses}", + type = "Research Note", + number = {RN/89/13}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@article{ISODE.Horizontal, + author = mtr, + title = "{ISODE: Horizontal Integration in Networking}", + journal = connexions, + volume = 1, + number = 1, + month = may, + year = 1987, + pages = {8--12}, + note = {ISSN 0894-5926} +} + +@techreport{IP, + key = {IP}, + author = {Jon B. Postel}, + title = "{Internet Protocol}", + type = rfc, + number = 791, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1777} +} + +@misc{IP.Requirements, + key = {NSF}, + title = "{Requirement for Internet Gateways~---~Draft}", + month = may, + year = 1986, + note = {Internet Request for Comments 985, prepared by + the Gateway Requirements Subcommitee of the National + Science Foundation's Network Technical Advisory Group, + David L.~Mills, chair} +} + +@misc{ISO.ALS, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Application Layer Structure}", + month = mar, + year = 1987, + howpublished= iso/iec, + note = {Draft Proposal 9534} +} + +@misc{ISO.ACS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Service Definition for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8649} +} + +@misc{ISO.ACS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~--~Protocol Specification for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8650} +} + +@misc{ISO.Directory, + key = {ISO}, + title = "{Information Processing Systems~---~Open + Systems Interconnection~---~The + Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= iso/iec, + note = {International Standard 9594-1} +} + +@misc{ISO.DLP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Data Link Service Definition}", + month = dec, + year = 1987, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8886--2} +} + +@misc{ISO.LAN, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802} +} + +@misc{ISO.LAN.LLC, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks~---~Logical Link Control}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802--2} +} + +@misc{ISO.FTAM, + key = {ISO}, + title = "{Information Processing Systems~---~File + Transfer, Access, and Management}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8571} +} + +@misc{ISO.LAN.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 over Local Area + Networks to Provide the OSI Connection-mode + Network Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8881} +} + +@misc{ISO.MOTIS, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~MOTIS~---~Message Handling: + System and Service Overview}", + month = dec, + year = 1988, + howpublished= iso/iec, + note = {International Standard 10021-1} +} + +@misc{ISO.NP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service Definition}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348} +} + +@misc{ISO.NP.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 1: Connectionless-mode + Transmission}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 1} +} + +@misc{ISO.NP.Addressing, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 2: Network Layer Addresisng}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 2} +} + +@misc{ISO.NP.CLNP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol for providing the + Connectionless-mode Network Service and Provision + of Underlying Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {Consolidated Final Text of Draft International + Standard 8473} +} + +@misc{ISO.NP.X25, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 to Provide the + OSI Connection-mode Network Service}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8878} +} + +@misc{ISO.X25.PLP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~X.25 Packet Level Protocol}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8208} +} + +@misc{ISO.X25.LAPB, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~High-level Data Link Control + Procedures~---~Description of the X.25 + LAPB-compatible DTE Data Link Procedures}", + month = dec, + year = 1986, + howpublished= iso/iec, + note = {International Standard 7776} +} + +@misc{ISO.NP.IONL, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Internal Organization of + the Network Layer}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8648} +} + +@misc{ISO.NS.Principles, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 1: General Principles}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--1} +} + +@misc{ISO.NS.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 2: Provision and Support of + the connection-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--2} +} + +@misc{ISO.NS.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 3: Provision and Support of + the connectionless-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--3} +} + +@misc{ISO.PP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Service Definition}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8822} +} + +@misc{ISO.PP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Protocol Specification}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8823} +} + +@misc{ISO.PP.Syntax, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Abstract Syntax + Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8824} +} + +@misc{ISO.PP.Encoding, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Basic Encoding + Rules for Abstract Syntax Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8825} +} + +@misc{ISO.ASN1.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8824/DAD 1} +} + +@misc{ISO.BER.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1 Basic Encoding Rules}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8825/DAD 1} +} + +@misc{ISO.ROS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~1: Model, Notation and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-1} +} + +@misc{ISO.ROS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-2} +} + +@misc{ISO.RTS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~1: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-1} +} + +@misc{ISO.RTS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-2} +} + +@misc{ISO.SP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8326} +} + +@misc{ISO.SP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8327} +} + +@misc{ISO.SS.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 1: + Session Symmetric Synchronization for the + Session Service}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 1} +} + +@misc{ISO.SP.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 1: + Session Symmetric Synchronization for the + Session Protocol}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 1} +} + +@misc{ISO.SS.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 2} +} + +@misc{ISO.SP.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 2} +} + +@misc{ISO.TP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Service Definition}", + mon = jun, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8072} +} + +@misc{ISO.TP-CL.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Service + Definition~---~Addendum 1: Connectionless-mode + Transmission}", + mon = dec, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8072/AD 1} +} + +@misc{ISO.TP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Protocol Specification}", + mon = jul, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8073} +} + +@misc{ISO.VT, + key = {ISO}, + title = "{Information Processing Systems~---~Virtual Terminal + Service: Basic Class}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 9040} +} + +@article{ISO.on.DDN, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{OSI Transport Services on top of the TCP}", + journal = cn/isdn, + volume = 12, + number = 3, + year = 1986, + note = {Also available as NRTC Technical Paper \#700.} +} + +@article{Internet.Architecture, + author = "Vinton G. Cerf and Edward A. Cain", + title = "{The DoD Internet Architecture Model}", + journal = cn/isdn, + volume = 7, + number = 10, + month = oct, + year = 1983, + pages = {307--318} +} + +@techreport{Internet.NM, + author = "Vinton G. Cerf", + title = "{IAB Recommendations for the Development of + Internet Network Management Standards}", + type = rfc, + number = 1052, + institution= nic, + address = sri, + month = apr, + year = 1988 +} + +@techreport{Internet.NM-2, + author = "Vinton G. Cerf", + title = "{Report of the Second Ad Hoc Network Management + Review Group}", + type = rfc, + number = 1109, + institution= nic, + address = sri, + month = aug, + year = 1989 +} + +@techreport{Internet.SMI, + author = "Marshall T. Rose and Keith McCloghrie", + title = "{Structure and Identification of Management + Information for TCP/IP based internets}", + type = rfc, + number = 1065, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@techreport{Internet.MIB, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Management Information Base Network Management + of TCP/IP based internets}", + type = rfc, + number = 1066, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@article{Interoperability.Testing, + author = mtr, + title = "{Interoperability Testing: + The Final Test of Open Systems}", + journal = connexions, + volume = 3, + number = 7, + month = jul, + year = 1989, + pages = {12--14}, + note = {ISSN 0894-5926} +} + +@inproceedings{Layers, + author = "Danny Cohen and Jon B. Postel", + title = "{The ISO Reference Model and Other Protocol + Architectures}", + booktitle= {Proceedings of the IFIP Congress}, + year = 1983, + note = {Paris, France} +} + +@inproceedings{Management.TCP-IP, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + booktitle= "{Proceedings of the Digital Equipment Computer + Users Society}", + pages = {167--169}, + month = "Fall", + year = 1988 +} + +@article{Management.TCP-IP.Again, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {3--9}, + note = {ISSN 0894-5926} +} + +@misc{MHS, + key = {CCITT}, + title = "{Message Handling Systems: System Model-Service + Elements}", + month = oct, + year = 1984, + note = ccitt +} + +@misc{MHS.Elements, + key = {CCITT}, + title = "{Message Handling Systems: Basic Service Elements + and Optional User Facilities}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.401} +} + +@misc{MHS.Conversion, + key = {CCITT}, + title = "{Message Handling Systems: Encoded Information Type + Conversion Rules}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.408} +} + +@misc{MHS.Notation, + key = {CCITT}, + title = "{Message Handling Systems: Presentation Transfer + Syntax and Notation}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.409} +} + +@misc{MHS.RTS, + key = {CCITT}, + title = "{Message Handling Systems: Remote Operations and + Reliable Transfer Server}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.410} +} + +@misc{MHS.P1, + key = {CCITT}, + title = "{Message Handling Systems: Message Transfer Layer}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.411} +} + +@misc{MHS.P2, + key = {CCITT}, + title = "{Message Handling Systems: Interpersonal Messaging + User Agent}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.420} +} + +@misc{MHS.Teletex, + key = {CCITT}, + title = "{Message Handling Systems: Access Protocol for + Teletex Terminals}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.430} +} + +@techreport{NETBLT, + author = "David D. Clark and Mark L. Lambert and Lixia Zhang", + title = "{NETBLT: A Bulk Data Transfer Protocol}", + type = rfc, + number = 998, + institution= nic, + address = sri, + month = mar, + year = 1987 +} + +@manual{NFS, + title = "Network File System Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@misc{NRC.Report, + key = {NRC}, + title = "{Transport Protocols for Department of Defense Data + Networks}", + howpublished= {National Academy Press}, + month = feb, + year = 1985, + note = {Report to the Department of Defense and + the National Bureau of Standards by the Committee on + Computer-Computer Communication Protocols, Board on + Telecommunications and Computer Applications + Commission on Engineering and Technical Systems, + National Research Council, + C. Chaplin Cutler, chair + (Executive Summary available as Internet Request + for Comments 939)} +} + +@article{Netman.Demo, + author = "George Marshall", + title = "{The NetMan Demonstration at INTEROP '88}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {20}, + note = {ISSN 0894-5926} +} + +@article{NSFnet.Backbone, + author = "David L. Mills and Hans-Werner Braun", + title = "{The NSFNET Backbone Network}", + journal = ccr, + volume = 17, + number = 5, + month = aug, + year = 1987, + pages = {191--196} +} + +@techreport{Official.Protocols, + author = "{IAB}", + title = "{IAB Official Protocol Standards}", + type = rfc, + number = 1100, + institution= nic, + address = sri, + month = apr, + year = 1989, + note = {Internet Activities Board} +} + +@article{OSI.ALS, + author = mtr, + title = "{The Application Layer Structure}", + journal = connexions, + volume = 4, + number = 1, + month = jan, + year = 1990, + pages = {2--9}, + note = {ISSN 0894-5926} +} + +@misc{OSI.Model, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Basic Reference Model}", + mon = oct, + year = 1984, + howpublished= iso/iec, + note = {Interational Standard 7498} +} + +@misc{OSI.CL-Model, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Basic Reference + Model~---~Addendum 1: Connectionless-mode + Transmission}", + mon = sep, + year = 1987, + howpublished= iso/iec, + note = {Interational Standard 7498/AD 1} +} + +@misc{OSI.Conventions, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Service Conventions}", + mon = sep, + year = 1987, + howpublished= iso/iec, + note = {Technical Report 8509} +} + +@misc{OSI.Implementors, + key = {NIST}, + title = "{Stable Implementation Agreements for Open + Systems Interconnection Protocols}", + month = dec, + year = 1988, + note = {Version 2, Edition 1} +} + +@article{OSI.POSIX, + author = mtr, + title = "{OSI Protocols within an openly available, + POSIX-conformant, Berkeley UNIX environment}", + journal = connexions, + volume = 2, + number = 10, + month = oct, + year = 1988, + pages = {11--13}, + note = {ISSN 0894-5926} +} + +@book{Open.Book, + author = mtr, + title = "{The Open Book: A Practical Perspective on Open + Systems Interconnection}", + publisher= {Prentice-hall}, + year = 1990, + note = {ISBN 0--13--643016--3} +} + +@inproceedings{PP.MTA, + author = "Stephen E. Kille", + title = "{PP~---~A Message Transfer Agent}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {115--128}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{Protocol.Conversion, + author = "Green, Jr., Paul E.", + title = "{Protocol Conversion}", + journal = ieeecom, + volume = {COM--34}, + number = 3, + month = mar, + year = 1986, + pages = {257--268} +} + +@techreport{PSAP.on.TCP.old, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = idea, + number = 17, + institution= nic, + address = sri, + month = mar, + year = 1988 +} + +@techreport{PSAP.on.TCP, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = rfc, + number = 1085, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{QUIPU.Design, + author = "Stephen E. Kille", + title = "{The Design of QUIPU}", + type = "Research Note", + number = {RN/89/19}, + institution= {Department of Computer Science}, + address = ucl, + month = mar, + year = 1989 +} + +@inproceedings{QUIPU.Directory, + author = "Stephen E. Kille", + title = "{The QUIPU Directory Service}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {173--185}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@techreport{RawPacket, + author = mtr, + title = "{Low Tech Connections in to the ARPA Internet: + The RawPacket Split-Gateway}", + number = 216, + institution= ics, + address = uci, + month = feb, + year = 1984 +} + +@techreport{RFC822, + author = "David H. Crocker", + title = "{Standard for the Format of ARPA Internet Text + Messages}", + type = rfc, + number = 822, + institution= nic, + address = sri, + month = aug, + year = 1982 +} + +@article{Session.Hints, + author = "Fausto Caneschi", + title = "{Hints for the Interpretation of the ISO + Session Layer}", + journal = ccr, + volume = 16, + number = 4, + month = aug, + year = 1986, + pages = {34--72} +} + +@techreport{Silly.Window, + author = "David D. Clark", + title = "{Window and Acknowledgement Strategy in TCP}", + type = rfc, + number = 813, + institution= nic, + address = sri, + month = jul, + year = 1982 +} + +@techreport{SMTP, + key = {SMTP}, + author = {Jon B. Postel}, + title = "{Simple Mail Transfer Protocol}", + type = rfc, + number = 821, + institution= nic, + address = sri, + month = aug, + year = 1982, + note = {See also \milstd/ 1781} +} + +@manual{SNA, + title = "{Systems Network Architecture Technical Overview}", + key = {IBM}, + organization= {International Business Machines, Incorporated, + Data Processing Division}, + address = {White Plains, New York}, + month = mar, + year = 1982, + note = {Document Number GC30--3073--0} +} + +@techreport{SGMP, + author = "James R. Davin and Jeffrey D. Case and Mark S. + Fedor and Martin L. Schoffstall", + title = "{A Simple Gateway Monitoring Protocol}", + type = rfc, + number = 1028, + institution= nic, + address = sri, + month = nov, + year = 1987 +} + +@inproceedings{SNA.convert.XNS, + author = "Kenneth O. Zoline and William P. Lidinksy", + title = "{An Approach for Interconnecting SNA and XNS + Networks}", + booktitle= "{Proceedings, Ninth Data Communications Symposium}", + pages = {184--198}, + organization= {ACM Special Interest Group on Communications}, + publisher= {IEEE Computer Society Press}, + month = sep, + year = 1985 +} + +@techreport{SNMP, + author = "Jeffrey D. Case and Mark S. Fedor and Martin L. + Schoffstall and James R. Davin", + title = "{A Simple Network Management Protocol}", + type = rfc, + number = 1098, + institution= nic, + address = sri, + month = apr, + year = 1989 +} + +@article{SNMP.Design, + author = "Jeffrey D. Case and James R. Davin + and Mark S. Fedor and Martin L. Schoffstall", + title = "{Network Management and the Design of SNMP}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {22--26}, + note = {ISSN 0894-5926} +} + +@techreport{String.Addresses, + author = "Stephen E. Kille", + title = "{A string encoding of Presentation Address}", + type = "Research Note", + number = {RN/89/14}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@techreport{TCP, + key = {TCP}, + author = {Jon B. Postel}, + title = "{Transmission Control Protocol}", + type = rfc, + number = 793, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1778} +} + +@article{TCP.convert.ISO, + author = "Inge Groenbaek", + title = "{Conversion Between the TCP and ISO Transport + Protocols as a Method of Achieving Interoperability + Between Data Communication Systems}", + journal = jsac, + volume = {SAC-4}, + number = 2, + month = mar, + year = 1986, + pages = {288--296} +} + +@article{TCP.convert.OSI, + author = "Michael Witt", + title = "{Moving from DoD to OSI Protocols: A First Step}", + journal = ccr, + volume = 16, + number = 2, + month = {April/May}, + year = 1986, + pages = {1--7} +} + +@inproceedings{TCP.transition.ISO, + author = "Irene Hu", + title = "{Managing the Transition from TCP/IP to ISO + Protcols}", + booktitle= "{Proceedings, Uniforum 1987 Conference}", + pages = {59--74}, + organization= {/usr/group}, + month = jan, + year = 1987 +} + +@article{TCP.wars, + author = mtr, + title = "{Comments on ``Comments on `Congestion Control + in TCP/IP Internetworks'\,''}", + journal = ccr, + volume = 15, + number = 5, + month = {October/November}, + year = 1985, + pages = {2--9} +} + +@inproceedings{TCP.losing.MILSTD, + author = "Deepinder P. Sidhu and Thomas P. Blumer", + title = "{Some Problems with the Specification of the + Military Standard Transmission Control Protocol}", + booktitle= {Proceedings, Fourth International Workshop on Protocol + Specification, Testing, and Verification}, + editor = "Y.~Yemini and et.~al.", + pages = {375--381}, + organization= {IFIP WG 6.1}, + publisher= {North-Holland Publishing Company}, + month = jun, + year = 1985, + note = {Skytop Lodge, Pennsylvania} +} + +@inproceedings{RTT.Improve, + author = "Phil Karn and Craig Partridge", + title = "{Improving Round-Trip Time Estimates in + Reliable Transport Protocols}", + booktitle= "{Proceedings, SIGCOMM '87 Workshop}", + pages = {2--7}, + organization= {ACM SIGCOMM}, + publisher= {ACM Press}, + month = aug, + year = 1987, + note = {Stowe, Vermont} +} + +@book{Standards.Process, + author = "Carl F. Cargill", + title = "{Information Technology Standardization: + Theory, Process, and Organizations}", + publisher= {Digital Press}, + address = {Maynard, Massachusetts}, + year = 1989, + note = {ISBN 1--55558--022--X} +} + +@techreport{TELNET, + key = {TELNET}, + author = {Jon B. Postel}, + title = "{TELNET Protocol Specification}", + type = rfc, + number = 854, + institution= nic, + address = sri, + month = may, + year = 1983, + note = {See also \milstd/ 1782} +} + +@techreport{TP0.bridge, + author = "Julian P. Onions and Marshall T. Rose", + title = "{ISO-TP0 bridge between TCP and X.25}", + type = rfc, + number = 1086, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@article{Transition.and.Coexistence, + author = mtr, + title = "{Transition and coexistence for TCP/IP to OSI}", + journal = connexions, + volume = 2, + number = 12, + month = dec, + year = 1988, + pages = {2--5}, + note = {ISSN 0894-5926} +} + +@article{Transition.and.Coexistence.Strategies, + author = mtr, + title = "{Transition and Coexistence Strategies for + TCP/IP to OSI}", + journal = jsac, + volume = {COM--37}, + year = 1989, + note = {(to appear)} +} + +@article{Transport.Bridges, + author = mtr, + title = "{Transport-level ``bridges'' from TCP/IP to OSI/ISO}", + journal = connexions, + volume = 2, + number = 1, + month = jan, + year = 1988, + pages = {2--6}, + note = {ISSN 0894-5926} +} + +@techreport{TSAP.on.TCP.old, + author = "Dwight E. Cass and Marshall T. Rose", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 983, + institution= nic, + address = sri, + month = apr, + year = 1986 +} + +@techreport{TSAP.on.TCP, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 1006, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@techreport{UDP, + key = {UDP}, + author = {Jon B. Postel}, + title = "{User Datagram Protocol}", + type = rfc, + number = 768, + institution= nic, + address = sri, + month = aug, + year = 1980 +} + +@inproceedings{Upcalls, + author = "David D. Clark", + title = "{The Structuring of systems using Upcalls}", + booktitle= "{Proceedings, Ninth Symposium on Operating + System Principles}", + pages = {171--180}, + month = dec, + year = 1985, + note = {Orcas Island, Washington} +} + +@misc{White.Book, + author = "{JNT}", + title = "{Transition to OSI Standards}", + howpublished= {U.K.~Joint Network Team}, + month = jul, + year = 1987, + note = {Final Report of the Academic Community OSI + Transition Group} +} + +@techreport{Whois, + key = {Whois}, + author = {Ken Harrenstien and Mary K. Stahl and Elizabeth J. + Feinler}, + title = "{NICNAME/WHOIS}", + type = rfc, + number = 954, + institution= nic, + address = sri, + month = oct, + year = 1985 +} + +@article{X.window, + author = "Robert W. Scheifler and Jim Gettys", + title = "{The X Window System}", + journal = tog, + volume = 5, + number = 2, + month = apr, + year = 1986, + pages = {79--109}, + note = {Special Issue on User Interface Software} +} + +@manual{XDR, + title = "External Data Representation Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@inproceedings{XDR.Comparison, + author = "Craig Partridge and Marshall T. Rose", + title = "{A Comparison of External Data Formats}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {233--245}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} diff --git a/doc/funet91/pp-slides.aux b/doc/funet91/pp-slides.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/funet91/pp-slides.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/funet91/pp-slides.tex b/doc/funet91/pp-slides.tex new file mode 100644 index 0000000..caa4391 --- /dev/null +++ b/doc/funet91/pp-slides.tex @@ -0,0 +1,456 @@ +% -*- LaTeX -* Although it's slitex really + +\documentstyle[blackandwhite,pagenumbers,small,oval,psfig,tgrind]{NRslides} + +\raggedright + +\begin{document} +\title {PP - The Fun and the Pain} + +\author{Julian P.~Onions\\ +j.onions@xtel.co.uk\\[.5in] +X-Tel Services Ltd.\\ +Nottingham University\\ +Nottingham NG7 2RD\\ +ENGLAND} + +\date {March 19th, 1991} + +\maketitle + + \begin{bwslide} +\ctitle {CONTENTS} +PART I +\begin{nrtc} +\item What is PP? + +\item The PP Architecture + +\item The PP Queue + +\item Submission + +\item Scheduling and Control + +\item Channels + +\item Status and Availability +\end{nrtc} +PART II +\begin{nrtc} +\item The scheduling story +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\part*{PART I\\ +Basic PP description} +\end{bwslide} + +\begin{bwslide} +\ctitle{What is PP} +\begin{nrtc} +\item Basically, A Mail transfer system (MTA in the jargon). + +\item Largely protocol independent, but deals with X.400 + and existing mail formats. + +\item Written by people at UCL and Nottingham + +\item Design aims include:- + \begin{itemize} + + \item High performance/throughput + \item Support for message conversion. + \item Support for multi-media + \item Clean interface for user interfaces. + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Why PP} +\begin{nrtc} +\item At the time there was no suitable alternative. + +\item Most implementations were in the ``toy'' category. + +\item Too expensive + +\item Only did X.400 - no gatewaying, or else added as an +afterthought. + +\item Worked to minimal profiles. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Some goals for PP} +\begin{nrtc} +\item Scheduling of messages in an optimal way, such that many +thousands of messages a day can be processed. + +\item Robustness. + +\item Support for RFC-822, X.400(84) and X.400(88) and others. + +\item Reformatting between body part types in a general manner. + +\item Provision of management, authorisation and monitoring tools. + +\item Use of standardised services such as X.500. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} +\begin{nrtc} +\item PP is based on a system of cooperating processes. + +\item Each process has a specific task to achieve. + +\item Most of these processes are ``dumb''. + +\item The ``intelligence'' of the system is provided by two processes. + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} + +\vskip .5in + +\diagram[p]{figure2} + +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Queue} +\begin{nrtc} +\item All messages are placed in a queue on disc. + +\item For each message there are two components + \begin{itemize} + \item A Control file holding all the envelope information. + \item The Message structure holding the Message data. + \end{itemize} +\item The Control file is text encoded. + +\item The Message is either a single file, or a directory hierarchy. + +\item The Message may undergo a number of transformations whilst in + the queue +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Submission} +\begin{nrtc} +\item The first intelligent process is {\em submit}. + +\item All messages entering the queue pass through this process. + +\item It validates the message in a number of ways: + \begin{itemize} + \item Ensures the originator can be reached. + \item Ensures the destination is known. + \item Works out a conversion path from incoming format to outgoing. + \item Applies access controls if required. + \end{itemize} +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Scheduling and Controlling} +\begin{nrtc} +\item The other ``intelligent'' process is the queue manager, {\em qmgr}. + +\item Keeps an in memory map of the queue. + +\item Drives all channel programs using network IPC. + +\item Makes all the scheduling decision about messages in the queue. + +\item Sorts the queue in ``optimal'' ways. + +\item Allows connections to interrogate queue status + +\item More about this later... +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Channels} +\begin{nrtc} +\item Channels in PP process messages. + +\item May reformat a message by conversion e.g. + \begin{itemize} + \item Mapping X.400 to RFC-822 message + \item Converting Telex to Ascii + \end{itemize} +\item May attempt delivery e.g. + \begin{itemize} + \item Drive the SMTP or X.400 protocols + \item Deliver to users + \end{itemize} +\item May restructure the message + \begin{itemize} + \item Convert a file into a directory hierarchy + \item Convert multiple body parts into one + \end{itemize} +\item Housekeeping +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{PP management} +\begin{nrtc} +\item The MTA console provides a good monitor of whats going on. +\item All address that are handled are logged in a special log which +an be processed to give statistics (and charging) information. +\item Authorisation can be controlled by user, host, content-type size +and route. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 was released on September 21st, 1990. + +\item It is providing a real service at a number of universities and + will shortly be providing the UK WEP service. + +\item PP is freely available for use and should be the backbone of + JANET as it transitions to X.400 protocols. + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 provides the following channels currently + + \begin{itemize} + \item SMTP with DNS support + \item X.400 (1984) + \item UUCP mail + \item JNT grey book mail + \item Distribution list expansion and maintenance + \item RFC822 local delivery and delivery time processing + \item RFC822 and X.400 conversion + \item X-windows based management console + \item Message authorisation checking + \item X.400(1988) P1 protocol (beta test) + \item X.500 distribution lists (beta test) + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{What is planned for the future} +\begin{nrtc} +\item Fax gateway to convert outgoing messages to faxes and vice +versa. + +\item More use of the X.500 directory, for routing and directory +name lookup. + +\item P7 Message store with remote access + +\item Improvements in throughput and robustness + +\item Some work on System Five portability and a DECNET channel by +people outside the PP group. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Availability and Support} +\begin{nrtc} +\item Source code is free by FTP/FTAM etc. +\item A distribution charge for a tape + +\item Available by FTP/FTAM from ucl, psi and eunet. + +\item Full support is also available if you require it from X-Tel. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\part*{PART II\\ +Fun and Games with Scheduling} +\end{bwslide} + +\begin{bwslide} +\ctitle{How to schedule a queue of messages} +\begin{nrtc} +\item Firstly, it's harder than you think, even when you take this +maxim into account + +\item Secondly, as Martin Padlipsky said, +\begin{quote}\em +``Optimality differs according to context''. +\end{quote} + +\item So -- apply a few general constraints: + \begin{enumerate} + \item Once you have a connection -- give it all you've got. + \item Reading the entire queue is expensive -- so don't if + you can help it. + \item When there is nothing to do -- don't do anything. + \item If there is something to do -- get on with it. + \item Keep in mind management. + \end{enumerate} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The first cut} +\begin{nrtc} +\item The first version of the qmgr was a shell script! +\item This was 152 lines long and ``cute'' +\item It read the queue every 5 seconds or so. +\item Directly started processes. +\item Was fun and easy to understand. +\item Of the list above, it did 1. +\item Lasted about 2 weeks as far as I recall +\item Other than that - it was essentially useless. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Lets get serious} +\begin{nrtc} +\item Next version was a C program. +\item It was fairly small and compact. +\item It had an attitude problem - it didn't believe anyone. +\item It read the queue frequently. +\item It communicated via UDP with submit +\item It directly executed programs. +\item Of the list above, it did 1 and 4. +\item It lasted a few months as I recall. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The current version} +\begin{nrtc} +\item Its the third version - a big plus for Frederick Brooks fans. +\item It is rather detached from reality. +\item It does all its communication via IPC (ROS). +\item It does not even have to run on the same machine as the rest. +\item I believe it does all 5 things mentioned above. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Tuning the scheduling - first cut} +\begin{nrtc} +\item First -- get it working with a single message. This includes: + \begin{itemize} + \item Make sure the message is processed as fast as possible + \item When the message is gone - the qmgr should do nothing. + \item The management facilities work + \end{itemize} +\item Next -- make sure it works with a few messages. This involves: + \begin{itemize} + \item Ensuring no fighting breaks out. + \item Check that unlocking a message allows it to be processed. + \end{itemize} +\item Then -- take a deep breath and try it for real! +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Did it work} +\begin{nrtc} +\item Yes -- at least for a while! +\item Until -- a glut of messages arrived. +\item Qmgr goes wild scheduling everything it can +\item Load average rises exponentially... +\item Phone starts ringing... +\item kernel tables overflow... +\item Lynching mobs are formed... +\item Ooops -- fixes required quickly. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle {The fixes} +\begin{nrtc} +\item First: check life insurance policy. +\item Second: Impose a limit on the maximum number of channels +\item This makes the system bounded. +\item Third: get the scheduling better so the limit is not required + so much. +\item Improvements involve + \begin{itemize} + \item Stop channel thrashing. + \item Cluster failures. + \item Stop spurious channel start ups. + \end{itemize} +\end{nrtc} +\end{bwslide} + +\begin{bwslide} + +\ctitle{Wider experience} +\begin{nrtc} +\item Next step, UCL. +\item Seemed to work fine there. +\item Some minor tweaks in performance +\item Some large tweaks in management information. +\item Pretty good all in all. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Feeling confident now!} +\begin{nrtc} +\item Brought into service at ULCC on nsfnet-relay duty. +\item Works well initially. +\item The disaster - thanksgiving outage wipes us out! +\item 11,000+ Messages in the queue - more arriving every second. +\item An \verb|ls| of the queue takes several minutes. +\item \verb|qmgr-load| grows to 50Mb and takes over an hour to run! +\item VM exhausted by the \verb|qmgr-load| $\rightarrow$ + \verb|qmgr| interaction. +\item Panic sets in, airports and ports are alerted with +descriptions of key PP people. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The fix - and the lessons} +\begin{nrtc} +\item \verb|qmgr-load| $\rightarrow$ \verb|qmgr| interaction made + into small batches. +\item Obvious really in hindsight. +\item Allow non running channels to request a piece of the action. +\item Better and cleverer heuristics. +\item Better data structures +\item Make everything go faster. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} + +\ctitle{Summary and Conclusions} +\begin{nrtc} +\item First -- its been mostly fun. +\item We think we have a good system. +\item We reckon we can handle about 1 message/second currently +\item With some tuning that should cope with about 10 message/second +\item This is just less than a million a day! +\item What more could you want? (this is a statement not a question!) +\end{nrtc} +\end{bwslide} + +\end{document} diff --git a/doc/funet91/pp.aux b/doc/funet91/pp.aux new file mode 100644 index 0000000..dba3a6d --- /dev/null +++ b/doc/funet91/pp.aux @@ -0,0 +1,39 @@ +\relax +\citation{ISODE} +\citation{CCITT.MHS} +\citation{RFC822} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1}Introduction}{1}} +\citation{MMDFII} +\citation{PP.MTA} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2}The design of PP}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1}The Process Structure}{2}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.1.1}Submit}{2}} +\citation{SMTP} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.1.2}Qmgr}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2}The Queue}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3}Channels}{3}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.1}Outbound Channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.2}Inbound Channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.3}Formatting and protocol conversion channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.4}Housekeeping and maintenance channels}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3}PP Status}{4}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1}The future}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.1}Reliability, robustness and efficiency}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.2}Use of directory}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.3}Message Store}{6}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4}Message Scheduling}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.1}The first cut}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.2}Take 2}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.3}The current version}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.4}Tuning performance - initial}{8}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.5}Tuning performance - for real}{9}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.6}... in the light of experience}{10}} +\bibdata{bcustom,networking,software} +\bibcite{CCITT.MHS}{CCI88} +\bibcite{RFC822}{Cro82} +\bibcite{MMDFII}{III84} +\bibcite{PP.MTA}{Kil88} +\bibcite{SMTP}{Pos82} +\bibcite{ISODE}{Ros90} +\bibstyle{alpha} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {5}Conclusions}{11}} diff --git a/doc/funet91/pp.bbl b/doc/funet91/pp.bbl new file mode 100644 index 0000000..4fd1485 --- /dev/null +++ b/doc/funet91/pp.bbl @@ -0,0 +1,40 @@ +\begin{thebibliography}{CCI88} + +\bibitem[CCI88]{CCITT.MHS} +{Message Handling: System and Service Overview}. +\newblock International Telegraph and Telephone Consultative Committee, 1988. +\newblock Recommendation X.400. + +\bibitem[Cro82]{RFC822} +David~H. Crocker. +\newblock {Standard for the Format of ARPA Internet Text Messages}. +\newblock Request for Comments 822, DDN Network Information Center, SRI + International, August 1982. + +\bibitem[III84]{MMDFII} +Douglas P.~Kingston III. +\newblock {MMDFII: A Technical Review}. +\newblock In {\em Proceedings, Summer Usenix Conference and Exhibition}, pages + 32--41, June 1984. +\newblock Salt Lake City, Utah. + +\bibitem[Kil88]{PP.MTA} +Stephen~E. Kille. +\newblock {PP~---~A Message Transfer Agent}. +\newblock In Einar Stefferud, editor, {\em {Proceedings, Fourth International + Symposium on Computer Message Systems}}, pages 115--128, September 1988. +\newblock Costa Mesa, California. + +\bibitem[Pos82]{SMTP} +Jon~B. Postel. +\newblock {Simple Mail Transfer Protocol}. +\newblock Request for Comments 821, DDN Network Information Center, SRI + International, August 1982. +\newblock See also \milstd/ 1781. + +\bibitem[Ros90]{ISODE} +Marshall~T. Rose. +\newblock {\em {The ISO Development Environment: User's Manual}}, 6.0 edition, + January 1990. + +\end{thebibliography} diff --git a/doc/funet91/pp.major b/doc/funet91/pp.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/funet91/pp.major @@ -0,0 +1 @@ +1 diff --git a/doc/funet91/pp.minor b/doc/funet91/pp.minor new file mode 100644 index 0000000..f04c001 --- /dev/null +++ b/doc/funet91/pp.minor @@ -0,0 +1 @@ +29 diff --git a/doc/funet91/pp.tex b/doc/funet91/pp.tex new file mode 100644 index 0000000..4223b68 --- /dev/null +++ b/doc/funet91/pp.tex @@ -0,0 +1,571 @@ +% -*- LaTeX -*- + +\input lcustom + +\documentstyle[11pt,a4]{article} + +\begin{document} + +\title{PP -- The Fun and the Pain} +\author{Julian P.~Onions\\[0.1in] +X-Tel Service Ltd.\\ +Nottingham University\\[0.1in] +jpo@xtel.co.uk} +\date{Tuesday 19th March 1991} + +\maketitle + +\begin{abstract} +This paper describes the design and implementation of +the PP message transport system. This is a message transfer system +that can relay a variety of protocols, and gateway between them. + +The paper describes what PP is now and some of its plans for +development. The second half of the paper is a report on some of the +experiences gained watching and tinkering with PP. +\end{abstract} + +\section{Introduction} + +This paper describes the design and implementation of PP\footnote{PP +is not an acronym. Despite many rumours to the contrary, the author is +sticking to this position!.}. PP is a generic Message Transfer Agent +capable of carrying a number of message formats. It has been written +as a joint project by University College London and Nottingham +University and is designed to run on \unix/ systems. It makes +use of the ISODE package\cite{ISODE}. Its design is heavily +influenced however, by the need to carry X.400 MHS\cite{CCITT.MHS} and +RFC-822\cite{RFC822} based mail. The major goals of PP include: +\begin{itemize} +\item Robustness. PP is designed for heavy use. It should be +capable of transferring high levels of traffic in an optimal way. + +\item A clean interface for submission and delivery. PP does not +provide a user agent but does provide a library interface which allows +user agents to be added to PP easily. + +\item Sophisticated message processing to optimise delivery and +remote transfers. + +\item Support for message conversion in an integrated way. + +\item Support for multiple addressing formats (initially two). + +\item Support for multi-media mail. + +\item Support for arbitrary message structures. + +\item Designed for large systems. PP is not designed to run on your +PC or even on a workstation. It is designed to be a central mail +processing hub for a group of computers. It is not a small piece of +software! +\end{itemize} + +As indicated above, PP is designed to deal with a large variety of +problems. The questions that comes to mind is ``why bother spending +all those years doing this?''. + +The answer is partly historical, but is still mostly relevant. When PP +was first thought about, there was very little that could be picked up +``off the shelf'' to deal with X.400 mail. What's more, the products we +had seen were just not suitable for the sort of environment we wanted +to run a mail system in. Most of the products then, and still now to +an extent, were what might be considered ``toy'' systems. Yes, they +would take an X.400 message and deliver it to a recipient, but there +is more to a reliable MTA than this. PP put management and monitoring +of the MTA very high on its list of desirable features. We believe +this has been attained - although not perfectly yet (what is). + +\section{The design of PP} + +The design of PP was influenced in part by the RFC-822 mail system +MMDF\cite{MMDFII}. In this model, extensive use is made of separate +processes to do different jobs. This allows each element to be built +and tested separately and encourages modularity. A fuller description +of the design of PP can be found in \cite{PP.MTA}. + +\subsection{The Process Structure} + +PP has a single queue of messages on which a number of processes +operate. There are two critical processes which undertake complex +functions, the rest of the processes are essentially ``dumb''. + +\subsubsection{Submit} +The first key process is that entitled {\em submit}. This process +guards the entrance to the queue. All messages entering the queue pass +through this process. It performs a variety of checks on the message +to ensure it can either be delivered or returned; works out the +routing for the message; calculates the reformatting of the message if +necessary; and applies other criteria such as authorisation and +authentication. By checking as much as possible at this point later +processes have to do less and completely undeliverable messages can be +stopped from entering the queue. + +As all message must pass though submit, all messages are checked at +this stage. This is where the authorisation policies are enforced. +Where possible, submit will always try and accept a message and return +it if necessary. Typically this leads to better error messages as +submit can take complete charge of generating the delivery report. + +Submit will refuse to accept a message when it can't parse or route +back to the originator. In this case, submit attempts to signal back +to the remote site that this message will not be accepted. In some +protocols, such as X.400(84), this is not possible. In this case, +submit gives up and the message as a whole is forwarded to the +postmaster to sort out. Fortunately, such occurrences are fairly rare. + +\subsubsection{Qmgr} +The second key process is the {\em \verb|qmgr|}, or queue manager. This +process is responsible for all the scheduling operations of the +messages in the queue. The \verb|qmgr| holds a representation of the queue in +memory and so can perform complex and optimal scheduling of messages. +This scheduling consists of either delivering the message locally or +remotely or else converting the message within the queue (e.g. +gatewaying between protocols). + +As the \verb|qmgr| holds a complete representation of the queue in memory it +also provides an information service. It can be queried by suitable +tools to display the state of the queue and such tools can even +control the behaviour of the \verb|qmgr|. This is the second half of the +management framework. As the \verb|qmgr| has a full overall picture of what +is going on in the queue - on a second to second basis, good global +decisions are possible. + +An X-windows based MTA console is provided with PP which can attach +to remote \verb|qmgr|'s and display the status in graphic detail, where +possible using colour to highlight problems. With suitable +authentication, the MTA console can also control the \verb|qmgr|'s behaviour. + +\subsection{The Queue} + +The queue of messages is held in two components. The first is an +address file which contains the envelope information about the +message. This is held in a text encoded form and is a generic envelope +structure which can hold both X.400 and RFC-822 messages. The text +encoding is a big advantage as it allows manipulation of the queues in +an emergency by a text editor. Whilst this should not normally be +necessary it is much easier than providing special management tools +to cover every eventuality. + +The second component is the message content. This includes the headers +and body parts. If no processing is necessary for the message this is +kept as a single file. However, if conversion is necessary, the +content is broken up into parts, each part being placed in a separate +file. Each time a message content is transformed, a new directory is +created and the appropriate files are changed. This allows simple +filters (such as {\em sed} even) to do the conversions. + + +\subsection{Channels} + +Most other processes in PP are termed {\em channels}. A channel takes +as input a message and outputs a different form of that message. +Channels are controlled directly by the \verb|qmgr| by means of a networked +protocol. Each channel does a specific job. Channels come in four +basic forms as described below. + +\subsubsection{Outbound Channels} +This style of channel is usually a protocol engine. It takes a message +out of the queue and delivers it. This delivery may be local as in the +case of delivering to a mailbox; or remote such as driving the +SMTP\cite{SMTP} or X.400 protocols. Each channel reads the internal +format of the queued message and converts it to the protocol specific +format. The \verb|qmgr| informs a channel which message to deliver and the +channel reports on the status of the message. This allows the \verb|qmgr| to +discover whether the delivery attempt was successful, the remote site +did not respond or whether the message cannot be delivered. This +information is then used by the \verb|qmgr| to schedule further deliveries. + +\subsubsection{Inbound Channels} +Inbound channels perform the opposite function to outbound channels. +They take care of the various protocols necessary to receive a +message, either from a user agent (local submission) or across a +network. Their main task is mapping from the protocol specific form of +the message to the form used withing the queue. This form is then +passed by a private protocol to submit which enqueue the message and +then informs the \verb|qmgr| of the new message. + +\subsubsection{Formatting and protocol conversion channels} +These channels transform the message in some way without delivering +it. They are treated in exactly the same way as outbound channels and +are scheduled by the \verb|qmgr|. These channels come in two basic types. +\begin{itemize} +\item Channels that change the directory structure. These either map +from the single file into a directory hierarchy, or the reverse. + +\item Simple reformatting. These channels might change, say, a teletex +body part into an ascii body part. When gatewaying is being performed, +such a channel might convert RFC-822 headers into X.400 headers. +\end{itemize} + +\subsubsection{Housekeeping and maintenance channels} +These channels do not usually have anything to do with delivery, but +perform meta tasks. These include loading the \verb|qmgr|, deleting +messages, timeing out messages and removing junk from the queue. + +\section{PP Status} + +PP currently contains the following parts. + +\begin{description} +\item[Core] The basic core of the system including the \verb|qmgr|, +submit and a number of support tools. + +\item[X.400 1984] The X.400 1984 protocols are supported. + +\item[SMTP] Smtp protocols are supported, including use of the +name server protocols for address resolution. + +\item[Grey Book] Grey book mail transfer is working, using the +unix-niftp blue book transfer system to provide non-spooled mail +transfer over JANET. + +\item[List] A list channel to offload the processing of +distribution lists. This helps speed up submission to large +distribution lists and allows list management. + + +\item[MTA Console] An X-windows based console display which +interrogates the \verb|qmgr| and displays the current state of the +queues. It emphasises problems in the queue and allows parameters to +be adjusted interactively. + +\item[UUCP] There is some support for UUCP though this has not really +been tested in a large UUCP environment. + +\item[Tools] Various auxiliary programs to configure the system and +provide debugging support. + +\end{description} + +PP also contains the following experimental modules. +\begin{description} +\item[X.400 1988] The 1988 version of X.400 is in a beta test +form. The 1988 version of X.400 is uncommon at present so interworking +testing is limited. This will include secure messaging and extensions. + +\item[Directory Lists] An experimental channel that store distribution +lists in the X.500 directory is provided. This will be emphasised more +in future releases. + +\end{description} + +\subsection{The future} +Work is already under way on the next version of PP. The next version +has three main thrusts. + +\subsubsection {Reliability, robustness and efficiency} +These are general goals, without any specific actions to be taken. In +general we hope the level of reliability and robustness of the +software to increase with each future release. At the same time, some +effort will be expended on streamlining the code and improving +throughput and decreasing machine load (the usual motherhood and apple +pie goals...). + +\subsubsection {Use of directory} +The next version of PP will make much larger use of the X.500 +directory. It will use the distribution list channel indicated above. +it will also be able to map Directory Names into O/R names by use of +the directory. Finally, work will be done on use of the directory for +routing. + +\subsubsection{Message Store} +A Message Store for PP is currently being written. It will allow +both P7 and P7+ access to messages. This will allow workstations and +portable computers to retrieve and store messages remotely. A user +agent for Unix with these features in mind is being written as a +separate project. + +\section{Message Scheduling} +Much of the PP system revolves around the \verb|qmgr| process which as +described above schedules the messages in the queue. The development +of this aspect of PP has been through many iterations, and is quite +interesting (at least to the author). + +\subsection{The first cut} +The first version of the \verb|qmgr| was a shell script! +It was 152 lines long by the time it was dropped, and originally had a +simplicity and understandability that was rather elegant (if I do say +so myself). All in all it was cute, and did the job reasonably well +for a week or two. + +At this stage though PP was very different to its current form +and no serious message process was being done. This version was only +used for experimentation, and I certainly would never have trusted my +mail with it. This version was never intended as anything other than +the proverbial {\em quick hack} to get things going. To my rather +faded memory it scheduled less than 100 messages in its short +lifetime. + +It was obvious though that this method was of limited potential. It +did not have the capability for interrogation. It did hold an in-core +copy of the queue as a shell variable but it refreshed this copy every +few minutes (can you say \verb|echo msg.*|). It was also clear that +with really big queues the lack of management and sophisticated +backoff and retry strategies alone would just not cut it. +Besides, who would have any credibility for a 15Mb mail system +claiming performance upwards of a message per second controlled by 100 +lines of shell! + +\subsection{Take 2} +The next version of the \verb|qmgr| was a C program. This was a small +program, I forget exactly the size. It did queue management in a +rather cavalier fashion. It scheduled messages by the simply +fork/exec'ing processes to deal with delivery. It read the queue +directly on start up and received UDP packets from submit to notify it +that new messages had arrived. The UDP packet contained a simple +string which was the queue name of the message. The \verb|qmgr| would then go +and read in this message, add it to the internal queues and start +scheduling it. + +It was cavalier in the respect that it did not trust anyone. The UDP +packet was a hint that a message had arrived. The \verb|qmgr| would +independently check this by attempting to read from the queue. Also, +as UDP is inherently unreliable - and also because the \verb|qmgr| had an +{\em attitude problem} - it would reread the entire queue frequently +to check what it thought was correct and that it hadn't missed +anything. + +This scheme works ok after a fashion. However, the frequent queue +reading we knew by experience would be a real performance killer. Most +of the queueing systems that we were familiar with have had as a +bottleneck the reading of the queue. UUCP has long had this problem, +with some very ingenious work-arounds to avoid quadratic behaviour with +large queues. MMDF had a similar problem, although to a lesser extent. +Normally MMDF will try and sort the mail queue optimally, but above a +threshold (300 messages) it admits defeat and gets very relaxed about +the whole thing, taking each message as it finds it without any +attempt at optimality. + +Another problem was this UDP issue. I liked it as it was simple, but +if we wanted to get away from the frequent queue reading, this +process would have to be reliable. We could obviously move to TCP for +reliability and then we could pass all the information we needed to +the \verb|qmgr|. But how to pass the data? We could have used something like +XDR and RPC from sun, which would probably do the job very well. +However, at the time I was deeply involved in work with ISODE and +getting ASN.1 tools together. We therefore decided - hey, we're +suppose to be pushing OSI, lets see if it can cut it. This leads on to ... + +\subsection{The current version} +The book {\em The Mythical Man Month} makes a great play of the fact +that the third and presumably subsequent versions of a piece of +software are usually the better versions. The first version being a +rather cautious attempt to see if you can do the job, having minimal +functionality and being a sort of prrof of concept case. The second +version is then usually a wild extravaganza of crazy ideas that you +thought up while writing the first version and just {\em had} to put +in. The third version then falls somewhere between these two. I am +rather proud therefore that there have been three rewrites of this +part of the system. + +The current version of the \verb|qmgr| is rather detached from reallity in +some respects. It never interacts directly with anything. Indeed the +\verb|qmgr| can run on a different machine to the rest of the system. +The \verb|qmgr| issues commands to other programs for all its +operations. In this way it is usually very responsive as it never has +to do serious amounts of work itself. When started up, the \verb|qmgr| +first schedules a channel called \verb|qmgr-load| which reads the +queue and passes its findings to the \verb|qmgr|. The \verb|qmgr| then +processes the messages in the queue calling different channels until +finally on each message the \verb|msg-clean| process is called to +remove each message. Every 6 hours or so, the \verb|qmgr| will +reschedule \verb|qmgr-load| to just check the queue is what it really +thinks it is. It also schedules irregularly a process called +\verb|trash| which will crawl around the queue looking for dead +messages or general junk. + +The \verb|qmgr| receives news of new messages via ROS operations from submit +and believes this information. From this it can be seen that the \verb|qmgr| +is not a trusted process. It just schedules the channels it thinks it +should on the basis of the information it receives. Each channel is +responsible for checking that the \verb|qmgr|'s request is reasonable. +This scheme appears to work fairly well. + +\subsection{Tuning performance - initial} +It turns out that scheduling is never as easy as you thought it might +be - even if you take this maxim into account! To begin with, I was +running the \verb|qmgr| on an empty queue and introducing one message at a +time to see that it scheduled things as it should. It took many +iterations before I had everything sorted out so that the \verb|qmgr| always +scheduled things that were ready to run. There is a fairly complex +interaction between address that have been cached for a while, +messages that are locked as they are being processed and the +intelligence of scheduling. Eventually this was solved, such that +messages appeared to do what they were suppose to. + +The next step was to introduce it into service. We ran it on a machine +at Nottingham processing maybe 100 messages a day delivering to a +handful of brave recipients. It turns out that 100 messages a day is +not too dissimilar to the one message at a time scenario. Things seem +to run fine. Then one day a glut of messages arrived at the same time +as several local messages were submitted. The machine (a sun 3/60 with +8Mb) practically died. The \verb|qmgr| was a little over eager - +scheduling everything it could We had 10-15 processes hammering away +at the queue and performance was non-existent. + +The first step to correct this was to put a limit on the total number +of simultaneous channels that could be run. By setting this figure to +one you can get back to linear behaviour and a figure of about 3 is +suitable for most reasonably small sites. The next thing that was +noticed was that with 2 messages were introduced into the queue, the +following happened. +\begin{quote}\small\begin{verbatim} +process1: deliver message1 to recipient +process1: message1 delivered +process2: start up and initialise +process1: deliver message2 to recipient +process2: delete message1 +process2: shutdown +process1: message2 delivered +process2: start up an initialise +process2: delete message1 +process2: shutdown +\end{verbatim}\end{quote} +As the delivery time is slightly longer than the time to delete a +message, the deletion process is started up and stopped many times. A +simple fix for this is to cache a channel for a few seconds when it +shuts down. By enforcing an idle period of, say, 20 seconds, between +the same process running, this cuts down thrashing of one process. +Another useful technique is to round up cache times. If you cache a +message, then you round that time off to the nearest whole minute. +This means when the channel restarts to retry these messages is may +have a number to try - rather than starting up for just one message +and again a few seconds later for another. + +\subsection{Tuning performance - for real} +The next step in the evolution was when PP was pressed into service at +UCL. Here there are many messages processed (about 30,000+ a week). +As far as I recall, this really didn't affect scheduling policy that +much. Most of the bugs had been shaken out and although the queues had +grown to perhaps 1-300 messages things still worked reasonably well. +What it did show up was that more management control was needed. Much +work was done with the \verb|MTAconsole| at this stage to allow a +variety of new controls and some graphical details on performance. + +It was pushed a little more heavily one week when most of UCL's +machines were down for air-conditioning maintenance. At this point +delivery to local users could not proceed as the relevant NFS +partitions were not present. It would have been nice to do some more +useful cacheing in this case, such as detecting that a whole disc was +missing so disabling delivery to a whole range of users. Unfortunately +this sort of thing is rather difficult to detect in software - +especially in a portable way. All you generally know is that a +chdir(2) or open(2)failed. + +Anyway, the \verb|qmgr| continued to run ok with a few minor tweaks here and +there - mainly to provide new statistics for the console process. + +And then... it was brought up at nsfnet-relay. + +Whereas at UCL the queues might peak at 1000 messages occasionally, +this sort of figure is the typical ``quiet'' day at nsfnet-relay. We +were rather staggered seeing at first hand the sort of traffic they +processed. The ULCC people had received a copy of the UCL system and +had been playing around with it to see if it did what was required. +Then one particularly heavy day, there was just too much traffic for +the MMDF and grey-book system to take. As some traffic had been +filtered through the PP system at nsfnet-relay already, it was decided +to switch to PP to clear the backlog. This was done, and a backlog of +5000 messages was cleared together with a constant stream of new +traffic within about a day. As everything appeared to be working ok +the system was left in production. + +This worked fine, although watching things carefully it was clear that +things were not being processed optimally. Of the 6 channels the \verb|qmgr| +had to work with it would start off by allocating the following. +\begin{quote} +\small +\begin{verbatim} +smtp: 2 +greybook: 2 +msg-clean: 1 +822touk: 1 +\end{verbatim} +\end{quote} +However, after a while, some of the channels cleared - or else all +hosts were deemed unreachable currently. The channel would then +shutdown and be reallocated. Then, at this point they would do other +work such as reformatting and messages would build up in one of the +outbound queues. Once the reformatting was complete, Channels would be +allocated to the outbound channel. As there were many messages on this +channel, as other channels finished they would be allocated to this +channel. This would result in an allocation such as: +\begin{quote} +\small +\begin{verbatim} +greybook: 5 +msg-clean: 1 +\end{verbatim} +\end{quote} +Eventually the greybook queue would clear, but by this time the smtp +queue had built up so processing switched to that. +This continued in a sort of bistable flip-flop routine. This is not +particularly serious - although probably not the sort of behaviour that +is required. + +The real disaster occurred a week or so later. It seems to have +happened after the US thanksgiving holiday. We suspect that during +this time a number of machines in the U.S. were either taken down or +crashed, making the mail pile up at nsfnet-relay. Then, when they came +back up - there was an enormous flood of mail. At one stage we had +over 11,000 messages in the queue. A simple ls(1) in the queue +directory took several minutes! PP continued to work through this +queue though, and was making some progress. Every night however, the +machine is taken down for 30 minutes or so to perform a full backup. +When the machine restarted, the \verb|qmgr| scheduled the +\verb|qmgr-load| process as normal. However, there were so many +messages in the directory (and unix behaves rather quadratically with +large directories) that this process took over an hour to read in all +the files. By this time the process had grown to about 50Mb in size. +Then it tried to transfer the queue to the +\verb|qmgr|, which also had to grow to 50Mb's to accomodate it. There was only +100Mb of VM configured - so not suprisingly the \verb|qmgr| ran out of +memory. Despite this it continued to run which I was quite pleased +about! + +This was desperate. The nsfnet-relay machine is not one that you can +say ``Oh well, never mind - thats one for the record books'', it {\em +has} to be fixed. There was a panic days work to convert the +qmgr-loader into an incremental process that loaded 50 messages at a +time rather than all at once. Meanwhile, a small debugging program we +had around that was used to load individual messages into the queue +was pressed into service. Together with ls and xargs it succeeded in +loading up the +\verb|qmgr| in about 2 hours total. The backlog of messages was cleared in +about two days total. + +In hindsight, this was an obvious problem waiting to happen, but it +was an issue that was hardly discussed until it happened. + +\subsection{... in the light of experience} +After the experiences with nsfnet-relay, we are adapting some of the +software. It is clear that more statistics are needed (such as number +of messages processed and messages processed/second). It also seems as +though the \verb|qmgr| is using too much of its memory when running. From +observation, it uses less than 1Mb of memory to hold just over 1000 +messages (e.g. the \verb|qmgr| at the peak traffic on nsfnet-relay was of the +order 11Mb). However, it also seems to use most of this memory most of +the time. This causes heavy paging traffic. With some subtle changes +to the internal data structures I believe it is possible to reduce the +working set size considerably - which will give other processes a +chance! + +\section{Conclusions} +PP has been an interesting project and we are now getting some real +feedback on the design decisions taken early on. It seems to be mostly +up to the job asked of it - even in the busiest environments. We +worked out using back-of-the-envelope calculations, that it can +process about a message/second at the present time - on input and +output. We think with a few of the changes hinted at above we can move +this to 10 messages/second without too much effort. This works out at +just less than a million messages a day. We hope this will be +sufficient for most peoples usage. (You could always buy another +machine!) + +\bibliography{bcustom,networking,software} +\bibliographystyle{alpha} + +\showsummary + +\end{document} diff --git a/doc/funet91/pp.vrsn b/doc/funet91/pp.vrsn new file mode 100644 index 0000000..5e5f57b --- /dev/null +++ b/doc/funet91/pp.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.29}% + \gdef\versiondate/{Wed Sep 18 08:20:27 BST 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/funet91/queuefig.fig b/doc/funet91/queuefig.fig new file mode 100644 index 0000000..1deae63 --- /dev/null +++ b/doc/funet91/queuefig.fig @@ -0,0 +1,47 @@ +#FIG 2.0 +80 2 +1 1 0 1 0 0 0 0 0.000 1 0.000 581 368 96 50 581 368 676 417 +1 1 0 1 0 0 0 0 0.000 1 0.000 139 370 96 50 139 370 234 419 +2 1 1 1 0 0 0 0 4.000 1 1 + 0 0 1.000 4.000 8.000 + 0 0 1.000 4.000 8.000 + 237 369 485 369 236 369 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 531 412 438 536 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 192 412 276 524 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 279 281 187 327 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 358 280 514 332 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 479 159 399 239 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 145 162 241 234 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 435 599 435 519 276 519 276 599 435 599 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 399 279 399 199 240 199 240 279 399 279 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 560 158 560 78 401 78 401 158 560 158 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 238 161 238 81 79 81 79 161 238 161 9999 9999 +2 4 0 0 0 0 0 0 0.000 6 0 0 + 239 159 239 81 79 81 79 159 239 159 9999 9999 +2 4 0 0 0 0 0 0 0.000 6 0 0 + 239 160 239 79 78 79 78 160 239 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 299 209 299 209 299 209 299 209 299 209 9999 9999 +4 0 0 12 0 0 0 0.000 1 9 90 323 564 Outbound channel +4 0 0 12 0 0 0 0.000 1 11 33 566 371 Queue +4 0 0 12 0 0 0 0.000 1 12 28 109 373 Qmgr +4 0 0 12 0 0 0 0.000 1 9 35 283 245 Submit +4 0 0 12 0 0 0 0.000 1 9 47 438 124 Local UA +4 0 0 12 0 0 0 0.000 1 9 84 119 122 Inbound Channel +echo shar: "6 control characters may be missing from 'queuefig.fig'" diff --git a/doc/funet91/sfwdoc.bib b/doc/funet91/sfwdoc.bib new file mode 100644 index 0000000..fb59687 --- /dev/null +++ b/doc/funet91/sfwdoc.bib @@ -0,0 +1,346 @@ +% ``Software'' bibliography database for BiB-TeX + + +@manual{AmSTeX, + author = "Michael Spivak", + title = "{Summary of \AmSTeX{}}", + month = sep, + year = 1983 +} + +@manual{BFLY.NRTC, + title = "{Using the BB\&N Butterfly at NRTC}", + author = "John L. Romine and Marshall T. Rose", + organization= nrtc, + month = may, + year = 1986 +} + +@manual{BibTeX, + author = "Oren Patashnik", + title = "{\BibTeX{}ing}", + month = may, + year = 1983 +} + +@manual{BSD.NET, + title = "{4.2BSD Networking Implementation Notes}", + author = "Samuel J. Leffler and William N. Joy and + Robert S. Fabry", + organization= {Computer Systems Research Group, + Computer Science Division}, + address = {Department of Electrical Engineering and Computer + Science, University of California, Berkeley}, + month = jul, + year = 1983 +} + +@book{C.Language, + author = "Brian W. Kernighan and Dennis M. Ritchie", + title = "{The C Programming Language}", + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + series = {Software Series}, + year = 1978 +} + +@manual{Emacs, + author = "James Gosling", + title = "{UNIX EMACS, UCI Version}", + month = may, + year = 1982 +} + +@manual{EtherTIP, + title = "{Using the Bridge CS/1 at NRTC}", + author = mtr, + organization= nrtc, + month = may, + year = 1986 +} + +@inproceedings{Face.Nation, + author = "Rob Pike and David L. Presotto", + title = "{Face the Nation}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {81--86}, + month = jun, + year = 1985, + note = {Portland, Oregon} +} + +@techreport{ISO.Environment, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{The ISO Development Environment at NRTC: User's + Manual}", + type = {Technical Paper}, + number = {\#702}, + institution= nrtc, + month = sep, + year = 1986 +} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {4.0}, + author = mtr, + organization= twg, + month = aug, + year = 1988 +} + +@book{LaTeXbook, + author = "Leslie Lamport", + title = "{\LaTeX{}: A Document Preparation System}", + publisher= {Addison-Wesley}, + address= {Reading, Massachusetts}, + year = 1985 +} + +@manual{MH.4, + title = "{Changes to the Rand MH Message Handling System: + MH.4}", + edition = {\mh4}, + author = mtr, + month = jul, + year = 1984, + note = {MH documentation set} +} + +@manual{MH.5, + title = "{Changes to the Rand MH Message Handling System: + MH.5}", + edition = {\mh5}, + author = mtr, + month = jan, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.6, + title = "{Changes to the Rand MH Message Handling System: + MH.6}", + author = mtr, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.ADM, + title = "{The Rand MH Message Handling System: + Administrator's Guide}", + author = mtr, + organization= ics, + address = uci, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.BB, + title = "{The Rand MH Message Handling System: + The UCI BBoards Facility}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.Beginners, + title = "{MH for Beginners}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.MM, + title = "{MH for MM Users}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@techreport{MH.POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{MH.XPOP, + author = mtr, + title = "{Post Office Protocol~---~Version 3: + Extended Service Offerings}", + type = rfc, + number = 1082, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@manual{MH.USR, + title = "{The Rand MH Message Handling System: + User's Manual}", + author = "Marshall T. Rose and John L. Romine", + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.TUT, + title = "{The Rand MH Message Handling System: + Tutorial}", + author = "Marshall T. Rose and Jerry N. Sweet", + month = may, + year = 1985, + note = {MH documentation set} +} + +@inproceedings{MMDF, + author = "David H. Crocker and E.S. Szurkowski and + David J. Farber", + title = "{An Internetwork Memo Distribution + Facility~---~MMDF}", + booktitle= "{Proceedings, Sixth Data Communications Symposium}", + pages = {18--25}, + month = nov, + year = 1979, + note = {Asilomar} +} + +@inproceedings{MMDFII, + author = "Douglas P. Kingston~III", + title = "{MMDFII: A Technical Review}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {32--41}, + month = jun, + year = 1984, + note = {Salt Lake City, Utah} +} + +@manual{PhDTeX, + author = "E. Timothy Morgan", + title = "{A Dissertation Style for \AmSTeX{}}", + month = sep, + year = 1984, + note = {Department of Information and Computer Science, + University of California, Irvine} +} + +@techreport{PIC, + author = "Brian W. Kernighan", + title = "{PIC --- A Graphics Language for Typesetting User + Manual}", + type = {Computing Science Technical Report}, + number = 85, + institution= {Bell Laboratories}, + address = {Murray Hill, New Jersey}, + month = mar, + year = 1982 +} + +@manual{SendMail, + title = "{SENDMAIL~---~An Internetwork Mail Router}", + author = "Eric Allman", + organization= {Britton-Lee, Inc.}, + address = {Berkeley, California}, + month = jul, + year = 1983 +} + +@manual{Slides, + title = "{Using \SLiTeX{} to Make Slides at NRTC}", + author = mtr, + organization= nrtc, + month = apr, + year = 1986 +} + +@manual{STREAMS, + key = {ATT}, + title = "{STREAMS Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@book{SVID, + key = {SVID}, + title = "{System V Interface Definition}", + publisher= {AT\&T Bell Laboratories}, + edition = {$2^{\underline{\mbox{\scriptsize nd}}}$}, + year = 1986 +} + +@book{TeXbook, + author = "Donald E. Knuth", + title = "{The \TeX{}book}", + publisher= {Addison-Wesley}, + address = {Reading, Massachusetts}, + year = 1983 +} + +@techreport{TeX.Roff, + author = "Michael Urban", + title = "{A Guide to \TeX{} for the Troff User}", + institution= {TRW Software Productivity Project}, + month = oct, + year = 1984 +} + +@misc{TeX.Trip, + author = "Donald E. Knuth", + title = "{A Test File for \TeX{}}", + month = jul, + year = 1983, + note = {Version 0.999} +} + +@manual{TLI, + key = {ATT}, + title = "{Network Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@manual{UCI.map, + title = "{The UCI RoadMap}", + author = mtr, + organization= nrtc, + month = jun, + year = 1986 +} + +@article{WEB.TUT, + author = "Donald E. Knuth", + title = "{Literate Programming}", + journal = {The Computer Journal}, + year = 1983 +} + +@manual{WEB.USR, + author = "Donald E. Knuth", + title = "{WEB USER MANUAL}", + year = 1983 +} diff --git a/doc/funet91/software.bib b/doc/funet91/software.bib new file mode 100644 index 0000000..75c7fb8 --- /dev/null +++ b/doc/funet91/software.bib @@ -0,0 +1,345 @@ +% ``Software'' bibliography database for BiB-TeX + + +@manual{AmSTeX, + author = "Michael Spivak", + title = "{Summary of \AmSTeX{}}", + month = sep, + year = 1983 +} + +@manual{BFLY.NRTC, + title = "{Using the BB\&N Butterfly at NRTC}", + author = "John L. Romine and Marshall T. Rose", + organization= nrtc, + month = may, + year = 1986 +} + +@manual{BibTeX, + author = "Oren Patashnik", + title = "{\BibTeX{}ing}", + month = may, + year = 1983 +} + +@manual{BSD.NET, + title = "{4.2BSD Networking Implementation Notes}", + author = "Samuel J. Leffler and William N. Joy and + Robert S. Fabry", + organization= {Computer Systems Research Group, + Computer Science Division}, + address = {Department of Electrical Engineering and Computer + Science, University of California, Berkeley}, + month = jul, + year = 1983 +} + +@book{C.Language, + author = "Brian W. Kernighan and Dennis M. Ritchie", + title = "{The C Programming Language}", + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + series = {Software Series}, + year = 1978 +} + +@manual{Emacs, + author = "James Gosling", + title = "{UNIX EMACS, UCI Version}", + month = may, + year = 1982 +} + +@manual{EtherTIP, + title = "{Using the Bridge CS/1 at NRTC}", + author = mtr, + organization= nrtc, + month = may, + year = 1986 +} + +@inproceedings{Face.Nation, + author = "Rob Pike and David L. Presotto", + title = "{Face the Nation}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {81--86}, + month = jun, + year = 1985, + note = {Portland, Oregon} +} + +@techreport{ISO.Environment, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{The ISO Development Environment at NRTC: User's + Manual}", + type = {Technical Paper}, + number = {\#702}, + institution= nrtc, + month = sep, + year = 1986 +} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {6.0}, + author = mtr, + month = jan, + year = 1990 +} + +@book{LaTeXbook, + author = "Leslie Lamport", + title = "{\LaTeX{}: A Document Preparation System}", + publisher= {Addison-Wesley}, + address= {Reading, Massachusetts}, + year = 1985 +} + +@manual{MH.4, + title = "{Changes to the Rand MH Message Handling System: + MH.4}", + edition = {\mh4}, + author = mtr, + month = jul, + year = 1984, + note = {MH documentation set} +} + +@manual{MH.5, + title = "{Changes to the Rand MH Message Handling System: + MH.5}", + edition = {\mh5}, + author = mtr, + month = jan, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.6, + title = "{Changes to the Rand MH Message Handling System: + MH.6}", + author = mtr, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.ADM, + title = "{The Rand MH Message Handling System: + Administrator's Guide}", + author = mtr, + organization= ics, + address = uci, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.BB, + title = "{The Rand MH Message Handling System: + The UCI BBoards Facility}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.Beginners, + title = "{MH for Beginners}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.MM, + title = "{MH for MM Users}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@techreport{MH.POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{MH.XPOP, + author = mtr, + title = "{Post Office Protocol~---~Version 3: + Extended Service Offerings}", + type = rfc, + number = 1082, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@manual{MH.USR, + title = "{The Rand MH Message Handling System: + User's Manual}", + author = "Marshall T. Rose and John L. Romine", + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.TUT, + title = "{The Rand MH Message Handling System: + Tutorial}", + author = "Marshall T. Rose and Jerry N. Sweet", + month = may, + year = 1985, + note = {MH documentation set} +} + +@inproceedings{MMDF, + author = "David H. Crocker and E.S. Szurkowski and + David J. Farber", + title = "{An Internetwork Memo Distribution + Facility~---~MMDF}", + booktitle= "{Proceedings, Sixth Data Communications Symposium}", + pages = {18--25}, + month = nov, + year = 1979, + note = {Asilomar} +} + +@inproceedings{MMDFII, + author = "Douglas P. Kingston~III", + title = "{MMDFII: A Technical Review}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {32--41}, + month = jun, + year = 1984, + note = {Salt Lake City, Utah} +} + +@manual{PhDTeX, + author = "E. Timothy Morgan", + title = "{A Dissertation Style for \AmSTeX{}}", + month = sep, + year = 1984, + note = {Department of Information and Computer Science, + University of California, Irvine} +} + +@techreport{PIC, + author = "Brian W. Kernighan", + title = "{PIC --- A Graphics Language for Typesetting User + Manual}", + type = {Computing Science Technical Report}, + number = 85, + institution= {Bell Laboratories}, + address = {Murray Hill, New Jersey}, + month = mar, + year = 1982 +} + +@manual{SendMail, + title = "{SENDMAIL~---~An Internetwork Mail Router}", + author = "Eric Allman", + organization= {Britton-Lee, Inc.}, + address = {Berkeley, California}, + month = jul, + year = 1983 +} + +@manual{Slides, + title = "{Using \SLiTeX{} to Make Slides at NRTC}", + author = mtr, + organization= nrtc, + month = apr, + year = 1986 +} + +@manual{STREAMS, + key = {ATT}, + title = "{STREAMS Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@book{SVID, + key = {SVID}, + title = "{System V Interface Definition}", + publisher= {AT\&T Bell Laboratories}, + edition = {$2^{\underline{\mbox{\scriptsize nd}}}$}, + year = 1986 +} + +@book{TeXbook, + author = "Donald E. Knuth", + title = "{The \TeX{}book}", + publisher= {Addison-Wesley}, + address = {Reading, Massachusetts}, + year = 1983 +} + +@techreport{TeX.Roff, + author = "Michael Urban", + title = "{A Guide to \TeX{} for the Troff User}", + institution= {TRW Software Productivity Project}, + month = oct, + year = 1984 +} + +@misc{TeX.Trip, + author = "Donald E. Knuth", + title = "{A Test File for \TeX{}}", + month = jul, + year = 1983, + note = {Version 0.999} +} + +@manual{TLI, + key = {ATT}, + title = "{Network Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@manual{UCI.map, + title = "{The UCI RoadMap}", + author = mtr, + organization= nrtc, + month = jun, + year = 1986 +} + +@article{WEB.TUT, + author = "Donald E. Knuth", + title = "{Literate Programming}", + journal = {The Computer Journal}, + year = 1983 +} + +@manual{WEB.USR, + author = "Donald E. Knuth", + title = "{WEB USER MANUAL}", + year = 1983 +} diff --git a/doc/funet91/trademark.tex b/doc/funet91/trademark.tex new file mode 100644 index 0000000..dbd5af8 --- /dev/null +++ b/doc/funet91/trademark.tex @@ -0,0 +1,75 @@ +% Trademarks... + +\def\gobble#1{} +\def\tradeORGfont{\sc} % used for organizations (e.g., ACM) +\def\tradeNAMfont{\sf} % used for names (e.g., Ada) + +\def\tradeorg#1{% + \tradeaux{#1}{\expandafter\gobble\string#1}\empty\tradeORGfont +} +\def\tradeorgn#1#2{% + \tradeaux{#1}{#2}\empty\tradeORGfont +} +\def\tradename#1#2#3{\tradeaux{#1}{#2}{#3}\tradeNAMfont} +\def\trademark#1#2{% + \tradeaux{#1}{\expandafter\gobble\string#1}{#2}\tradeNAMfont +} + +\def\tradeaux#1#2#3#4{% + \def#1/{\relax}% % in case #3 references #1 + \setbox0=\hbox{#3}% % when we make the \hbox + \ifdim\wd0>0pt + \gdef#1/{% + \tradeaux{#1}{#2}\empty{#4}% + #1/\footnote{#1/ is a trademark of #3.}% + }% + \else + \gdef#1/{{#4#2}}% + \fi +} + +\tradeorg\acm +\tradeorg\ansi +\tradename\Ada{Ada} + {the Department of Defense (\Ada/ Joint Program Office)} +\tradename\balance{Balance} {Sequent Computer Systems, Incorporated} +\tradeorg\bsd +\tradename\butterfly{Butterfly}{Bolt, Beranek, and Newman, Incorporated} +\tradeorg\ccitt +\tradename\cms{CMS} {International Business Machines, Incorporated} +\tradename\cpm{CP/M} {Digital Research Corporation} +\tradename\chrysalis{Chrysalis}{Bolt, Beranek, and Newman, Incorporated} +\tradename\decnet{DECnet} {Digital Equipment Corporation} +\tradeorgn\dod{DoD} +\tradename\dynix{DYNIX} {Sequent Computer Systems, Incorporated} +\tradename\ethernet{Ethernet} {the Xerox Corporation} +\tradename\eunice{Eunice} \empty +\tradename\exos{EXOS} {Excelan, Incorporated} +\tradename\ibmpc{IBM PC} {International Business Machines, Incorporated} +\tradename\ibmpcat{IBM PC/AT} {International Business Machines, Incorporated} +\tradeorg\ieee +\tradename\iPSC{iPSC} {Intel Corporation} +\tradename\lattice{Lattice} {Lattice, Incorporated} +\tradename\locus{Locus} {Locus Computing Corporation} +\def\microvax/{$\mu$\vax/} +\def\microvms/{$\mu$\vms/} +\tradeorg\milstd +\tradename\msdos{MS-DOS} {Microsoft Corporation} +\tradename\mvs{MVS} {International Business Machines, Incorporated} +\tradename\pcdos{PC-DOS} {International Business Machines, Incorporated} +\tradename\pcinterface{PC-Interface}% + {Locus Computing Corporation} +\tradename\pdp{PDP} {Digital Equipment Corporation} +\tradename{\tops20}{Tops20} {Digital Equipment Corporation} +\tradename\trustedmail{Trusted\ Mail}% + {Trusted Technologies, Incorporated} +\tradename\tseries{T-Series} {Floating Point Systems} +\tradename\ultrix{ULTRIX} {Digital Equipment Corporation} +\tradename\unibus{UNIBUS} {Digital Equipment Corporation} +\tradename\unix{UNIX} {AT\&T Bell Laboratories} +\tradename\vax{VAX} {Digital Equipment Corporation} +\tradename\vaxstation{VAXstation}% + {Digital Equipment Corporation} +\tradename\vm{VM} {International Business Machines, Incorporated} +\tradename\vms{VMS} {Digital Equipment Corporation} +\tradename\xenix{Xenix} {Microsoft Corporation} diff --git a/doc/funet91/version.sh b/doc/funet91/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/funet91/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/ifip6.5-88/Makefile b/doc/ifip6.5-88/Makefile new file mode 100644 index 0000000..8ff98fa --- /dev/null +++ b/doc/ifip6.5-88/Makefile @@ -0,0 +1,39 @@ +# Make for ifip paper +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + + + +############################################################ +# +# Building Rules +# +############################################################ + +default:; + +install: + +clean:; + +tidy:; + +lint:; + +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/doc/ifip6.5-88/make b/doc/ifip6.5-88/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/ifip6.5-88/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/ifip6.5-88/paper.psc b/doc/ifip6.5-88/paper.psc new file mode 100644 index 0000000..46896b5 --- /dev/null +++ b/doc/ifip6.5-88/paper.psc @@ -0,0 +1,8846 @@ +%! for use by dvi2ps Version 2.00 +% a start (Ha!) at a TeX mode for PostScript. +% The following defines procedures assumed and used by program "dvi2ps" +% and must be downloaded or sent as a header file for all TeX jobs. + +% By: Neal Holtz, Carleton University, Ottawa, Canada +% +% +% June, 1985 +% Last Modified: Aug 25/85 +% oystr 12-Feb-1986 +% Changed @dc macro to check for a badly formed bits in character +% definitions. Can get a <> bit map if a character is not actually +% in the font file. This is absolutely guaranteed to drive the +% printer nuts - it will appear that you can no longer define a +% new font, although the built-ins will still be there. + +% To convert this file into a downloaded file instead of a header +% file, uncomment all of the lines beginning with %-% + +%-%0000000 % Server loop exit password +%-%serverdict begin exitserver +%-% systemdict /statusdict known +%-% {statusdict begin 9 0 3 setsccinteractive /waittimeout 300 def end} +%-% if + +/TeXDict 200 dict def % define a working dictionary +TeXDict begin % start using it. + + % units are in "dots" (300/inch) +/Resolution 300 def +/Inch {Resolution mul} def % converts inches to internal units + +/Mtrx 6 array def + +%%%%%%%%%%%%%%%%%%%%% Page setup (user) options %%%%%%%%%%%%%%%%%%%%%%%% + +% dvi2ps will output coordinates in the TeX system ([0,0] 1" down and in +% from top left, with y +ive downward). The default PostScript system +% is [0,0] at bottom left, y +ive up. The Many Matrix Machinations in +% the following code are an attempt to reconcile that. The intent is to +% specify the scaling as 1 and have only translations in the matrix to +% properly position the text. Caution: the default device matrices are +% *not* the same in all PostScript devices; that should not matter in most +% of the code below (except for lanscape mode -- in that, rotations of +% -90 degrees resulted in the the rotation matrix [ e 1 ] +% [ 1 e ] +% where the "e"s were almost exactly but not quite unlike zeros. + +% NOTE: We use A4 size paper. For letter size paper the constants '340' in the +% following code should be changed to '310'. + +/@a4 +{a4 initmatrix +72 Resolution div dup neg scale +270 -3215 translate +Mtrx currentmatrix pop +}def +/@letter + { letter initmatrix + 72 Resolution div dup neg scale % set scaling to 1. + 310 -3005 translate % move origin to top (these are not exactly 1" + Mtrx currentmatrix pop % and -10" because margins aren't set exactly right) + } def + % note mode is like letter, except it uses less VM +/@note + { note initmatrix + 72 Resolution div dup neg scale % set scaling to 1. + 310 -3005 translate % move origin to top + Mtrx currentmatrix pop + } def + + % A3 modes courtesy of Francis Pintos, UCL + +/@a3landscape +{a3 initmatrix +72 Resolution div dup neg scale +-90 rotate +300 310 translate +Mtrx currentmatrix pop +statusdict begin 1 setpapertray end +}def + +/@a3portrait +{a3 initmatrix +72 Resolution div dup neg scale +300 310 translate +Mtrx currentmatrix pop +statusdict begin 1 setpapertray end +}def + +/@landscape + { letter initmatrix + 72 Resolution div dup neg scale % set scaling to 1. + -90 rotate % it would be nice to be able to do this +% Mtrx currentmatrix 0 0.0 put % but instead we have to do things like this because what +% Mtrx 1 -1.0 put % should be zero terms aren't (and text comes out wobbly) +% Mtrx 2 1.0 put % Fie! This likely will not work on QMS printers +% Mtrx 3 0.0 put % (nor on others where the device matrix is not like +% Mtrx setmatrix % like it is on the LaserWriter). + 300 310 translate % move origin to top + Mtrx currentmatrix pop + } def + +/@legal + { legal initmatrix + 72 Resolution div dup neg scale % set scaling to 1. + 295 -3880 translate % move origin to top + Mtrx currentmatrix pop + } def + +/@manualfeed + { statusdict /manualfeed true put + } def + % n @copies - set number of copies +/@copies + { /#copies exch def + } def +/@restore /restore load def +/restore + {vmstatus pop + dup @VMused lt{pop @VMused}if % calculate virtual memory used + exch pop exch @restore /@VMused exch def + }def + +/@pri + { + ( ) print + ( ) cvs print + }def + +/@FontMatrix [1 0 0 -1 0 0] def +/@FontBBox [0 0 1 1] def + +%%%%%%%%%%%%%%%%%%%% Procedure Defintions %%%%%%%%%%%%%%%%%%%%%%%%%% + +/@newfont % id @newfont - -- initialize a new font dictionary + { /newname exch def + newname 7 dict def % allocate new font dictionary + newname load begin + /FontType 3 def + /FontMatrix @FontMatrix def + /FontBBox @FontBBox def + /BitMaps 128 array def + /BuildChar {CharBuilder} def + /Encoding 128 array def + 0 1 127 {Encoding exch /.undef put} for + end + newname newname load definefont pop + } def + + +% the following is the only character builder we need. it looks up the +% char data in the BitMaps array, and paints the character if possible. +% char data -- a bitmap descriptor -- is an array of length 6, of +% which the various slots are: + +/ch-image {ch-data 0 get} def % the hex string image +/ch-width {ch-data 1 get} def % the number of pixels across +/ch-height {ch-data 2 get} def % the number of pixels tall +/ch-xoff {ch-data 3 get} def % number of pixels below origin +/ch-yoff {ch-data 4 get} def % number of pixels to left of origin +/ch-tfmw {ch-data 5 get} def % spacing to next character + +/CharBuilder % fontdict ch Charbuilder - -- image one character + {save 3 1 roll exch /BitMaps get exch get /ch-data exch def + ch-data null ne + {ch-tfmw 0 ch-xoff neg ch-yoff neg ch-width ch-xoff sub ch-height ch-yoff sub + setcachedevice + ch-width ch-height true [1 0 0 1 ch-xoff ch-yoff] + {ch-image} imagemask + }if + restore + } def + + +/@sf % fontdict @sf - -- make that the current font + { dup + % All smallcaps fonts must have the string SmallCaps in their name + /FontName known + { dup /FontName get tempstring cvs (SmallCaps) search + {/smallcaps true def pop pop pop} + {/smallcaps false def pop} + ifelse + } + {/smallcaps false def} + ifelse + setfont + } def + + % in the following, the font-cacheing mechanism requires that + % a name unique in the particular font be generated + +/@dc % char-data ch @dc - -- define a new character bitmap in current font + { /ch-code exch def +% ++oystr 12-Feb-86++ + dup 0 get + length 2 lt + { pop [ <00> 1 1 0 0 8.00 ] } % replace <> with null + if +% --oystr 12-Feb-86-- + /ch-data exch def + currentfont /BitMaps get ch-code ch-data put + currentfont /Encoding get ch-code + dup ( ) cvs cvn % generate a unique name simply from the character code + put + } def + +/@pc % char-data ch @pc - -- print a character bitmap not downloaded + {pop + /ch-data exch def + currentpoint translate + ch-width ch-height true [1 0 0 -1 ch-xoff ch-yoff] + {ch-image}imagemask + }def + +/@bop0 % n @bop0 - -- begin the char def section of a new page + { pop + } def + +/@bop1 % n @bop1 - -- begin a brand new page + { pop + erasepage initgraphics + Mtrx setmatrix + /SaveImage save def +% +% RLW: +% The following is a fix necessary since a /@beginspecial immediately +% following a /@bop1 failed. This was due to a lack of definition of the +% current point, something which can only happen in the one situation. +% Suffer the extra code for all other case as new pages don't happen too often. +% + 0 0 moveto +% + } def + +/@eop % - @eop - -- end a page + { showpage + SaveImage restore + } def + +/@start % - @start - -- start everything + { @a4 % (there is not much to do) + vmstatus pop /@VMused exch def pop + } def + +/@end % - @end - -- done the whole shebang + {(VM used: ) print @VMused @pri + (. Unused: ) print vmstatus @VMused sub @pri pop pop + (\n) print flush + end + } def + +/p % x y p - -- move to position + { moveto + } def + +/r % x r - -- move right + { 0 rmoveto + } def + +/s % string s - -- show the string + { smallcaps {SmallCapShow} {show} ifelse + } def + +/c % ch c - -- show the character (code given) + { c-string exch 0 exch put + c-string s + } def + +/c-string ( ) def + +/ru % dx dy ru - -- set a rule (rectangle) + { /dy exch neg def % because dy is height up from bottom + /dx exch def + /x currentpoint /y exch def def % remember current point + newpath x y moveto + dx 0 rlineto + 0 dy rlineto + dx neg 0 rlineto + closepath fill + x y moveto + } def + +/l % x y l - -- draw line to + { lineto + } def + +/rl % dx dy rl - -- draw relative line + { rlineto + } def + +/rc % x0 y0 x1 y1 y2 y2 rc -- draw bezier curve + { rcurveto + } def + +/np % np - -- start a new path and save currenpoint + { /SaveX currentpoint /SaveY exch def def % remember current point + newpath + } def + +/st % st - -- draw the last path and restore currentpoint + { stroke + SaveX SaveY moveto % restore the current point + } def + +/f % f -- fill the last path and restore currentpoint + { fill + SaveX SaveY moveto % restore the current point + } def + +/ellipse % xc yc xrad yrad startAngle endAngle ellipse + { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + + /savematrix matrix currentmatrix def + + x y translate + xrad yrad scale + 0 0 1 startangle endangle arc + savematrix setmatrix + } def + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% the \special command junk +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The structure of the PostScript produced by dvi2ps for \special is: +% @beginspecial +% - any number of @hsize, @hoffset, @hscale, etc., commands +% @setspecial +% - the users file of PostScript commands +% @endspecial + +% The @beginspecial command recognizes whether the Macintosh Laserprep +% has been loaded or not, and redfines some Mac commands if so. +%%% NOTE: This has been disabled as we don't use it !! +% The @setspecial handles the users shifting, scaling, clipping commands + + +% The following are user settable options from the \special command. + +/@SpecialDefaults + { /hs 8.5 Inch def + /vs 11.68 Inch def + /ho 0 def + /vo 0 def + /hsc 1 def + /vsc 1 def + /CLIP false def + } def + +% d @hsize - specify a horizontal clipping dimension +% these 2 are executed before the MacDraw initializations +/@hsize {/hs exch def /CLIP true def} def +/@vsize {/vs exch def /CLIP true def} def +% d @hoffset - specify a shift for the drwgs +/@hoffset {/ho exch def} def +/@voffset {/vo excl def} def +% s @hscale - set scale factor +/@hscale {/hsc exch def} def +/@vscale {/vsc exch def} def + +/@setclipper + { hsc vsc scale + CLIP + { newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip } + if + } def + +% this will be invoked as the result of a \special command (for the +% inclusion of PostScript graphics). The basic idea is to change all +% scaling and graphics back to defaults, but to shift the origin +% to the current position on the page. Due to TeXnical difficulties, +% we only set the y-origin. The x-origin is set at the left edge of +% the page. + +/@beginspecial % - @beginspecial - -- enter special mode + { gsave /SpecialSave save def + % the following magic incantation establishes the current point as + % the users origin, and reverts back to default scalings, rotations + currentpoint transform initgraphics itransform translate + @SpecialDefaults % setup default offsets, scales, sizes +%%% @MacSetUp % fix up Mac stuff -- DISABLED + /showpage {} def %%% Ignore showpage commands + } def + +/@setspecial % to setup user specified offsets, scales, sizes (for clipping) + { + MacDrwgs + {md begin /pxt ho def /pyt vo neg def end} + {ho vo translate @setclipper} + ifelse + } def + +/@endspecial % - @endspecial - -- leave special mode + { SpecialSave restore + grestore + } def + +%! +% All software, documentation, and related files in this distribution of +% psfig/tex are Copyright (c) 1987 Trevor J. Darrell +% +% Permission is granted for use and non-profit distribution of psfig/tex +% providing that this notice be clearly maintained, but the right to +% distribute any portion of psfig/tex for profit or as part of any commercial +% product is specifically reserved for the author. +% +% +% psfigTeX PostScript Prolog +% $Header: tex.ps,v 1.13 87/12/14 00:57:00 van Exp $ +% +/psf$TeXscale { 65536 div } def + +/DocumentInitState [ matrix currentmatrix currentlinewidth currentlinecap +currentlinejoin currentdash currentgray currentmiterlimit ] cvx def + +% x y bb-llx bb-lly bb-urx bb-ury startFig - +/startTexFig { + /psf$SavedState save def + userdict maxlength dict begin + currentpoint transform + + DocumentInitState setmiterlimit setgray setdash setlinejoin setlinecap + setlinewidth setmatrix + + itransform moveto + + /psf$ury exch psf$TeXscale def + /psf$urx exch psf$TeXscale def + /psf$lly exch psf$TeXscale def + /psf$llx exch psf$TeXscale def + /psf$y exch psf$TeXscale def + /psf$x exch psf$TeXscale def + + currentpoint /psf$cy exch def /psf$cx exch def + + /psf$sx psf$x psf$urx psf$llx sub div def % scaling for x + /psf$sy psf$y psf$ury psf$lly sub div def % scaling for y + + psf$sx psf$sy scale % scale by (sx,sy) + + psf$cx psf$sx div psf$llx sub + psf$cy psf$sy div psf$ury sub translate + + /DefFigCTM matrix currentmatrix def + + /initmatrix { + DefFigCTM setmatrix + } def + /defaultmatrix { + DefFigCTM exch copy + } def + + /initgraphics { + DocumentInitState setmiterlimit setgray setdash + setlinejoin setlinecap setlinewidth setmatrix + DefFigCTM setmatrix + } def + + /showpage { + initgraphics + } def + @MacSetUp +} def + +% llx lly urx ury doclip - (args in figure coordinates) +/doclip { + currentpoint 6 2 roll + newpath 4 copy + 4 2 roll moveto + 6 -1 roll exch lineto + exch lineto + exch lineto + closepath clip + newpath + moveto +} def + +% - endTexFig - +/endTexFig { end psf$SavedState restore } def + + + +%%%% Additions by LA Carr to reencode Adobe fonts as TeX fonts (almost) +%%%% Based on routine in LaserWriter Cookbook +/ReEncodeForTeX + { /newfontname exch def + /basefontname exch def + /TeXstr 30 string def + + /basefontdict basefontname findfont def + /newfont basefontdict maxlength dict def + basefontdict + { exch dup /FID ne + { dup /Encoding eq + { exch dup length array copy + newfont 3 1 roll put } + { exch newfont 3 1 roll put } + ifelse + } + { pop pop } + ifelse + } forall + +%% newfont /FontName newfontname put %% + basefontname TeXstr cvs (Dingbat) search + { pop pop pop } + { pop + /TeXvec basefontname TeXstr cvs (Courier) search + { pop pop pop TeXcourvec } + { pop TeXnormalvec } + ifelse def + TeXvec aload pop + + TeXvec length 2 idiv + { newfont /Encoding get 3 1 roll put } + repeat + } + ifelse + + newfontname newfont definefont pop + } def + +/TeXnormalvec + [ 8#014 /fi 8#015 /fl 8#020 /dotlessi 8#022 /grave 8#023 /acute + 8#024 /caron 8#025 /breve 8#026 /macron 8#027 /ring 8#030 /cedilla + 8#031 /germandbls 8#032 /ae 8#033 /oe 8#034 /oslash 8#035 /AE + 8#036 /OE 8#037 /Oslash 8#042 /quotedblright 8#074 /exclamdown + 8#076 /questiondown 8#134 /quotedblleft 8#136 /circumflex + 8#137 /dotaccent 8#173 /endash 8#174 /emdash 8#175 /quotedbl + 8#177 /dieresis ] def +/TeXcourvec + [ 8#016 /exclamdown 8#017 /questiondown 8#020 /dotlessi 8#022 /grave + 8#023 /acute 8#024 /caron 8#025 /breve 8#026 /macron 8#027 /ring + 8#030 /cedilla 8#031 /germandbls 8#032 /ae 8#033 /oe 8#034 /oslash + 8#035 /AE 8#036 /OE 8#037 /Oslash 8#074 /less 8#076 /greater + 8#134 /backslash 8#136 /circumflex 8#137 /underscore 8#173 /braceleft + 8#174 /bar 8#175 /braceright 8#177 /dieresis ] def + +/TeXPSmakefont { % defines a routine for generating PS fonts, fudged! + /TeXsize exch def + findfont + [ TeXsize 0 0 TeXsize neg 0 0 ] makefont + } def + +%Create a General Oblique font +/ObliqueFont { + /ObliqueAngle exch def + /ObliqueBaseName exch def + /ObliqueFontName exch def + /ObliqueTransform [1 0 ObliqueAngle sin ObliqueAngle cos div 1 0 0] def + /basefontdict ObliqueBaseName findfont ObliqueTransform makefont def + /newfont basefontdict maxlength dict def + basefontdict + { exch dup /FID ne + { dup /Encoding eq + { exch dup length array copy + newfont 3 1 roll put } + { exch newfont 3 1 roll put } + ifelse + } + { pop pop } + ifelse + } forall + + newfont /FontName ObliqueFontName put + ObliqueFontName newfont definefont + pop + } def + +/Times-Oblique /Times-Roman 15.5 ObliqueFont +/Times-BoldOblique /Times-Bold 15 ObliqueFont +%/Palatino-Oblique /Palatino-Roman 10 ObliqueFont +%/Palatino-BoldOblique /Palatino-Bold 10 ObliqueFont +/Times-ItalicUnslanted /Times-Italic -15.15 ObliqueFont + +%Create a Palatino-ItalicUnslanted font? You must be joking! + +%Create a General SmallCaps font +/SmallCapsFont { + /SmallCapsBaseName exch def + /SmallCapsFontName exch def + /basefontdict SmallCapsBaseName findfont def + /newfont basefontdict maxlength dict def + basefontdict + { exch dup /FID ne + { dup /Encoding eq + { exch dup length array copy + newfont 3 1 roll put } + { exch newfont 3 1 roll put } + ifelse + } + { pop pop } + ifelse + } forall + + newfont /FontName SmallCapsFontName put + SmallCapsFontName newfont definefont + pop + } def + +/Times-SmallCaps /Times-Roman SmallCapsFont +%/Palatino-SmallCaps /Palatino-Roman SmallCapsFont + +/SmallCapShow { + % string smallcaps show + /achar (A) def + /xfac 0.8 def + /yfac 0.8 def + /xrec 1 xfac div def + /yrec 1 yfac div def + { dup dup + 8#141 ge exch 8#172 le and + { 8#40 sub achar exch 0 exch put achar + xfac yfac scale show xrec yrec scale } + { achar exch 0 exch put achar show } + ifelse + } forall +} def + +/tempstring 100 string def % used for string conversions +%%%% Additions by LA Carr to reencode Adobe fonts as TeX fonts (almost) +%%%% Based on routine in LaserWriter Cookbook + +/MacDrwgs false def % will get set if we think the Mac LaserPrep file has been loaded + + % - @MacSetUp - turn-off/fix-up all the MacDraw stuff that might hurt us + % we depend on 'psu' being the first procedure executed + % by a Mac document. We redefine 'psu' to adjust page + % translations, and to do all other the fixups required. + % This stuff will not harm other included PS files +/@MacSetUp + { userdict /md known % if md is defined + { userdict /md get type /dicttype eq % and if it is a dictionary + { /MacDrwgs true def + md begin % then redefine some stuff + /psu % redfine psu to set origins, etc. + /psu load + % this procedure contains almost all the fixup code + { /letter {} def % it is bad manners to execute the real + /note {} def % versions of these (clears page image, etc.) + /legal {} def + statusdict /waittimeout 300 put + /page {pop} def % no printing of pages + /pyt vo neg def % x & y pixel translations + /pxt ho def + } + concatprocs + def + /od % redefine od to set clipping region + /od load + { @setclipper } + concatprocs + def + end } + if } + if + } def + +% p1 p2 concatprocs p - concatenate procedures +/concatprocs + { /p2 exch cvlit def + /p1 exch cvlit def + /p p1 length p2 length add array def + p 0 p1 putinterval + p p1 length p2 putinterval + p cvx + } def + +end % revert to previous dictionary + +statusdict /waittimeout 300 put +TeXDict begin @start +%%Title: paper-t.dvi +%%Creator: dvi2ps +%%EndProlog +13 @bop0 +/cmr10.329 @newfont +cmr10.329 @sf +[ 31 31 -1 0 33] 82 @dc +[<03F8000FFE001F87003E03807C0180780000F80000F00000F00000F00000FFFF80FFFF80F00380F007807807807807003C0F + 001E1E000FFC0003F000> 17 20 -1 0 20] 101 @dc +[ 13 20 -2 0 18] 115 @dc +[<1F83C03FE7E07C7FF0F81F30F01F30F00F30F00F30F80F007C0F003E0F000FCF0003FF00000F00000F00380F007C1F007C1E + 007C7E007FFC001FF000> 20 20 -2 0 23] 97 @dc +[ 16 20 0 0 18] 114 @dc +[<03F00FFC1F0E3E077C037800F800F000F000F000F000F000F000F000781C783E3C3E1E3E0FFE03F8> 16 20 -2 0 20] 99 @dc +[ 24 32 0 0 25] 104 @dc +[ 31 31 -1 0 34] 78 @dc +[<01F80007FE001E07803C03C03801C07801E07000E0F000F0F000F0F000F0F000F0F000F0F000F07000E07000E03801C03C03 + C01E078007FE0001F800> 20 20 -1 0 23] 111 @dc +[<07E00FF01F301E181E181E181E181E181E001E001E001E001E001E001E001E001E001E00FFF8FFF83E001E000E000E000600 + 060006000600> 13 28 -1 0 18] 116 @dc +[ 16 45 -3 11 23] 47 @dc +[<07F0001FFC003E1F00780780700380F001C0E001C0E001C0E003C0E007C0F00FC0781FC03C7F801FFF000FFF000FFC001FF8 + 003FFE003FCF007F07007C0780780380700380700380700780380F001E1F000FFE0003F800> 18 29 -2 0 23] 56 @dc +[<07F0003FFC007C3F00F81F00FC0F80FC07C0FC07C0FC07C07807C00007C00007C0000780000F80001F00003E0003F00003F8 + 00007E00001F00000F00000F807C0F807C0F807E0F807C0F807C0F003C3F001FFE0007F000> 18 29 -2 0 23] 51 @dc +[<7FFF7FFF03C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C003C0F3C0 + FFC00FC001C000C0> 16 29 -3 0 23] 49 @dc +[ 7 45 -4 11 13] 91 @dc +[ 18 29 -2 0 23] 50 @dc +[ 7 45 -1 11 13] 93 @dc +[<001FE00000FFF80003F83C0007E00E000F8007001F0003801E0001803E0001C07C0000C07C0000C07C0000C0F8000000F800 + 0000F8000000F8000000F8000000F8000000F8000000F8000000F80000C07C0000C07C0000C07C0001C03E0001C01E0003C0 + 1F0003C00F8007C007E00FC003F83DC000FFF8C0001FC0C0> 26 31 -3 0 33] 67 @dc +[ 15 31 0 0 16] 73 @dc +[<07FFFF0007FFFF00000F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8000000F + 8000000F8000000F8000000F8000000F8000000F8000000F8000000F8000C00F8030C00F8030C00F8030C00F8030E00F8070 + 600F8060600F8060700F80E07C0F81E07FFFFFE07FFFFFE0> 28 31 -2 0 33] 84 @dc +[ 18 31 -3 0 25] 83 @dc +[<001FF06000FFFCE001FC1FE007E007E00FC003E01F0003E01F0003E03E0003E07C0003E07C0003E07C0003E0F800FFFCF800 + FFFCF8000000F8000000F8000000F8000000F8000000F8000000F80000607C0000607C0000607C0000E03E0000E01F0001E0 + 1F0001E00F8003E007E00FE001F81EE000FFF860001FE060> 30 31 -3 0 36] 71 @dc +[<07F0001FFC007C3E00701F00F80F80F80780F807C0F807C0F807C00007C00007C00007C0000780380F803C0F003E1F003FFC + 0033F8003000003000003000003000003000003000003FF0003FFC003FFE003FFF00380700> 18 29 -2 0 23] 53 @dc +[<0003800000038000000380000007C0000007C000000FE000000FE000000FE000001FB000001F3000001F3000003E1800003E + 1800003E1800007C0C00007C0C0000FC0E0000F8060000F8060001F8030001F0030001F0030003E0018003E0018003E00180 + 07C000C007C000C00FC000E00FC001F0FFF807FEFFF807FE> 31 31 -1 0 34] 86 @dc +[<60F07038181C0C0C0C7CFCFCF870> 6 14 -4 9 13] 44 @dc +[<381C7C3EFC7EFC7EF87CC060C060C060E07060307038381C3C1E180C> 15 14 -5 -18 23] 92 @dc +[ 38 20 0 0 39] 109 @dc +[ 24 20 0 0 25] 110 @dc +[<07E3FC1FFBFC3E1FC03C0FC07807C07803C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C07803C07803C03C07 + C01E1FC00FFFC007F3C00003C00003C00003C00003C00003C00003C00003C00003C00003C0003FC0003FC00003C0> 22 32 -2 0 25] 100 @dc +[ 11 31 0 0 13] 105 @dc +[ 31 31 -1 0 34] 88 @dc +[<70F8F8F870> 5 5 -4 0 13] 46 @dc +[<01FFE001FFE0001E00001E00001E00001E00001E00001E00FFFFF0FFFFF0E01E00601E00301E00381E00181E000C1E000E1E + 00061E00031E00039E00019E0000DE0000FE00007E00003E00003E00001E00000E00000E00> 20 29 -1 0 23] 52 @dc +[<03F0000FFC001E1E003C0F00380700780780700380700380F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003 + C0F003C0F003C0F003C0F003C07003807003807807803807003C0F001E1E000FFC0003F000> 18 29 -2 0 23] 48 @dc +[<6030F0787038381C180C1C0E0C060C060C067C3EFC7EFC7EF87C7038> 15 14 -2 -18 23] 34 @dc +[ 39 31 -1 0 42] 77 @dc +[<03FC001FFF803E07C07801E0F000F0E00070E00070E00070F000F07803F03FFFE01FFFE03FFF803FFE003800003000003000 + 0037F0003FFC003E3E003C1E00780F00780F00780F00780F00780F003C1E703E3EF01FFFF007F1E0> 20 30 -1 10 23] 103 @dc +[ 31 31 -1 0 34] 72 @dc +[ 12 32 0 0 13] 108 @dc +[<3C00007F0000E38000C18000F8C00070C00000600000600000600000700000700000700000F80000F80001FC0001EC0001EC + 0003EE0003C60003C6000783000783000783000F01800F01800F01C01F03E0FFC7F8FFC7F8> 21 29 -1 9 24] 121 @dc +[ 10 3 -1 -9 15] 45 @dc +[<70F8F8F8700000000000000000000070F8F8F870> 5 20 -4 0 13] 58 @dc +[<00700000700000700000F80000F80001FC0001EC0001EC0003EE0003C60003C6000783000783000783000F01800F01800F01 + C01F03E0FFC7F8FFC7F8> 21 20 -1 0 24] 118 @dc +[ 28 31 -1 0 31] 69 @dc +[<003FC00000FFF00003E07C0007C03E000F801F001F000F801E0007803E0007C07C0003E07C0003E07C0003E0F80001F0F800 + 01F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E07C0003E03C0003C03C0003C01E000780 + 1E0007800F000F0007801E0003E07C0000FFF000003FC000> 28 31 -3 0 35] 79 @dc +[<0C3F800E7FC00FE1E00F80F00F80780F00780F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F00780F00780F80 + F00FE1F00FFFE00F1F800F00000F00000F00000F00000F00000F00000F00000F00000F0000FF0000FF00000F0000> 22 32 0 0 25] 98 @dc +[<0FC0003FF000787C007C1C007C0E007C0F007C07000007800007800003800183C00FF3C01FFBC03C1FC0780FC07007C0F007 + C0F003C0F003C0F003C0F003C0F00380F003807007807807003C0F001E1E000FFC0003F000> 18 29 -2 0 23] 57 @dc +[ 30 31 -1 0 35] 68 @dc +[<00E01C0000E01C0000F03C0001F03E0001F03E0001F87E0003F87F0003D87B0003D8730003CCF300078CF180078CE1800787 + E1800F07E0C00F07C0C00F03C0C01E03C0E01E07C0F0FF9FF3FCFF9FF3FC> 30 20 -1 0 33] 119 @dc +[ 31 31 -1 0 34] 65 @dc +[ 22 29 0 9 25] 112 @dc +[ 22 32 0 0 24] 107 @dc +[ 17 32 0 0 14] 102 @dc +[ 26 31 -1 0 30] 70 @dc +[ 26 31 -1 0 31] 80 @dc +[ 23 20 0 0 24] 120 @dc +[<01F8FF07FEFF0F87F00F03F00F01F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00F00 + F0FF0FF0FF0FF00F00F0> 24 20 0 0 25] 117 @dc +[ 31 31 -1 0 35] 75 @dc +/cmsl10.329 @newfont +cmsl10.329 @sf +[<00FE000007FF80000F83C0001F00E0001E0070003E0038003C001C003C000C003E000C003E000E003E0006003E0006003E00 + 06003E0006003F0007001F0007001F0003001F0003001F0003001F0003001F8003800F8003800F8001800F8001800F800180 + 0F8001800FC001C007C001C007C003E0FFFE1FFEFFFE1FFE> 31 31 -6 0 34] 85 @dc +[ 15 20 -2 0 18] 115 @dc +[<0FE0001FF8003E1E00780600F00700F00000F00000E00000F00000F00000FFFF80FFFF80F003807803807803803C07801E07 + 000F0F0007FE0001FC00> 17 20 -3 0 20] 101 @dc +[ 23 20 -1 0 25] 110 @dc +[ 12 31 -1 0 13] 105 @dc +[ 24 20 -1 0 24] 120 @dc +[<007F800003FFE00007E078000F801C001F000E003E0007003C0003807C0003807C000180780001C0F80000C0F8000000F800 + 0000F8000000FC0000007C0000007C0000007C0000007C0000003E0000603E0000703F0000701F0000700F80007007C000F0 + 07E000F003F001F800F803F8007F07F8001FFE380003F818> 29 31 -5 0 33] 67 @dc +[<07E0001FFC003C1E00700700F00380F003C0E001C0E001E0E001E0F000F0F000F0F000F0F000F07000F03800E03C00E01E01 + C00F038003FF0000FC00> 20 20 -3 0 23] 111 @dc +[ 21 32 -1 0 14] 102 @dc +[ 18 20 -1 0 18] 114 @dc +[<0FE03FF87C3C780CF00EF000F000E000F000F000F000F000F0007800781E3C1F1E1F0F1F07FF01FC> 16 20 -4 0 20] 99 @dc +cmr10.329 @sf +[ 24 31 -1 0 28] 76 @dc +[<00E001E003C0038007000F000E001E001C003C00380038007800780070007000F000F000F000F000F000F000F000F000F000 + F000F000F000F000F0007000700078007800380038003C001C001E000E000F000700038003C001E000E0> 11 46 -3 12 18] 40 @dc +[ 11 46 -3 12 18] 41 @dc +[<03F8000FFC001E1E003C0F003807807803807803C07003C0F003C0F003C0F003C0F003C0F803C0F80380FC0780FE0F00F7FE + 00F3FC00F06000700000780000780000380F803C0F801E0F800F0F8007878003FF0000FE00> 18 29 -2 0 23] 54 @dc +[<03800007C00007C00007C00007C00007C00007C00007C00007C00003C00003C00003C00003C00001C00001E00000E00000E0 + 00006000007000003800001800C01C00C00E00C00600E007007FFF807FFFC07FFFC07FFFC0600000> 18 30 -3 0 23] 55 @dc +[<000FF000003FFC00007C1E0000F0070001E0038003E0018003C0018007C001C007C000C007C000C007C000C007C000C007C0 + 00C007C000C007C000C007C000C007C000C007C000C007C000C007C000C007C000C007C000C007C000C007C000C007C000C0 + 07C000C007C000C007C000C007C001E0FFFE1FFEFFFE1FFE> 31 31 -1 0 34] 85 @dc +cmsl10.329 @sf +[ 30 31 -1 0 31] 80 @dc +[<0FC7F81FFFF83C3FC0780FC07807C07003C07003C0F003C0F803E07803E07801E07801E07801E03C01E03C01F01E01F01F01 + F00F87F003FFF001FCF00000F80000F800007800007800007800007800007C00007C00007C0003FC0001FC00003C> 22 32 -3 0 25] 100 @dc +[<07FC001FFF003E0FC07801E0F000F0F00070F000707000787800783C01F01FFFF00FFFF01FFFE01FFF801E00001C00000C00 + 000CFC0007FF000787800F03C00F01E00F01E00F01E00F81E00781E007C1E703E3EF01FFFF007F1F> 24 30 0 10 23] 103 @dc +cmr10.329 @sf +[ 27 31 -1 0 32] 66 @dc +[<1FC0003FF00078FC00FC7C00FC3E00FC3E00FC3E00783E00003E00003E00003E00003E00003E00003E00003E00003E00003E + 00003E00003E00003E00003E00003E00003E00003E00003E00003E00003E00003E00003E000FFFE00FFFE0> 19 31 -1 0 23] 74 @dc +cmsl10.329 @sf +[<1FC0007FF000F1F800F8FC00FC7E00FC3E00FC3E00783E00003F00003F00001F00001F00001F00001F00001F80001F80000F + 80000F80000F80000F80000FC0000FC00007C00007C00007C00007C00007E00007E00007E000FFFC00FFFE> 23 31 -2 0 23] 74 @dc +[ 36 31 -1 0 34] 78 @dc +[<3FFFF8001FFFF800007E0000003E0000003E0000003E0000003E0000003E0000003F0000001F0000001F0000001F0000001F + 0000001F0000001F8000000F8000000F8000000F8000000F8000000F8000C00FC0306007C0306007C0386007C0187007C018 + 3007C0383807E0383803E0381E03E0F81FFFFFF81FFFFFF8> 29 31 -5 0 33] 84 @dc +[ 44 31 -1 0 42] 77 @dc +[<3F07807FCFC0F8EF60F03F30F01F30F00F30F00F30780F007C0F803F0F800FE78001FF800007800007801E07801F07801F07 + 801F1F801FFF0007FC00> 20 20 -3 0 23] 97 @dc +[ 12 32 -1 0 13] 108 @dc +[<1F007F8079C078C078607860786078607C003C003C003C003C003C003E001E001E001E00FFF8FFF83E000F00070007000300 + 030003000180> 13 28 -4 0 18] 116 @dc +[<030007000E001C001C003800380038007000700070007000F000F000F000F000F000F000F000F000F0007000700078007800 + 7800780038003C003C001C001E001E000E000F0007000780038001C001E000E000700038001C000E0007> 16 46 -4 12 18] 40 @dc +[<03800003800003C00003C00003E00007E00007B00007B000079800079C000F8C000F0E000F06000F03000F03001F01801E01 + 801F03E0FFC7F8FFC7F8> 21 20 -4 0 24] 118 @dc +[ 15 29 -4 0 23] 49 @dc +[<70F8F87878> 5 5 -4 0 13] 46 @dc +[<0FC0001FF000387800701C00700E00F00F00E00700F00780F00780F00780F003C0F003C0F003C0F003C0F003C07801E07801 + E07801E07801E03801E03C01E03C01E01C01E01C01E00E01C00701C003838001FF00007E00> 19 29 -4 0 23] 48 @dc +[ 15 46 -1 12 18] 41 @dc +[ 30 31 -1 0 31] 69 @dc +[<007FC18001FFF38007F07FC00FC01FC01F000FC03E0007C03E0007C07C0007C07C0007E0780007E0780003E0F800FFFCF800 + FFFCF8000000FC0000007C0000007C0000007C0000007C0000003E0000303E0000381F0000381F0000380F80003807C00078 + 03E0007801F000FC00FC01FC007F07BC001FFF1C0003FC0C> 30 31 -5 0 36] 71 @dc +[ 7 14 -3 9 13] 44 @dc +cmr10.329 @sf +[<07F01FC01FFC7FE03E1EFC707C07F038F807E018F80FE000F00FE000F01F7000F03E3800F07E1800787C1C0038F80C001CF8 + 0E000FF0070007E0030003E0038003E0038003E007E003F01FFC07F81FFC079C0000078E0000078E00000787000007830000 + 07830000078300000783000003C7000003C6000001FE0000007C0000> 30 32 -2 0 35] 38 @dc +cmsl10.329 @sf +[ 30 31 -2 0 34] 65 @dc +[ 37 20 -1 0 39] 109 @dc +[ 25 29 1 9 25] 112 @dc +[<0FC7F83FF7F83C3FC03C0FC03C07C03C07C03C03C03C03C03E03E01E03E01E01E01E01E01E01E01E01E01F01F00F01F01F01 + F0FF0FF07F07F00F00F0> 21 20 -3 0 25] 117 @dc +[ 32 31 -1 0 33] 82 @dc +[<0300E0000700E0000780F0000780F00007C0F80007C1F80007E1FC000FE1EC000F31EE000F31C6000F19C7000F1BC3000F0F + C3801F0FC1801E07C1C01E07C0C01E0380E01E07C0F0FF9FF3FCFF9FF3FC> 30 20 -4 0 33] 119 @dc +[ 20 31 0 0 16] 73 @dc +[ 30 31 -1 0 30] 70 @dc +[<00C000C0000000E000E0000000E000E0000001F001F0000001F001F0000001F801F8000001F801F8000001FC01FC000001FC + 01FC000003F601F6000003E603E6000003E303E3000003E303E3000003E183E1800003E183E1800007E1C3E0C00007C0C7E0 + C00007C0E7C0600007C067C0600007C077C0300007C037C0300007C03FC018000FC01FC018000F801F801C000F800F800C00 + 0F800F800E000F800F8006000F800F8007001F801F800F80FFF8FFF83FF0FFF8FFF83FF0> 44 31 -6 0 47] 87 @dc +[<0FE0003FF8003C7C00781E00700F00F00F00F00780F00780F00780F007C0F003C0F003C0F803C0F803C0FC07807E07807BFF + 0079FE007830003C00003C00001E00001E03E00F03E00783E003C3E001F0E0007FC0001F80> 19 29 -4 0 23] 54 @dc +[<0FE0003FF800787E00E01F00F00F80F80F80F807C0F807C07807E00007E00003E00003E00003C00C03C00E07C00F8F800FFF + 000CFC000C00000E000006000006000006000006000007FE0007FF8003FFE003FFF0038070> 20 29 -3 0 23] 53 @dc +[ 36 31 -1 0 34] 72 @dc +[ 22 31 -3 0 25] 83 @dc +[<3C0000007F000000E3800000C1800000F8C00000786000000060000000300000003000000038000000380000003C0000003C + 0000003E0000007E0000007B0000007B0000007980000079C00000F8C00000F0E00000F0600000F0300000F0300001F01800 + 01E0180001F03E000FFC7F800FFC7F80> 25 29 0 9 24] 121 @dc +[ 33 31 -1 0 35] 68 @dc +[ 20 32 -4 0 25] 98 @dc +cmr10.329 @sf +[<000600060000000E00070000000F000F0000000F000F0000001F000F8000001F801F8000001F801F8000003F801FC000003E + C03EC000003EC03EC000003EC03EC000007C607C6000007C607C6000007C607C600000F830F8300000F830F8300000F830F8 + 300001F019F0180001F019F0180001F019F0180003E00FF00C0003E00FE00C0003E00FE00C0007C00FE0060007C007C00600 + 07C007C006000F800FC003000F800F8007001F800F800F80FFF8FFF83FF0FFF8FFF83FF0> 44 31 -1 0 47] 87 @dc +[ 22 31 -3 0 28] 90 @dc +cmsl10.329 @sf +[ 26 31 -1 0 28] 76 @dc +[ 23 32 -1 0 24] 107 @dc +cmr10.329 @sf +[<00000F8000001FC000001FE000001FE000003FF000003C70000038300000301000003010003FE01000FFF00003F87C0007F0 + 7E000F38CF001F3F8F801E0F07803C0003C07C0003E07C0003E0780001E0F80001F0F80001F0F80001F0F80001F0F80001F0 + F80001F0F80001F0F80001F0F80001F0780001E07C0003E03C0003C03C0003C01E0007801F000F800F000F0007C03E0003E0 + 7C0000FFF000003FC000> 28 40 -3 9 35] 81 @dc +[ 30 32 0 0 27] 11 @dc +cmsl10.329 @sf +[<3F8000FFE000E1F000F07800F83C00F81E00F80F00000F000007800007800107C00FF3C01FFBC03C1FC03807C07807E07803 + E07803E07801E07801E07C01E03C01E03C01E03C01E01E01C00F03C007C78003FF0000FE00> 19 29 -4 0 23] 57 @dc +[<0FE0003FFC00787E00F81F00FC0F80FC0FC0FC07C0FC07C07807C00007C00003C00003C00007C0000780000F0000FC0000FE + 00001F800007C00003E00003E00F81F00F81F00F81F00F81F00F81F007C3E003FFC0007F00> 20 29 -3 0 23] 51 @dc +[<03FFE003FFE0003E00003E00001E00001E00001E00001E00FFFFF07FFFF8600F00300F00180F000C0F000E0F000707800307 + 8001878000C780006780007780003BC0001BC0000FC00007C00003C00003C00001E00000E0> 21 29 -2 0 23] 52 @dc +cmr10.329 @sf +[ 24 32 0 0 25] 12 @dc +13 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +216 195 p ([2]) s +21 r (CCITT) s +20 r (SG) s +19 r (5/VI) s +1 r (I,) s +20 r (\\Recommendati) s +-1 r (ons) s +18 r (X.400,") s +17 r (Message) s +19 r (Handling) s +19 r (Sys-) s +286 252 p (tems:) s +14 r (System) s +14 r (Mo) s +1 r (del) s +15 r 45 c +15 r (Service) s +16 r (Elemen) s +-1 r (ts,) s +13 r (Octob) s +1 r (er) s +15 r (1984.) s +216 320 p ([3]) s +21 r (CCITT) s +16 r (SG) s +15 r (5/VI) s +1 r (I,) s +16 r (\\CCITT) s +15 r (Recommendations) s +14 r (X.400/) s +14 r (ISO) s +17 r (DIS) s +16 r (10021,") s +286 377 p (Message) s +15 r (Handling:) s +14 r (System) s +14 r (and) s +16 r (Service) s +15 r (Ov) s +(erview) s +14 r 44 c +15 r (April) s +14 r (1988.) s +216 446 p ([4]) s +21 r (D.H.) s +21 r (Cro) s +1 r 99 c +107 c +-1 r (er,) s +19 r (\\Standard) s +21 r (of) s +20 r (the) s +22 r 70 c +-3 r (orm) s +-1 r (at) s +18 r (of) s +21 r (ARP) s +-3 r 65 c +21 r (In) s +(ternet) s +21 r 84 c +-3 r (ext) s +20 r (Mes-) s +286 502 p (sages,") s +14 r (RF) s +67 c +14 r (822,) s +14 r (August) s +15 r (1982.) s +216 571 p ([5]) s +21 r (D.P) s +-3 r 46 c +10 r (Kingston,) s +10 r (\\MMDFI) s +1 r (I:) s +11 r 65 c +11 r 84 c +-3 r (ec) s +(hnical) s +9 r (Review,") s +cmsl10.329 @sf +11 r (Usenix) s +11 r (Conference) s +cmr10.329 @sf +3 r 44 c +11 r (Salt) s +286 628 p (Lak) s +101 c +15 r (Cit) s +121 c +5 r (\(August) s +15 r (1984\).) s +216 697 p ([6]) s +21 r (E.) s +15 r (Allman,) s +13 r (\\SENDMAIL) s +16 r 45 c +15 r (An) s +15 r (In) s +(ternet) s +119 c +-1 r (or) s +-1 r 107 c +14 r (Mail) s +13 r (Router,") s +15 r 80 c +(ap) s +1 r (er,) s +14 r (1983.) s +216 765 p ([7]) s +21 r (D.L.) s +22 r (Presotto,) s +21 r (\\Upas) s +22 r 45 c +23 r 97 c +22 r (simpler) s +21 r (approac) s +104 c +21 r (to) s +21 r (net) s +119 c +(or) s +-1 r 107 c +21 r (mail,) s +-1 r 34 c +cmsl10.329 @sf +20 r (Usenix) s +286 822 p (Pro) s +1 r (ceedings) s +cmr10.329 @sf +10 r (\(1985\).) s +216 891 p ([8]) s +21 r (CCITT/ISO,) s +18 r (\\The) s +18 r (Directory) s +16 r 45 c +18 r (Ov) s +(erview) s +16 r (of) s +17 r (Concepts,) s +17 r (Mo) s +1 r (dels) s +17 r (and) s +18 r (Ser-) s +286 947 p (vices,") s +15 r (CCITT) s +15 r (Recommendation) s +13 r (X.500) s +14 r 47 c +15 r (ISO) s +16 r (DIS) s +16 r (9594-1) s +14 r 44 c +14 r (Ma) s +121 c +14 r (1988.) s +216 1016 p ([9]) s +21 r (S.E.) s +12 r (Kille,) s +11 r (\\Mapping) s +12 r (Bet) s +119 c +-1 r (een) s +11 r (X.400) s +11 r (and) s +13 r (RF) s +67 c +11 r (822,") s +11 r (UK) s +12 r (Academic) s +12 r (Com-) s +286 1073 p 109 c +(unit) s +-1 r 121 c +13 r (Rep) s +1 r (ort) s +15 r (\(MG.19\)) s +13 r 47 c +15 r (RF) s +67 c +14 r (987,) s +14 r (June) s +16 r (1986.) s +193 1142 p ([10]) s +21 r (J.B.) s +13 r 80 c +(ostel) s +-1 r 44 c +10 r (\\SIMPLE) s +13 r (MAIL) s +13 r (TRANSFER) s +13 r (PR) s +(OTOCOL,") s +12 r (RF) s +67 c +11 r (821,) s +11 r (Au-) s +286 1198 p (gust) s +15 r (1982.) s +193 1267 p ([11]) s +21 r (S.E.) s +17 r (Kille,) s +17 r (ed.,) s +cmsl10.329 @sf +17 r (JNT) s +18 r (Mail) s +16 r (Proto) s +1 r (col) s +17 r (\(revision) s +16 r (1.0\)) s +cmr10.329 @sf +1 r 44 c +16 r (Join) s +116 c +16 r (Net) s +119 c +-1 r (or) s +-1 r 107 c +16 r 84 c +-3 r (eam,) s +286 1323 p (Rutherford) s +16 r (Appleton) s +15 r (Lab) s +1 r (oratory,) s +14 r (Marc) s +104 c +14 r (1984.) s +193 1392 p ([12]) s +21 r (S.E.) s +19 r (Kille,) s +19 r (\\Addressing) s +19 r (in) s +20 r (MMDF) s +18 r 73 c +1 r (I,") s +cmsl10.329 @sf +20 r (Pro) s +1 r (c.) s +19 r (EUUG) s +19 r (Conference,) s +20 r 80 c +(aris) s +cmr10.329 @sf +286 1449 p (\(April) s +15 r (1985\).) s +193 1518 p ([13]) s +21 r (S.E.) s +14 r (Kille,) s +12 r (\\MHS) s +14 r (Use) s +14 r (of) s +13 r (Directory) s +12 r (Service) s +14 r 70 c +-3 r (or) s +13 r (Routing,") s +12 r (North) s +14 r (Holland,) s +286 1574 p (IFIP) s +16 r (6.5) s +14 r (Conference) s +16 r (on) s +15 r (Message) s +15 r (Handling,) s +14 r (Munic) s +(h,) s +14 r (April) s +14 r (1987.) s +193 1643 p ([14]) s +21 r (S.E.) s +21 r (Kille) s +21 r 38 c +21 r (D.H.) s +20 r (Brink,) s +21 r (\\A) s +21 r (Mo) s +1 r (del) s +21 r (of) s +21 r (Message) s +20 r (Flo) s +119 c +19 r (Con) s +(trol,) s +-1 r 34 c +cmsl10.329 @sf +19 r 65 c +(CM) s +286 1699 p (Computer) s +14 r (Comm) s +-2 r (unicatio) s +-1 r 110 c +14 r (Review) s +cmr10.329 @sf +11 r (\(Octob) s +1 r (er) s +16 r (1985\).) s +193 1768 p ([15]) s +21 r (S.E.) s +20 r (Kille,) s +19 r (\\Gatew) s +-1 r 97 c +-1 r (ying) s +18 r 98 c +1 r (et) s +119 c +-1 r (een) s +19 r (X.400) s +19 r (and) s +20 r (other) s +20 r (message) s +18 r (proto) s +1 r (cols,") s +286 1825 p (ONLINE,) s +19 r (Online) s +17 r (Conference) s +18 r (on) s +18 r (Electronic) s +16 r (Messaging) s +17 r (Systems,) s +16 r (August) s +286 1881 p (1986.) s +193 1950 p ([16]) s +21 r (J.P) s +-3 r 46 c +15 r (Onions) s +16 r 38 c +16 r (M.T.) s +14 r (Rose,) s +16 r (\\The) s +15 r (Applications) s +15 r (Co) s +1 r (okb) s +1 r 111 c +1 r (ok,") s +cmsl10.329 @sf +15 r (IFIP) s +16 r 87 c +71 c +13 r (6.5) s +286 2007 p (Conference) s +17 r (on) s +16 r (Message) s +15 r (Handling) s +16 r (Systems) s +14 r (and) s +17 r (Distributed) s +15 r (Applications) s +cmr10.329 @sf +286 2063 p (\(Septem) s +98 c +1 r (er) s +14 r (1988\).) s +193 2132 p ([17]) s +21 r (D.B.) s +14 r 84 c +-3 r (erry,) s +13 r (M.) s +14 r 80 c +(ain) s +-1 r (t) s +-1 r (er,) s +12 r (D.W.) s +14 r (Riggle) s +13 r 38 c +15 r (S.) s +14 r (Zhou,) s +14 r (\\The) s +15 r (Berk) s +(eley) s +13 r (In) s +(ternet) s +286 2188 p (Name) s +14 r (Domain) s +14 r (Serv) s +(er,") s +cmsl10.329 @sf +13 r (Usenix,) s +15 r (Salt) s +14 r (Lak) s +101 c +15 r (Cit) s +-1 r 121 c +cmr10.329 @sf +10 r (\(August) s +15 r (1984\).) s +193 2257 p ([18]) s +21 r (S.E.) s +13 r (Kille,) s +12 r (\\The) s +13 r (QUIPU) s +14 r (Directory) s +12 r (Service,") s +cmsl10.329 @sf +12 r (IFIP) s +14 r 87 c +71 c +11 r (6.5) s +12 r (Conference) s +14 r (on) s +286 2314 p (Message) s +11 r (Handling) s +11 r (Systems) s +11 r (and) s +12 r (Distributed) s +10 r (Applications) s +cmr10.329 @sf +9 r (\(Octob) s +1 r (er) s +11 r (1988\).) s +193 2383 p ([19]) s +21 r (M.T.) s +14 r (Rose) s +15 r 38 c +15 r (E.A.) s +14 r (Ste\013erud,) s +14 r (\\Prop) s +1 r (osed) s +15 r (Standard) s +15 r (for) s +14 r (Message) s +14 r (Encapsu-) s +286 2439 p (lation,") s +cmsl10.329 @sf +14 r (RF) s +67 c +13 r (934) s +cmr10.329 @sf +11 r (\(Jan) s +(uary) s +13 r (1985\).) s +193 2508 p ([20]) s +21 r (ISO/CCITT,) s +16 r (\\Remote) s +14 r (Op) s +1 r (erations:) s +15 r (Mo) s +1 r (del,) s +14 r (Notation) s +14 r (and) s +16 r (Service) s +15 r (De\014ni-) s +286 2564 p (tion,") s +12 r (CCITT) s +12 r (Recommendation) s +11 r (X.219) s +11 r 47 c +12 r (ISO) s +14 r (IS) s +13 r (9072-1) s +12 r 44 c +12 r (No) s +118 c +-1 r (em) s +-2 r 98 c +1 r (er) s +11 r (1987.) s +193 2633 p ([21]) s +21 r (CCITT) s +10 r (SG) s +10 r (5/VI) s +1 r (I,) s +11 r (\\CCITT) s +9 r (Recommendations) s +8 r (X.413/) s +9 r (ISO) s +11 r (nnnn-1,") s +11 r (Mes-) s +286 2690 p (sage) s +11 r (Handling) s +10 r (Systems:) s +9 r (Message) s +10 r (Store:) s +9 r (Abstract) s +10 r (Service) s +11 r (De\014nition) s +10 r (\(Final) s +286 2746 p (Draft) s +14 r 45 c +16 r (Gloucester\),) s +13 r (No) s +118 c +(em) s +-2 r 98 c +1 r (er) s +13 r (1987.) s +949 2916 p (13) s +@eop +12 @bop0 +/cmbx10.432 @newfont +cmbx10.432 @sf +[<01FE000007FFC0000FFFE0001F07F8001F01FC003F80FE003FC0FF003FC07F003FC07F803FC07F801F803FC00F003FC00000 + 3FC000003FC000083FE001FF3FE007FFBFE00FFFFFE01FC0FFE03F80FFE07F807FE07F807FE0FF807FE0FF803FE0FF803FE0 + FF803FE0FF803FE0FF803FC0FF803FC0FF803FC0FF803FC07F803F807F803F803F807F001FC07E000FE1FE0007FFFC0003FF + F000007FC000> 27 39 -3 0 34] 57 @dc +[ 48 41 -3 0 52] 82 @dc +[<003FF00001FFFE0003FFFF800FFC0FC01FF003C03FC001E03F8000E07F8000007F800000FF000000FF000000FF000000FF00 + 0000FFFFFFE0FFFFFFE0FFFFFFE0FF0007E0FF0007E07F0007E07F800FC03F800FC03FC01FC01FC03F800FF07F0007FFFE00 + 01FFFC00003FE000> 27 27 -2 0 32] 101 @dc +[ 22 27 -2 0 27] 115 @dc +[<007FC3FF8001FFF3FF8007FFFBFF8007F03FF8000FE00FF8000FE007F8000FE007F8000FE003F8000FE003F8000FE003F800 + 0FE003F8000FE003F8000FE003F8000FE003F8000FE003F8000FE003F8000FE003F8000FE003F8000FE003F8000FE003F800 + 0FE003F8000FE003F8000FE003F8000FE003F800FFE03FF800FFE03FF800FFE03FF800> 33 27 -3 0 38] 117 @dc +[ 15 42 -3 0 20] 108 @dc +[<003F8000FFE001FFF003F8F007F87807F03807F03807F03807F03807F03807F03807F00007F00007F00007F00007F00007F0 + 0007F00007F00007F00007F00007F00007F00007F000FFFFF0FFFFF0FFFFF01FF00007F00003F00001F00001F00000F00000 + F000007000007000007000007000> 21 38 -1 0 27] 116 @dc +[<03FC07FC0FFF0FFC3FFFDFFC7FC3FFC07F00FF80FF007F80FE003F80FE003F80FE003F80FF003F807F003F803F803F801FE0 + 3F800FFE3F8003FFFF80003FFF8000003F8000003F801F803F803FC03F803FC03F803FC07F003FC0FF003FC1FE001FFFFC00 + 0FFFF00003FFC000> 30 27 -2 0 33] 97 @dc +[ 33 27 -3 0 38] 110 @dc +[<007FC3FF8001FFF3FF8007FFFBFF800FF07FF8001FC01FF8003FC00FF8003F8007F8007F8003F8007F0003F800FF0003F800 + FF0003F800FF0003F800FF0003F800FF0003F800FF0003F800FF0003F800FF0003F800FF0003F8007F0003F8007F8003F800 + 3F8003F8003FC007F8001FE00FF8000FF83FF80007FFFFF80001FFFBF800003FC3F800000003F800000003F800000003F800 + 000003F800000003F800000003F800000003F800000003F800000003F800000003F800000003F800000003F80000003FF800 + 00003FF80000003FF800> 33 42 -2 0 38] 100 @dc +[ 47 41 -2 0 52] 65 @dc +[<0001C000000003E000000003E000000007F000000007F00000000FF80000000FF80000000FF80000001FDC0000001FDC0000 + 003FDE0000003F8E0000007F8F0000007F070000007F07000000FE03800000FE03800001FC01C00001FC01C00003FC01E000 + 03F800E00007F800F00007F000700007F0007000FFFE03FF80FFFE03FF80FFFE03FF80> 33 27 -1 0 36] 118 @dc +[ 15 43 -3 0 20] 105 @dc +[<0E01FE00000F07FFC0000F9FFFF0000FFE0FF8000FF803FC000FF001FE000FE000FE000FE000FF000FE0007F000FE0007F80 + 0FE0007F800FE0007F800FE0007F800FE0007F800FE0007F800FE0007F800FE0007F800FE0007F800FE0007F000FE000FF00 + 0FE000FE000FF001FE000FF801FC000FFF07F8000FFFFFF0000FE7FFC0000FE1FF00000FE00000000FE00000000FE0000000 + 0FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE0000000FFE0000000 + FFE0000000FFE0000000> 33 42 -2 0 38] 98 @dc +[<0F800000003FE00000007FF8000000F67C000000FE1C000000FE0E000000FE0F0000007C0700000038078000000003800000 + 00038000000001C000000001C000000003E000000003E000000007F000000007F00000000FF80000000FF80000000FF80000 + 001FDC0000001FDC0000003FDE0000003F8E0000007F8F0000007F070000007F07000000FE03800000FE03800001FC01C000 + 01FC01C00003FC01E00003F800E00007F800F00007F000700007F0007000FFFE03FF80FFFE03FF80FFFE03FF80> 33 39 -1 12 36] 121 @dc +cmr10.329 @sf +[<3F807FE0F9F0F8F0F87870780078007800780078007800780078007800780078007800780078007800780078007800780078 + 00F807F807F80078000000000000000000000000007000F800F800F80070> 13 40 3 9 14] 106 @dc +[<70F8F8F870000000000070707070707070707070707070F8F8F8F8F8F8F8F870> 5 32 -4 0 13] 33 @dc +cmbx10.432 @sf +[<7FFFFE7FFFFE7FFFFE00FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF + 0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF00F8FF00FF + FF00FFFF0007FF00007F00000F00000700> 23 39 -5 0 34] 49 @dc +[<003F800001FFF00007FFFC000FE0FE001FC07F001F803F003F803F803F001F807F001FC07F001FC07F001FC07F001FC0FF00 + 1FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0FF001FE0 + FF001FE0FF001FE07F001FC07F001FC07F001FC07F001FC03F001F803F803F801F803F001FC07F000FE0FE0007FFFC0001FF + F000003F8000> 27 39 -3 0 34] 48 @dc +[<00007FF800000007FFFF0000001FFFFFC000007FF807F00000FFC000F80003FF00007C0007FE00001E000FFC00000F000FF8 + 000007001FF0000007803FF0000003803FE0000003807FE0000003807FE0000003807FC000000000FFC000000000FFC00000 + 0000FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000FFC000000000 + FFC0000000007FC0000007807FE0000007807FE0000007803FE000000F803FF000000F801FF000001F800FF800001F800FFC + 00003F8007FE00007F8003FF0000FF8000FFC003FF80007FF80FFF80001FFFFF8F800007FFFE078000007FF00380> 41 41 -4 0 50] 67 @dc +[<003FE00001FFFC0007FFFF000FF07F801FC01FC03F800FE03F800FE07F0007F07F0007F0FF0007F8FF0007F8FF0007F8FF00 + 07F8FF0007F8FF0007F8FF0007F8FF0007F87F0007F07F0007F07F0007F03F800FE03F800FE01FC01FC00FF07F8003FFFE00 + 01FFFC00003FE000> 29 27 -2 0 34] 111 @dc +[<003FF00001FFFC0007FFFF000FFC0F801FF003803FC003C03FC001C07F8000007F800000FF000000FF000000FF000000FF00 + 0000FF000000FF000000FF000000FF000000FF0000007F003F007F807F803F807F803FC07F801FE07F800FF87F8007FFFF00 + 01FFFE00003FF800> 26 27 -2 0 31] 99 @dc +/cmsy10.329 @newfont +cmsy10.329 @sf +[<07E01FF83FFC7FFE7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFE7FFE3FFC1FF807E0> 16 18 -3 -2 23] 15 @dc +cmr10.329 @sf +[<003FFC003FFC0003C00003C00003C00003C00003C00003C00003C007E3C01FFBC03E1FC03C0FC07C07C07803C0F803C0F003 + C0F003C0F003C0F003C0F003C0F003C0F803C07803C07C07C03C0FC01F1DC00FF9C007F0C0> 22 29 -2 9 24] 113 @dc +cmbx10.432 @sf +[ 31 42 -2 0 36] 107 @dc +[<00078003C00000078003C000000FC007E000000FC007E000000FC007E000001FE00FF000001FE00FF000003FF01FF800003F + F01FB800003FF01FB800007F783F3C00007F383F1C0000FF383F1E0000FE1C7E0E0000FE1C7E0E0001FE1EFC0F0001FC0EFC + 070001FC0EFC070003F807F8038003F807F8038007F807F803C007F003F001C007F003F001C00FE007E000E0FFFE7FFC0FFE + FFFE7FFC0FFEFFFE7FFC0FFE> 47 27 -1 0 50] 119 @dc +[<00FFF80007FFFF001FFFFFC03FE03FE07F0007F07E0003F0FE0003F8FC0001F8FC0001F8FC0001F8FE0003F87E000FF83FFF + FFF01FFFFFF00FFFFFE01FFFFFC03FFFFF003FFFFC003E0000003C0000003C0000003800000038FF80001FFFF0000FFFF800 + 1FC1FC003F80FE003F007E007F007F007F007F007F007F007F007F007F007F007F007F003F007E783F80FE7C1FC1FEFC0FFF + FFFC07FFF7FC00FF81F0> 30 40 -2 13 34] 103 @dc +[ 53 27 -3 0 60] 109 @dc +cmr10.329 @sf +[ 16 20 -1 0 20] 122 @dc +cmbx10.432 @sf +[ 27 39 -3 0 34] 50 @dc +[<7FFF80007FFF80007FFF800007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 + 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F00000FFFFC000 + FFFFC000FFFFC00007F0000007F0000007F0000007F0000007F0000007F0000007F03F0007F07F8007F87F8003F87F8003FC + 7F8001FF7F80007FFF00003FFE000007FC00> 25 42 -2 0 21] 102 @dc +[ 24 27 -2 0 28] 114 @dc +cmr10.329 @sf +[<60F07038181C0C0C0C7CFCFCF870> 6 14 -4 -18 13] 39 @dc +12 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +cmbx10.432 @sf +224 195 p 57 c +69 r (Results) s +21 r (and) s +24 r (Av) s +-3 r (ailabil) s +-1 r (i) s +-1 r 116 c +-2 r 121 c +cmr10.329 @sf +224 297 p (The) s +20 r (PP) s +18 r (pro) s +3 r (ject) s +19 r (is) s +18 r (no) s +119 c +18 r 111 c +118 c +-1 r (er) s +17 r (three) s +20 r 121 c +(ears) s +17 r (old.) s +31 r (Dev) s +(elopmen) s +-1 r 116 c +17 r (of) s +18 r (this) s +19 r (system) s +224 353 p (has) s +21 r (in) s +118 c +-1 r (olv) s +-2 r (ed) s +20 r 109 c +(uc) s +-1 r 104 c +19 r (more) s +20 r 119 c +(ork) s +19 r (than) s +21 r (originall) s +-1 r 121 c +19 r (an) s +(ticipated!) s +36 r (Although) s +20 r (the) s +224 409 p (system) s +13 r (is) s +14 r (not) s +14 r (fully) s +14 r (op) s +1 r (erational,) s +13 r (the) s +15 r (ma) s +3 r (jor) s +12 r (comp) s +1 r (onen) s +(ts) s +12 r (are) s +15 r (all) s +13 r 119 c +(orking.) s +17 r (It) s +15 r (is) s +224 466 p (exp) s +1 r (ected) s +19 r (that) s +18 r (PP) s +18 r (will) s +16 r 98 c +1 r 101 c +19 r (brough) s +116 c +17 r (in) s +(to) s +16 r (service) s +18 r (shortly) s +17 r 98 c +1 r (efore) s +18 r (this) s +17 r (pap) s +1 r (er) s +19 r (is) s +224 522 p (presen) s +(ted.) s +295 579 p (PP) s +21 r (has) s +21 r 98 c +1 r (een) s +22 r (released) s +22 r (in) s +(to) s +19 r (the) s +21 r (Public) s +21 r (Domain,) s +21 r (and) s +21 r (will) s +20 r 98 c +1 r 101 c +22 r 97 c +21 r (part) s +21 r (of) s +224 635 p (the) s +17 r (ISODE) s +18 r ([1].) s +24 r (This) s +17 r (will) s +15 r 98 c +1 r 101 c +18 r (for) s +16 r (release) s +17 r (5.0,) s +16 r (whic) s +104 c +16 r (is) s +16 r (curren) s +(tly) s +16 r (planned) s +17 r (for) s +224 692 p (Jan) s +(uary) s +14 r (1989.) s +cmbx10.432 @sf +224 835 p (10) s +70 r (Conclusions) s +cmr10.329 @sf +224 936 p (This) s +14 r (pap) s +1 r (er) s +16 r (has) s +14 r (giv) s +(en) s +13 r (an) s +15 r 111 c +118 c +-1 r (erview) s +12 r (of) s +15 r (the) s +15 r (PP) s +14 r (system.) s +18 r (It) s +15 r (is) s +14 r (hop) s +1 r (ed) s +16 r (that) s +14 r (it) s +14 r (will) s +224 993 p (pro) s +118 c +-1 r 101 c +14 r (to) s +14 r 98 c +1 r 101 c +16 r 97 c +15 r (useful) s +15 r (basis) s +15 r (for) s +15 r 119 c +(ork) s +13 r (in) s +15 r 97 c +15 r 110 c +(um) s +-1 r 98 c +1 r (er) s +13 r (of) s +15 r (directions:) s +cmsy10.329 @sf +292 1099 p 15 c +cmr10.329 @sf +23 r (Pro) s +(visi) s +-1 r (on) s +17 r (of) s +18 r (service,) s +19 r (particularly) s +17 r (in) s +19 r (the) s +19 r (academic) s +17 r (and) s +19 r (researc) s +104 c +18 r (com-) s +338 1156 p 109 c +-1 r (unit) s +-1 r 121 c +-4 r 46 c +cmsy10.329 @sf +292 1249 p 15 c +cmr10.329 @sf +23 r (Dev) s +(elopm) s +-1 r (en) s +-1 r 116 c +16 r (of) s +17 r 97 c +18 r 110 c +(um) s +-2 r 98 c +1 r (er) s +17 r (of) s +17 r (adv) s +-2 r (anced) s +18 r (User) s +18 r (Agen) s +(ts,) s +16 r (esp) s +1 r (ecially) s +18 r (those) s +338 1306 p (with) s +14 r (supp) s +1 r (ort) s +16 r (for) s +14 r 109 c +(ult) s +-1 r (im) s +-1 r (edia) s +13 r (capabilit) s +-1 r 121 c +-4 r 46 c +cmsy10.329 @sf +292 1400 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +12 r (for) s +11 r (Message) s +11 r (Store) s +11 r (proto) s +1 r (cols,) s +11 r (and) s +12 r (in) s +11 r (particular) s +11 r (P7[21].) s +17 r (It) s +11 r (is) s +12 r 98 c +1 r (e-) s +338 1456 p (liev) s +(ed) s +12 r (that) s +13 r (the) s +14 r (QMGR) s +13 r (system) s +12 r (can) s +14 r 98 c +1 r 101 c +14 r (quite) s +14 r (easily) s +12 r (extended) s +15 r (to) s +13 r (pro) s +(vide) s +338 1513 p (these) s +15 r (services) s +15 r (in) s +15 r (an) s +15 r (elegan) s +116 c +14 r (manner.) s +cmsy10.329 @sf +292 1606 p 15 c +cmr10.329 @sf +23 r 70 c +-3 r (uller) s +9 r (use) s +11 r (of) s +10 r (X.500) s +10 r (directory) s +9 r (services.) s +19 r (This) s +10 r (migh) s +-1 r 116 c +8 r 98 c +1 r 101 c +12 r (done) s +11 r 98 c +121 c +9 r (extending) s +338 1663 p (Submit) s +15 r (to) s +15 r (recognise) s +15 r (Directory) s +15 r (Names) s +14 r (as) s +16 r 97 c +15 r (third) s +16 r (name) s +15 r (form,) s +13 r (and) s +17 r (also) s +338 1719 p (to) s +14 r (utilise) s +14 r (Directory) s +14 r (Services) s +16 r (for) s +14 r (routing.) s +cmbx10.432 @sf +224 1863 p (11) s +70 r (Ac) s +-1 r (kno) s +-1 r (wl) s +-1 r (e) s +-1 r (dgem) s +-2 r (e) s +-1 r 110 c +-1 r (t) s +-1 r 115 c +cmr10.329 @sf +224 1964 p (There) s +15 r (are) s +14 r (man) s +121 c +12 r 112 c +1 r (eople) s +15 r (who) s +15 r (deserv) s +101 c +13 r (credit) s +15 r (for) s +13 r (PP) s +-3 r 46 c +14 r 73 c +15 r (ap) s +1 r (ologise) s +13 r (to) s +14 r (an) s +121 c +13 r 73 c +15 r (ha) s +118 c +-1 r 101 c +224 2020 p (omitted.) s +31 r (Julian) s +19 r (Onions) s +20 r (of) s +19 r (Nottingham) s +17 r (Univ) s +(ersit) s +-1 r 121 c +17 r (has) s +20 r 119 c +(ork) s +-1 r (ed) s +18 r (on) s +19 r (the) s +20 r (PP) s +224 2077 p (design) s +12 r (from) s +10 r (the) s +13 r (start,) s +11 r (and) s +12 r (has) s +12 r (done) s +12 r 109 c +(uc) s +-1 r 104 c +10 r (of) s +12 r (the) s +12 r (implemen) s +-1 r (t) s +-1 r (ati) s +-1 r (on.) s +17 r (Phil) s +12 r (Co) s +1 r 99 c +(k-) s +224 2133 p (croft,) s +18 r (formerly) s +16 r (of) s +17 r (UCL,) s +18 r 119 c +(ork) s +-1 r (ed) s +17 r (on) s +17 r (the) s +19 r (early) s +17 r (design,) s +18 r (and) s +19 r (pro) s +1 r (duced) s +19 r 97 c +17 r (large) s +224 2190 p (amoun) s +116 c +14 r (of) s +16 r (the) s +17 r (\014rst) s +16 r (system.) s +23 r (Alina) s +16 r (daCruz,) s +17 r (Marshall) s +15 r (Rose,) s +17 r (Doug) s +16 r (Kingston,) s +224 2246 p (Bruce) s +20 r (Wilford,) s +19 r (Jim) s +18 r (Craigie,) s +19 r (Prof.) s +31 r 80 c +(eter) s +18 r (Kirstein,) s +20 r (Caroline) s +18 r (Platt,) s +19 r (Adrian) s +224 2303 p (Joseph,) s +16 r (George) s +15 r (Mic) s +(haelson,) s +14 r (and) s +16 r (Daniel) s +15 r (Karren) s +98 c +1 r (erg) s +15 r (ha) s +118 c +-1 r 101 c +14 r (all) s +15 r (con) s +(tributed) s +14 r (to) s +224 2359 p (PP) s +15 r (in) s +15 r 118 c +-2 r (arious) s +14 r 119 c +97 c +-1 r (ys.) s +18 r 80 c +(art) s +13 r (of) s +14 r (PP) s +15 r 119 c +(as) s +14 r (funded) s +16 r 98 c +121 c +14 r (the) s +15 r (Join) s +116 c +14 r (Net) s +119 c +-1 r (ork) s +13 r 84 c +-3 r (eam.) s +cmbx10.432 @sf +224 2502 p (12) s +70 r (Reference) s +-1 r 115 c +cmr10.329 @sf +216 2660 p ([1]) s +21 r (M.T.) s +11 r (Rose,) s +11 r (\\The) s +12 r (ISO) s +13 r (Dev) s +(elopm) s +-1 r (en) s +-1 r 116 c +9 r (En) s +(vironmen) s +-1 r (t:) s +9 r (User's) s +11 r (Man) s +(ual) s +10 r (\(v) s +(ersio) s +-1 r 110 c +286 2717 p (4.0\),") s +14 r (July) s +15 r (1988.) s +949 2916 p (12) s +@eop +11 @bop0 +cmsy10.329 @sf +[<000000060000000007000000000300000000038000000001C000000000E00000000070FFFFFFFFFCFFFFFFFFFC0000000070 + 00000000E000000001C00000000380000000030000000007000000000600> 38 16 -3 -3 45] 33 @dc +cmbx10.432 @sf +[<00FFC00007FFF8000FFFFE001FC07F003F000F807E0007807C0007C0FC0003C0F80003E0F80003E0F80007E0F80007E0F800 + 1FE0FC007FE07C00FFE07E03FFE03F0FFFC01FBFFFC00FFFFF8007FFFF0003FFFE0007FFFC000FFFF8001FFFFC001FFFFE00 + 3FFE3F003FF81F003FF01F803FC00F803F000F803E000F803E000F801E001F801E001F000F003F000FC0FE0007FFFC0001FF + F800007FC000> 27 39 -3 0 34] 56 @dc +[<0000FFE00000000FFFFE0000003FFFFF800000FFC07FE00001FF001FF00003FE000FF80007FC0007FC000FF80003FE001FF0 + 0001FF001FF00001FF003FE00000FF803FE00000FF807FE00000FFC07FE00000FFC07FC000007FC0FFC000007FE0FFC00000 + 7FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0 + 7FC000007FC07FC000007FC07FC000007FC07FE00000FFC03FE00000FF803FE00000FF801FF00001FF001FF00001FF000FF8 + 0003FE0007F80003FC0003FC0007F80001FF001FF000007FC07FC000003FFFFF80000007FFFC00000000FFE00000> 43 41 -4 0 52] 79 @dc +[ 33 42 -3 0 38] 104 @dc +[ 23 41 -1 0 26] 73 @dc +[ 33 39 -2 12 38] 112 @dc +cmr10.329 @sf +[<007FFF0000007FFF00000003E000000003E000000003E000000003E000000003E000000003E000000003E000000003E00000 + 0003E000000003E000000003E000000007E000000007F00000000FF80000000F980000001F9C0000001F0C0000003F060000 + 007E060000007E03000000FC03800000F801800001F801C00001F000C00003F000600003E000700007E000F800FFFC03FF80 + FFFC03FF80> 33 31 0 0 34] 89 @dc +[ 24 32 0 0 25] 13 @dc +11 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +cmsy10.329 @sf +292 195 p 15 c +cmr10.329 @sf +23 r (Single) s +15 r (Message.) s +cmsy10.329 @sf +292 289 p 15 c +cmr10.329 @sf +23 r (An) s +15 r (MT) s +-3 r (A/Channel) s +14 r (pair.) s +cmsy10.329 @sf +292 383 p 15 c +cmr10.329 @sf +23 r 65 c +15 r (whole) s +15 r 99 c +(hannel.) s +cmsy10.329 @sf +292 477 p 15 c +cmr10.329 @sf +23 r (The) s +15 r (en) s +(tire) s +14 r (queue.) s +295 583 p (The) s +15 r (manager) s +13 r (or) s +15 r (user) s +15 r (can) s +15 r (read) s +15 r (selected) s +15 r (informati) s +-1 r (on) s +13 r (ab) s +1 r (out) s +15 r (progress.) s +19 r (Fil-) s +224 639 p (ters) s +15 r (ma) s +-1 r 121 c +13 r (also) s +14 r 98 c +1 r 101 c +16 r (applied,) s +15 r (so) s +15 r (that) s +14 r (the) s +15 r (user) s +16 r (can) s +15 r (ask) s +15 r (\\T) s +-3 r (ell) s +13 r (me) s +14 r (ab) s +1 r (out) s +15 r (all) s +14 r (of) s +15 r 109 c +121 c +224 696 p (messages".) s +32 r (The) s +20 r (manager) s +18 r (can) s +20 r (turn) s +20 r (pro) s +1 r (cessing) s +20 r (on) s +19 r (or) s +20 r (o\013) s +19 r (at) s +19 r (an) s +121 c +18 r (lev) s +(el,) s +19 r (and) s +224 752 p (mo) s +1 r (dify) s +17 r (the) s +18 r (con) s +(ten) s +(ts) s +16 r (of) s +18 r 112 c +1 r (er) s +19 r (message) s +17 r (and) s +18 r 112 c +1 r (er) s +19 r (host) s +18 r (cac) s +(hes.) s +29 r (There) s +18 r (is) s +18 r (almost) s +224 809 p (certainly) s +19 r (scop) s +1 r 101 c +21 r (for) s +19 r (co) s +1 r (op) s +1 r (erating) s +19 r (QMGRs) s +20 r (to) s +19 r (optimise) s +18 r (pro) s +1 r (cessing) s +20 r (in) s +20 r 97 c +19 r (lo) s +1 r (cal) s +224 865 p (en) s +(vironmen) s +-1 r 116 c +14 r (\(e.g.) s +23 r 98 c +121 c +16 r (sharing) s +16 r (informat) s +-1 r (ion) s +15 r (on) s +16 r (MT) s +-3 r 65 c +16 r (failures\).) s +22 r (The) s +17 r (manager) s +224 922 p (ma) s +-1 r 121 c +14 r (also) s +14 r 99 c +(ho) s +1 r (ose) s +14 r (to) s +15 r (force) s +15 r (imm) s +-1 r (ediat) s +-1 r 101 c +14 r (pro) s +1 r (cessing) s +15 r (of) s +15 r (sp) s +1 r (eci\014c) s +16 r (messages.) s +295 978 p (The) s +14 r (Queue) s +15 r (Manger) s +14 r (will) s +12 r (also) s +13 r (con) s +(trol) s +12 r (clean) s +(up) s +13 r (of) s +14 r (the) s +14 r (queue.) s +20 r (Sp) s +1 r (ecial) s +14 r 99 c +(han-) s +224 1034 p (nels) s +14 r (will) s +12 r 98 c +1 r 101 c +14 r (in) s +118 c +(o) s +-1 r 107 c +-1 r (ed) s +12 r (to) s +13 r (generate) s +14 r 119 c +(arning) s +11 r (messages,) s +12 r (and) s +14 r (to) s +13 r (generate) s +14 r (Deliv) s +(ery) s +224 1091 p (Noti\014cations) s +11 r (on) s +13 r (message) s +11 r (timeout.) s +17 r 65 c +12 r 99 c +(hannel) s +12 r (will) s +11 r 98 c +1 r 101 c +13 r (used) s +13 r (to) s +12 r (delete) s +13 r (messages) s +224 1147 p (whic) s +104 c +14 r (do) s +15 r (not) s +15 r (require) s +15 r (further) s +15 r (pro) s +1 r (cessing.) s +295 1204 p (The) s +16 r (full) s +16 r (functionalit) s +-1 r 121 c +15 r (of) s +16 r (the) s +16 r (QMGR) s +17 r (proto) s +1 r (cols) s +15 r (will) s +15 r 98 c +1 r 101 c +17 r (used) s +17 r 98 c +121 c +15 r (an) s +17 r (MT) s +-3 r 65 c +224 1260 p (Console) s +19 r (pro) s +1 r (cess.) s +35 r (This) s +19 r (will) s +19 r (giv) s +101 c +18 r 97 c +20 r 112 c +1 r (ermanen) s +116 c +18 r (displa) s +121 c +18 r (of) s +20 r (the) s +20 r (status) s +19 r (of) s +19 r (the) s +224 1317 p (MT) s +-3 r (A,) s +16 r (refreshed) s +17 r (at) s +17 r (appropriate) s +16 r (in) s +(terv) s +-2 r (al) s +-1 r (s.) s +24 r (This) s +17 r (will) s +15 r 98 c +1 r 101 c +18 r (orien) s +(ted) s +16 r (to) s +16 r 97 c +17 r (colour) s +224 1373 p (displa) s +121 c +-3 r 44 c +19 r (so) s +20 r (that) s +19 r (error) s +20 r (states) s +19 r (can) s +21 r 98 c +1 r 101 c +21 r (indicated) s +20 r 98 c +121 c +19 r 97 c +21 r 99 c +(hange) s +19 r (from) s +19 r (green) s +cmsy10.329 @sf +20 r 33 c +cmr10.329 @sf +224 1430 p 121 c +(ello) s +-1 r 119 c +cmsy10.329 @sf +13 r 33 c +cmr10.329 @sf +15 r (red.) s +20 r (This) s +15 r (should) s +15 r (substan) s +(tiall) s +-1 r 121 c +14 r (help) s +15 r (pro) s +(vision) s +13 r (of) s +15 r (MT) s +-3 r 65 c +14 r (services.) s +cmbx10.432 @sf +224 1573 p 56 c +69 r (Other) s +23 r (Im) s +-1 r (pl) s +-1 r (em) s +-3 r (e) s +-1 r 110 c +-1 r (t) s +-1 r (ation) s +21 r (Asp) s +2 r (ects) s +cmr10.329 @sf +224 1674 p (There) s +16 r (are) s +15 r 97 c +15 r (few) s +15 r (asp) s +1 r (ects) s +15 r (of) s +15 r (the) s +15 r (implemen) s +-1 r (ta) s +-1 r (tio) s +-1 r 110 c +14 r (whic) s +104 c +14 r (are) s +15 r 119 c +(orth) s +-1 r 121 c +13 r (of) s +15 r (sp) s +1 r (eci\014c) s +224 1731 p (note.) s +22 r (The) s +16 r (\014rst) s +16 r (is) s +15 r (the) s +16 r (use) s +16 r (of) s +16 r (the) s +16 r (ISODE) s +16 r (pac) s +107 c +-2 r (age) s +14 r ([1].) s +21 r (This) s +16 r (has) s +16 r (pro) s +(vided) s +14 r (the) s +224 1787 p (underlying) s +17 r (OSI) s +19 r (required) s +17 r (for) s +17 r (X.400,) s +16 r (and) s +18 r (the) s +17 r (QMGR) s +18 r 82 c +(OS.) s +17 r (The) s +17 r (PEPY) s +17 r (to) s +1 r (ol) s +224 1844 p (has) s +17 r 98 c +1 r (een) s +18 r (used) s +18 r (to) s +16 r (automati) s +-1 r (call) s +-1 r 121 c +15 r (generate) s +17 r (the) s +17 r (X.400) s +16 r (ASN.1,) s +16 r (and) s +18 r (the) s +17 r 82 c +(OSY) s +224 1900 p (and) s +16 r (POSY) s +15 r (to) s +1 r (ols) s +14 r (ha) s +118 c +101 c +13 r 98 c +1 r (een) s +17 r (used) s +15 r (to) s +15 r (automate) s +13 r (the) s +15 r (QMGR) s +15 r (proto) s +1 r (cols.) s +295 1957 p (The) s +17 r (whole) s +17 r (PP) s +18 r (system) s +16 r (uses) s +17 r 97 c +17 r (\015exible) s +18 r (run) s +(tim) s +-1 r 101 c +16 r (tailoring) s +15 r (system.) s +25 r (This) s +17 r (is) s +224 2013 p (used) s +16 r (to) s +14 r (set) s +15 r 118 c +-2 r (arious) s +14 r (things) s +15 r (whic) s +104 c +14 r (ma) s +-1 r 121 c +13 r 118 c +-2 r (ary) s +14 r (across) s +15 r 97 c +15 r (site.) s +19 r (In) s +16 r (particular:) s +cmsy10.329 @sf +292 2119 p 15 c +cmr10.329 @sf +23 r (Proto) s +1 r (col) s +14 r (and) s +15 r 70 c +-3 r (orm) s +-1 r (att) s +-1 r (ing) s +13 r (Channel) s +15 r (De\014nitions) s +cmsy10.329 @sf +292 2213 p 15 c +cmr10.329 @sf +23 r (Addressing) s +15 r 84 c +-3 r (ables) s +cmsy10.329 @sf +292 2307 p 15 c +cmr10.329 @sf +23 r (De\014nitions) s +14 r (of) s +15 r (Enco) s +1 r (ded) s +16 r (Information) s +13 r 84 c +(yp) s +1 r (es) s +295 2413 p (This) s +12 r (allo) s +(w) s +-1 r 115 c +11 r (for) s +13 r 118 c +(ery) s +11 r (rapid) s +13 r (extension) s +12 r (to) s +13 r (add) s +13 r (in) s +12 r (new) s +14 r (net) s +119 c +-1 r (ork) s +-1 r 115 c +11 r (or) s +13 r (reformat) s +-1 r 45 c +224 2470 p (ting.) s +295 2526 p (Extensiv) s +101 c +13 r (use) s +16 r (is) s +15 r (made) s +14 r (of) s +15 r (logging,) s +13 r (whic) s +104 c +14 r (can) s +15 r 98 c +1 r 101 c +16 r (tailored) s +14 r (to) s +15 r 97 c +15 r (wide) s +15 r (range) s +224 2583 p (of) s +13 r (lev) s +(els.) s +18 r (Besides) s +14 r (basic) s +13 r (logs) s +13 r (for) s +13 r (op) s +1 r (erator,) s +13 r (statisti) s +-1 r (cs,) s +12 r (and) s +14 r (debugging,) s +13 r (it) s +13 r (is) s +14 r (also) s +224 2639 p 112 c +1 r (ossible) s +15 r (to) s +15 r (select) s +15 r (logs) s +14 r (for) s +14 r (sp) s +1 r (eci\014c) s +16 r 99 c +(hannels) s +15 r (or) s +14 r (sp) s +1 r (eci\014c) s +17 r (messages.) s +949 2916 p (11) s +@eop +10 @bop0 +cmr10.329 @sf +[ 37 32 0 0 38] 14 @dc +cmbx10.432 @sf +[<0078000000FC000001FE000001FE000001FE000001FE000001FE000001FE000001FE000001FE000000FE000000FE000000FE + 000000FE0000007E0000007E0000007F0000003F0000003F0000003F0000001F0000000F8000000F80000007C0000007C000 + E003E000E001F000E000F8007000780070007C0070003E007FFFFF007FFFFF807FFFFFC07FFFFFC03FFFFFE03FFFFFF03FFF + FFF03FFFFFF03E00000038000000> 28 41 -4 0 34] 55 @dc +[<00000000FC0000000001FE0000000003FF0000000007FF8000000007FFC00000000FFFC00000000FFFC00000000FFFE00000 + 000FFFE00000001FFFE00000001FC1E00000001F80600000FFFF0060000FFFFE0000003FFFFF800000FFE07FE00001FFC07F + F00003FFC07FF80007FDE1F7FC000FF8FFE3FE001FF07FC1FF001FF03F01FF003FE00000FF803FE00000FF807FE00000FFC0 + 7FC000007FC07FC000007FC0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC000007FE0FFC0 + 00007FE0FFC000007FE0FFC000007FE0FFC000007FE07FC000007FC07FC000007FC07FC000007FC07FE00000FFC03FE00000 + FF803FE00000FF801FF00001FF001FF00001FF000FF80003FE0007FC0007FC0003FE000FF80001FF001FF000007FC07FC000 + 003FFFFF80000007FFFC00000000FFE00000> 43 53 -4 12 52] 81 @dc +[ 58 41 -3 0 65] 77 @dc +/cmti10.329 @newfont +cmti10.329 @sf +[<1C01F03E03F81E079C1E078E1E07C61F03C60F03C70F03E00F01E00F81E00781F00780F00780F0E7C0F063C0F863E07873F0 + 7833F8F03F9FF01F0FC0> 24 20 -3 0 26] 110 @dc +[<0FE0001FFC003C3E00780700700300700000F00000F00000F00000F800007FF0007FFC00781F007C07003C03801E01800F03 + 8007C78003FF0000FE00> 17 20 -4 0 21] 101 @dc +[<03F00007F8000F9C000F0E000F07000F03000F03000F01800F01800F81800781C00780C007C0C0E3C0C063C0E063E1E071E3 + E039E3E01FC3E00F81C0> 19 20 -3 0 21] 118 @dc +[<1C00003E00001E00001E00001E00001F00000F00000F00000F00000F8000078000078000078000E7C38063C3C063C3C073E3 + C033F1C03FBF801F1F00> 18 20 -3 0 19] 114 @dc +[<1F0F803FDFC079FCC0707CE0F03C60F03C60F03E70F01E00F01E00F81E00781F00780F00780F003C0F003C0F801E07800F0F + 80079FC003FFC000FB80> 20 20 -4 0 23] 97 @dc +[<3E007F00F300F380F180F980F9C0780078007C007C003C003C003E003E001E001E001F001F000F000F000F800F8007800780 + 07C007C003C003C01FE01FE003E0> 11 32 -3 0 12] 108 @dc +[<0FFF000FFF0000F800007800007800007800007C00003C00003C001FBC003FFE0078FE00707E00F03E00F01F00F00F00F00F + 00F00F00F80F807807807807807807803C07C03C03C01E07C00F07C0078FE003FFE000F860> 19 29 -4 9 21] 113 @dc +[<03E3E007FFF00F3F300F0F380F0F180F0F180F0F9C0F07800F07800F87800787C00783C007C3C0E3C3C063C3E063E1E071E1 + E039E1F01FC1F00F80E0> 22 20 -3 0 24] 117 @dc +[<0FC0003FF8003C7C00781E00700F00F00780F00780F003C0F003C0F803E07803E07801E07801E03C01E03C01E01E01C00F03 + C007C78003FF80007E00> 19 20 -4 0 23] 111 @dc +[<1F003F8079C078E078607C607C703C003C003E003E001E001E001F001F000F000F000F80FFF0FFF0078007C007C003C003C0 + 03E003E001C0> 12 28 -4 0 15] 116 @dc +[<7007C0F80FE0781E70781E38781F187C0F183C0F1C3C0F803C07803E07801E07C01E03C01E03C01F03C00F03E00F81E00FC1 + E00FE3C007FFC007BF0007800007C00003C00003C00003C00003E00001E00001E00001E0000FF0000FF00001F000> 22 32 -2 0 23] 104 @dc +[<1F0F803FDFC079FCC0707CE0F03C60F03E60F03E70F01E00F01E00F81F00781F00780F00780F003C0F803C0F801E07800F0F + 80079FC003FFC000FBC00003C00003E00003E00001E00001E00001F00001F00000F00000F00007F80007F80000F8> 21 32 -4 0 23] 100 @dc +[<1F003F803DC03CE03C603E601E701E001F000F000F000F800780E78067C063C073C03BC01FC00F8000000000000000000000 + 0000000000E000F000F000F0> 12 31 -3 0 14] 105 @dc +[<1FC07FF0F078F03CF01CF01C701E003E03FE07FE0FFC1FF81FF01F000E0F0E0F0F0F078703FE00FC> 16 20 -3 0 19] 115 @dc +[<700F80F81FC0783DC0783CE0783C607C3C603C3E703C3E003C7C003FFC001FF0001FC0001FC0001FE0E00F70F00F38F00F1C + F00F8E300787F00781E007800007C00003C00003C00003C00003E00001E00001E00001E0000FF0000FF00001F000> 20 32 -2 0 21] 107 @dc +10 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +224 195 p (to) s +17 r (asso) s +1 r (ciate) s +16 r (it) s +16 r (with,) s +17 r (so) s +17 r (that) s +17 r 97 c +16 r (giv) s +(en) s +16 r (recipien) s +116 c +16 r (can) s +17 r 98 c +1 r 101 c +18 r (mark) s +-1 r (ed) s +16 r (as) s +17 r (\\deliv) s +(ered) s +224 252 p (and) s +14 r (con\014rmed".) s +19 r (This) s +13 r (is) s +13 r (lik) s +(ely) s +12 r (to) s +13 r (sa) s +118 c +-1 r 101 c +12 r (on) s +13 r (net) s +119 c +(o) s +-1 r (rk) s +12 r (tra\016c.) s +18 r (More) s +13 r (imp) s +1 r (ortan) s +-1 r (tly) s +-4 r 44 c +224 308 p (it) s +13 r (will) s +12 r (pro) s +(vide) s +13 r (the) s +13 r (return) s +14 r (of) s +13 r (con) s +(ten) s +116 c +11 r (service) s +14 r (\(whic) s +104 c +12 r (is) s +13 r (particularly) s +12 r (imp) s +1 r (ortan) s +-1 r 116 c +224 364 p (for) s +18 r (proto) s +1 r (col) s +18 r (con) s +118 c +-1 r (ersion\)) s +16 r (in) s +19 r (the) s +18 r (ligh) s +116 c +17 r (of) s +18 r (man) s +-1 r 121 c +17 r (X.400) s +17 r (services) s +19 r (whic) s +104 c +17 r (do) s +19 r (not) s +224 421 p (pro) s +(vide) s +20 r (it) s +20 r (as) s +21 r 97 c +20 r (remote) s +20 r (service.) s +37 r (The) s +21 r (utilit) s +121 c +18 r (of) s +21 r (this) s +21 r (approac) s +104 c +19 r (will) s +20 r (dep) s +1 r (end) s +224 477 p 118 c +(ery) s +18 r 109 c +-1 r (uc) s +104 c +17 r (on) s +19 r (PTT) s +18 r (MHS) s +19 r 99 c +(harging) s +18 r (strategies.) s +29 r (Asso) s +1 r (ciated) s +19 r (with) s +18 r (this) s +19 r (is) s +18 r (the) s +224 534 p (option) s +13 r (to) s +12 r (sp) s +1 r (ecify) s +14 r (\\reliable) s +12 r (deliv) s +(ery",) s +11 r (where) s +14 r (PP) s +13 r (will) s +12 r (sp) s +1 r (ecify) s +13 r 112 c +1 r (ositiv) s +101 c +12 r (Deliv) s +(ery) s +224 590 p (Noti\014cation,) s +14 r (and) s +16 r (not) s +16 r (dequeue) s +17 r (the) s +16 r (message) s +14 r (un) s +(til) s +14 r (it) s +15 r (arriv) s +(es.) s +20 r (This) s +15 r (ma) s +-1 r 121 c +14 r (pro) s +118 c +-1 r 101 c +224 647 p (to) s +15 r 98 c +1 r 101 c +16 r 97 c +14 r 118 c +-2 r (aluable) s +14 r (user) s +16 r (service.) s +cmbx10.432 @sf +224 787 p 55 c +69 r (Queue) s +22 r (Managemen) s +-2 r 116 c +cmr10.329 @sf +224 888 p (The) s +13 r (QMGR) s +12 r (\(queue) s +12 r (manager\)) s +10 r (is) s +12 r (an) s +12 r (in) s +(teresting) s +10 r (comp) s +1 r (onen) s +116 c +10 r (of) s +12 r (PP) s +-3 r 46 c +11 r (Exp) s +1 r (erience) s +224 945 p (has) s +16 r (sho) s +(wn) s +15 r (that) s +16 r (disk) s +16 r (based) s +16 r (queues) s +17 r (cause) s +17 r (serious) s +16 r 112 c +1 r (erformance) s +15 r (problems) s +15 r (due) s +224 1001 p (to) s +20 r (the) s +20 r 111 c +118 c +(erhead) s +18 r (of) s +20 r (reading) s +20 r 97 c +21 r (large) s +19 r (queue,) s +22 r 116 c +(ypically) s +18 r (stored) s +20 r (in) s +20 r 97 c +20 r (directory) s +-3 r 46 c +224 1057 p (Therefore) s +20 r (the) s +19 r (QMGR) s +20 r (is) s +19 r (memo) s +-1 r (ry) s +18 r (based,) s +20 r (and) s +cmti10.329 @sf +20 r (never) s +cmr10.329 @sf +19 r (accesses) s +20 r (the) s +19 r (queue) s +21 r (on) s +224 1114 p (disk.) s +26 r (The) s +17 r (QMGR) s +17 r (accesses) s +17 r (the) s +18 r (external) s +16 r 119 c +(orld) s +15 r 98 c +121 c +16 r (use) s +18 r (of) s +16 r 97 c +17 r 82 c +(OS) s +17 r (based) s +18 r (pro-) s +224 1170 p (to) s +1 r (col) s +16 r (whic) s +104 c +15 r (supp) s +1 r (orts) s +17 r 97 c +17 r (wide) s +16 r (range) s +16 r (of) s +17 r (functionalit) s +-1 r (y[) s +-1 r (20].) s +22 r (This) s +16 r (usage) s +16 r (of) s +17 r 82 c +(OS) s +224 1227 p (means) s +15 r (that) s +15 r (the) s +15 r (QMGR) s +16 r (do) s +1 r (es) s +16 r (not) s +15 r (ev) s +(en) s +15 r (ha) s +118 c +101 c +14 r (to) s +15 r 98 c +1 r 101 c +16 r (residen) s +116 c +14 r (on) s +16 r (the) s +15 r (same) s +15 r (ma-) s +224 1283 p 99 c +(hine) s +12 r (as) s +13 r (the) s +13 r (queue,) s +14 r (and) s +13 r (one) s +13 r (QMGR) s +13 r (could) s +13 r (manage) s +11 r (sev) s +(eral) s +11 r (queues.) s +20 r (Pro) s +1 r (cesses) s +224 1340 p (whic) s +104 c +13 r (are) s +14 r (in) s +118 c +-1 r (ok) s +-1 r (ed) s +12 r 98 c +121 c +13 r (the) s +14 r (QMGR) s +14 r (are) s +14 r (initialised) s +12 r (in) s +14 r (exactly) s +14 r (the) s +14 r (same) s +12 r (manner) s +224 1396 p (as) s +16 r (an) s +121 c +15 r (other) s +15 r (ISODE) s +17 r (serv) s +(er.) s +21 r (The) s +16 r (\014rst) s +16 r (op) s +1 r (eration) s +15 r 97 c +16 r (QMGR) s +16 r 109 c +(ust) s +14 r (apply) s +16 r (is) s +15 r (to) s +224 1453 p (access) s +13 r 97 c +11 r (pro) s +1 r (cess) s +13 r (whic) s +104 c +11 r (will) s +11 r (read) s +12 r (the) s +12 r (queue.) s +20 r (Whilst) s +11 r (this) s +12 r 109 c +(ust) s +10 r 98 c +1 r 101 c +12 r (sync) s +(hronous) s +224 1509 p (at) s +17 r (startup,) s +18 r (later) s +17 r (usage) s +18 r (ma) s +-1 r 121 c +16 r 98 c +1 r 101 c +19 r (async) s +(hronous,) s +17 r (to) s +17 r (ensure) s +19 r (that) s +17 r (the) s +18 r (QMGR's) s +224 1566 p (list) s +14 r (re\015ects) s +15 r (the) s +cmti10.329 @sf +15 r 114 c +-1 r 101 c +-2 r (al) s +14 r (queue) s +17 r (on) s +15 r (the) s +17 r (disk) s +cmr10.329 @sf +46 c +19 r (It) s +15 r (ma) s +-1 r 121 c +13 r (then) s +15 r (start) s +14 r 99 c +(hannels) s +14 r 98 c +121 c +14 r (estab-) s +224 1622 p (lishing) s +16 r (asso) s +1 r (ciations,) s +15 r (and) s +17 r (sending) s +17 r (comma) s +-1 r (nds) s +16 r (to) s +16 r (deliv) s +(er) s +15 r (messages) s +15 r (to) s +16 r (explicit) s +224 1678 p (recipien) s +(ts.) s +19 r (As) s +15 r (the) s +15 r (QMGR) s +16 r (do) s +1 r (es) s +15 r (no) s +15 r (pro) s +1 r (cessing) s +15 r (of) s +15 r (messages,) s +14 r (it) s +14 r (should) s +15 r 98 c +1 r 101 c +16 r (fast) s +224 1735 p (and) s +16 r (able) s +14 r (to) s +15 r (con) s +(trol) s +13 r (man) s +121 c +13 r 99 c +(hannels.) s +295 1791 p (The) s +16 r (queue) s +17 r (message) s +15 r (con) s +(trol) s +14 r (\014les) s +16 r (are) s +16 r (read) s +16 r (in) s +(to) s +14 r (primary) s +14 r (memor) s +-1 r 121 c +-3 r 44 c +14 r (and) s +16 r (or-) s +224 1848 p (dered) s +17 r (in) s +(to) s +14 r 97 c +17 r (link) s +(ed) s +15 r (structure) s +16 r (with) s +15 r (complex) s +15 r (cross-links) s +16 r (sorting) s +15 r (the) s +16 r (queue) s +18 r (in) s +224 1904 p (sev) s +(eral) s +18 r (fashions.) s +32 r (The) s +20 r (queue) s +21 r (can) s +20 r (then) s +20 r 98 c +1 r 101 c +20 r (sc) s +(heduled) s +19 r (on) s +20 r (the) s +20 r (basis) s +19 r (of) s +19 r (man) s +121 c +224 1961 p (criteria,) s +14 r (including:) s +cmsy10.329 @sf +292 2042 p 15 c +cmr10.329 @sf +23 r (Main) s +(t) s +-1 r (aining) s +15 r 97 c +17 r (connection) s +17 r (with) s +17 r 97 c +17 r (remote) s +15 r (MT) s +-3 r 65 c +16 r (\(this) s +17 r (can) s +17 r 98 c +1 r 101 c +18 r 97 c +(wkw) s +-1 r (a) s +-1 r (rd) s +338 2099 p (with) s +14 r 97 c +15 r (disk) s +15 r (based) s +16 r (queue\).) s +cmsy10.329 @sf +292 2185 p 15 c +cmr10.329 @sf +23 r (Keeping) s +16 r 97 c +14 r 99 c +(hannel) s +15 r (asso) s +1 r (ciation) s +13 r (op) s +1 r (en.) s +cmsy10.329 @sf +292 2272 p 15 c +cmr10.329 @sf +23 r (Pro) s +1 r (cessing) s +15 r (high) s +15 r (priorit) s +-1 r 121 c +13 r (messages) s +14 r (rapidly) s +-3 r 46 c +cmsy10.329 @sf +292 2359 p 15 c +cmr10.329 @sf +23 r (Handling) s +14 r (timeouts/connection) s +13 r (failures) s +15 r (to) s +14 r (remote) s +14 r (MT) s +-3 r (As.) s +cmsy10.329 @sf +292 2446 p 15 c +cmr10.329 @sf +23 r (Reducing) s +16 r (pro) s +1 r (cessing) s +15 r (e\013ort) s +14 r (when) s +16 r (the) s +15 r (CPU) s +15 r (load) s +14 r 97 c +118 c +(era) s +-1 r (ge) s +13 r (increases.) s +cmsy10.329 @sf +292 2532 p 15 c +cmr10.329 @sf +23 r (Sc) s +(heduling) s +14 r (to) s +15 r (optimise) s +13 r (PTT) s +15 r (MHS) s +15 r (tari\013s.) s +295 2614 p (The) s +16 r (QMGR) s +16 r (also) s +15 r (allo) s +(w) s +-1 r 115 c +14 r (for) s +16 r 97 c +15 r 110 c +(um) s +-1 r 98 c +1 r (er) s +15 r (of) s +15 r (useful) s +17 r (managem) s +-1 r (en) s +-1 r 116 c +14 r (asp) s +1 r (ects.) s +22 r (It) s +224 2670 p (will) s +11 r (con) s +(trol) s +10 r (queue) s +13 r (main) s +(t) s +-1 r (enance,) s +11 r (and) s +13 r (send) s +13 r (o\013) s +11 r 119 c +(arning) s +11 r (and) s +12 r (timeout) s +10 r (messages.) s +224 2727 p (This) s +19 r (is) s +19 r 97 c +19 r 118 c +-2 r (aluable) s +18 r (function) s +20 r (not) s +19 r (pro) s +(vided) s +18 r 98 c +121 c +18 r (X.400.) s +32 r (In) s +20 r (addition) s +18 r (there) s +20 r (are) s +224 2783 p (op) s +1 r (erations) s +14 r (to) s +15 r (monitor) s +13 r (and) s +15 r (con) s +(trol) s +13 r (the) s +15 r (queue) s +16 r (at) s +15 r 118 c +-2 r (arious) s +14 r (lev) s +(els:) s +949 2916 p (10) s +@eop +9 @bop0 +cmbx10.432 @sf +[<007FE00001FFF80003FFFC0007F0FF000FE07F801FC03F803F803FC03F803FC07F803FE07F803FE07F803FE07F803FE0FF80 + 3FE0FF803FE0FF803FE0FF803FE0FFC03FE0FFC03FC0FFC03FC0FFE03F80FFE07F00FFFFFE00FFBFFC00FF9FF000FF820000 + 7F8000007F8000007F801E007FC03F003FC07F803FC07F801FC07F800FE07F800FF03F8007F81F0001FE1F0000FFFE00003F + FC000007F800> 27 39 -3 0 34] 54 @dc +[ 47 41 -3 0 54] 72 @dc +[ 45 41 -3 0 53] 68 @dc +[ 47 41 -3 0 54] 78 @dc +[<7FFF1FFFC07FFF1FFFC07FFF1FFFC007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC00 + 07F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC00 + 07F001FC0007F001FC0007F001FC0007F001FC00FFFFFFFC00FFFFFFFC00FFFFFFFC0007F000000007F000000007F0000000 + 07F000000007F000F00007F001F80007F003FC0007F003FC0007F803FC0003F803FC0001FE01FC0000FF80F800007FFFF000 + 001FFFE0000001FF8000> 34 42 -1 0 38] 12 @dc +9 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +295 195 p (In) s +15 r (terms) s +12 r (of) s +14 r (the) s +15 r 111 c +118 c +-1 r (eral) s +-1 r 108 c +12 r (queue) s +15 r (structure,) s +14 r 97 c +14 r (reformatti) s +-1 r (ng) s +13 r 99 c +(hannel) s +13 r (will) s +13 r (tak) s +101 c +224 252 p (the) s +16 r (message) s +14 r (directory) s +14 r (of) s +15 r 97 c +15 r (giv) s +(en) s +14 r (name,) s +14 r (and) s +15 r (then) s +16 r (create) s +15 r 97 c +15 r (parallel) s +14 r (directory) s +224 308 p (with) s +17 r (the) s +18 r (new,) s +17 r (reformatted) s +16 r (message) s +16 r (in) s +17 r (it.) s +26 r (The) s +18 r (new) s +17 r (directory) s +17 r (will) s +16 r (ha) s +118 c +101 c +15 r (the) s +224 364 p (name) s +19 r (of) s +19 r (the) s +20 r (old) s +19 r (one,) s +21 r (with) s +19 r (the) s +20 r (name) s +19 r (of) s +19 r (the) s +20 r (formatti) s +-1 r (ng) s +18 r 99 c +(hannel) s +19 r (app) s +1 r (ended) s +224 421 p (\(e.g.) s +21 r (when) s +17 r 99 c +(hannel) s +15 r (\\bitmap2f) s +-1 r (ax") s +14 r (is) s +15 r (applied) s +16 r (to) s +15 r (message) s +14 r (directory) s +16 r (\\base",) s +15 r 97 c +224 477 p (directory) s +16 r (\\base.bitma) s +-1 r (p2fax") s +14 r (is) s +16 r (created\).) s +23 r (This) s +17 r (will) s +15 r (ensure) s +17 r (uniqueness) s +17 r (when) s +224 534 p 97 c +17 r (message) s +16 r (undergo) s +1 r (es) s +18 r (sev) s +(eral) s +15 r (complex) s +16 r (sequences) s +18 r (of) s +17 r (transformat) s +-1 r (ions) s +15 r (for) s +17 r (dif-) s +224 590 p (feren) s +116 c +14 r (recipien) s +(ts,) s +13 r (and) s +16 r (will) s +14 r (optimi) s +-1 r (se) s +14 r (reformat) s +-1 r (ting) s +13 r (for) s +14 r 109 c +(ulti) s +-1 r (ple) s +13 r (recipien) s +(ts.) s +295 647 p (There) s +22 r (are) s +21 r 116 c +119 c +-1 r 111 c +20 r (basic) s +22 r 116 c +(yp) s +1 r (es) s +20 r (of) s +22 r (reformatt) s +-1 r (ing:) s +31 r (those) s +22 r (whic) s +104 c +20 r (preserv) s +101 c +21 r (the) s +224 703 p (directory) s +19 r (structure,) s +20 r (and) s +19 r (those) s +20 r (whic) s +104 c +18 r (do) s +19 r (not.) s +33 r (The) s +19 r 99 c +(hannels) s +19 r (whic) s +104 c +18 r 99 c +(hange) s +224 760 p (directory) s +12 r (structure) s +12 r (are) s +12 r 116 c +(ypicall) s +-1 r 121 c +10 r (single) s +12 r (pro) s +1 r (cesses) s +13 r (sp) s +1 r (eci\014cally) s +12 r (designed) s +13 r (for) s +11 r (the) s +224 816 p (transformat) s +-1 r (ion) s +9 r (in) s +12 r (question.) s +18 r (Channels) s +11 r (in) s +12 r (PP) s +11 r (whic) s +104 c +10 r (fall) s +10 r (in) s +(to) s +10 r (this) s +11 r (category) s +10 r (are:) s +cmsy10.329 @sf +292 922 p 15 c +cmr10.329 @sf +23 r (Mapping) s +22 r (from) s +21 r 97 c +22 r (\015at) s +22 r (\(i.e.) s +41 r (ASN.1) s +22 r (enco) s +1 r (ded\)) s +24 r (P2) s +22 r (message) s +21 r (in) s +(to) s +20 r 97 c +23 r (PP) s +338 979 p (directory) s +14 r (hierarc) s +104 c +121 c +-4 r 46 c +cmsy10.329 @sf +292 1073 p 15 c +cmr10.329 @sf +23 r (The) s +15 r (rev) s +(erse) s +14 r (of) s +15 r (the) s +15 r (previous) s +15 r (mapping) s +cmsy10.329 @sf +292 1166 p 15 c +cmr10.329 @sf +23 r (Mapping) s +12 r (from) s +10 r 97 c +12 r (directory) s +12 r (hierarc) s +104 c +-1 r 121 c +11 r (in) s +(to) s +10 r (an) s +13 r (RF) s +67 c +11 r (822) s +11 r (message,) s +11 r (accord-) s +338 1223 p (ing) s +15 r (to) s +14 r (RF) s +67 c +14 r (934[19].) s +295 1329 p (Man) s +121 c +13 r (other) s +15 r (reformatti) s +-1 r (ng) s +13 r 99 c +(hannels) s +15 r (preserv) s +101 c +14 r (the) s +15 r (directory) s +15 r (hierarc) s +104 c +-1 r 121 c +-4 r 44 c +13 r (and) s +224 1386 p (simply) s +20 r (map) s +20 r (from) s +20 r (one) s +22 r 98 c +1 r 111 c +1 r (dy) s +22 r (part) s +21 r (syn) s +(tax) s +20 r (to) s +21 r (another.) s +38 r (These) s +22 r 99 c +(hannels) s +21 r (are) s +224 1442 p (supp) s +1 r (orted) s +14 r 98 c +121 c +11 r (use) s +13 r (of) s +13 r 97 c +12 r (generic) s +13 r (reformatti) s +-1 r (ng) s +11 r 99 c +(hannel) s +12 r (whic) s +104 c +12 r (will) s +11 r (driv) s +101 c +11 r 97 c +13 r (simple) s +224 1499 p (\014lter) s +19 r (to) s +19 r 112 c +1 r (erform) s +18 r (the) s +19 r (mapping.) s +31 r (Bo) s +1 r (dy) s +20 r (parts) s +18 r (whic) s +104 c +18 r (are) s +19 r (not) s +19 r (a\013ected) s +19 r 98 c +121 c +18 r (the) s +224 1555 p (\014lter) s +13 r (are) s +13 r (simply) s +12 r (link) s +(ed) s +12 r (across,) s +12 r (whic) s +104 c +13 r 97 c +118 c +-1 r (o) s +-1 r (ids) s +12 r (excess) s +13 r 98 c +(yte) s +13 r (cop) s +(ying.) s +17 r (It) s +14 r (is) s +13 r (hop) s +1 r (ed) s +224 1611 p (that) s +15 r (this) s +14 r (will) s +14 r (enable) s +16 r 97 c +14 r (wide) s +15 r (range) s +15 r (of) s +15 r 98 c +1 r 111 c +1 r (dy) s +16 r (part) s +15 r 116 c +(yp) s +1 r (es) s +14 r (to) s +14 r 98 c +1 r 101 c +16 r (supp) s +1 r (orted.) s +295 1668 p (Proto) s +1 r (col) s +20 r (Con) s +118 c +-1 r (ersion) s +20 r (is) s +21 r (an) s +22 r (imp) s +1 r (ortan) s +-1 r 116 c +19 r (form) s +20 r (of) s +22 r (reformatt) s +-1 r (ing.) s +38 r (In) s +22 r (terms) s +224 1724 p (of) s +17 r (the) s +18 r (PP) s +17 r (mo) s +1 r (del,) s +17 r (proto) s +1 r (col) s +17 r (con) s +118 c +-1 r (ersion) s +16 r 99 c +(hannels) s +16 r (are) s +18 r (no) s +17 r (di\013eren) s +116 c +16 r (from) s +16 r (other) s +224 1781 p (reformatti) s +-1 r (ng) s +21 r 99 c +(hannels.) s +41 r (The) s +23 r (initial) s +21 r 118 c +(ersion) s +20 r (of) s +23 r (PP) s +22 r (will) s +21 r (supp) s +1 r (ort) s +23 r (RF) s +67 c +21 r (987) s +224 1837 p (reformatti) s +-1 r (ng) s +16 r 98 c +1 r (et) s +119 c +(een) s +17 r (X.400) s +16 r (and) s +19 r (RF) s +67 c +16 r (822,) s +18 r (and) s +18 r (also) s +17 r (reformatti) s +-1 r (ng) s +16 r 98 c +1 r (et) s +119 c +(een) s +224 1894 p 118 c +-2 r (arian) s +-1 r (ts) s +18 r (of) s +20 r (RF) s +67 c +19 r (822.) s +35 r (Reformatti) s +-1 r (ng) s +18 r 98 c +1 r (et) s +119 c +(een) s +19 r (P22\(88\)) s +19 r (and) s +20 r (P2\(84\)) s +19 r (will) s +19 r 98 c +1 r 101 c +224 1950 p (added) s +16 r (later.) s +cmbx10.432 @sf +224 2093 p 54 c +69 r (Handling) s +23 r (Deli) s +-1 r 118 c +-2 r (ery) s +21 r (Noti\014cations) s +cmr10.329 @sf +224 2195 p (The) s +19 r (manner) s +17 r (in) s +19 r (whic) s +104 c +17 r (deliv) s +(ery) s +17 r (noti\014cations) s +17 r (are) s +18 r (handled) s +19 r (is) s +18 r (particularly) s +16 r (in-) s +224 2251 p (teresting.) s +27 r (Deliv) s +-1 r (ery) s +16 r (noti\014cations) s +16 r (are) s +18 r (stored) s +17 r (with) s +17 r (the) s +18 r (message,) s +16 r (as) s +18 r (describ) s +1 r (ed) s +224 2308 p (ab) s +1 r 111 c +118 c +(e.) s +33 r (The) s +21 r (queue) s +21 r (in) s +(terface) s +19 r (library) s +19 r (allo) s +(w) s +-1 r 115 c +19 r (an) s +121 c +19 r 99 c +(hannel) s +20 r (to) s +19 r (add) s +21 r 97 c +20 r (deliv) s +(ery) s +224 2364 p (noti\014cation.) s +29 r (Th) s +(us,) s +18 r (if) s +18 r 97 c +18 r (pro) s +1 r (cessing) s +18 r (error) s +18 r 111 c +1 r (ccurs,) s +20 r (the) s +18 r 99 c +(hannel) s +18 r (detecting) s +18 r (the) s +224 2421 p (error) s +14 r (will) s +14 r (up) s +1 r (date) s +15 r (the) s +15 r (queue) s +16 r (and) s +15 r (create) s +15 r (an) s +15 r (appropriate) s +14 r (deliv) s +(ery) s +13 r (noti\014cation.) s +224 2477 p 65 c +116 c +15 r 97 c +15 r (later) s +15 r (stage,) s +15 r (the) s +16 r (QMGR) s +16 r (can) s +16 r (in) s +118 c +(o) s +-1 r 107 c +-1 r 101 c +14 r (pro) s +1 r (cessing) s +16 r (of) s +16 r (deliv) s +(ery) s +14 r (noti\014cations) s +224 2534 p (through) s +15 r 97 c +15 r 99 c +(hannel) s +14 r (appropriate) s +14 r (for) s +15 r (the) s +15 r (message) s +14 r (originator.) s +295 2590 p (When) s +12 r (return) s +13 r (of) s +11 r (con) s +(ten) s +116 c +10 r (is) s +12 r (requested) s +13 r (as) s +12 r 97 c +12 r (service,) s +12 r (the) s +12 r (QMGR) s +13 r (ma) s +-1 r 121 c +10 r (ask) s +12 r (for) s +224 2646 p (deliv) s +(ery) s +14 r (ac) s +(kno) s +-1 r (wledgem) s +-1 r (en) s +-1 r 116 c +13 r (and) s +15 r (hold) s +15 r (the) s +15 r (message) s +14 r (lo) s +1 r (cally) s +-3 r 44 c +13 r (rather) s +14 r (than) s +15 r (asking) s +224 2703 p (for) s +19 r (return) s +19 r (of) s +18 r (con) s +(ten) s +116 c +17 r (as) s +18 r 97 c +19 r (remote) s +17 r (service.) s +32 r (When) s +19 r (the) s +19 r (appropriate) s +18 r (deliv) s +(ery) s +224 2759 p (noti\014cation) s +9 r (returns,) s +11 r (Submit) s +9 r (will) s +9 r (determine) s +9 r (\(from) s +8 r (the) s +10 r (QMGR\)) s +10 r (whic) s +104 c +9 r (message) s +960 2916 p 57 c +@eop +8 @bop0 +cmr10.329 @sf +[<40E07030303818181878F8F8F8700000000000000000000070F8F8F870> 5 29 -4 9 13] 59 @dc +/cmbx10.360 @newfont +cmbx10.360 @sf +[<07FC001FFF803FFFC07E1FF07C07F0FE07F8FF03F8FF03FCFF03FCFF03FC7E03FC3C03FC0003FC0003FC0003F83803F83C07 + F03F0FE03FFFC039FE003800003800003800003800003FF8003FFE003FFF803FFFC03FFFE03FFFF03E01F0300030> 22 32 -3 0 29] 53 @dc +[<3C7EFFFFFFFF7E3C> 8 8 -4 0 16] 46 @dc +[<01FF000FFFE03FFFF87F07FC7F01FEFF81FEFF80FFFF80FFFF80FFFF80FF7F00FF3E00FF0000FE0001FE0001FC0007F000FF + 8000FF80000FE00007F00003F81F83F83FC3FC3FC1FC3FC1FC3FC1FC3FC1FC3F83F81F87F80FFFF007FFE001FF00> 24 32 -2 0 29] 51 @dc +[ 20 34 -1 0 22] 73 @dc +[ 27 22 -3 0 32] 110 @dc +[<1C1FF0001E7FFC001FF07F001FE03F801FC01F801F801FC01F800FC01F800FE01F800FE01F800FE01F800FE01F800FE01F80 + 0FE01F800FE01F800FE01F800FC01F800FC01F801F801FE03F801FF87F001FFFFC001F8FF0001F8000001F8000001F800000 + 1F8000001F8000001F8000001F8000001F8000001F8000001F800000FF800000FF800000FF800000> 27 35 -2 0 32] 98 @dc +[<00FF0007FFE00FC3F01F00F83F00FC7E007E7E007EFE007FFE007FFE007FFE007FFE007FFE007FFE007F7E007E7E007E7E00 + 7E3F00FC1F00F80FC3F007FFE000FF00> 24 22 -2 0 29] 111 @dc +[<01FE3FE007FFBFE00FC3FFE01F80FF001F807F001F807F001F803F001F803F001F803F001F803F001F803F001F803F001F80 + 3F001F803F001F803F001F803F001F803F001F803F001F803F00FF81FF00FF81FF00FF81FF00> 27 22 -3 0 32] 117 @dc +[<01FE3FE007FFBFE01FC3FFE03F80FF003F007F007E003F007E003F00FE003F00FE003F00FE003F00FE003F00FE003F00FE00 + 3F00FE003F00FE003F007E003F007F003F003F003F003F807F001FC1FF0007FFFF0001FF3F0000003F0000003F0000003F00 + 00003F0000003F0000003F0000003F0000003F0000003F0000003F000001FF000001FF000001FF00> 27 35 -2 0 32] 100 @dc +[<0003FF0000003FFFE00000FFFFF80001FF80FC0007FC003E000FF8000F001FE00007801FC00003803FC00003C07F800001C0 + 7F800001C07F800001C0FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000 + FF00000000FF000001C07F800001C07F800003C07F800003C03FC00003C01FC00007C01FE0000FC00FF8001FC007FC003FC0 + 01FF80FFC000FFFFF7C0003FFFE1C00003FF00C0> 34 34 -3 0 41] 67 @dc +[ 27 35 -3 0 32] 104 @dc +[<0FF03F803FFCFF807F0FFF80FE07F800FC03F800FC01F800FC01F800FE01F8007E01F8007F81F8001FE1F8000FFFF80000FF + F8000001F8003E01F8007F01F8007F01F8007F03F8007F03F0007F0FE0003FFFC0000FFE0000> 25 22 -2 0 28] 97 @dc +[<00FF0007FFE00FC1F01F80703F00387F00387E0000FE0000FE0000FE0000FE0000FFFFF8FFFFF8FE00F8FE00F87E01F87E01 + F03F01F01F03E00FC7E007FF8001FE00> 21 22 -2 0 26] 101 @dc +[ 12 35 -2 0 15] 108 @dc +[ 18 22 -2 0 23] 115 @dc +[<01FFFF01FFFF01FFFF0007F00007F00007F00007F00007F00007F0FFFFFFFFFFFFFFFFFFF003F07003F03803F01C03F00E03 + F00703F00783F00383F001C3F000E3F00073F0003BF0001FF0001FF0000FF00007F00003F00001F00000F00000F0> 24 32 -2 0 29] 52 @dc +[ 49 34 -2 0 54] 77 @dc +[<01FFE0000FFFFC003F807F007E001F80FC000FC0F80007C0F80007C0F80007C0FC000FC07E003FC03FFFFF800FFFFF800FFF + FF001FFFFE001FFFF0001E0000001C0000001C0000001DFF00000FFFC0000FC7E0001F83F0003F01F8003F01F8003F01F800 + 3F01F8003F01F8003F01F9003F01FFC01F83F7C00FC7F9C007FFFFC001FF1F80> 26 33 -1 11 29] 103 @dc +[ 40 34 -2 0 43] 82 @dc +[<7FFC007FFC007FFC000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0 + 000FC0000FC000FFFE00FFFE00FFFE000FC0000FC0000FC0000FC0000FC0000FC1F00FC3F80FC3F807E3F807F3F803F9F800 + FFF0001FE0> 21 35 -2 0 18] 102 @dc +[ 20 22 -2 0 24] 114 @dc +[ 44 22 -3 0 51] 109 @dc +[<01FC0003FE0007E7000FC7800FC3800FC3800FC3800FC3800FC3800FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0 + 000FC0000FC000FFFF00FFFF003FFF000FC00007C00007C00003C00003C00003C00001C00001C00001C00001C000> 17 32 -1 0 22] 116 @dc +[ 12 36 -2 0 15] 105 @dc +[ 33 34 -2 0 39] 80 @dc +[<01FF0007FFC01FE1E03F80F03F80707F00007F0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE03E07E07F07F07 + F03F07F03F87F01FC7F007FFE001FF80> 20 22 -2 0 25] 99 @dc +[<000E0000001F0000001F0000003F8000003F8000007FC000007FC000007FC00000FCE00000FCE00001FCF00001F8700003F8 + 780003F0380003F0380007E01C0007E01C000FE01E000FC00E00FFF03FE0FFF03FE0FFF03FE0> 27 22 -1 0 30] 118 @dc +8 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +224 195 p 112 c +1 r (ermission) s +12 r (to) s +13 r (send) s +14 r (to) s +13 r (the) s +13 r (list\),) s +12 r (and) s +14 r (resubmit) s +12 r (the) s +13 r (message) s +12 r (as) s +13 r 97 c +14 r (new) s +13 r (message.) s +224 252 p (This) s +13 r (means) s +13 r (that) s +13 r (lists) s +12 r (will) s +12 r 98 c +1 r 101 c +14 r (pro) s +(vided) s +13 r (at) s +12 r (the) s +14 r (P2) s +13 r (lev) s +(el,) s +12 r (rather) s +13 r (than) s +13 r (at) s +13 r (the) s +14 r (P1) s +224 308 p (lev) s +(el.) s +18 r 70 c +-3 r (or) s +13 r (PP) s +-3 r 44 c +14 r (the) s +14 r (ma) s +3 r (jor) s +13 r (consideration) s +13 r (is) s +14 r (the) s +15 r (abilit) s +-1 r 121 c +13 r (to) s +14 r (supp) s +1 r (ort) s +15 r (distribution) s +224 364 p (lists) s +15 r (for) s +16 r (RF) s +67 c +16 r (822) s +15 r (and) s +17 r (X.400\(1984\)) s +14 r (systems.) s +23 r (There) s +16 r (are) s +17 r (man) s +-1 r 121 c +15 r (reasons) s +16 r (as) s +16 r (to) s +224 421 p (wh) s +121 c +12 r (this) s +13 r (is) s +13 r (preferable,) s +14 r (and) s +13 r (the) s +14 r (author) s +13 r (is) s +13 r (disapp) s +1 r (oin) s +(ted) s +12 r (in) s +13 r (the) s +14 r 99 c +(hoice) s +12 r (made) s +13 r 98 c +121 c +224 477 p (CCITT/ISO.) s +16 r (The) s +16 r (X.400\(88\)) s +13 r (list) s +15 r (mec) s +(hanism) s +-1 r 115 c +13 r (will) s +15 r 98 c +1 r 101 c +16 r (supp) s +1 r (orted) s +17 r (in) s +15 r (as) s +16 r (far) s +15 r (as) s +224 534 p (PP) s +14 r (will) s +13 r 98 c +1 r (eha) s +118 c +101 c +13 r (correctly) s +13 r (in) s +15 r (relation) s +12 r (to) s +14 r (other) s +14 r (systems) s +13 r (follo) s +-1 r (wing) s +12 r (the) s +14 r (sp) s +1 r (eci\014ed) s +224 590 p (pro) s +1 r (cedures.) s +22 r (PP) s +16 r (will) s +14 r (also) s +14 r (align) s +15 r (to) s +15 r (the) s +16 r (X.400\(88\)) s +13 r (list) s +14 r (informatio) s +-1 r 110 c +14 r (structures,) s +224 647 p (when) s +16 r (using) s +15 r (the) s +15 r (OSI) s +16 r (Directory) s +295 703 p (There) s +15 r (is) s +15 r (also) s +15 r (an) s +15 r (outb) s +1 r (ound) s +16 r 99 c +(hannel) s +15 r (to) s +14 r (supp) s +1 r (ort) s +16 r (the) s +15 r (RF) s +67 c +14 r (987) s +15 r (mapping) s +14 r (of) s +224 760 p (deliv) s +(ery) s +16 r (noti\014cations) s +16 r (on) s +(to) s +16 r (text) s +17 r (messages.) s +25 r (PP) s +17 r (will) s +16 r (map) s +17 r (all) s +16 r (errors) s +17 r (on) s +(to) s +15 r (De-) s +224 816 p (liv) s +(ery) s +13 r (Noti\014cations;) s +13 r (Therefore) s +15 r (this) s +14 r 99 c +(hannel) s +14 r (is) s +14 r 97 c +15 r (critical) s +13 r (comp) s +1 r (onen) s +(t,) s +12 r 98 c +1 r (ecause) s +224 873 p (RF) s +67 c +17 r (822) s +17 r (based) s +18 r (systems) s +17 r (do) s +18 r (not) s +17 r (supp) s +1 r (ort) s +19 r (Deliv) s +-1 r (ery) s +16 r (Noti\014cations) s +17 r (as) s +18 r (proto) s +1 r (col) s +224 929 p (elemen) s +(ts.) s +295 985 p (Use) s +19 r (is) s +20 r (made) s +18 r (of) s +19 r (appropriate) s +19 r (Nameserv) s +-1 r (ers) s +18 r (and) s +20 r (Directories.) s +31 r (The) s +20 r (SMTP) s +224 1042 p 99 c +(hannel) s +19 r (uses) s +20 r (the) s +19 r (BIND) s +20 r (Nameserv) s +(er[) s +-1 r (17]) s +-1 r 46 c +31 r (The) s +20 r (X.400\(88\)) s +17 r 99 c +(hannels) s +19 r (and) s +19 r (the) s +224 1098 p (list) s +13 r 99 c +(hannel) s +14 r (utilise) s +13 r (X.500) s +13 r (Directory) s +13 r (Services) s +15 r 98 c +121 c +13 r (means) s +13 r (of) s +14 r (the) s +15 r (QUIPU) s +15 r (imple-) s +224 1155 p (men) s +(tat) s +-1 r (ion) s +13 r ([18].) s +cmbx10.360 @sf +224 1277 p (5.3) s +57 r (In) s +-1 r 98 c +2 r (ou) s +-1 r (nd) s +17 r (Channels) s +cmr10.329 @sf +224 1362 p (In) s +98 c +1 r (ound) s +17 r 99 c +(hannels) s +16 r 112 c +1 r (erform) s +15 r (the) s +17 r (opp) s +1 r (osite) s +16 r (to) s +16 r (outb) s +1 r (ound) s +17 r 99 c +(hannels.) s +23 r 70 c +-3 r (or) s +15 r (eac) s +104 c +16 r (of) s +224 1419 p (the) s +20 r (proto) s +1 r (cols) s +18 r (supp) s +1 r (orted,) s +21 r (there) s +19 r (is) s +19 r 97 c +20 r 99 c +(hannel) s +18 r (whic) s +104 c +19 r (will) s +18 r (act) s +19 r (as) s +19 r 97 c +19 r (serv) s +(er) s +18 r (for) s +224 1475 p (the) s +14 r (proto) s +1 r (col.) s +18 r (When) s +15 r (an) s +13 r (in) s +98 c +1 r (ound) s +14 r (message) s +12 r (is) s +13 r (receiv) s +(ed,) s +13 r (the) s +14 r 99 c +(hannel) s +13 r (will) s +13 r (in) s +118 c +-1 r (ok) s +-2 r 101 c +224 1532 p (Submit.) s +19 r (The) s +15 r 99 c +(hannel) s +15 r (will) s +14 r (then) s +15 r (pass) s +15 r (messages) s +14 r (in) s +(to) s +13 r (Submit.) s +295 1588 p (It) s +17 r (is) s +17 r (also) s +17 r 112 c +1 r (ossible) s +17 r (for) s +17 r 97 c +18 r 99 c +(hannel) s +16 r (to) s +17 r (act) s +17 r (as) s +18 r 98 c +1 r (oth) s +17 r (in) s +98 c +1 r (ound) s +17 r (and) s +18 r (outb) s +1 r (ound.) s +224 1645 p (This) s +20 r (is) s +19 r (necessary) s +21 r (to) s +19 r (supp) s +1 r (ort) s +20 r (Tw) s +111 c +18 r 87 c +-3 r 97 c +121 c +18 r (Alternate) s +19 r (mo) s +1 r (de) s +19 r (Reliable) s +20 r 84 c +-3 r (ransfer) s +224 1701 p (for) s +15 r (X.400,) s +13 r (or) s +15 r (to) s +14 r (supp) s +1 r (ort) s +15 r (P3/P7) s +14 r (st) s +(yle) s +14 r (message) s +13 r (retriev) s +-2 r (al) s +13 r (whic) s +104 c +14 r (is) s +15 r (User) s +15 r (Agen) s +116 c +224 1758 p (initiated.) s +17 r (In) s +12 r (this) s +10 r (case,) s +12 r (the) s +11 r 99 c +(hannel) s +10 r (will) s +9 r (start) s +10 r (as) s +11 r (an) s +11 r (in) s +98 c +1 r (ound) s +10 r 99 c +(hannel) s +10 r (\(t) s +(ypically) s +224 1814 p 98 c +121 c +15 r 98 c +1 r (eing) s +16 r (in) s +118 c +-1 r (ok) s +-1 r (ed) s +14 r (as) s +15 r 97 c +15 r (proto) s +1 r (col) s +15 r (serv) s +(er\).) s +20 r (Then) s +16 r (it) s +15 r (will) s +14 r (connect) s +17 r (to) s +15 r (the) s +15 r (QMGR) s +224 1870 p (using) s +14 r 82 c +(OS.) s +14 r (The) s +15 r (QMGR) s +15 r (can) s +14 r 99 c +(ho) s +1 r (ose) s +14 r (to) s +14 r (accept) s +14 r (or) s +14 r (reject) s +15 r (the) s +14 r (asso) s +1 r (ciation.) s +18 r (If) s +15 r (it) s +224 1927 p (accepts) s +17 r (the) s +16 r (asso) s +1 r (ciation,) s +15 r (the) s +17 r (QMGR) s +17 r (will) s +15 r (tak) s +101 c +15 r (con) s +(trol) s +14 r (and) s +17 r (then) s +17 r (the) s +16 r 99 c +(hannel) s +224 1983 p (then) s +18 r 98 c +1 r (eha) s +118 c +(es) s +15 r (as) s +17 r (an) s +18 r (outb) s +1 r (ound) s +18 r 99 c +(hannel.) s +25 r (In) s +18 r (terms) s +16 r (of) s +17 r (the) s +18 r (QMGR,) s +17 r (the) s +17 r (use) s +18 r (of) s +224 2040 p 82 c +(OS) s +15 r (mak) s +-1 r (es) s +14 r (this) s +14 r (con) s +(trol) s +13 r (mo) s +1 r (del) s +14 r (straigh) s +(tf) s +-1 r (orw) s +-2 r (ard) s +13 r (to) s +15 r (pro) s +(vide.) s +cmbx10.360 @sf +224 2161 p (5.4) s +57 r (Message) s +18 r (Reform) s +-2 r (atting) s +18 r (and) s +18 r (Proto) s +2 r (col) s +19 r (Con) s +-1 r 118 c +-1 r (ersion) s +cmr10.329 @sf +224 2247 p (The) s +17 r (\015exible) s +16 r (handling) s +16 r (of) s +16 r (reformatt) s +-1 r (ing) s +14 r (is) s +16 r (one) s +17 r (of) s +16 r (the) s +16 r (most) s +14 r (imp) s +1 r (ortan) s +-1 r 116 c +14 r (comp) s +1 r (o-) s +224 2304 p (nen) s +(ts) s +13 r (of) s +14 r (PP) s +-3 r 46 c +13 r (This) s +13 r (is) s +14 r (ac) s +(hiev) s +-1 r (ed) s +13 r 98 c +121 c +13 r (reformatt) s +-1 r (ing) s +12 r 99 c +(hannels) s +13 r (whic) s +104 c +13 r (map) s +13 r (from) s +12 r (one) s +224 2360 p (message) s +15 r (form) s +14 r (in) s +(to) s +15 r (another.) s +22 r (As) s +16 r (discussed,) s +17 r (Submit) s +15 r (will) s +15 r (calculate) s +15 r 97 c +16 r (sequence) s +224 2417 p (of) s +17 r (reformat) s +-1 r (ting) s +15 r 99 c +(hannels) s +16 r (for) s +16 r (eac) s +104 c +16 r (recipien) s +(t,) s +16 r (in) s +17 r (order) s +17 r (to) s +16 r (pro) s +(vide) s +16 r (the) s +17 r (correct) s +224 2473 p (con) s +118 c +(ersi) s +-1 r (ons.) s +26 r (In) s +(ternally) s +-3 r 44 c +16 r (PP) s +18 r (represen) s +(ts) s +17 r (di\013eren) s +116 c +16 r 98 c +1 r 111 c +1 r (dy) s +19 r (part) s +17 r (and) s +19 r (header) s +18 r (for-) s +224 2530 p (mats) s +13 r (as) s +15 r (strings) s +13 r (\(e.g.) s +19 r (\\IA5") s +15 r (or) s +14 r (\\JNT-Mail"\).) s +18 r (Channels) s +15 r (will) s +14 r (supp) s +1 r (ort) s +15 r 97 c +14 r (set) s +15 r (of) s +224 2586 p (formats,) s +10 r (represen) s +(ted) s +12 r 98 c +121 c +11 r (these) s +13 r (strings.) s +18 r (The) s +12 r 99 c +(hannel) s +12 r (ma) s +-1 r 121 c +10 r 99 c +(ho) s +1 r (ose) s +11 r (to) s +12 r (map) s +11 r (these) s +224 2642 p (in) s +(to) s +12 r (proto) s +1 r (col) s +12 r (sp) s +1 r (eci\014c) s +14 r (enco) s +1 r (dings) s +14 r (\(e.g.) s +19 r (P1) s +13 r (Enco) s +1 r (ded) s +14 r (Information) s +12 r 84 c +(yp) s +1 r (es\).) s +18 r (This) s +224 2699 p (approac) s +104 c +19 r (lets) s +20 r (complex) s +19 r (mappings) s +19 r (to) s +20 r 98 c +1 r 101 c +21 r (calculated,) s +20 r (and) s +21 r (allo) s +-1 r (ws) s +18 r (for) s +20 r (general) s +224 2755 p (extension.) s +960 2916 p 56 c +@eop +7 @bop0 +cmbx10.432 @sf +[<00FF800007FFF0000FFFFC003F83FE003C00FF007C007F80FF007FC0FF003FC0FF803FE0FF803FE0FF803FE0FF003FE07F00 + 3FE03C003FE000003FE000003FE000003FC000003FC01E007F801F007F801FC1FF001FFFFE001FFFF8001E7FC0001E000000 + 1E0000001E0000001E0000001E0000001FFE00001FFF80001FFFE0001FFFF0001FFFFC001FFFFC001FFFFE001FFFFF001F80 + 3F001C000700> 27 39 -3 0 34] 53 @dc +cmti10.329 @sf +[<0FE0003FFC003C3E00780700700300F00000F00000F00000F00000F800007800007800007800003C02003C07801E07800F07 + 8007C38003FF00007E00> 17 20 -4 0 21] 99 @dc +cmbx10.360 @sf +[<7FFFF07FFFF07FFFF001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC + 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC00FFFC00FFFC00FFFC0001FC00007C00001C00> 20 32 -4 0 29] 49 @dc +[<0007FE0000003FFFC00000FE07F00003F801FC0007F000FE000FE0007F001FC0003F801FC0003F803F80001FC07F80001FE0 + 7F80001FE07F00000FE0FF00000FF0FF00000FF0FF00000FF0FF00000FF0FF00000FF0FF00000FF0FF00000FF0FF00000FF0 + FF00000FF07F00000FE07F00000FE07F00000FE03F80001FC03F80001FC01F80001F801FC0003F800FE0007F0007F000FE00 + 03F801FC0000FE07F000003FFFC0000007FE0000> 36 34 -3 0 43] 79 @dc +[ 22 32 -3 0 29] 50 @dc +7 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +cmbx10.432 @sf +224 195 p 53 c +69 r (Channels) s +cmr10.329 @sf +224 297 p (The) s +14 r (term) s +cmti10.329 @sf +13 r (channel) s +cmr10.329 @sf +13 r (is) s +13 r (used) s +15 r (in) s +13 r (PP) s +14 r (to) s +13 r (describ) s +1 r 101 c +15 r 97 c +13 r 110 c +(um) s +-1 r 98 c +1 r (er) s +13 r (of) s +13 r (somewhat) s +12 r (di\013eren) s +116 c +224 353 p (comp) s +1 r (onen) s +(ts.) s +26 r (In) s +19 r (essence,) s +19 r (eac) s +104 c +17 r 99 c +(hannel) s +17 r (tak) s +(es) s +16 r 97 c +18 r (message) s +16 r (as) s +18 r (input,) s +18 r (and) s +18 r (then) s +224 409 p (pro) s +(vides) s +10 r 97 c +11 r (di\013eren) s +116 c +9 r (message) s +10 r (as) s +11 r (output.) s +19 r (Channels) s +11 r (whic) s +104 c +10 r (are) s +11 r (con) s +(troll) s +-1 r (ed) s +10 r 98 c +121 c +10 r (the) s +224 466 p (QMGR,) s +12 r (access) s +13 r (the) s +13 r (queue) s +13 r (through) s +13 r 97 c +12 r (library) s +-3 r 46 c +17 r (They) s +13 r (are) s +12 r (trusted) s +12 r (pro) s +1 r (cesses,) s +13 r (and) s +224 522 p (will) s +11 r (up) s +1 r (date) s +13 r (the) s +13 r (queue.) s +20 r 65 c +12 r 99 c +(hannel) s +12 r (will) s +11 r (op) s +1 r (erate) s +12 r (en) s +(tirely) s +10 r (under) s +14 r (the) s +12 r (direction) s +12 r (of) s +224 579 p (the) s +15 r (QMGR,) s +14 r (and) s +15 r (no) s +14 r (in) s +(telligence) s +13 r (is) s +14 r (in) s +118 c +-1 r (olv) s +-2 r (ed.) s +19 r (The) s +14 r 118 c +-2 r (arious) s +13 r (\015a) s +118 c +(ours) s +12 r (of) s +14 r 99 c +(hannel) s +224 635 p (are) s +15 r (no) s +119 c +14 r (describ) s +1 r (ed.) s +cmbx10.360 @sf +224 757 p (5.1) s +57 r (Outb) s +2 r (ound) s +17 r (Proto) s +2 r (col) s +19 r (Channels) s +cmr10.329 @sf +224 843 p (This) s +17 r (basic) s +17 r 116 c +(yp) s +1 r 101 c +16 r (of) s +17 r 99 c +(hannel) s +16 r (will) s +16 r (tak) s +101 c +16 r 97 c +17 r (message) s +16 r (from) s +15 r (the) s +17 r (queue,) s +19 r (and) s +17 r (trans-) s +224 899 p (fer) s +17 r (it) s +16 r (using) s +16 r 97 c +17 r (Message) s +16 r 84 c +-3 r (ransfer) s +16 r (Proto) s +1 r (col.) s +23 r (The) s +17 r (outb) s +1 r (ound) s +18 r (proto) s +1 r (col) s +15 r 99 c +(hannels) s +224 955 p (supp) s +1 r (orted) s +16 r 98 c +121 c +14 r (PP) s +15 r (initially) s +13 r (will) s +14 r 98 c +1 r (e:) s +cmsy10.329 @sf +292 1060 p 15 c +cmr10.329 @sf +23 r (X.400/P1) s +13 r (\(1984\)) s +cmsy10.329 @sf +292 1153 p 15 c +cmr10.329 @sf +23 r (X.400/P1) s +13 r (\(1988\)) s +cmsy10.329 @sf +292 1246 p 15 c +cmr10.329 @sf +23 r (JNT) s +15 r (Mail) s +cmsy10.329 @sf +292 1340 p 15 c +cmr10.329 @sf +23 r (SMTP) s +cmsy10.329 @sf +292 1433 p 15 c +cmr10.329 @sf +23 r (UUCP) s +295 1537 p (In) s +(terestingly) s +-4 r 44 c +17 r (the) s +19 r (implem) s +-1 r (en) s +(t) s +-1 r (ati) s +-1 r (on) s +17 r (of) s +18 r (the) s +19 r (X.400) s +17 r (proto) s +1 r (col) s +18 r (is) s +18 r (not) s +18 r (really) s +18 r 97 c +224 1594 p (ma) s +3 r (jor) s +17 r (problem.) s +31 r (The) s +19 r (use) s +20 r (of) s +19 r (the) s +19 r (PEPY) s +20 r (ASN.1) s +19 r (Compiler) s +17 r (from) s +17 r (the) s +20 r (ISODE) s +224 1650 p (pac) s +107 c +-2 r (age) s +16 r (has) s +18 r (made) s +17 r (the) s +18 r (mapping) s +17 r (of) s +18 r (the) s +18 r (PP) s +18 r (Message) s +17 r 84 c +-3 r (ransfer) s +17 r (Services) s +18 r (on) s +(to) s +224 1707 p (OSI) s +16 r 97 c +15 r (relativ) s +(el) s +-1 r 121 c +14 r (mec) s +(hani) s +-1 r (cal) s +13 r (op) s +1 r (eration[1],) s +13 r ([16].) s +cmbx10.360 @sf +224 1828 p (5.2) s +57 r (Other) s +19 r (Outb) s +2 r (ound) s +17 r (Channels) s +cmr10.329 @sf +224 1914 p (An) s +18 r (outb) s +1 r (ound) s +18 r 99 c +(hannel) s +16 r (is) s +17 r (alw) s +97 c +-2 r (ys) s +15 r (the) s +18 r (last) s +16 r (applied) s +17 r (to) s +17 r 97 c +17 r (recipien) s +(t,) s +15 r (and) s +18 r (so) s +17 r (will) s +224 1970 p (cause) s +20 r (the) s +20 r (message) s +19 r (to) s +19 r (lea) s +118 c +-1 r 101 c +18 r (the) s +20 r (queue) s +20 r (\(for) s +19 r (that) s +19 r (recipien) s +(t\).) s +32 r (This) s +20 r (do) s +1 r (es) s +20 r (not) s +224 2027 p (include) s +17 r (handling) s +17 r (of) s +16 r (deliv) s +(ery) s +15 r (noti\014cations,) s +15 r (whic) s +104 c +16 r (will) s +15 r (happ) s +1 r (en) s +18 r (after) s +16 r (the) s +17 r (out-) s +224 2083 p 98 c +1 r (ound) s +21 r 99 c +(hannel) s +19 r (is) s +20 r (run.) s +34 r (There) s +20 r (are) s +20 r 97 c +19 r 110 c +(um) s +-1 r 98 c +1 r (er) s +19 r (of) s +19 r (outb) s +1 r (ound) s +21 r 99 c +(hannels,) s +20 r (whic) s +104 c +224 2140 p (are) s +17 r (not) s +16 r (proto) s +1 r (col) s +16 r 99 c +(hannels.) s +24 r (The) s +17 r (\014rst) s +17 r (is) s +16 r (lo) s +1 r (cal) s +16 r (deliv) s +(ery) s +-3 r 44 c +14 r (where) s +18 r (the) s +17 r (message) s +15 r (is) s +224 2196 p (simply) s +14 r (deliv) s +(ered) s +14 r (in) s +(to) s +13 r 97 c +15 r (lo) s +1 r (cal) s +14 r (\014le.) s +20 r (PP) s +15 r (supp) s +1 r (orts) s +15 r 116 c +119 c +-1 r 111 c +13 r (st) s +(yles) s +13 r (of) s +15 r (lo) s +1 r (cal) s +14 r (deliv) s +(ery:) s +280 2301 p (1.) s +22 r (Deliv) s +(ery) s +13 r (in) s +(to) s +13 r 97 c +15 r (UNIX/MMDF) s +14 r (st) s +(yle) s +13 r (\014le) s +16 r (with) s +14 r (CTRL-A) s +16 r (separators.) s +280 2394 p (2.) s +22 r (Deliv) s +(ery) s +19 r (in) s +(to) s +20 r 97 c +21 r (directory) s +20 r (structured) s +22 r (message,) s +21 r (equiv) s +-2 r (alen) s +116 c +19 r (to) s +21 r (the) s +22 r (PP) s +338 2450 p (queue) s +16 r (mo) s +1 r (del.) s +295 2555 p (Lo) s +1 r (cal) s +13 r (deliv) s +(ery) s +13 r (will) s +12 r (implemen) s +-1 r 116 c +11 r (the) s +14 r (deliv) s +(ery) s +12 r (time) s +12 r (pro) s +1 r (cessing) s +14 r (supp) s +1 r (orted) s +15 r 98 c +121 c +224 2611 p (MMDF[5].) s +295 2668 p (An) s +22 r (outb) s +1 r (ound) s +22 r 99 c +(hannel) s +20 r (is) s +21 r (also) s +21 r (used) s +22 r (to) s +21 r (supp) s +1 r (ort) s +21 r (distribution) s +21 r (lists.) s +37 r (The) s +224 2724 p (destination,) s +21 r (in) s +20 r (terms) s +20 r (of) s +20 r (the) s +21 r (incoming) s +19 r (message,) s +20 r (will) s +20 r 98 c +1 r 101 c +21 r (the) s +21 r (list.) s +36 r (The) s +21 r (list) s +224 2781 p 99 c +(hannel) s +11 r (will) s +11 r (expand) s +12 r (the) s +12 r (list,) s +11 r 112 c +1 r (erform) s +10 r (an) s +121 c +11 r (necessary) s +12 r (managem) s +-1 r (en) s +-1 r 116 c +10 r 99 c +(hec) s +(ks) s +10 r (\(e.g.) s +960 2916 p 55 c +@eop +6 @bop0 +6 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +280 195 p (1.) s +22 r (An) s +121 c +20 r (errors) s +21 r (will) s +20 r 98 c +1 r 101 c +22 r (passed) s +22 r (bac) s +107 c +20 r (to) s +21 r (the) s +22 r (submitting) s +19 r (pro) s +1 r (cess.) s +39 r (This) s +21 r (is) s +338 252 p (useful) s +15 r (for) s +15 r (User) s +15 r (Agen) s +(ts,) s +13 r (and) s +16 r (in) s +(teracti) s +-1 r 118 c +-1 r 101 c +13 r (proto) s +1 r (cols) s +14 r (suc) s +104 c +15 r (as) s +15 r (SMTP[10].) s +280 345 p (2.) s +22 r 65 c +13 r (successful) s +14 r (resp) s +1 r (onse) s +13 r (is) s +13 r (alw) s +97 c +-2 r (ys) s +11 r (passed) s +14 r (bac) s +107 c +12 r (to) s +12 r (the) s +14 r (submitti) s +-1 r (ng) s +12 r (pro) s +1 r (cess,) s +338 402 p (and) s +19 r (deliv) s +(ery) s +18 r (noti\014cations) s +18 r (are) s +19 r (generated) s +19 r (if) s +19 r (necessary) s +19 r (\(these) s +19 r (reside) s +20 r (in) s +338 458 p (the) s +13 r (queue) s +13 r (for) s +13 r (later) s +11 r (pro) s +1 r (cessing\).) s +19 r (This) s +13 r (mec) s +(hani) s +-1 r (sm) s +10 r (is) s +12 r (useful) s +13 r (for) s +13 r (proto) s +1 r (cols) s +338 515 p (suc) s +104 c +14 r (as) s +15 r (X.400) s +14 r (or) s +15 r (JNT) s +15 r (Mail) s +14 r ([11].) s +295 621 p (Address) s +21 r 99 c +(hec) s +(king) s +18 r (will) s +19 r (\014rst) s +20 r (determine) s +20 r (the) s +21 r (MT) s +-3 r 65 c +19 r (to) s +20 r (whic) s +104 c +19 r (the) s +21 r (message) s +224 677 p (should) s +23 r 98 c +1 r 101 c +24 r (sen) s +(t.) s +41 r (Curren) s +(tly) s +-3 r 44 c +22 r (PP) s +23 r (uses) s +23 r (table) s +22 r (based) s +23 r (address) s +23 r (handling,) s +24 r (with) s +224 734 p (access) s +20 r (optimi) s +-1 r (sed) s +18 r 98 c +121 c +18 r (the) s +19 r (use) s +20 r (of) s +19 r (hashed) s +19 r (lo) s +1 r (okup.) s +32 r (In) s +(ternally) s +-3 r 44 c +17 r (MT) s +-3 r (As) s +18 r (are) s +19 r (rep-) s +224 790 p (resen) s +(ted) s +15 r 98 c +121 c +14 r (domain) s +14 r (names) s +14 r (\(e.g.) s +20 r (CS.UCL.A) s +(C.) s +-1 r (UK\).) s +13 r 70 c +-3 r (or) s +14 r (RF) s +67 c +14 r (822) s +15 r (addresses,) s +224 847 p (this) s +20 r (utilises) s +20 r (the) s +21 r (MMDF) s +19 r (approac) s +104 c +19 r (whic) s +104 c +20 r (is) s +20 r (describ) s +1 r (ed) s +22 r (elsewhere[12].) s +35 r (This) s +224 903 p (pap) s +1 r (er) s +19 r (also) s +16 r (giv) s +(es) s +17 r 97 c +17 r (more) s +17 r (detailed) s +17 r (analysis) s +17 r (of) s +17 r (the) s +18 r 98 c +1 r (ene\014ts) s +19 r (of) s +18 r (using) s +17 r 99 c +(hannels) s +224 960 p (to) s +21 r (giv) s +101 c +20 r 97 c +22 r 116 c +119 c +-1 r 111 c +19 r (phase) s +22 r (address) s +22 r (binding.) s +40 r 70 c +-3 r (or) s +20 r (O/R) s +22 r (Addresses,) s +23 r (an) s +22 r (hierarc) s +(hi-) s +224 1016 p (cally) s +15 r (structured) s +17 r (table) s +15 r (is) s +16 r (used) s +17 r (to) s +15 r (determine) s +15 r (the) s +17 r (MT) s +-3 r (A.) s +14 r (This) s +16 r (is) s +16 r 97 c +16 r (table) s +15 r (based) s +224 1073 p (implemen) s +-1 r (t) s +-1 r (atio) s +-1 r 110 c +18 r (of) s +19 r (an) s +19 r (approac) s +104 c +18 r (describ) s +1 r (ed) s +20 r 98 c +121 c +19 r (Kille[13].) s +30 r (After) s +19 r (the) s +20 r (MT) s +-3 r 65 c +18 r (is) s +224 1129 p (determined,) s +16 r (an) s +16 r (outb) s +1 r (ound) s +17 r 99 c +(hannel) s +15 r (is) s +16 r (selected.) s +23 r (Where) s +17 r (an) s +16 r (MT) s +-3 r 65 c +15 r (is) s +16 r (accessible) s +224 1186 p 98 c +121 c +17 r 109 c +(ult) s +-1 r (iple) s +16 r 99 c +(hannels,) s +18 r 99 c +(hannel) s +17 r (binding) s +18 r (attempts) s +16 r (to) s +17 r (minim) s +-1 r (ise) s +16 r (proto) s +1 r (col) s +17 r (con-) s +224 1242 p 118 c +(ersions.) s +34 r (Managemen) s +-1 r 116 c +18 r 99 c +(hec) s +(king) s +19 r (is) s +19 r (also) s +20 r (carried) s +20 r (out) s +20 r (at) s +20 r (this) s +19 r 112 c +1 r (oin) s +(t,) s +20 r (as) s +20 r (it) s +20 r (is) s +224 1298 p (sometim) s +-1 r (es) s +16 r (imp) s +1 r (ortan) s +-1 r 116 c +16 r (to) s +17 r (con) s +(trol) s +16 r 99 c +(hannel) s +17 r 99 c +(hoice) s +17 r (for) s +18 r (administr) s +-1 r (ati) s +-1 r 118 c +-1 r 101 c +16 r (reasons.) s +224 1355 p (This) s +17 r (includes) s +18 r (application) s +16 r (of) s +18 r (authorisatio) s +-1 r 110 c +16 r (con) s +(trols,) s +15 r (so) s +18 r (that) s +17 r (routing) s +16 r (can) s +18 r 98 c +1 r 101 c +224 1411 p (regulated) s +20 r (on) s +21 r (the) s +21 r (basis) s +20 r (host,) s +21 r (net) s +119 c +(o) s +-1 r (rk) s +19 r (and) s +21 r (user.) s +36 r 65 c +21 r (full) s +20 r (description) s +20 r (of) s +20 r (the) s +224 1468 p (general) s +15 r (approac) s +104 c +14 r (is) s +14 r (giv) s +(en) s +14 r (in) s +15 r 97 c +15 r (pap) s +1 r (er) s +16 r 98 c +121 c +14 r (Kille) s +14 r (and) s +16 r (Brink[14].) s +295 1524 p 70 c +-3 r (ollo) s +-2 r (wing) s +14 r (the) s +16 r (determinatio) s +-1 r 110 c +15 r (of) s +15 r (the) s +16 r (outb) s +1 r (ound) s +17 r 99 c +(hannel,) s +15 r (the) s +17 r (reformat) s +-1 r (ting) s +224 1581 p (requiremen) s +(ts) s +12 r (are) s +14 r (calculated.) s +19 r (This) s +13 r (will) s +13 r 98 c +1 r 101 c +15 r 97 c +14 r (sequence) s +15 r (of) s +14 r 99 c +(hannels,) s +13 r (whic) s +104 c +13 r (will) s +224 1637 p 112 c +1 r (erform) s +19 r (the) s +19 r (correct) s +19 r (series) s +20 r (of) s +19 r (proto) s +1 r (col) s +18 r (and) s +20 r 98 c +1 r 111 c +1 r (dy) s +20 r (part) s +19 r (reformatti) s +-1 r (ng) s +18 r (on) s +19 r (the) s +224 1694 p (message) s +12 r (in) s +13 r (question.) s +19 r (This) s +13 r (is) s +13 r 97 c +13 r (surprisingly) s +13 r (di\016cult) s +13 r (calculation) s +12 r (to) s +12 r (mak) s +(e,) s +11 r (but) s +224 1750 p (it) s +15 r (can) s +15 r 98 c +1 r 101 c +16 r (done) s +15 r (in) s +15 r 97 c +15 r (reasonably) s +15 r (general) s +14 r (manner.) s +295 1807 p (When) s +17 r (all) s +15 r (of) s +17 r (the) s +17 r (recipien) s +116 c +15 r (addresses) s +17 r (ha) s +118 c +-1 r 101 c +15 r 98 c +1 r (een) s +18 r (accepted,) s +17 r (the) s +17 r (transfer) s +16 r (of) s +224 1863 p (the) s +15 r (con) s +(ten) s +116 c +13 r (tak) s +(es) s +14 r (place.) s +19 r (There) s +16 r (is) s +15 r 97 c +15 r (separate) s +14 r (transfer) s +15 r (for) s +14 r (eac) s +104 c +15 r (comp) s +1 r (onen) s +116 c +13 r (of) s +224 1919 p (the) s +15 r (initial) s +14 r (message) s +13 r (stored) s +15 r (in) s +15 r (the) s +16 r (queue.) s +20 r 70 c +-3 r (or) s +14 r (example:) s +cmsy10.329 @sf +292 2026 p 15 c +cmr10.329 @sf +23 r (An) s +15 r (RF) s +67 c +14 r (822) s +14 r (message) s +14 r (is) s +15 r (submitted) s +14 r (as) s +15 r 116 c +119 c +-1 r 111 c +12 r (\014les.) s +cmsy10.329 @sf +292 2120 p 15 c +cmr10.329 @sf +23 r 65 c +15 r (P2) s +15 r (message) s +14 r (is) s +14 r (submitted) s +14 r (as) s +15 r (one) s +15 r (\014le.) s +cmsy10.329 @sf +292 2213 p 15 c +cmr10.329 @sf +23 r 65 c +17 r (lo) s +1 r (cal) s +16 r (submission) s +16 r (of) s +17 r 97 c +17 r (complex) s +16 r (directory) s +16 r (hierarc) s +104 c +121 c +15 r (is) s +17 r (submitted) s +15 r (di-) s +338 2270 p (rectly) s +-3 r 46 c +295 2376 p (Finally) s +-4 r 44 c +18 r (an) s +121 c +18 r (remaining) s +17 r (managem) s +-1 r (en) s +-1 r 116 c +17 r 99 c +(hec) s +(ks) s +17 r (are) s +19 r (done) s +19 r (\(for) s +18 r (example) s +18 r (an) s +121 c +224 2432 p (required) s +21 r 99 c +(hec) s +(ks) s +19 r (on) s +21 r (message) s +20 r (con) s +(ten) s +-1 r (t\),) s +20 r (and) s +21 r (the) s +21 r (message) s +19 r (is) s +21 r (lo) s +1 r 99 c +107 c +-1 r (ed) s +19 r (in) s +(to) s +19 r (the) s +224 2489 p (queue.) s +295 2545 p (In) s +20 r (addition,) s +19 r (Submit) s +18 r (understands) s +20 r (the) s +19 r (P1) s +19 r (lev) s +(el) s +17 r (asp) s +1 r (ects) s +20 r (of) s +19 r (RF) s +67 c +18 r (987) s +18 r ([9],) s +224 2602 p ([15].) s +18 r (This) s +14 r (means) s +12 r (that) s +13 r (it) s +13 r (can) s +14 r (map) s +13 r (addresses) s +14 r 98 c +1 r (et) s +119 c +-1 r (een) s +13 r (the) s +14 r 116 c +119 c +-1 r 111 c +11 r (forms,) s +12 r (and) s +14 r (will) s +224 2658 p (correctly) s +15 r (handle) s +15 r (trace) s +15 r (and) s +15 r (Message) s +15 r (Ids.) s +960 2916 p 54 c +@eop +5 @bop0 +cmbx10.432 @sf +[<007FFFF8007FFFF8007FFFF80000FF000000FF000000FF000000FF000000FF000000FF000000FF00FFFFFFF8FFFFFFF8FFFF + FFF8F0007F0078007F003C007F001E007F001E007F000F007F0007807F0003C07F0001C07F0001E07F0000F07F0000787F00 + 003C7F00003C7F00001E7F00000F7F000007FF000003FF000003FF000001FF000000FF0000007F0000007F0000003F000000 + 1F0000000F00> 29 39 -2 0 34] 52 @dc +[ 29 41 -4 0 38] 83 @dc +/cmr8.300 @newfont +cmr8.300 @sf +[<1F807FE0F1F0F0F0F078F078707800780078607078F07FE06F8060006000600060007FC07FE07FF07030> 13 21 -2 0 18] 53 @dc +/cmr6.300 @newfont +cmr6.300 @sf +[<3F007FC0E1C0E0E0E0E000E000E060E071C07F806000600078007F007F806180> 11 16 -1 0 15] 53 @dc +/cmr9.300 @newfont +cmr9.300 @sf +[<007F000001FFC00007C1F0000F0078001E003C003C001E0038000E0078000F0078000F00F0000780F0000780F0000780F000 + 0780F0000780F0000780F0000780F00007807000070078000F0038000E003C001E001E003C000F00780007C1F00001FFC000 + 007F0000> 25 26 -2 0 30] 79 @dc +[ 18 16 -1 0 21] 110 @dc +[ 23 26 -1 0 27] 66 @dc +[ 16 26 -2 0 21] 83 @dc +[ 25 26 -1 0 29] 68 @dc +[<003F800000FFE00001E0F00003C03800078018000F801C000F000C000F000C000F000C000F000C000F000C000F000C000F00 + 0C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F001E00FFF0FFC0 + FFF0FFC0> 26 26 -1 0 29] 85 @dc +[ 26 26 -1 0 29] 78 @dc +[ 12 26 -1 0 14] 73 @dc +[ 26 26 -1 0 29] 88 @dc +[<6060703038181878F8F8F870> 5 12 -3 7 11] 44 @dc +[<07800FC01EE01C601C601C601C601C001C001C001C001C001C001C00FFC0FFC03C001C001C000C000C000C000C00> 11 23 -1 0 15] 116 @dc +[ 18 26 -1 0 21] 104 @dc +[ 9 26 0 0 10] 105 @dc +[ 12 16 -1 0 15] 115 @dc +[<07E01FF83C3C781E700EF00FF00FF00FF00FF00FF00F700E781E3C3C1FF807E0> 16 16 -1 0 19] 111 @dc +[<07E01FF83E1C7C0C7800F000F000F000F000F000F0007818783C3E3C1FFC07F8> 14 16 -1 0 17] 99 @dc +[ 18 26 -1 0 20] 107 @dc +[<07E01FF83E1C7C0C7800F000F000F000F000FFFCFFFC703C783C3C781FF007E0> 14 16 -1 0 17] 101 @dc +[<70F8F8F870> 5 5 -3 0 11] 46 @dc +5 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +224 195 p (constrained) s +14 r (to) s +14 r (In) s +(ter) s +14 r 80 c +(ersonal) s +13 r (Messaging) s +13 r (\(IPM\),) s +14 r (although) s +13 r (IPM) s +15 r (is) s +14 r (the) s +15 r (ma) s +3 r (jor) s +224 252 p (target.) s +21 r (The) s +17 r (main) s +14 r (reason) s +16 r (for) s +15 r (this) s +16 r (structure) s +16 r (is) s +15 r (to) s +16 r (facilitate) s +14 r (reformatt) s +-1 r (ing.) s +20 r (By) s +224 308 p (putting) s +14 r (the) s +14 r 118 c +-2 r (arious) s +12 r (comp) s +1 r (onen) s +(ts) s +12 r (in) s +(to) s +12 r (separate) s +13 r (\014les,) s +14 r (reformatt) s +-1 r (ing) s +12 r (can) s +14 r 98 c +1 r 101 c +15 r (car-) s +224 364 p (ried) s +14 r (out) s +14 r (in) s +15 r 97 c +14 r (straigh) s +-1 r (tfo) s +-1 r (rw) s +-1 r (ar) s +-1 r 100 c +13 r (manner.) s +19 r (It) s +14 r (is) s +14 r (exp) s +1 r (ected) s +16 r (that) s +13 r 97 c +14 r (PP) s +15 r (related) s +13 r (User) s +224 421 p (Agen) s +116 c +15 r 119 c +(ould) s +15 r (also) s +16 r (use) s +17 r (this) s +16 r (structure,) s +16 r (as) s +16 r (it) s +16 r (app) s +1 r (ears) s +17 r (to) s +16 r (o\013er) s +15 r 97 c +17 r (go) s +1 r 111 c +1 r 100 c +16 r (basis) s +16 r (for) s +224 477 p (\015exible) s +15 r (construction) s +15 r (of) s +15 r (Multim) s +-1 r (edia) s +13 r (Messages.) s +cmbx10.432 @sf +224 621 p 52 c +69 r (Message) s +23 r (Submi) s +-1 r (ssion) s +cmr10.329 @sf +224 722 p (The) s +20 r (pro) s +1 r (cess) s +19 r (of) s +19 r (message) s +18 r (submission) s +17 r (is) s +19 r (no) s +119 c +18 r (considered) s +19 r (in) s +20 r 97 c +18 r (little) s +18 r (more) s +18 r (de-) s +224 778 p (tail.) s +25 r 65 c +17 r (message) s +16 r (is) s +17 r (submitted) s +16 r 98 c +121 c +16 r (either) s +17 r 97 c +17 r (User) s +17 r (Agen) s +116 c +16 r (\(lo) s +1 r (cal) s +16 r (submission\)) s +15 r (or) s +224 835 p 98 c +121 c +19 r (an) s +20 r (in) s +98 c +1 r (ound) s +20 r 99 c +(hannel,) s +20 r (whic) s +104 c +19 r (in) s +(teract) s +-1 r 115 c +18 r (with) s +20 r (Submit) s +19 r (through) s +19 r 97 c +20 r (proto) s +1 r (col.) s +224 891 p (The) s +13 r (curren) s +116 c +12 r 118 c +(ersion) s +11 r (of) s +12 r (this) s +12 r (proto) s +1 r (col) s +12 r (uses) s +13 r 97 c +12 r (UNIX) s +13 r (In) s +(ter-Pro) s +1 r (cess) s +12 r (Comm) s +-2 r (unica-) s +224 948 p (tion) s +13 r (\(IPC\)) s +13 r (mec) s +(hanism) s +cmr8.300 @sf +666 933 p 53 c +cmr10.329 @sf +684 948 p 44 c +13 r (although) s +13 r (in) s +13 r 97 c +14 r (later) s +12 r 118 c +(ersion) s +12 r (OSI) s +15 r (Remote) s +13 r (Op) s +1 r (erations) s +224 1004 p (\(R) s +(OS\)) s +18 r (ma) s +121 c +17 r 98 c +1 r 101 c +19 r (used.) s +33 r (The) s +19 r (enco) s +1 r (ding) s +19 r (of) s +19 r (the) s +19 r (curren) s +116 c +18 r (proto) s +1 r (col) s +18 r (is) s +19 r (text) s +19 r (based,) s +224 1061 p (with) s +19 r (parameters) s +17 r (equiv) s +-2 r (alen) s +116 c +17 r (to) s +18 r (the) s +19 r (queue) s +20 r (structure.) s +31 r 70 c +-3 r (or) s +18 r 97 c +19 r 110 c +(um) s +-2 r 98 c +1 r (er) s +18 r (of) s +19 r (rea-) s +224 1117 p (sons,) s +14 r (it) s +14 r 119 c +(as) s +13 r (decided) s +16 r (not) s +14 r (to) s +14 r (use) s +15 r 97 c +14 r (standard) s +14 r (proto) s +1 r (col,) s +14 r (in) s +14 r (particular) s +14 r (P3,) s +14 r (whic) s +104 c +224 1174 p (is) s +15 r (the) s +15 r (ob) s +(vious) s +14 r (candidate:) s +cmsy10.329 @sf +292 1280 p 15 c +cmr10.329 @sf +23 r (There) s +17 r (is) s +17 r 97 c +17 r (need) s +18 r (for) s +17 r (services) s +17 r (not) s +17 r (supp) s +1 r (orted) s +18 r 98 c +121 c +16 r (the) s +17 r (standard) s +17 r (proto) s +1 r (col.) s +338 1336 p (P3) s +15 r (do) s +1 r (es) s +15 r (not) s +15 r (allo) s +-1 r 119 c +13 r (for) s +15 r (this) s +15 r (form) s +13 r (of) s +15 r (priv) s +-2 r (ate) s +14 r (extension.) s +cmsy10.329 @sf +292 1430 p 15 c +cmr10.329 @sf +23 r (There) s +17 r (is) s +17 r 97 c +17 r (di\016cult) s +121 c +16 r (with) s +16 r (migrati) s +-1 r (on.) s +25 r (Migrati) s +-1 r (on) s +16 r 98 c +1 r (ecomes) s +17 r 109 c +-1 r (uc) s +-1 r 104 c +16 r (easier) s +338 1487 p (when) s +15 r (this) s +14 r 107 c +(ey) s +13 r (in) s +(ternal) s +13 r (proto) s +1 r (col) s +14 r (is) s +14 r 97 c +14 r (sup) s +1 r (erset) s +15 r (of) s +14 r (all) s +14 r (supp) s +1 r (orted) s +15 r (external) s +338 1543 p (proto) s +1 r (cols.) s +cmsy10.329 @sf +292 1637 p 15 c +cmr10.329 @sf +23 r 70 c +-3 r (or) s +9 r (user) s +12 r (agen) s +(ts,) s +10 r (and) s +11 r (some) s +10 r (proto) s +1 r (cols,) s +11 r (it) s +10 r (is) s +11 r (imp) s +1 r (ortan) s +-1 r 116 c +9 r (to) s +10 r 112 c +1 r (erform) s +10 r (address) s +338 1693 p 99 c +(hec) s +(king) s +11 r (prior) s +13 r (to) s +13 r (transferring) s +13 r (the) s +13 r (con) s +(ten) s +116 c +12 r (of) s +13 r (the) s +14 r (message.) s +18 r (P3) s +13 r (do) s +1 r (es) s +14 r (not) s +338 1750 p (supp) s +1 r (ort) s +15 r (this,) s +14 r (whic) s +104 c +14 r (is) s +15 r 97 c +15 r (ma) s +3 r (jor) s +13 r (de\014ciency) s +-3 r 46 c +cmsy10.329 @sf +292 1844 p 15 c +cmr10.329 @sf +23 r (Submit) s +13 r (supp) s +1 r (orts) s +15 r 98 c +1 r (oth) s +15 r (the) s +15 r (Message) s +14 r 84 c +-3 r (ransfer) s +13 r (Abstract) s +14 r (Service) s +15 r (and) s +15 r (the) s +338 1900 p (MT) s +-3 r 65 c +14 r (Abstract) s +14 r (Service,) s +15 r (whereas) s +15 r (P3) s +15 r (only) s +15 r (supp) s +1 r (orts) s +15 r (the) s +15 r (former.) s +295 2006 p (The) s +19 r (\014rst) s +18 r (stage) s +18 r (of) s +19 r (message) s +17 r (submission) s +18 r (is) s +18 r (for) s +18 r (the) s +19 r (submitting) s +17 r (pro) s +1 r (cess) s +19 r (to) s +224 2063 p (either) s +14 r (in) s +118 c +-1 r (ok) s +-1 r 101 c +12 r 97 c +14 r (Submit) s +13 r (pro) s +1 r (cess,) s +14 r (or) s +14 r (to) s +14 r (connect) s +14 r (to) s +14 r (an) s +14 r (already) s +13 r (existing) s +14 r (Submit) s +224 2119 p (daemon.) s +30 r (An) s +19 r (in) s +118 c +-1 r (ok) s +-2 r (ed) s +18 r (Submit) s +17 r (pro) s +1 r (cess) s +19 r (will) s +18 r (then) s +19 r (connect) s +19 r (to) s +18 r (the) s +19 r (QMGR,) s +18 r (to) s +224 2176 p (ensure) s +20 r (that) s +18 r (message) s +17 r (submission) s +18 r (is) s +18 r (not) s +19 r (curren) s +(tly) s +17 r (prohibited.) s +31 r (Then) s +19 r (all) s +18 r (the) s +224 2232 p 112 c +1 r (er-message) s +14 r (parameters) s +14 r (will) s +13 r 98 c +1 r 101 c +16 r (sen) s +116 c +14 r (to) s +15 r (Submit,) s +13 r (whic) s +104 c +14 r (will) s +14 r 112 c +1 r (erform) s +14 r 118 c +-2 r (alidit) s +-1 r 121 c +224 2289 p 99 c +(hec) s +(ks) s +20 r (and) s +22 r (initial) s +20 r (managemen) s +-1 r 116 c +19 r 99 c +(hec) s +(ks.) s +38 r (Submit) s +21 r (then) s +22 r (ac) s +(kno) s +(wl) s +-1 r (edges) s +20 r (these) s +224 2345 p (parameters,) s +13 r (and) s +16 r (address) s +15 r 99 c +(hec) s +(king) s +13 r 98 c +1 r (egins.) s +295 2402 p (PP) s +20 r (curren) s +(tly) s +18 r (recognises) s +20 r 116 c +119 c +-1 r 111 c +18 r (forms) s +18 r (of) s +20 r (address:) s +29 r (RF) s +67 c +19 r (822) s +19 r (address,) s +21 r (and) s +224 2458 p (X.400) s +15 r (O/R) s +16 r (Address.) s +23 r (Both) s +15 r (of) s +16 r (these) s +16 r (are) s +16 r (handled) s +16 r (using) s +16 r 97 c +15 r (text) s +16 r (enco) s +1 r (ding.) s +22 r 70 c +-3 r (or) s +224 2514 p (X.400,) s +16 r (this) s +16 r (uses) s +17 r (the) s +17 r (RF) s +67 c +16 r (987) s +16 r ([9]) s +16 r (domain) s +15 r (orien) s +(ted) s +15 r (enco) s +1 r (ding.) s +26 r 65 c +17 r (submitting) s +224 2571 p (pro) s +1 r (cess) s +13 r (will) s +12 r (select) s +12 r (the) s +13 r (appropriate) s +12 r (form,) s +11 r (and) s +13 r (then) s +13 r (o\013er) s +12 r (eac) s +104 c +12 r (address) s +13 r (in) s +13 r (turn.) s +224 2627 p (There) s +16 r (are) s +14 r 116 c +119 c +-1 r 111 c +13 r (mo) s +1 r (des) s +15 r (of) s +14 r (in) s +(teraction:) s +224 2658 p 598 2 ru +cmr6.300 @sf +276 2686 p 53 c +cmr9.300 @sf +293 2701 p (On) s +13 r (BSD) s +14 r (UNIX,) s +12 r (this) s +13 r (is) s +14 r (So) s +1 r 99 c +107 c +(ets.) s +cmr10.329 @sf +960 2916 p 53 c +@eop +4 @bop0 +cmr8.300 @sf +[<1FE07FF8F07CF83EF81EF81E701E001E003C007807E007F000F80078303C783C7C3C783C78783FF80FE0> 15 21 -1 0 18] 51 @dc +[<03FE03FE0070007000700070FFFEFFFEE0707070307018701C700E700670077003F001F000F000F00070> 15 21 -1 0 18] 52 @dc +cmr10.329 @sf +[ 44 2 0 -11 45] 124 @dc +cmr6.300 @sf +[<3F00FFC0E1C0E0E0E0E000E000E001C00F80038001C021C071C073C07F801F00> 11 16 -1 0 15] 51 @dc +cmr9.300 @sf +[<03FFF00003FFF000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E0000001E + 0000001E0000001E0000001E0000001E0000C01E0180C01E0180C01E0180E01E0380601E0300601E0300781E0F007FFFFF00 + 7FFFFF00> 25 26 -1 0 28] 84 @dc +[<3F1E007FFF00F8F980F07980F03980F03800F838007C38003F380007F80000380030380078780078F8007FF0003FC000> 17 16 -1 0 19] 97 @dc +[<19F8001BFE001F1F001E07801C07801C03C01C03C01C03C01C03C01C03C01C03C01C07801E07801F0F001FFE001CFC001C00 + 001C00001C00001C00001C00001C00001C00001C0000FC0000FC0000> 18 26 -1 0 21] 98 @dc +[ 12 16 -1 0 15] 114 @dc +[ 18 23 -1 7 21] 112 @dc +[<0FCFC01FFFC03C3E00781E00780E00F00E00F00E00F00E00F00E00F00E00F00E00780E00781E003E3E001FFE000FEE00000E + 00000E00000E00000E00000E00000E00000E00000E00007E00007E00> 18 26 -1 0 21] 100 @dc +[ 19 16 0 0 20] 120 @dc +[<7FE07FE00E000E000E000E000E000E000E000E000E000E000E000E00FFC0FFC00E000E000E000E000E000E3C0F3C07BC03FC + 00F8> 14 26 0 0 12] 102 @dc +[<07CFC00FEFC01E3E001C1E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0E00FC7E00FC7E00> 18 16 -1 0 21] 117 @dc +[<07FF07FF00700070007000700070FFFFFFFFE07060703070387018700C700E7006700770037001F001F000F000700070> 16 24 -1 0 19] 52 @dc +[<07E01FF83C3C381C700E700E700EF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F700E700E700E381C3C3C1FF807E0> 16 24 -1 0 19] 48 @dc +[<01C00380070007000E001C001C00380038007000700070006000E000E000E000E000E000E000E000E000E000E000E000E000 + 6000700070007000380038001C001C000E0007000700038001C0> 10 38 -2 10 15] 40 @dc +[<0FC03FF07C787038F01CE01CE01CE03CF03C70FC79F83FF81FF03FC03FF07E707838701860186018703838701FE00FC0> 14 24 -2 0 19] 56 @dc +[ 10 38 -2 10 15] 41 @dc +cmr6.300 @sf +[<1FE01FE0038003800380FFE0FFE0C380638033801B800B800F80078003800180> 11 16 -1 0 15] 52 @dc +cmr9.300 @sf +[ 29 16 -1 0 32] 109 @dc +/cmti9.300 @newfont +cmti9.300 @sf +[<3E3C007FFE00F3F700F0F300E07300F07B00F07800F03800F03800F83C00783C00781C003C3C001E7E000FFE0003EE00000E + 00000F00000F00000700000700000780000780000380001F80001F80> 17 26 -4 0 20] 100 @dc +[<3E003F0073007B80398039803C001C001C001E00CE00CE00EF0067007E003E00000000000000000000000380078007800380> 9 25 -3 0 12] 105 @dc +[<700078007800380038003C003C001C001C001E00DE38CE3CCF3CEF9C7FFC3CF8> 14 16 -3 0 16] 114 @dc +[<1F803FE078F0F038F018F000F000F000FF80FFF0787878383C181E380FF803F0> 13 16 -4 0 18] 101 @dc +[<1F807FE078F0F038E018F000F000F000F000F800780078783C781F780FF803F0> 13 16 -4 0 18] 99 @dc +[<7C00FE00E700E380E180F18070007000700078003800380038003C00FFC0FFC01C001E000E000E000E000E000600> 10 23 -4 0 13] 116 @dc +[<1F807FE079F0F078E03CF03CF03EF01EF01EF81E781E780E3C1E1F3C0FFC03F0> 15 16 -4 0 20] 111 @dc +[<7F0000FF8000F3E000F0F000F070002078000038000FF8001FF8001C7C003C3C00381C003C1C001C1E001C0E001C0E001E0E + 00CE0F00CE0700EF07006707007E07803E0380> 17 23 -3 7 19] 121 @dc +cmr9.300 @sf +[<780000FE0000C70000F3000061800001800001800001C00001C00001C00003E00003E00007F0000730000730000E38000E18 + 000E18001C0C001C0C003C0E00FF3F80FF3F80> 17 23 -1 7 20] 121 @dc +cmti9.300 @sf +[ 26 26 -3 0 29] 68 @dc +cmr9.300 @sf +[<0380E0000380E0000380E00007C1F00007C1F00007C1B0000763B0000E6398000E6318000E3718001C370C001C360C001C3E + 0C003C1E0E00FF3F9F80FF3F9F80> 25 16 -1 0 28] 119 @dc +[<1F803FE070F0E078F03CF03CF03C703C003C003C003C707878F87FF06FC0600060006000600060007FE07FF07FF87038> 14 24 -2 0 19] 53 @dc +4 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +295 195 p (The) s +14 r (recipien) s +116 c +13 r (parameters) s +13 r (whic) s +104 c +13 r 99 c +(hange) s +14 r (whilst) s +13 r (the) s +15 r (message) s +13 r (is) s +14 r 98 c +1 r (eing) s +15 r (pro-) s +224 252 p (cessed) s +14 r (are) s +12 r (enco) s +1 r (ded) s +14 r (in) s +13 r 97 c +12 r (\014xed) s +13 r (format,) s +11 r (to) s +12 r (maxim) s +-1 r (ise) s +10 r (robustness) s +13 r (when) s +13 r 97 c +13 r (con) s +(trol) s +224 308 p (\014le) s +16 r (is) s +15 r (altered.) s +22 r (There) s +16 r (are) s +16 r (also) s +14 r 97 c +16 r (large) s +15 r 110 c +(um) s +-1 r 98 c +1 r (er) s +14 r (of) s +16 r (parameters) s +14 r (whic) s +104 c +14 r (apply) s +16 r (to) s +224 364 p (the) s +16 r (whole) s +16 r (message.) s +21 r (These) s +17 r (include) s +16 r (parameters) s +14 r (to) s +16 r (represen) s +116 c +15 r (all) s +15 r (of) s +15 r (the) s +17 r (X.400) s +224 421 p (Message) s +15 r 84 c +-3 r (ransfer) s +13 r (Service:) s +cmsy10.329 @sf +292 521 p 15 c +cmr10.329 @sf +23 r (The) s +21 r (message) s +19 r (originato) s +-1 r (r,) s +20 r (using) s +20 r (the) s +21 r (same) s +19 r (enco) s +1 r (ding) s +21 r (as) s +20 r 97 c +20 r (recipien) s +(t,) s +20 r (to) s +338 578 p (facilitate) s +13 r (error) s +14 r (returns.) s +cmsy10.329 @sf +292 670 p 15 c +cmr10.329 @sf +23 r (The) s +15 r (Message) s +15 r (ID.) s +cmsy10.329 @sf +292 762 p 15 c +cmr10.329 @sf +23 r 65 c +18 r (list) s +16 r (of) s +18 r (enco) s +1 r (ded) s +19 r (informati) s +-1 r (on) s +16 r 116 c +(yp) s +1 r (es,) s +17 r (whic) s +104 c +17 r (is) s +18 r (not) s +17 r (restricted) s +17 r (to) s +18 r (those) s +338 818 p (de\014ned) s +16 r (in) s +15 r (P2.) s +cmsy10.329 @sf +292 910 p 15 c +cmr10.329 @sf +23 r (Deferred) s +15 r (deliv) s +(ery) s +14 r (date.) s +cmsy10.329 @sf +292 1003 p 15 c +cmr10.329 @sf +23 r 84 c +-3 r (race) s +14 r (informat) s +-1 r (ion) s +295 1103 p (In) s +16 r (addition,) s +13 r (there) s +16 r (are) s +15 r 118 c +-2 r (arious) s +13 r (services) s +15 r (not) s +15 r (supp) s +1 r (orted) s +16 r 98 c +121 c +14 r (X.400:) s +cmsy10.329 @sf +292 1203 p 15 c +cmr10.329 @sf +23 r (Con) s +(trol) s +12 r (of) s +15 r (logging) s +14 r (on) s +15 r 97 c +15 r 112 c +1 r (er) s +15 r (message) s +14 r (basis.) s +cmsy10.329 @sf +292 1295 p 15 c +cmr10.329 @sf +23 r (Pro) s +(visi) s +-1 r (on) s +18 r (of) s +20 r (message) s +18 r (dela) s +121 c +(ed) s +18 r (deliv) s +(ery) s +18 r 119 c +(arnings) s +18 r (at) s +20 r 97 c +20 r (user) s +20 r (con) s +(trol) s +-1 r (led) s +338 1352 p (in) s +(terv) s +-2 r (a) s +-1 r (l.) s +cmsy10.329 @sf +292 1444 p 15 c +cmr10.329 @sf +23 r (Sp) s +1 r (eci\014cation) s +15 r (of) s +15 r (non-deliv) s +(ery) s +14 r (timeout) s +cmr8.300 @sf +1071 1429 p 51 c +cmr10.329 @sf +1089 1444 p 46 c +295 1544 p (The) s +17 r (message) s +15 r (itself) s +16 r (is) s +16 r (stored) s +16 r (within) s +16 r 97 c +16 r (directory) s +cmr8.300 @sf +1224 1529 p 52 c +cmr10.329 @sf +1243 1544 p 44 c +17 r (whic) s +104 c +16 r (con) s +(tai) s +-1 r (ns) s +15 r (sev) s +(eral) s +224 1601 p (things:) s +cmsy10.329 @sf +292 1701 p 15 c +cmr10.329 @sf +23 r 65 c +15 r (directory) s +14 r (called) s +15 r (\\base",) s +15 r (whic) s +104 c +14 r (con) s +(tains) s +13 r (the) s +15 r (message) s +14 r (as) s +15 r (submitted.) s +cmsy10.329 @sf +292 1793 p 15 c +cmr10.329 @sf +23 r (Zero) s +17 r (or) s +17 r (more) s +16 r (additional) s +16 r (directories,) s +17 r (whic) s +104 c +16 r (con) s +(tain) s +16 r (mo) s +1 r (di\014ed) s +17 r (forms) s +16 r (of) s +338 1849 p (the) s +18 r (original) s +15 r (message.) s +26 r (These) s +18 r (directories) s +17 r (are) s +17 r (lab) s +1 r (elled) s +17 r (according) s +17 r (to) s +17 r (the) s +338 1906 p (sequence) s +16 r (of) s +15 r (mo) s +1 r (di\014cations) s +13 r (\(c) s +(hannels\)) s +14 r (whic) s +104 c +14 r (ha) s +118 c +-1 r 101 c +14 r 98 c +1 r (een) s +16 r (applied.) s +cmsy10.329 @sf +292 1998 p 15 c +cmr10.329 @sf +23 r (Zero) s +12 r (or) s +12 r (more) s +11 r (deliv) s +(ery) s +11 r (noti\014cations,) s +12 r (whic) s +104 c +11 r (are) s +13 r (referenced) s +13 r (from) s +11 r (the) s +13 r (con-) s +338 2054 p (trol) s +18 r (\014le.) s +31 r (Sev) s +(eral) s +18 r (recipien) s +(ts) s +18 r (can) s +19 r (share) s +19 r (one) s +19 r (deliv) s +(ery) s +18 r (noti\014cation.) s +30 r (The) s +338 2111 p (adv) s +-2 r (an) s +(ta) s +-1 r (ges) s +15 r (of) s +17 r (storing) s +16 r (the) s +18 r (deliv) s +(ery) s +15 r (noti\014cation) s +16 r (with) s +17 r (the) s +17 r (original) s +15 r (mes-) s +338 2167 p (sage) s +15 r (are) s +14 r (discussed) s +16 r (later.) s +295 2268 p 65 c +17 r (PP) s +18 r (message) s +16 r (con) s +(ten) s +-1 r 116 c +15 r (is) s +17 r (stored) s +17 r (as) s +17 r (directory) s +-3 r 46 c +26 r (The) s +17 r (message) s +16 r (header) s +18 r (\(P2) s +224 2324 p (or) s +15 r (equiv) s +-2 r (alen) s +(t\),) s +13 r (and) s +16 r (eac) s +104 c +14 r 98 c +1 r 111 c +1 r (dy) s +17 r (part) s +15 r (are) s +15 r (stored) s +15 r (as) s +15 r (\014les.) s +21 r 70 c +-3 r (orw) s +-1 r (arded) s +14 r (Messages) s +224 2381 p (are) s +14 r (stored) s +13 r (as) s +13 r (sub) s +1 r (directories) s +14 r 124 c +14 r (the) s +14 r (format) s +11 r (de\014nition) s +14 r (is) s +13 r (recursiv) s +(e.) s +18 r (Eac) s +104 c +13 r (com-) s +224 2437 p 112 c +1 r (onen) s +116 c +18 r (is) s +19 r (lab) s +1 r (elled) s +18 r (according) s +19 r (to) s +18 r (its) s +18 r 116 c +(yp) s +1 r (e.) s +30 r (Bo) s +1 r (dy) s +19 r (parts) s +19 r (also) s +17 r (ha) s +118 c +101 c +17 r 97 c +19 r 110 c +(um) s +-2 r 98 c +1 r (er,) s +224 2493 p (so) s +21 r (that) s +20 r (sequencing) s +21 r (can) s +21 r 98 c +1 r 101 c +21 r (preserv) s +(ed.) s +36 r 70 c +-3 r (or) s +20 r (example:) s +30 r 65 c +20 r (\014le) s +21 r (called) s +21 r (\\3.ia5") s +224 2550 p 119 c +(ould) s +17 r 98 c +1 r 101 c +20 r (the) s +19 r (third) s +18 r 98 c +1 r 111 c +1 r (dy) s +20 r (part) s +18 r (con) s +(taining) s +17 r (IA5) s +19 r (text;) s +20 r 65 c +19 r (\014le) s +19 r (called) s +18 r (\\hdr.P2") s +224 2606 p 119 c +(ould) s +19 r (con) s +(tai) s +-1 r 110 c +19 r 97 c +19 r (heading) s +20 r (enco) s +1 r (ded) s +22 r (according) s +19 r (to) s +19 r (P2.) s +34 r (This) s +20 r (structure) s +19 r (is) s +20 r (not) s +224 2644 p 598 2 ru +cmr6.300 @sf +276 2672 p 51 c +cmr9.300 @sf +293 2687 p (This) s +14 r (can) s +13 r 98 c +1 r 101 c +14 r (represen) s +(ted) s +13 r (in) s +14 r (an) s +13 r (extension) s +15 r (feature) s +13 r (of) s +13 r (X.400\(88\)) s +cmr6.300 @sf +276 2718 p 52 c +cmr9.300 @sf +293 2733 p (The) s +18 r (term) s +cmti9.300 @sf +17 r (dir) s +-1 r 101 c +-2 r (cto) s +-1 r (ry) s +cmr9.300 @sf +16 r (is) s +18 r (tak) s +(en) s +17 r (to) s +17 r (mean) s +18 r 97 c +18 r (UNIX) s +17 r (directory) s +-2 r 44 c +18 r (as) s +18 r (distinct) s +19 r (from) s +18 r (the) s +17 r (term) s +cmti9.300 @sf +224 2778 p (Dir) s +-1 r 101 c +-1 r (c) s +-1 r (tory) s +cmr9.300 @sf +10 r (whic) s +104 c +13 r (refers) s +13 r (to) s +13 r (an) s +13 r (X.500) s +13 r (Directory) s +-2 r 46 c +cmr10.329 @sf +960 2916 p 52 c +@eop +3 @bop0 +cmti10.329 @sf +[<0001F0000001FC000003FC000003FE000003FF000003C70000038300000181800001808000FF008007FF80000FC3E0001EC1 + F8003EE33C003C7F1E007C3E0F0078000F80780007C0F80003C0F80003E0F80001E0F80001F0F80001F07C0000F87C0000F8 + 7C0000F83C0000F83E0000F83E0000781F0000781F0000780F800078078000F803C000F001E000F000F001E0007803E0001F + 07C0000FFF000001FC00> 29 40 -6 9 35] 81 @dc +[ 42 31 -3 0 41] 77 @dc +[<00FF040007FFCC000FC0FE001F003E003E001E003C001F007C001F0078000F0078000F00F8000F80F8000F80F800FFF0F800 + FFF0FC0000007C0000007C0000007C0000007E0000003E0000003E0000601F0000601F0000600F80007007C0007007C00070 + 03F000F001F800F8007C01F8003F87B8000FFF180001FC0C> 30 31 -6 0 35] 71 @dc +[ 29 31 -3 0 33] 82 @dc +cmbx10.432 @sf +[<00FFC00007FFF8001FFFFC003F83FF007F01FF807F80FF80FFC0FFC0FFC07FC0FFC07FE0FFC07FE0FFC07FE07F807FE07F80 + 7FE01E007FE000007FE000007FC00000FFC00000FF800001FF000003FE0000FFF80000FFC00000FFF0000007F8000003FC00 + 0001FE000F81FF001FC0FF003FE0FF803FE0FF803FE0FF803FE0FF803FE0FF803FC0FF801F81FF000FC3FE0007FFFC0003FF + F80000FFC000> 27 39 -3 0 34] 51 @dc +3 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +295 195 p (The) s +11 r (second) s +11 r 107 c +(ey) s +9 r (pro) s +1 r (cess) s +11 r (is) s +10 r (the) s +cmti10.329 @sf +11 r (QMGR) s +cmr10.329 @sf +44 c +10 r (or) s +10 r (queue) s +12 r (manager,) s +9 r (whic) s +104 c +10 r (sc) s +(hedules) s +224 252 p (all) s +11 r (op) s +1 r (erations) s +12 r (within) s +11 r (PP) s +-3 r 46 c +11 r (The) s +12 r (QMGR) s +13 r (holds) s +12 r (the) s +12 r (full) s +12 r (queue) s +13 r (status) s +11 r (in) s +12 r (memory) s +-4 r 44 c +224 308 p (and) s +21 r (con) s +(trols) s +18 r (the) s +21 r (pro) s +1 r (cesses) s +21 r (whic) s +104 c +19 r 112 c +1 r (erform) s +20 r (the) s +20 r 119 c +(ork.) s +34 r (By) s +21 r (cen) s +(tralising) s +18 r (this) s +224 364 p (informati) s +-1 r (on) s +9 r (in) s +11 r 97 c +11 r (single) s +10 r (pro) s +1 r (cess,) s +12 r 97 c +11 r (range) s +10 r (of) s +11 r (useful) s +11 r (sc) s +(heduling) s +10 r (and) s +11 r (managemen) s +-1 r 116 c +224 421 p (options) s +17 r (are) s +17 r (made) s +16 r 97 c +118 c +-2 r (ai) s +-1 r (labl) s +-1 r (e,) s +16 r (and) s +18 r 112 c +1 r (erformance) s +16 r (is) s +17 r (also) s +16 r (impro) s +-1 r 118 c +-1 r (ed.) s +24 r (The) s +18 r (ma) s +3 r (jor) s +224 477 p (comp) s +1 r (onen) s +(ts) s +17 r (con) s +(troll) s +-1 r (ed) s +18 r 98 c +121 c +17 r (the) s +19 r (QMGR) s +19 r (are) s +18 r 99 c +(hannels,) s +19 r (whic) s +104 c +17 r 112 c +1 r (erform) s +18 r (one) s +19 r (of) s +224 534 p 116 c +119 c +-1 r 111 c +13 r (functions:) s +280 640 p (1.) s +22 r (Deliv) s +(ery) s +15 r (of) s +16 r 97 c +17 r (message,) s +15 r (either) s +17 r (lo) s +1 r (cally) s +15 r (or) s +17 r 98 c +121 c +15 r (use) s +18 r (of) s +16 r 97 c +17 r (Message) s +16 r 84 c +-3 r (ransfer) s +338 696 p (Proto) s +1 r (col) s +14 r (\(e.g.) s +19 r (the) s +15 r (X.400) s +14 r (P1\).) s +280 790 p (2.) s +22 r (Manipulation) s +18 r (of) s +20 r (the) s +20 r (message) s +18 r (within) s +19 r (the) s +20 r (queue) s +21 r (\(e.g.) s +33 r (to) s +20 r (carry) s +19 r (out) s +20 r 97 c +338 846 p (format) s +13 r (con) s +118 c +-1 r (ersion\)) s +-1 r 46 c +295 952 p 70 c +-3 r (or) s +10 r 97 c +12 r (giv) s +(en) s +10 r (MT) s +-3 r (A,) s +11 r (there) s +12 r (is) s +11 r 97 c +12 r (single) s +11 r (queue) s +13 r (and) s +12 r 97 c +12 r (single) s +11 r (QMGR.) s +12 r (There) s +12 r (ma) s +121 c +224 1008 p 98 c +1 r 101 c +13 r 109 c +(ul) s +-1 r (tiple) s +10 r (instances) s +12 r (of) s +12 r (the) s +12 r (Submit) s +11 r (pro) s +1 r (cess) s +12 r (acting) s +12 r (at) s +11 r (an) s +121 c +11 r (one) s +12 r (time.) s +17 r (Channel) s +224 1065 p (pro) s +1 r (cesses) s +16 r (and) s +16 r (UA) s +16 r (pro) s +1 r (cesses) s +17 r (are) s +15 r (generic) s +16 r (\(i.e.) s +21 r (there) s +15 r (are) s +16 r (di\013eren) s +116 c +14 r 116 c +(yp) s +1 r (es\),) s +14 r (and) s +224 1121 p (there) s +15 r (ma) s +121 c +13 r 98 c +1 r 101 c +16 r 109 c +-1 r (ultipl) s +-1 r 101 c +14 r (instances) s +15 r (of) s +15 r (an) s +121 c +13 r (sp) s +1 r (eci\014c) s +16 r 99 c +(hannel) s +15 r (or) s +15 r (UA.) s +cmbx10.432 @sf +224 1265 p 51 c +69 r (Queue) s +22 r (Structure) s +cmr10.329 @sf +224 1366 p 70 c +-3 r (or) s +14 r (eac) s +104 c +14 r (message) s +14 r (in) s +15 r (the) s +15 r (queue,) s +16 r (there) s +15 r (are) s +15 r 116 c +119 c +-1 r 111 c +13 r (comp) s +1 r (onen) s +(ts:) s +280 1472 p (1.) s +22 r 65 c +17 r (\014le) s +18 r (con) s +(taining) s +15 r (the) s +18 r (con) s +(trol) s +15 r (informat) s +-1 r (ion) s +15 r (for) s +17 r (pro) s +1 r (cessing) s +18 r (the) s +17 r (message.) s +338 1528 p (This) s +15 r (roughly) s +14 r (corresp) s +1 r (onds) s +16 r (to) s +14 r (the) s +15 r (en) s +118 c +(elop) s +1 r 101 c +14 r (informat) s +-1 r (ion) s +13 r (of) s +15 r (X.400.) s +280 1622 p (2.) s +22 r 65 c +21 r (directory) s +21 r (con) s +(taining) s +19 r (the) s +22 r (message) s +20 r (as) s +21 r (it) s +21 r (arriv) s +(ed) s +20 r (and) s +21 r (zero) s +22 r (or) s +21 r (more) s +338 1678 p (pro) s +1 r (cessed) s +15 r (forms) s +13 r (of) s +14 r (the) s +14 r (message,) s +13 r (together) s +14 r (with) s +13 r (an) s +121 c +13 r (asso) s +1 r (ciated) s +14 r (deliv) s +(ery) s +338 1735 p (noti\014cations.) s +295 1841 p (The) s +13 r (con) s +(trol) s +11 r (\014le) s +13 r (is) s +13 r (text) s +13 r (enco) s +1 r (ded,) s +15 r (as) s +12 r (there) s +14 r (is) s +13 r 97 c +13 r (big) s +12 r (adv) s +-2 r (an) s +(tage) s +11 r (in) s +13 r 98 c +1 r (eing) s +14 r (able) s +224 1897 p (to) s +17 r (view) s +17 r (and) s +17 r (manipulate) s +16 r 97 c +17 r (queued) s +18 r (message) s +16 r 98 c +121 c +17 r (use) s +17 r (of) s +17 r 97 c +17 r (text) s +17 r (editor.) s +26 r (Whilst) s +224 1954 p (this) s +18 r (should) s +18 r (de\014nitely) s +18 r (not) s +17 r 98 c +1 r 101 c +19 r 97 c +18 r (normal) s +16 r (ev) s +(en) s +(t) s +-1 r 44 c +17 r (it) s +17 r (is) s +18 r (hard) s +18 r (to) s +17 r (design) s +18 r (manage-) s +224 2010 p (men) s +116 c +18 r (to) s +1 r (ols) s +18 r (for) s +19 r (ev) s +(ery) s +19 r (ev) s +(en) s +(tuali) s +-1 r 116 c +-1 r 121 c +-4 r 46 c +31 r (The) s +20 r (queue) s +21 r (enco) s +1 r (ding) s +20 r (format) s +18 r (is) s +19 r (designed) s +224 2066 p (to) s +17 r 98 c +1 r 101 c +18 r (generic,) s +18 r (and) s +17 r (not) s +18 r (tied) s +17 r (to) s +17 r 97 c +17 r (sp) s +1 r (eci\014c) s +18 r (proto) s +1 r (col.) s +26 r (This) s +17 r (is) s +17 r (imp) s +1 r (ortan) s +-1 r 116 c +15 r (when) s +224 2123 p (attempting) s +13 r (to) s +14 r (supp) s +1 r (ort) s +15 r 97 c +15 r (range) s +14 r (of) s +15 r (proto) s +1 r (cols.) s +19 r (The) s +15 r 107 c +(ey) s +14 r (elemen) s +116 c +12 r (of) s +15 r (the) s +15 r (con) s +(trol) s +224 2179 p (\014le) s +19 r (is) s +18 r 97 c +18 r (single) s +17 r (line) s +18 r (of) s +18 r (informatio) s +-1 r 110 c +17 r (for) s +18 r (eac) s +104 c +17 r (recipien) s +(t.) s +28 r (The) s +19 r (more) s +17 r (imp) s +1 r (ortan) s +-1 r 116 c +224 2236 p (\(p) s +1 r (er) s +16 r (recipien) s +(t\)) s +13 r (parameters) s +13 r (are:) s +cmsy10.329 @sf +292 2342 p 15 c +cmr10.329 @sf +23 r 65 c +15 r (unique) s +16 r (\(in) s +(teger\)) s +12 r 107 c +(ey) s +-3 r 46 c +cmsy10.329 @sf +292 2435 p 15 c +cmr10.329 @sf +23 r (The) s +15 r (address) s +15 r (of) s +15 r (the) s +16 r (recipien) s +116 c +13 r (in) s +15 r (one) s +16 r (or) s +14 r (more) s +14 r (forms.) s +cmsy10.329 @sf +292 2529 p 15 c +cmr10.329 @sf +23 r (The) s +11 r (sequence) s +13 r (of) s +11 r 99 c +(hannels) s +10 r (whic) s +104 c +10 r (the) s +12 r (message) s +9 r (should) s +12 r 98 c +1 r 101 c +12 r (passed) s +11 r (through.) s +cmsy10.329 @sf +292 2623 p 15 c +cmr10.329 @sf +23 r (The) s +20 r (status) s +20 r (of) s +20 r (pro) s +1 r (cessing) s +20 r (for) s +20 r (the) s +21 r (recipien) s +(t,) s +20 r (whic) s +104 c +19 r 119 c +(ould) s +19 r (include) s +20 r (the) s +338 2679 p (format) s +-1 r (ting) s +18 r 99 c +(hannels) s +20 r (whic) s +104 c +20 r (ha) s +118 c +-1 r 101 c +19 r 98 c +1 r (een) s +22 r (applied,) s +21 r (whether) s +21 r (the) s +21 r (message) s +338 2736 p (has) s +21 r 98 c +1 r (een) s +23 r (deliv) s +(ered) s +21 r (to) s +21 r (that) s +21 r (recipien) s +(t,) s +21 r (and) s +22 r (an) s +121 c +21 r (deliv) s +(ery) s +20 r (noti\014cations) s +338 2792 p (needed.) s +960 2916 p 51 c +@eop +2 @bop0 +cmbx10.432 @sf +[ 39 41 -3 0 47] 80 @dc +/cmr10.300 @newfont +cmr10.300 @sf +[<003FC00001FFF00003F03C0007C00E000F8007001F0003003E0003807C0001807C0001807C000180F8000000F8000000F800 + 0000F8000000F8000000F8000000F8000000F80001807C0001807C0003807C0003803E0003801F0007800F800F8007C01F80 + 03F07B8001FFF380003FC180> 25 28 -2 0 30] 67 @dc +[ 20 29 -1 0 23] 104 @dc +[<1F87807FEFC07C7E60F81E60F00E60F00E60F80E00780E007E0E001F8E0003FE00000E00000E00180E003C1E003C3C003FF8 + 001FE000> 19 18 -1 0 21] 97 @dc +[ 20 18 -1 0 23] 110 @dc +[<07F00FF83F1C3C0E78067800F000F000F000F000FFFEFFFEF01E781E781C3E7C1FF807E0> 15 18 -1 0 18] 101 @dc +[ 9 29 -1 0 12] 108 @dc +[<003F800001FFF00003E0F80007803C000F001E001E000F003E000F803C0007807C0007C07C0007C0F80003E0F80003E0F800 + 03E0F80003E0F80003E0F80003E0F80003E0F80003E0780003C07C0007C03C0007803C0007801E000F000F001E0007803C00 + 03E0F80001FFF000003F8000> 27 28 -2 0 32] 79 @dc +[<07E3F00FFBF01E1F801C0F801C07801C03801C03801C03801C03801C03801C03801C03801C03801C03801C03801C0380FC1F + 80FC1F80> 20 18 -1 0 23] 117 @dc +[<07C00FE01E701C301C301C301C301C301C001C001C001C001C001C001C001C00FFE0FFE03C001C001C000C000C000C000C00 + 0C00> 12 26 -1 0 16] 116 @dc +[<18FE001BFF801F87C01E03C01E01E01C01E01C00F01C00F01C00F01C00F01C00F01C00F01C00F01C01E01E03E01F87C01FFF + 801CFE001C00001C00001C00001C00001C00001C00001C00001C00001C0000FC0000FC0000> 20 29 -1 0 23] 98 @dc +[<03F0000FFC001E1E00380700780780700380F003C0F003C0F003C0F003C0F003C0F003C07003807807803807001E1E000FFC + 0003F000> 18 18 -1 0 21] 111 @dc +[<07E3F01FFBF03E1F807C0F80780780F00380F00380F00380F00380F00380F00380F00380F803807803807C07803E1F801FFF + 8007F380000380000380000380000380000380000380000380000380000380001F80001F80> 20 29 -1 0 23] 100 @dc +[<00000F0000001FC000003FC000003FC000003FE0000078E00000706000007020003FE02001FFF00003F8F80007B0FC000F39 + 9E001E3F8F003C1F07803C0007807C0007C0780003C0F80003E0F80003E0F80003E0F80003E0F80003E0F80003E0F80003E0 + F80003E0780003C07C0007C03C0007803E000F801E000F000F001E0007803C0003E0F80001FFF000003F8000> 27 36 -2 8 32] 81 @dc +[ 33 28 -2 0 38] 77 @dc +[<003FE18001FFFB8003F83F8007C00F800F8007801F0007803E0007807C0007807C0007807C000780F800FFF0F800FFF0F800 + 0000F8000000F8000000F8000000F8000000F80001807C0001807C0003807C0003803E0003801F0007800F800F8007C01F80 + 03F07B8001FFF380003FC180> 28 28 -2 0 33] 71 @dc +[ 28 28 -2 0 31] 82 @dc +[ 18 28 -2 0 23] 83 @dc +[ 33 18 -1 0 36] 109 @dc +[ 9 29 -1 0 12] 105 @dc +[<003F800000FFC00001F0F00003C0700007803800078018000F001C000F000C000F000C000F000C000F000C000F000C000F00 + 0C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C000F000C00 + 0F001E00FFF0FFC0FFF0FFC0> 26 28 -2 0 31] 85 @dc +[ 28 28 -1 0 31] 65 @dc +[ 12 28 -1 0 15] 73 @dc +cmti10.329 @sf +[<3FC000FFF000F8F800787C00703E00001E00001F00001F00000F0007EF000FFF801E3F801C1F803C0F803C07C03C07C03C03 + C03C03C03E03E03E03E01E01E01E01E00F01F00F01F00781F003C1F001E3F800FFF8003E70> 21 29 -2 9 21] 103 @dc +[ 26 31 -3 0 26] 83 @dc +[<1F80003FE00078F000707800F03C00F01E00F01E00F00F00F00F00F80F80780F807807807807807C07807C07803E07803F07 + 003F8F003FFE001EFC001E00001F00001F00000F00000F00000F80000F80000780000780003FC0003FC00007C000> 17 32 -4 0 21] 98 @dc +[<1C03803E003E07C07F001E07C0F3801E03C0F1C01E03C0F8C01F03E078C00F03E078E00F01E07C000F01E03C000F81F03C00 + 0781F03E000780F01E000780F01E00E7C0F81E0063C0F81F0063E07C0F0073F07E0F0033F8F71E003F9FF3FE001F0FC1F800> 35 20 -3 0 37] 109 @dc +2 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +cmbx10.432 @sf +224 195 p 50 c +69 r (Pro) s +2 r (cess) s +23 r (Structure) s +cmr10.329 @sf +224 297 p (The) s +19 r (ideas) s +19 r (for) s +19 r (the) s +19 r (basic) s +19 r (structure) s +19 r (dra) s +119 c +17 r (hea) s +(vily) s +17 r (on) s +19 r (the) s +19 r (MMDF) s +18 r (system) s +18 r ([5].) s +224 353 p (Extensiv) s +101 c +17 r (use) s +19 r (is) s +19 r (made) s +17 r (of) s +19 r (UNIX) s +19 r (pro) s +1 r (cesses) s +19 r (to) s +18 r (pro) s +(vide) s +17 r (mo) s +1 r (dularit) s +-1 r 121 c +-4 r 44 c +17 r (whic) s +104 c +18 r (is) s +224 409 p (fundamen) s +(tal) s +10 r (to) s +12 r (PP) s +-3 r 46 c +11 r (The) s +13 r (aim) s +10 r (has) s +12 r 98 c +1 r (een) s +14 r (to) s +12 r (mak) s +-1 r 101 c +11 r (eac) s +104 c +11 r (pro) s +1 r (cess) s +13 r 112 c +1 r (erform) s +11 r 97 c +12 r (single) s +224 466 p (function.) s +30 r (This) s +19 r (allo) s +-1 r (ws) s +17 r (for) s +18 r (\015exible) s +18 r (construction) s +18 r (of) s +19 r (complex) s +17 r (pro) s +1 r (cessing,) s +19 r (and) s +224 522 p (minim) s +-1 r (ises) s +15 r (side) s +16 r (e\013ects.) s +24 r (The) s +17 r 111 c +118 c +(era) s +-1 r (ll) s +14 r (pro) s +1 r (cess) s +17 r (structure) s +17 r (is) s +16 r (illustrated) s +15 r (in) s +16 r (\014gure) s +224 579 p (1.) s +224 630 p 1495 2 ru +2 setlinewidth +np 1524 1159 275 50 130 arc st +np 1533 1372 304 233 304 arc st +np 1528 916 275 50 130 arc st +np 1153 753 176 93 0 360 ellipse st +np 542 764 176 93 0 360 ellipse st +np 868 1034 176 93 0 360 ellipse st +np 864 1604 176 93 0 360 ellipse st +np 410 1285 176 93 0 360 ellipse st +np 731 945 p 759 959 l st +np 741 934 p 759 959 l +628 846 l st +np 656 860 p 628 846 l st +np 646 872 p 628 846 l st +np 999 930 p 980 955 l st +np 1008 942 p 980 955 l +1115 846 l st +np 1097 871 p 1115 846 l st +np 1087 859 p 1115 846 l st +np 1063 1077 p 1033 1071 l st +np 1057 1091 p 1033 1071 l +1344 1214 l st +np 1314 1208 p 1344 1214 l st +np 1320 1195 p 1344 1214 l st +np 685 1090 p 707 1067 l st +np 677 1077 p 707 1067 l +500 1199 l st +np 521 1177 p 500 1199 l st +np 530 1189 p 500 1199 l st +np 1036 1525 p 1014 1547 l st +np 1044 1538 p 1014 1547 l +1344 1349 l st +np 1322 1371 p 1344 1349 l st +np 1315 1358 p 1344 1349 l st +np 551 1369 p 523 1356 l st +np 542 1381 p 523 1356 l +751 1533 l st +np 723 1520 p 751 1533 l st +np 732 1508 p 751 1533 l st +np 620 1277 p 590 1285 l st +np 620 1292 p 590 1285 l st +[15] 0 setdash +np 590 1285 p 1344 1285 l st +[] 0 setdash +np 1314 1292 p 1344 1285 l st +np 1314 1277 p 1344 1285 l st +np 1708 1124 p 1708 1364 l st +cmr10.300 @sf +789 1653 p (Channel) s +778 1593 p (Outb) s +1 r (ound) s +1412 1271 p (Queue) s +336 1312 p (QMGR) s +785 1064 p (Submit) s +1082 779 p (UA) s +459 824 p (Channel) s +444 764 p (In) s +98 c +1 r (ound) s +np 1348 1128 p 1348 1367 l st +cmr10.329 @sf +658 1802 p (Figure) s +14 r (1:) s +20 r (PP) s +15 r (Pro) s +1 r (cess) s +15 r (Structure) s +224 1821 p 1495 2 ru +295 1927 p (PP) s +15 r (has) s +15 r 97 c +cmti10.329 @sf +15 r (single) s +cmr10.329 @sf +13 r (queue.) s +21 r (This) s +15 r (is) s +15 r (imp) s +1 r (ortan) s +-2 r 116 c +13 r (for) s +15 r (the) s +15 r (follo) s +(w) s +-1 r (ing) s +13 r (reasons:) s +280 2033 p (1.) s +22 r (It) s +15 r (increases) s +15 r (robustness.) s +280 2127 p (2.) s +22 r (It) s +15 r (facilitates) s +13 r (uniform) s +14 r (handling) s +15 r (of) s +14 r (errors.) s +280 2221 p (3.) s +22 r (It) s +15 r (simpli\014es) s +13 r (managemen) s +-1 r (t.) s +295 2327 p (There) s +18 r (are) s +17 r 116 c +119 c +-1 r 111 c +16 r (critical) s +16 r (pro) s +1 r (cesses) s +18 r (with) s +17 r (complex) s +17 r (functionalit) s +-1 r 121 c +-4 r 46 c +26 r (All) s +17 r (of) s +17 r (the) s +224 2383 p (others) s +18 r (are) s +19 r (\\dum) s +(b".) s +28 r (The) s +19 r (\014rst) s +19 r 107 c +(ey) s +17 r (pro) s +1 r (cess) s +19 r (in) s +19 r (PP) s +19 r (is) s +cmti10.329 @sf +18 r (Submit) s +cmr10.329 @sf +46 c +31 r (Submit) s +17 r (tak) s +(es) s +224 2440 p (an) s +18 r (incoming) s +16 r (message,) s +17 r (and) s +18 r (places) s +17 r (it) s +17 r (in) s +18 r (the) s +18 r (queue.) s +29 r (Submit) s +16 r (will) s +17 r 112 c +1 r (erform) s +17 r (all) s +224 2496 p (calculations) s +16 r (of) s +17 r (the) s +17 r (pro) s +1 r (cessing) s +17 r (required) s +17 r (for) s +17 r 97 c +17 r (giv) s +(en) s +15 r (message,) s +16 r (and) s +17 r (determine) s +224 2553 p (ho) s +119 c +14 r (it) s +15 r (will) s +14 r 98 c +1 r 101 c +16 r (deliv) s +(ered.) s +20 r (Early) s +15 r 99 c +(hec) s +(king) s +13 r (ensures) s +16 r (that) s +15 r (errors) s +15 r (are) s +15 r (detected) s +16 r (at) s +224 2609 p (the) s +18 r (earliest) s +17 r 112 c +1 r (oin) s +(t,) s +17 r (and) s +18 r (that) s +17 r (later) s +17 r (pro) s +1 r (cesses) s +19 r (can) s +18 r 98 c +1 r 101 c +19 r (implem) s +-1 r (en) s +-1 r (ted) s +16 r (in) s +18 r 97 c +18 r (more) s +224 2666 p (straigh) s +(t) s +-1 r (forw) s +-2 r (ard) s +15 r (fashion.) s +24 r (The) s +17 r (initial) s +15 r 99 c +(hec) s +(king) s +14 r (includes) s +18 r (all) s +15 r (managemen) s +-1 r 116 c +14 r (and) s +224 2722 p (address) s +19 r 118 c +(eri\014catio) s +-1 r (n.) s +28 r (Messages) s +18 r (ma) s +121 c +16 r 98 c +1 r 101 c +19 r (passed) s +19 r (to) s +18 r (Submit) s +18 r (either) s +18 r 98 c +121 c +17 r 97 c +18 r (User) s +224 2779 p (Agen) s +(t,) s +14 r (or) s +14 r 98 c +121 c +14 r 97 c +15 r (proto) s +1 r (col) s +14 r (serv) s +(er) s +14 r 124 c +16 r (kno) s +(wn) s +14 r (as) s +15 r (an) s +15 r (in) s +98 c +1 r (ound) s +15 r 99 c +(hannel.) s +960 2916 p 50 c +@eop +1 @bop0 +cmr8.300 @sf +[<7FF07FF0070007000700070007000700070007000700070007000700070007000700F700FF000F000300> 12 21 -2 0 18] 49 @dc +/cmss10.329 @newfont +cmss10.329 @sf +[<00FE0007FF800FFFC01F83E03E00F07C00F87C007878003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF800 + 3CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003CF8003C> 22 32 -4 0 31] 85 @dc +[ 23 32 -4 0 32] 78 @dc +[ 5 32 -4 0 13] 73 @dc +[ 27 32 -1 0 30] 88 @dc +cmr8.300 @sf +[ 13 21 -2 0 18] 50 @dc +cmr6.300 @sf +[ 9 16 -2 0 15] 49 @dc +cmr9.300 @sf +[<0FF03FFC7C3EF00FE007E007E00F701F3FFE3FFC3FF8300030003FC03FE03CF0787878787878787878783CF71FFF0FCF> 16 24 -1 8 19] 103 @dc +[ 9 26 0 0 10] 108 @dc +[<01C00001C00001C00003E00003E00007F0000730000730000E38000E18000E18001C0C001C0C003C0E00FF3F80FF3F80> 17 16 -1 0 20] 118 @dc +[ 22 26 -1 0 26] 80 @dc +[<70F8F8F87000000000707070707070707070F8F8F8F8F8F8F870> 5 26 -3 0 11] 33 @dc +cmr6.300 @sf +[ 11 16 -1 0 15] 50 @dc +/cmss9.300 @newfont +cmss9.300 @sf +[<03F8000FFE001FFF003E0F807C07C07803C0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001 + E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0F001E0> 19 26 -3 0 26] 85 @dc +[ 20 26 -3 0 27] 78 @dc +[ 4 26 -3 0 11] 73 @dc +[ 23 26 -1 0 26] 88 @dc +cmr9.300 @sf +[ 26 26 -1 0 29] 65 @dc +[<0FC0FC003FF3FF007C7FC300F81F0180F83F0180F07F0000F07B8000F0F1C000F1E0C00079E0E0003FC070001F8030000F80 + 380007803C0007C0FF800FE0FF800EF000000E7000000E3800000E1800000E1800000E1800000E1800000738000003F00000 + 01E00000> 25 26 -2 0 30] 38 @dc +[ 20 26 -1 0 24] 76 @dc +1 @bop1 +cmr10.329 @sf +1213 50 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +cmbx10.432 @sf +224 195 p 49 c +69 r (In) s +-1 r (tro) s +2 r (duction) s +cmr10.329 @sf +224 297 p (This) s +20 r (pap) s +1 r (er) s +21 r (describ) s +1 r (es) s +21 r (the) s +21 r (design) s +21 r (and) s +20 r (implemen) s +-1 r (ta) s +-1 r (tio) s +-1 r 110 c +19 r (of) s +20 r (PP) s +cmr8.300 @sf +1457 282 p 49 c +cmr10.329 @sf +1476 297 p 44 c +20 r (whic) s +104 c +20 r (is) s +20 r 97 c +224 353 p (Message) s +18 r 84 c +-3 r (ransfer) s +17 r (Agen) s +116 c +17 r (orien) s +(ted) s +17 r (to) s +119 c +-1 r (ards) s +16 r (supp) s +1 r (ort) s +19 r (of) s +18 r (the) s +19 r (X.400) s +17 r (series) s +18 r (rec-) s +224 409 p (ommendati) s +-1 r (ons) s +10 r ([2],) s +11 r ([3].) s +18 r (PP) s +12 r (is) s +11 r (implemen) s +-1 r (ted) s +10 r (to) s +11 r (run) s +13 r (under) s +12 r (the) s +cmss10.329 @sf +12 r (UNIX) s +cmr8.300 @sf +1498 394 p 50 c +cmr10.329 @sf +1530 409 p (op) s +1 r (erating) s +224 466 p (system.) s +22 r (Although) s +16 r (the) s +17 r (implem) s +-1 r (en) s +-1 r (tati) s +-1 r (on) s +15 r (of) s +16 r (an) s +16 r (X.400) s +15 r (MT) s +-3 r 65 c +15 r (is) s +16 r (no) s +119 c +15 r 97 c +16 r (far) s +16 r (from) s +224 522 p (un) s +(usual) s +14 r (ev) s +(en) s +(t,) s +13 r 97 c +15 r (pap) s +1 r (er) s +15 r (is) s +15 r (justi\014ed) s +15 r 98 c +1 r (ecause) s +17 r (of) s +14 r (the) s +16 r (far) s +14 r (reac) s +(hing) s +14 r (goals) s +14 r (for) s +14 r (PP) s +-3 r 46 c +295 579 p (There) s +11 r (has) s +11 r 98 c +1 r (een) s +12 r (extensiv) s +101 c +10 r (exp) s +1 r (erience) s +12 r (with) s +11 r 97 c +11 r 110 c +(um) s +-2 r 98 c +1 r (er) s +10 r (of) s +11 r (sophisticated) s +10 r (text-) s +224 635 p (based) s +17 r (Message) s +15 r 84 c +-3 r (ransfer) s +15 r (Systems,) s +15 r (usually) s +16 r (based) s +17 r (on) s +16 r (the) s +17 r (RF) s +67 c +14 r (822) s +16 r (standards) s +224 692 p ([4],) s +15 r ([5],) s +16 r ([6],) s +15 r ([7].) s +22 r (Man) s +121 c +15 r (emerging) s +15 r (X.400) s +15 r (systems,) s +15 r (whilst) s +15 r (o\013ering) s +15 r (the) s +17 r (sup) s +1 r (erior) s +224 748 p (X.400) s +14 r (proto) s +1 r (cols,) s +14 r (in) s +15 r (man) s +-1 r 121 c +14 r (resp) s +1 r (ects) s +15 r (o\013er) s +14 r 97 c +15 r 112 c +1 r 111 c +1 r (orer) s +15 r (service) s +16 r (than) s +15 r (the) s +15 r (older) s +15 r (sys-) s +224 805 p (tems.) s +23 r (PP) s +16 r 119 c +(as) s +14 r (ev) s +(olv) s +-1 r (ed) s +15 r (when) s +17 r 97 c +16 r (group) s +17 r (of) s +16 r (us) s +16 r (aimed) s +15 r (to) s +16 r (dra) s +119 c +15 r (on) s +16 r (the) s +17 r (results) s +16 r (of) s +224 861 p (earlier) s +15 r 119 c +(ork) s +13 r (and) s +16 r (create) s +15 r 97 c +15 r (Message) s +15 r 84 c +-3 r (ransfer) s +14 r (System) s +14 r (with) s +15 r (high) s +15 r (functionalit) s +121 c +-4 r 46 c +224 918 p (The) s +16 r (ma) s +3 r (jo) s +-1 r 114 c +13 r (goals) s +14 r (of) s +15 r (PP) s +15 r (are:) s +cmsy10.329 @sf +292 1024 p 15 c +cmr10.329 @sf +23 r (Pro) s +(visi) s +-1 r (on) s +14 r (of) s +15 r 97 c +16 r (clean) s +16 r (in) s +(terface) s +14 r (for) s +15 r (message) s +14 r (submission) s +15 r (and) s +16 r (deliv) s +(ery) s +-4 r 44 c +14 r (so) s +338 1080 p (that) s +14 r 97 c +15 r (wide) s +15 r (range) s +15 r (of) s +15 r (User) s +15 r (Agen) s +(ts) s +14 r (ma) s +-1 r 121 c +13 r 98 c +1 r 101 c +16 r (supp) s +1 r (orted.) s +cmsy10.329 @sf +292 1174 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +15 r (for) s +15 r (all) s +14 r (of) s +15 r (the) s +16 r (Message) s +14 r 84 c +-3 r (ransfer) s +14 r (Service) s +15 r (Elemen) s +(ts) s +13 r (sp) s +1 r (eci\014ed) s +17 r 98 c +121 c +338 1231 p (the) s +15 r (1984) s +14 r (and) s +16 r (1988) s +14 r 118 c +(ersions) s +13 r (of) s +15 r (X.400.) s +cmsy10.329 @sf +292 1324 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +15 r (for) s +15 r (some) s +14 r (services) s +15 r (not) s +15 r (pro) s +(vided) s +14 r 98 c +121 c +14 r (X.400.) s +cmsy10.329 @sf +292 1418 p 15 c +cmr10.329 @sf +23 r (Sp) s +1 r (eci\014c) s +16 r (supp) s +1 r (ort) s +15 r (to) s +15 r (facilitate) s +13 r (the) s +15 r (handling) s +15 r (of) s +15 r 109 c +(ult) s +-1 r (im) s +-1 r (edia) s +13 r (messages.) s +cmsy10.329 @sf +292 1512 p 15 c +cmr10.329 @sf +23 r (Robustness) s +16 r (and) s +15 r (e\016ciency) s +16 r (required) s +15 r (to) s +14 r (supp) s +1 r (ort) s +16 r (high) s +15 r (lev) s +(els) s +13 r (of) s +15 r (tra\016c.) s +cmsy10.329 @sf +292 1606 p 15 c +cmr10.329 @sf +23 r (Sc) s +(heduling) s +13 r (of) s +14 r (message) s +13 r (deliv) s +(ery) s +13 r (in) s +14 r 97 c +14 r (sophisticated) s +13 r (manner,) s +13 r (to) s +14 r (optimi) s +-1 r (se) s +338 1662 p (lo) s +1 r (cal) s +14 r (and) s +15 r (comm) s +-1 r (unicati) s +-1 r (on) s +13 r (resources.) s +cmsy10.329 @sf +292 1756 p 15 c +cmr10.329 @sf +23 r (Pro) s +(visi) s +-1 r (on) s +20 r (of) s +21 r 97 c +21 r (range) s +21 r (of) s +21 r (managemen) s +-1 r (t) s +-1 r 44 c +21 r (authorisation) s +20 r (and) s +21 r (monitoring) s +338 1813 p (facilities.) s +cmsy10.329 @sf +292 1906 p 15 c +cmr10.329 @sf +23 r (Reformatti) s +-1 r (ng) s +14 r 98 c +1 r (et) s +119 c +-1 r (een) s +14 r 98 c +1 r 111 c +1 r (dy) s +16 r (part) s +15 r 116 c +(yp) s +1 r (es) s +14 r (in) s +15 r 97 c +15 r (general) s +14 r (manner.) s +cmsy10.329 @sf +292 2000 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +15 r (for) s +15 r 109 c +(ul) s +-1 r (tiple) s +13 r (address) s +15 r (formats) s +13 r (\(initiall) s +-1 r 121 c +14 r 116 c +119 c +-1 r (o) s +-1 r (\).) s +cmsy10.329 @sf +292 2094 p 15 c +cmr10.329 @sf +23 r (Use) s +15 r (of) s +15 r (standardised) s +15 r (OSI) s +16 r (Directory) s +14 r (Services) s +15 r ([8].) s +cmsy10.329 @sf +292 2188 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +15 r (for) s +15 r (message) s +14 r (proto) s +1 r (col) s +14 r (con) s +118 c +(ers) s +-1 r (ion) s +13 r (in) s +15 r (an) s +15 r (in) s +(tegrated) s +13 r (fashion.) s +cmsy10.329 @sf +292 2282 p 15 c +cmr10.329 @sf +23 r 70 c +-3 r (ull) s +11 r (access) s +13 r (to) s +12 r (the) s +13 r (Message) s +12 r 84 c +-3 r (ransfer) s +11 r (Service) s +13 r (for) s +12 r (applications) s +11 r (other) s +13 r (than) s +338 2338 p (In) s +(ter-P) s +(erso) s +-1 r (nal) s +13 r (Messaging.) s +295 2444 p (The) s +16 r (rest) s +16 r (of) s +15 r (this) s +16 r (pap) s +1 r (er) s +16 r (then) s +17 r (discusses) s +16 r (the) s +16 r (features) s +16 r (of) s +15 r (PP) s +16 r (in) s +16 r (more) s +15 r (detail,) s +224 2501 p (and) s +16 r (explains) s +14 r (ho) s +119 c +14 r (they) s +15 r (are) s +15 r (used) s +16 r (to) s +14 r (ac) s +(hiev) s +101 c +13 r (the) s +16 r (listed) s +14 r (goals.) s +224 2540 p 598 2 ru +cmr6.300 @sf +276 2568 p 49 c +cmr9.300 @sf +293 2583 p (In) s +13 r (this) s +14 r (age) s +13 r (of) s +13 r (acron) s +(yms) s +13 r (it) s +13 r (will) s +15 r 98 c +1 r 101 c +13 r 97 c +13 r (surprise) s +15 r (to) s +13 r (disco) s +118 c +(er) s +12 r (that) s +13 r (PP) s +13 r (is) s +14 r (not) s +13 r (an) s +14 r (acron) s +(ym!) s +cmr6.300 @sf +276 2614 p 50 c +cmss9.300 @sf +293 2629 p (UNIX) s +cmr9.300 @sf +13 r (is) s +14 r 97 c +13 r (trademark) s +13 r (of) s +13 r 65 c +-2 r (T&T) s +11 r (Bell) s +14 r (Lab) s +1 r (oratories.) s +cmr10.329 @sf +960 2916 p 49 c +@eop +0 @bop0 +/cmr10.432 @newfont +cmr10.432 @sf +[ 35 41 -2 0 41] 80 @dc +[ 59 2 0 -15 60] 124 @dc +[ 40 42 -2 0 45] 65 @dc +[ 50 41 -2 0 55] 77 @dc +[<007F0003FFE007F0F00FC0381F00183F001C7E000C7E00007C0000FC0000FC0000FC0000FC0000FC0000FFFFFCFFFFFCFC00 + 7C7C007C7C007C7E00F83E00F81F01F81F81F007C7E003FFC000FF00> 22 26 -2 0 27] 101 @dc +[ 19 26 -2 0 24] 115 @dc +[<07F81F001FFE7F803F8F7FC07E03F860FE01F860FC01F860FC00F860FC00F860FC00F860FE00F8007F00F8003F80F8001FE0 + F8000FFCF80001FFF800001FF8000000F8000000F8000000F8001E00F8003F01F8003F01F0003F03F0003F07E0001FFF8000 + 07FE0000> 27 26 -2 0 30] 97 @dc +[<00FF800007FFF0001FC1FC003E003E007C001F00F8000F80F0000780F0000780F0000780F0000780F8000F8078001F803E00 + 7F001FFFFF000FFFFE001FFFF8001FFFE0003E00000038000000380000003800000039FE00001FFF80001F87C0001F03E000 + 3F03F0003E01F0007E01F8007E01F8007E01F8007E01F8007E01F8007E01F8003E01F0003F03F1801F03E3C00F87F3C007FF + FBC001FE3FC000000F80> 26 40 -2 13 30] 103 @dc +[<01FFFFFE0001FFFFFE000001FE00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC0000 + 0000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC0000 + 0000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC0000C000FC000CC000FC000CC000FC000C + C000FC000CC000FC000CE000FC001CE000FC001C6000FC00186000FC00187000FC00387800FC00787E00FC01F87FFFFFFFF8 + 7FFFFFFFF8> 38 41 -2 0 43] 84 @dc +[ 20 26 -1 0 23] 114 @dc +[ 30 26 -1 0 33] 110 @dc +[ 20 42 -1 0 18] 102 @dc +[<007E0001FF0003F38003E18007C1C007C0C007C0C007C0C007C0C007C0C007C0C007C00007C00007C00007C00007C00007C0 + 0007C00007C00007C00007C00007C00007C00007C000FFFF80FFFF801FC0000FC00007C00003C00001C00001C00001C00000 + C00000C00000C00000C000> 18 37 -1 0 23] 116 @dc +/cmr10.360 @newfont +cmr10.360 @sf +[ 21 34 -3 0 28] 83 @dc +[<78FCFCFCFC78> 6 6 -4 0 14] 46 @dc +[ 30 34 -2 0 34] 69 @dc +[ 34 34 -2 0 39] 75 @dc +[ 11 34 0 0 13] 105 @dc +[ 12 35 0 0 13] 108 @dc +[<01FC0007FF000FC3C03F01C03E00E07C00607C0000F80000F80000F80000F80000F80000FFFFE0FFFFE07801E07C03E03C03 + C03E07C01F0F8007FF0001FC00> 19 21 -1 0 22] 101 @dc +/cmbx10.329 @newfont +cmbx10.329 @sf +[ 35 31 -2 0 40] 65 @dc +[<1C1FE0001E7FF8001FF0FC001FC07E001F803F001F801F001F801F801F801F801F801F801F801F801F801F801F801F801F80 + 1F801F801F801F801F001F803F001FC03E001FF0FC001FFFF8001F9FE0001F8000001F8000001F8000001F8000001F800000 + 1F8000001F8000001F8000001F800000FF800000FF800000FF800000> 25 32 -1 0 29] 98 @dc +[ 16 20 -2 0 21] 115 @dc +[<03F00FFC0FDC1F8E1F8E1F8E1F8E1F8E1F801F801F801F801F801F801F801F801F80FFFCFFFC3FFC1F800F80078007800780 + 0380038003800380> 15 29 -1 0 20] 116 @dc +[ 19 20 -1 0 22] 114 @dc +[<0FF0FE3FFDFE7E1FFEFC07F0F803F0F803F0F803F0FC03F07E03F03FC3F00FFFF001FFF00003F01E03F03F03F03F03F03F07 + E03F0FE01FFF8007FE00> 23 20 -1 0 25] 97 @dc +[<03FE000FFF801FC3C03F01E07E00E07E0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC07807C0FC07E0FC03F0F + C01F8FC00FFF8003FE00> 19 20 -2 0 23] 99 @dc +cmr10.360 @sf +[ 32 34 -2 0 38] 68 @dc +[ 24 31 -1 10 28] 112 @dc +[<0FC1E03FF3F87E3FDCFC1F8CF80F8CF8078CF8078CF807807C07807E07803F87800FFF8003FF80000F800007803807807C0F + 807C0F007C3F007FFE001FF000> 22 21 -2 0 25] 97 @dc +[ 17 21 -1 0 20] 114 @dc +[<01F007F807980F1C0F0C0F0C0F0C0F0C0F0C0F000F000F000F000F000F000F000F000F000F00FFF8FFF83F001F000F000700 + 070007000300030003000300> 14 31 -1 0 19] 116 @dc +[ 40 21 -1 0 43] 109 @dc +[ 25 21 -1 0 28] 110 @dc +[<00FC0007FF800F03C01E01E03C00F07C00F8780078F8007CF8007CF8007CF8007CF8007CF8007CF8007C7800787800783C00 + F01E01E00F03C007FF8000FC00> 22 21 -1 0 25] 111 @dc +[<7FFC007FFC000780000780000780000780000780000780000780000780000780000780000780000780000780000780000780 + 00078000078000FFF800FFF800078000078000078000078000078000078000078000078000078F8003CF8003EF8001FF8000 + FF00003F00> 17 35 0 0 15] 102 @dc +[<000FF800007FFE0000FE0F0003F003C007E001C00FC000E01F8000701F0000303F0000303E0000387E0000187E000018FC00 + 0018FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000018FC0000187E0000187E0000383E000038 + 3F0000381F0000781F8000780FC000F807E001F803F003F800FE0F38007FFE38000FF018> 29 34 -3 0 36] 67 @dc +[<01FC7F8007FF7F800783FC000F01F8000F00F8000F00F8000F0078000F0078000F0078000F0078000F0078000F0078000F00 + 78000F0078000F0078000F0078000F0078001F00F800FF07F800FF07F8000F007800> 25 21 -1 0 28] 117 @dc +[<03FC000FFF001F87803F01803E01C07C00C07C0000F80000F80000F80000F80000F80000F80000F800007800007C07003C0F + 803E0F801F0F800FFF8003FE00> 18 21 -2 0 22] 99 @dc +[<0007F000001FFC00007E1E0000F8070001F0038003E001C003E000C003C000E007C0006007C0006007C0006007C0006007C0 + 006007C0006007C0006007C0006007C0006007C0006007C0006007C0006007C0006007C0006007C0006007C0006007C00060 + 07C0006007C0006007C0006007C0006007C0006007C0006007C001F8FFFE0FFFFFFE0FFF> 32 34 -2 0 37] 85 @dc +[<003800003800007C00007C00007C0000FE0000F60000F60001E30001E30001E30003C18003C18007C1C00780C00780C00F00 + E00F00E01F00F8FFE3FEFFE3FE> 23 21 -1 0 26] 118 @dc +[ 15 21 -2 0 20] 115 @dc +[<3E00007F0000FB8000F8C000F8C000F86000006000007000003000003000003800003800007C00007C00007C0000FE0000F6 + 0000F60001E30001E30001E30003C18003C18007C1C00780C00780C00F00E00F00E01F00F8FFE3FEFFE3FE> 23 31 -1 10 26] 121 @dc +[<03FF000FFFC03F03F07C00F8700038F0003CE0001CE0001CE0003CF0003C7801F83FFFF81FFFF03FFFE03FFF803C00003800 + 003000003BF8003FFE001F1F003E0F807C07C07C07C07C07C07C07C07C07C07C07C03E0F9C1F1FBC0FFFFC03F8F8> 22 32 -1 11 25] 103 @dc +[ 26 34 -2 0 31] 76 @dc +[<03F8FF0FFEFF1F0FF83E03F07C01F07C00F07800F0F800F0F800F0F800F0F800F0F800F0F800F0F800F07800F07C00F07C00 + F03E01F01F87F00FFFF003F8F00000F00000F00000F00000F00000F00000F00000F00000F00000F00000F00001F0000FF000 + 0FF00000F0> 24 35 -2 0 28] 100 @dc +0 @bop1 +cmr10.329 @sf +224 252 p (Researc) s +104 c +15 r (Note) s +15 r (RN/88/31) s +811 r (Researc) s +104 c +224 308 p (August) s +15 r (1988) s +1150 r (Note) s +cmr10.432 @sf +535 1269 p (PP) s +19 r 124 c +20 r 65 c +20 r (Message) s +17 r 84 c +-4 r (ransfer) s +20 r (Agen) s +-1 r 116 c +cmr10.360 @sf +867 1463 p (S.E.) s +16 r (Kille) s +cmbx10.329 @sf +871 1628 p (Abstract) s +cmr10.329 @sf +295 1711 p (This) s +11 r (pap) s +1 r (er) s +12 r (is) s +11 r (to) s +11 r 98 c +1 r 101 c +12 r (presen) s +(ted) s +11 r (at) s +11 r (the) s +12 r (IFIP) s +12 r 87 c +71 c +10 r (6.5) s +10 r (Conference) s +13 r (on) s +11 r (Message) s +224 1768 p (Handling) s +15 r (Systems) s +14 r (and) s +15 r (Distributed) s +14 r (Applications) s +15 r 124 c +15 r (Octob) s +1 r (er) s +16 r (1988.) s +295 1824 p (This) s +15 r (pap) s +1 r (er) s +16 r (describ) s +1 r (es) s +17 r (the) s +16 r (design) s +16 r (and) s +16 r (implem) s +-1 r (en) s +-1 r (tat) s +-1 r (ion) s +14 r (of) s +15 r (PP) s +-3 r 44 c +15 r (whic) s +104 c +14 r (is) s +16 r (an) s +224 1880 p (adv) s +-2 r (anced) s +16 r (system) s +15 r (for) s +15 r (pro) s +(vision) s +14 r (of) s +16 r (Message) s +15 r 84 c +-3 r (ransfer) s +15 r (Services.) s +22 r (The) s +17 r (follo) s +-1 r (wing) s +224 1937 p (features) s +15 r (are) s +15 r (of) s +15 r (particular) s +13 r (note:) s +cmsy10.329 @sf +292 2020 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +17 r (for) s +17 r 97 c +16 r (wide) s +17 r (range) s +17 r (of) s +16 r (enco) s +1 r (ded) s +19 r (informa) s +-1 r (tio) s +-1 r 110 c +16 r 116 c +(yp) s +1 r (es,) s +16 r (and) s +17 r (for) s +16 r (con-) s +338 2076 p 118 c +(ersion) s +13 r 98 c +1 r (et) s +119 c +(een) s +14 r (them.) s +cmsy10.329 @sf +292 2163 p 15 c +cmr10.329 @sf +23 r (Supp) s +1 r (ort) s +17 r (for) s +16 r (di\013eren) s +116 c +15 r (Message) s +16 r 84 c +-3 r (ransfer) s +15 r (Proto) s +1 r (cols,) s +15 r (and) s +17 r (con) s +118 c +(ers) s +-1 r (ion) s +15 r 98 c +1 r (e-) s +338 2220 p 116 c +119 c +-1 r (een) s +14 r (them.) s +cmsy10.329 @sf +292 2307 p 15 c +cmr10.329 @sf +23 r (Robustness) s +16 r (and) s +15 r (e\016ciency) s +16 r (for) s +14 r (use) s +16 r (in) s +15 r (large) s +14 r (scale) s +15 r (service) s +15 r (en) s +(vironm) s +-1 r (en) s +(t) s +-1 r (s.) s +295 2389 p (This) s +14 r (pap) s +1 r (er) s +15 r (describ) s +1 r (es) s +16 r (the) s +15 r (approac) s +(hes) s +13 r (used) s +16 r (to) s +14 r (ac) s +(hiev) s +-1 r 101 c +13 r (these) s +15 r (features,) s +14 r (and) s +224 2446 p (considers) s +13 r (ho) s +119 c +12 r (they) s +14 r (could) s +13 r 98 c +1 r 101 c +15 r (used) s +14 r (as) s +13 r 97 c +13 r (basis) s +13 r (for) s +13 r (future) s +13 r (services) s +13 r (and) s +14 r (researc) s +(h.) s +224 2502 p (PP) s +14 r (will) s +12 r 98 c +1 r 101 c +14 r (released) s +14 r (in) s +(to) s +11 r (the) s +14 r (public) s +14 r (domain,) s +12 r (as) s +13 r 97 c +13 r (part) s +13 r (of) s +13 r (the) s +14 r (ISODE) s +14 r 80 c +(ac) s +-1 r 107 c +-2 r (ag) s +-1 r 101 c +224 2559 p ([1].) s +cmr10.360 @sf +608 2700 p (Departmen) s +-2 r 116 c +15 r (of) s +17 r (Computer) s +14 r (Science) s +682 2756 p (Univ) s +(ersit) s +121 c +16 r (College) s +18 r (London) s +@eop +@end diff --git a/doc/ifip6.5-88/slides/Makefile b/doc/ifip6.5-88/slides/Makefile new file mode 100644 index 0000000..bae6f67 --- /dev/null +++ b/doc/ifip6.5-88/slides/Makefile @@ -0,0 +1,35 @@ +########################################################################## +# Instructions to Make, for generation of nice-looking slides using SLiTeX +########################################################################## + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps . +fig + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.fig.pic:; sh -c 'if f2p < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + + +.pic.tex:; tpic $< + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.ps:; sh -c 'if dvi2ps $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + + +all: ifip88-pp.dvi + +ifip88-pp.dvi: ifip88-pp.tex structure.pic structure.tex dir.pic dir.tex + +print: ifip88-pp.dvi + dvi2ps ifip88-pp.dvi | lpr -Ppsc + +clean:; rm -f ifip88-pp.dvi + + diff --git a/doc/ifip6.5-88/slides/dir.fig b/doc/ifip6.5-88/slides/dir.fig new file mode 100644 index 0000000..6a775fb --- /dev/null +++ b/doc/ifip6.5-88/slides/dir.fig @@ -0,0 +1,57 @@ +#FIG 1.4 +80 2 +2 1 0 1 0 0 0 0 0.000 0 0 + 340 462 540 381 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 497 379 577 379 577 359 497 359 497 379 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 394 379 474 379 474 359 394 359 394 379 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 239 379 339 464 434 379 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 299 484 379 484 379 464 299 464 299 484 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 449 159 499 259 554 159 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 434 359 499 279 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 399 279 434 359 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 239 159 299 259 359 159 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 239 359 299 279 9999 9999 +2 1 0 1 0 0 0 0 0.000 0 0 + 239 359 199 279 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 509 160 589 160 589 59 509 59 509 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 409 160 489 160 489 59 409 59 409 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 318 160 398 160 398 59 318 59 318 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 198 160 278 160 278 59 198 59 198 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 359 279 439 279 439 178 359 178 359 279 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 158 279 238 279 238 178 158 178 158 279 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 459 279 539 279 539 259 459 259 459 279 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 259 279 339 279 339 259 259 259 259 279 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 199 379 279 379 279 359 199 359 199 379 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 88 519 168 519 168 418 88 418 88 519 9999 9999 +4 0 0 16 0 0 0 0.000 1 16 40 504 374 dn.22 +4 0 0 16 0 0 0 0.000 1 16 64 399 374 base.t2f +4 0 0 16 0 0 0 0.000 1 16 64 519 139 1.P2.fax +4 0 0 16 0 0 0 0.000 1 16 48 419 139 hdr.P2 +4 0 0 16 0 0 0 0.000 1 16 64 329 139 1.P2.ia5 +4 0 0 16 0 0 0 0.000 1 16 48 204 139 hdr.P2 +4 0 0 16 0 0 0 0.000 1 16 48 374 254 hdr.P2 +4 0 0 16 0 0 0 0.000 1 16 40 464 274 1.IPM +4 0 0 16 0 0 0 0.000 1 16 40 264 274 1.IPM +4 0 0 16 0 0 0 0.000 1 16 48 169 259 hdr.P2 +4 0 0 16 0 0 0 0.000 1 16 32 204 374 base +4 0 0 16 0 0 0 0.000 1 16 56 304 479 msg.nnn +4 0 0 16 0 0 0 0.000 1 16 64 99 499 addr.nnn diff --git a/doc/ifip6.5-88/slides/dir.pic b/doc/ifip6.5-88/slides/dir.pic new file mode 100644 index 0000000..bc31901 --- /dev/null +++ b/doc/ifip6.5-88/slides/dir.pic @@ -0,0 +1,62 @@ +.PS +line from 4.250,4.725 to 6.750,5.737 +line from 6.213,5.763 to 7.213,5.763 to 7.213,6.013 to 6.213,6.013 to 6.213,5. +763 +line from 4.925,5.763 to 5.925,5.763 to 5.925,6.013 to 4.925,6.013 to 4.925,5. +763 +line from 2.987,5.763 to 4.237,4.700 to 5.425,5.763 +line from 3.737,4.450 to 4.737,4.450 to 4.737,4.700 to 3.737,4.700 to 3.737,4. +450 +line from 5.612,8.512 to 6.237,7.263 to 6.925,8.512 +line from 5.425,6.013 to 6.237,7.013 +line from 4.987,7.013 to 5.425,6.013 +line from 2.987,8.512 to 3.737,7.263 to 4.487,8.512 +line from 2.987,6.013 to 3.737,7.013 +line from 2.987,6.013 to 2.487,7.013 +line from 6.362,8.500 to 7.362,8.500 to 7.362,9.762 to 6.362,9.762 to 6.362,8. +500 +line from 5.112,8.500 to 6.112,8.500 to 6.112,9.762 to 5.112,9.762 to 5.112,8. +500 +line from 3.975,8.500 to 4.975,8.500 to 4.975,9.762 to 3.975,9.762 to 3.975,8. +500 +line from 2.475,8.500 to 3.475,8.500 to 3.475,9.762 to 2.475,9.762 to 2.475,8. +500 +line from 4.487,7.013 to 5.487,7.013 to 5.487,8.275 to 4.487,8.275 to 4.487,7. +013 +line from 1.975,7.013 to 2.975,7.013 to 2.975,8.275 to 1.975,8.275 to 1.975,7. +013 +line from 5.737,7.013 to 6.737,7.013 to 6.737,7.263 to 5.737,7.263 to 5.737,7. +013 +line from 3.237,7.013 to 4.237,7.013 to 4.237,7.263 to 3.237,7.263 to 3.237,7. +013 +line from 2.487,5.763 to 3.487,5.763 to 3.487,6.013 to 2.487,6.013 to 2.487,5. +763 +line from 1.100,4.013 to 2.100,4.013 to 2.100,5.275 to 1.100,5.275 to 1.100,4. +013 +.ps 11 +"dn.22" at 6.300,5.856 ljust +.ps 11 +"base.t2f" at 4.987,5.856 ljust +.ps 11 +"1.P2.fax" at 6.487,8.793 ljust +.ps 11 +"hdr.P2" at 5.237,8.793 ljust +.ps 11 +"1.P2.ia5" at 4.112,8.793 ljust +.ps 11 +"hdr.P2" at 2.550,8.793 ljust +.ps 11 +"hdr.P2" at 4.675,7.356 ljust +.ps 11 +"1.IPM" at 5.800,7.106 ljust +.ps 11 +"1.IPM" at 3.300,7.106 ljust +.ps 11 +"hdr.P2" at 2.112,7.293 ljust +.ps 11 +"base" at 2.550,5.856 ljust +.ps 11 +"msg.nnn" at 3.800,4.543 ljust +.ps 11 +"addr.nnn" at 1.238,4.293 ljust +.PE diff --git a/doc/ifip6.5-88/slides/dir.tex b/doc/ifip6.5-88/slides/dir.tex new file mode 100644 index 0000000..544f3b5 --- /dev/null +++ b/doc/ifip6.5-88/slides/dir.tex @@ -0,0 +1,131 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\gr +aph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{pa 3149 5036}% + \special{pa 5649 4024}% + \special{fp}% + \special{pa 5112 3998}% + \special{pa 6112 3998}% + \special{pa 6112 3748}% + \special{pa 5112 3748}% + \special{pa 5112 3998}% + \special{fp}% + \special{pa 3824 3998}% + \special{pa 4824 3998}% + \special{pa 4824 3748}% + \special{pa 3824 3748}% + \special{pa 3824 3998}% + \special{fp}% + \special{pa 1886 3998}% + \special{pa 3136 5061}% + \special{pa 4324 3998}% + \special{fp}% + \special{pa 2636 5311}% + \special{pa 3636 5311}% + \special{pa 3636 5061}% + \special{pa 2636 5061}% + \special{pa 2636 5311}% + \special{fp}% + \special{pa 4511 1249}% + \special{pa 5136 2498}% + \special{pa 5824 1249}% + \special{fp}% + \special{pa 4324 3748}% + \special{pa 5136 2748}% + \special{fp}% + \special{pa 3886 2748}% + \special{pa 4324 3748}% + \special{fp}% + \special{pa 1886 1249}% + \special{pa 2636 2498}% + \special{pa 3386 1249}% + \special{fp}% + \special{pa 1886 3748}% + \special{pa 2636 2748}% + \special{fp}% + \special{pa 1886 3748}% + \special{pa 1386 2748}% + \special{fp}% + \special{pa 5261 1261}% + \special{pa 6261 1261}% + \special{pa 6261 0}% + \special{pa 5261 0}% + \special{pa 5261 1261}% + \special{fp}% + \special{pa 4011 1261}% + \special{pa 5011 1261}% + \special{pa 5011 0}% + \special{pa 4011 0}% + \special{pa 4011 1261}% + \special{fp}% + \special{pa 2874 1261}% + \special{pa 3874 1261}% + \special{pa 3874 0}% + \special{pa 2874 0}% + \special{pa 2874 1261}% + \special{fp}% + \special{pa 1374 1261}% + \special{pa 2374 1261}% + \special{pa 2374 0}% + \special{pa 1374 0}% + \special{pa 1374 1261}% + \special{fp}% + \special{pa 3386 2748}% + \special{pa 4386 2748}% + \special{pa 4386 1486}% + \special{pa 3386 1486}% + \special{pa 3386 2748}% + \special{fp}% + \special{pa 874 2748}% + \special{pa 1874 2748}% + \special{pa 1874 1486}% + \special{pa 874 1486}% + \special{pa 874 2748}% + \special{fp}% + \special{pa 4636 2748}% + \special{pa 5636 2748}% + \special{pa 5636 2498}% + \special{pa 4636 2498}% + \special{pa 4636 2748}% + \special{fp}% + \special{pa 2136 2748}% + \special{pa 3136 2748}% + \special{pa 3136 2498}% + \special{pa 2136 2498}% + \special{pa 2136 2748}% + \special{fp}% + \special{pa 1386 3998}% + \special{pa 2386 3998}% + \special{pa 2386 3748}% + \special{pa 1386 3748}% + \special{pa 1386 3998}% + \special{fp}% + \special{pa 0 5748}% + \special{pa 999 5748}% + \special{pa 999 4486}% + \special{pa 0 4486}% + \special{pa 0 5748}% + \special{fp}% + \special{pn 11}% + \rlap{\kern 5.199in\lower 3.947in\hbox to0pt{dn.22\hss}}% + \rlap{\kern 3.886in\lower 3.947in\hbox to0pt{base.t2f\hss}}% + \rlap{\kern 5.386in\lower 1.010in\hbox to0pt{1.P2.fax\hss}}% + \rlap{\kern 4.136in\lower 1.010in\hbox to0pt{hdr.P2\hss}}% + \rlap{\kern 3.011in\lower 1.010in\hbox to0pt{1.P2.ia5\hss}}% + \rlap{\kern 1.449in\lower 1.010in\hbox to0pt{hdr.P2\hss}}% + \rlap{\kern 3.574in\lower 2.447in\hbox to0pt{hdr.P2\hss}}% + \rlap{\kern 4.699in\lower 2.697in\hbox to0pt{1.IPM\hss}}% + \rlap{\kern 2.199in\lower 2.697in\hbox to0pt{1.IPM\hss}}% + \rlap{\kern 1.011in\lower 2.510in\hbox to0pt{hdr.P2\hss}}% + \rlap{\kern 1.449in\lower 3.947in\hbox to0pt{base\hss}}% + \rlap{\kern 2.699in\lower 5.260in\hbox to0pt{msg.nnn\hss}}% + \rlap{\kern 0.137in\lower 5.510in\hbox to0pt{addr.nnn\hss}}% + \kern 6.262in + }\vss}% + \kern 5.749in +} diff --git a/doc/ifip6.5-88/slides/ifip88-pp.tex b/doc/ifip6.5-88/slides/ifip88-pp.tex new file mode 100644 index 0000000..224abbb --- /dev/null +++ b/doc/ifip6.5-88/slides/ifip88-pp.tex @@ -0,0 +1,381 @@ +\documentstyle[blackandwhite,small,trademark] {NRslides} + +\title {PP --- A Message Transfer Agent} + +\author {S.E. Kille \\ +Department of Computer Science \\ +University College London} + +\date {October 1988} +\raggedright + +\begin {document} + +\maketitlepage + +\begin {bwslide} +\ctitle {What is PP} + +\begin {itemize} +\item A Message Transfer Agent: + +\begin {itemize} +\item Multiple Message Transfer Protocols, including X.400 +\item Protocol and Format Conversion +\item Suitability for high levels of traffic +\end {itemize} +\item Use on \unix/. +\item Openly Available as a part of the ISODE +\item A name and not an acronym +\end {itemize} + + +\end {bwslide} + +\begin {bwslide} +\ctitle {Why PP} + +\begin {itemize} +\item Current RFC 822 based MTAs such as MMDF or Sendmail have: +\begin {itemize} +\item Support for multiple UAs +\item Support for a range of protocols +\item Integrated within the \unix/ environment +\item No support for X.400 +\item Not suitable to extend for X.400 +\end {itemize} + +\item X.400 MTAs considered for replacing the older MTAs have: +\begin {itemize} +\item X.400 +\item Not a lot else (procrustean) +\item Wrong price +\item Caveat: I may not have looked at {\em your} MTA +\end {itemize} + +\item PP Aims to +\begin {itemize} +\item Support {\em full} X.400 functionality --- not just the protocols + +\item Provide good local functionality + +\item Be available at the right price --- free + +\item Encourage a higher standard of X.400 implementation +\end {itemize} + +\end {itemize} + +\end {bwslide} + + + +\begin {bwslide} +\ctitle {Goals (1)} + +\begin {itemize} +\item Provision of a clean interface for message submission and +delivery, to support a wide range of User Agents. +\begin {itemize} +\item Procedural +\item Protocol +\end {itemize} + +\item Support for all of the Message Transfer Service Elements specified by +the 1984 and 1988 versions of X.400. + +\item Support for some services not provided by X.400. + +\item Specific support to facilitate the handling of multimedia +messages. + +\item Robustness and efficiency required to support high levels of +traffic. + +\item Scheduling of message delivery in a sophisticated manner, to +optimise local and communication resources. +\end {itemize} +\end {bwslide} + +\begin {bwslide} +\ctitle {Goals (2)} + +\begin {itemize} +\item Provision of a range of management, authorisation and monitoring +facilities. + +\item Reformatting between body part types in a general manner. + +\item Support for multiple address formats (initially two). + +\item Use of +standardised OSI Directory Services. + +\item Support for message protocol conversion in an integrated +fashion. + +\item Full access to the Message Transfer Service for applications +other than Inter-Personal Messaging. + +\end {itemize} +\end {bwslide} + + +\begin {bwslide} +\ctitle {Process Structure} +\vspace{2ex} +\diagram[p]{structure} +\end {bwslide} + + +\begin {bwslide} +\ctitle {Queue Structure} +\begin {itemize} +\item Each queued message is represented by a text encoded file, with +functionality corresponding to the P1 envelope, with extensions. This +includes the following per-message parameters: +\begin {itemize} +\item Message Originator +\item Message ID +\item Trace Information +\item Open-ended list of encoded information types +\end {itemize} + +And include the following per-user parameters: +\begin {itemize} +\item Unique key +\item Address of the recipient +\item Sequence of channels to process the message +\item Processing status +\end {itemize} + + +\item A \unix/ directory containing: +\begin {itemize} +\item The original message +\item Converted variants of the original message +\item Associated Delivery Notifications +\end {itemize} + +\end {itemize} + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Queue Example (part 1)} + +\footnotesize +\begin {verbatim} +Start-of-MsgEnvPrm +Message-type User-Mpdu +Message-size 257 +Queued-date "880919163408+0000" +Departure-date +Inbound-channel x400in +Inbound-host cs.ucl.ac.uk +Number-warnings 0 +Warning-time 0 +Return-time 0 +Content-type p2 +Encoded-info EncTypes undefined +Priority normal +PerMsg-Flags disclose-recipients +PerMsg-Flags return-contents +MsgId Country GB +MsgId Admin GOLD 400 +MsgId Prmd UK.AC +MsgId string "880919152949+0000" +Trace Country GB +Trace Admin GOLD 400 +Trace Prmd UK.AC +Trace arrival-time "880919152949+0000" +Trace action relayed +Trace End-of-unit +Trace Country GB +Trace Admin GOLD 400 +Trace Prmd UK.AC +Trace arrival-time "880919163413+0000" +Trace action relayed +Trace End-of-block +\end{verbatim} +\end {bwslide} + + +\begin {bwslide} +\ctitle {Queue Example (part 2)} + +\footnotesize +\begin{verbatim} +Start-of-MsgEnvAddr +Origs rno=000 status=done dn=000 reform-nxt=000 + reform-list=empty ext-id=0 + resp=n mta-rreq=basic usr-rreq=basic + mta=pyr1.cs.ucl.ac.uk + outchan=local explicit=0 + type=a822 subtype=empty + orig=/S=alina/OU=CS/O=UCL/PRMD=UK.AC/ADMD=GOLD\ 400/C=GB/ + x400=/S=alina/OU=CS/O=UCL/PRMD=UK.AC/ADMD=GOLD\ 400/C=GB/ + rfc=alina@cs.ucl.ac.uk + End-of-addr +Recip rno=001 status=dliv dn=001 reform-nxt=000 + reform-list=empty ext-id=1 + resp=y mta-rreq=basic usr-rreq=basic + mta=pamir + outchan=x400out explicit=0 + type=x400 subtype=empty + orig=/S=test/OU=mirsa/O=inria/PRMD=aristote/ADMD=PTT/C=Fr/ + x400=/S=test/OU=mirsa/O=inria/PRMD=aristote/ADMD=PTT/C=Fr/ + rfc=empty + End-of-addr +\end{verbatim} +\end {bwslide} + + +\begin {bwslide} +\ctitle {Queue Structure} +\vspace{2ex} +\diagram[p]{dir} + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Message Submission} +\begin {itemize} +\item Submission may be from: +\begin {itemize} +\item Local User Agent +\item Remote User Agent (e.g P3) +\item Protocol Server (e.g. P1) +\end {itemize} + +\item Submit process uses a private protocol: +\begin {itemize} +\item Text based (derived from queue structure) +\item Local IPC +\item Superset of features of other protocols +\item Address checking before message copying +\end {itemize} + +\item Initial Address checking provides: +\begin {itemize} +\item Routing +\item Conversion control +\item Authorisation +\item Multiple address formats +\end {itemize} + +\item Submission of one or more body parts + +\end {itemize} +\end {bwslide} + + + +\begin {bwslide} +\ctitle {Conversion} +\begin {itemize} +\item Messages structured as \unix/ directory hierarchy + +\item Body part names indicate their type (e.g. ``3.P2.IA5'') + +\item Conversion creates new copy of message + +\item Unaffected body parts are linked + +\item Format conversion of body parts + +\item Message restructuring + +\item Protocol conversion +\end {itemize} + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Queue Mangement} + +\begin {itemize} +\item The Queue Manager (QMGR) holds representation of queue in memory, and {\ +em +never} reads the disk + +\item Access to the QMGR is through ROS +\begin {itemize} +\item Use of ROSY from ISODE +\end {itemize} + +\item Controls channels, and gives flexible scheduling + +\item Management facilities + +\item MTA Console +\end {itemize} + + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Items for PP 4.0} +\begin {itemize} +\item Protocols +\begin {itemize} +\item P1(1984) +\item SMTP +\item JNT Mail +\item UUCP +\end {itemize} + +\item Conversion +\begin {itemize} +\item RFC 987/1026 +\item RFC 934 +\item UK domain ordering +\end {itemize} + +\item User Interfaces +\begin {itemize} +\item Text based X.400 interface +\item MH +\item Assorted RFC 822 interfaces +\end {itemize} + +\item Distribution Lists + +\item Use of X.500 (QUIPU) + +\end {itemize} + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Further Items} +\begin {itemize} +\item MTA Console +\item P1 (1988) +\item Additional body part formatters +\item RFC 987 (1988) +\item P2 $\Leftrightarrow$ P22 +\item Message Store (P3/P7) +\item Operation over PSTN +\end {itemize} + +\end {bwslide} + + +\begin {bwslide} +\ctitle {Availability of PP} +\begin {itemize} +\item To be distributed with ISODE 5.0 in January 1989 +\item Available by Internet FTP and FTAM from Delaware +\item Available by NIFTP and FTAM from UCL +\item Available by post from Pennsylvania Univ, UCL, CWI and CSIRO +\end {itemize} + +\end {bwslide} + +\end {document} diff --git a/doc/ifip6.5-88/slides/structure.fig b/doc/ifip6.5-88/slides/structure.fig new file mode 100644 index 0000000..1296980 --- /dev/null +++ b/doc/ifip6.5-88/slides/structure.fig @@ -0,0 +1,28 @@ +80 2 600 800 +6 6 107 469 466 +5 5 0 1 0.000000 1 0 0 8 4 363.000000 247.558823 316 304 364 321 410 304 +5 5 0 1 0.000000 0 0 0 8 4 365.407806 304.166656 317 239 364 223 411 237 +5 5 0 1 0.000000 1 0 0 8 4 364.000000 182.558823 317 239 365 256 411 239 +1 1 0 1 0.000000 1 264 139 47 25 264 139 310 163 +1 1 0 1 0.000000 1 101 142 47 25 101 142 147 166 +1 1 0 1 0.000000 1 188 214 47 25 188 214 234 238 +1 1 0 1 0.000000 1 187 366 47 25 187 366 233 390 +1 1 0 1 0.000000 1 66 281 47 25 66 281 112 304 +2 6 0 1 4.000000 1 1 8 4 159 194 124 164 9999 9999 +2 6 0 1 4.000000 1 1 8 4 218 193 254 164 9999 9999 +2 6 0 1 4.000000 1 1 8 4 232 224 315 262 9999 9999 +2 6 0 1 4.000000 1 1 8 4 145 223 90 258 9999 9999 +2 6 0 1 4.000000 1 1 8 4 227 351 315 298 9999 9999 +2 6 0 1 4.000000 1 1 8 4 96 300 157 347 9999 9999 +2 6 1 1 4.000000 1 1 8 4 114 281 315 281 9999 9999 +2 6 0 1 4.000000 0 0 8 4 412 238 412 302 9999 9999 +2 6 0 1 4.000000 0 0 8 4 316 239 316 303 9999 9999 +4 0 0 0 16 56 167 376 Channel +4 0 0 0 16 64 164 360 Outbound +4 0 0 0 16 40 333 274 Queue +4 0 0 0 16 32 46 285 QMGR +4 0 0 0 16 48 166 219 Submit +4 0 0 0 16 16 245 143 UA +4 0 0 0 16 56 79 155 Channel +4 0 0 0 16 56 75 139 Inbound +-6 diff --git a/doc/ifip6.5-88/slides/structure.pic b/doc/ifip6.5-88/slides/structure.pic new file mode 100644 index 0000000..b9ffd19 --- /dev/null +++ b/doc/ifip6.5-88/slides/structure.pic @@ -0,0 +1,51 @@ +.PS +"\D't 0.00875i'" +arc at 4.537,7.406 from 3.950,6.700 to 5.125,6.700 +arc at 4.568,6.698 from 3.962,7.513 to 5.138,7.537 cw +arc at 4.550,8.218 from 3.962,7.513 to 5.138,7.513 +ellipse at 3.300,8.762 wid 1.175 ht 0.625 +ellipse at 1.262,8.725 wid 1.175 ht 0.625 +ellipse at 2.350,7.825 wid 1.175 ht 0.625 +ellipse at 2.337,5.925 wid 1.175 ht 0.625 +ellipse at 0.825,6.987 wid 1.175 ht 0.625 +line from 1.895,8.121 to 1.988,8.075 to 1.928,8.159 +line from 1.988,8.075 to 1.550,8.450 +line from 1.642,8.404 to 1.550,8.450 to 1.610,8.366 +line from 2.787,8.170 to 2.725,8.088 to 2.819,8.131 +line from 2.725,8.088 to 3.175,8.450 +line from 3.113,8.368 to 3.175,8.450 to 3.081,8.407 +line from 3.001,7.681 to 2.900,7.700 to 2.981,7.636 +line from 2.900,7.700 to 3.938,7.225 +line from 3.836,7.244 to 3.938,7.225 to 3.857,7.289 +line from 1.742,7.638 to 1.813,7.713 to 1.715,7.680 +line from 1.813,7.713 to 1.125,7.275 +line from 1.196,7.350 to 1.125,7.275 to 1.223,7.308 +line from 2.910,6.186 to 2.837,6.112 to 2.936,6.143 +line from 2.837,6.112 to 3.938,6.775 +line from 3.865,6.702 to 3.938,6.775 to 3.839,6.745 +line from 1.294,6.709 to 1.200,6.750 to 1.264,6.669 +line from 1.200,6.750 to 1.962,6.162 +line from 1.868,6.204 to 1.962,6.162 to 1.899,6.243 +dashwid = 0.050i +line from 1.525,7.013 to 1.425,6.987 to 1.525,6.962 +line dashed from 1.425,6.987 to 3.938,6.987 +line from 3.837,6.962 to 3.938,6.987 to 3.837,7.013 +line from 5.150,7.525 to 5.150,6.725 +line from 3.950,7.513 to 3.950,6.713 +.ps 11 +"Channel" at 2.087,5.831 ljust +.ps 11 +"Outbound" at 2.050,6.031 ljust +.ps 11 +"Queue" at 4.162,7.106 ljust +.ps 11 +"QMGR" at 0.575,6.968 ljust +.ps 11 +"Submit" at 2.075,7.793 ljust +.ps 11 +"UA" at 3.063,8.743 ljust +.ps 11 +"Channel" at 0.988,8.593 ljust +.ps 11 +"Inbound" at 0.938,8.793 ljust +.PE diff --git a/doc/ifip6.5-88/slides/structure.tex b/doc/ifip6.5-88/slides/structure.tex new file mode 100644 index 0000000..b8b04f1 --- /dev/null +++ b/doc/ifip6.5-88/slides/structure.tex @@ -0,0 +1,127 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\gr +aph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{ar 4299 1668 918 918 0.876 2.264}% + \special{ar 4330 2376 1014 1014 4.073 5.309}% + \special{ar 4312 856 918 918 0.877 2.264}% + \special{ar 3062 312 587 311 0.000 6.283}% + \special{ar 1025 349 587 311 0.000 6.283}% + \special{ar 2112 1249 587 311 0.000 6.283}% + \special{ar 2100 3149 587 311 0.000 6.283}% + \special{ar 587 2086 587 311 0.000 6.283}% + \special{pa 1657 953}% + \special{pa 1749 999}% + \special{fp}% + \special{pa 1690 915}% + \special{pa 1749 999}% + \special{pa 1312 624}% + \special{fp}% + \special{pa 1405 671}% + \special{pa 1312 624}% + \special{fp}% + \special{pa 1372 709}% + \special{pa 1312 624}% + \special{fp}% + \special{pa 2549 904}% + \special{pa 2487 986}% + \special{fp}% + \special{pa 2581 943}% + \special{pa 2487 986}% + \special{pa 2937 624}% + \special{fp}% + \special{pa 2875 707}% + \special{pa 2937 624}% + \special{fp}% + \special{pa 2844 668}% + \special{pa 2937 624}% + \special{fp}% + \special{pa 2764 1393}% + \special{pa 2662 1374}% + \special{fp}% + \special{pa 2743 1439}% + \special{pa 2662 1374}% + \special{pa 3700 1849}% + \special{fp}% + \special{pa 3599 1830}% + \special{pa 3700 1849}% + \special{fp}% + \special{pa 3620 1785}% + \special{pa 3700 1849}% + \special{fp}% + \special{pa 1504 1436}% + \special{pa 1575 1361}% + \special{fp}% + \special{pa 1478 1394}% + \special{pa 1575 1361}% + \special{pa 887 1799}% + \special{fp}% + \special{pa 958 1725}% + \special{pa 887 1799}% + \special{fp}% + \special{pa 985 1767}% + \special{pa 887 1799}% + \special{fp}% + \special{pa 2673 2888}% + \special{pa 2600 2961}% + \special{fp}% + \special{pa 2699 2931}% + \special{pa 2600 2961}% + \special{pa 3700 2299}% + \special{fp}% + \special{pa 3627 2372}% + \special{pa 3700 2299}% + \special{fp}% + \special{pa 3602 2329}% + \special{pa 3700 2299}% + \special{fp}% + \special{pa 1057 2366}% + \special{pa 962 2324}% + \special{fp}% + \special{pa 1026 2405}% + \special{pa 962 2324}% + \special{pa 1724 2912}% + \special{fp}% + \special{pa 1630 2871}% + \special{pa 1724 2912}% + \special{fp}% + \special{pa 1660 2831}% + \special{pa 1724 2912}% + \special{fp}% + \special{pa 1287 2061}% + \special{pa 1187 2086}% + \special{fp}% + \special{pa 1287 2111}% + \special{pa 1187 2086}% + \special{fp}% + \special{pa 1187 2086}% + \special{pa 3700 2086}% + \special{da 0.050}% + \special{pa 3600 2111}% + \special{pa 3700 2086}% + \special{fp}% + \special{pa 3600 2061}% + \special{pa 3700 2086}% + \special{fp}% + \special{pa 4912 1549}% + \special{pa 4912 2349}% + \special{fp}% + \rlap{\kern 1.850in\lower 3.315in\hbox to0pt{Channel\hss}}% + \rlap{\kern 1.812in\lower 3.115in\hbox to0pt{Outbound\hss}}% + \rlap{\kern 3.924in\lower 2.040in\hbox to0pt{Queue\hss}}% + \rlap{\kern 0.337in\lower 2.177in\hbox to0pt{QMGR\hss}}% + \rlap{\kern 1.837in\lower 1.353in\hbox to0pt{Submit\hss}}% + \rlap{\kern 2.825in\lower 0.403in\hbox to0pt{UA\hss}}% + \rlap{\kern 0.750in\lower 0.552in\hbox to0pt{Channel\hss}}% + \rlap{\kern 0.700in\lower 0.353in\hbox to0pt{Inbound\hss}}% + \special{pa 3712 1562}% + \special{pa 3712 2361}% + \special{fp}% + \kern 4.913in + }\vss}% + \kern 3.461in +} diff --git a/doc/make b/doc/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/doc/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/manual/Make.defs b/doc/manual/Make.defs new file mode 100644 index 0000000..fd26d4e --- /dev/null +++ b/doc/manual/Make.defs @@ -0,0 +1,30 @@ +############################################################ +# +# Default Configuration values for Documentation +# +############################################################ +# +# +############################################################ +# +# @(#) $Header: /cs/research/pp/hubris/pp-beta/doc/manual/RCS/Make.defs,v 5.0 90/09/20 16:36:08 pp Exp Locker: pp $ +# +# $Log: Make.defs,v $ +# Revision 5.0 90/09/20 16:36:08 pp +# rcsforce : 5.0 public release +# +# +############################################################ + + + +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = + +# TEXEDIT=/usr/ucl/jove +%d %s diff --git a/doc/manual/Makefile b/doc/manual/Makefile new file mode 100644 index 0000000..ecc7513 --- /dev/null +++ b/doc/manual/Makefile @@ -0,0 +1,37 @@ +# Documentation building Makefile +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + + + +VOLS = volume0 volume1 volume2 volume3 +INPUTS = texinputs + +default: all + +all: + @for x in $(VOLS) ; \ + do (echo "cd $$x;$(MAKE)"; cd $$x ; $(MAKE)); done + +ps: true + @for x in $(VOLS); \ + do (echo "cd $$x; $(MAKE) $@"; cd $$x; $(MAKE) $@); done + +clean tidy: + @for x in $(VOLS) ; \ + do (echo "cd $$x; $(MAKE) $@"; cd $$x ; $(MAKE) $@ ); done + rm -f core *.old *.BAK + +define depend lint install:; + +true: diff --git a/doc/manual/README b/doc/manual/README new file mode 100644 index 0000000..d2548c0 --- /dev/null +++ b/doc/manual/README @@ -0,0 +1,18 @@ +~pp/doc/manual/README +--------------------- +The PP manual is contained in the three directories volume1, 2 and 3. +Each shares some files from the directory /texinputs. + + Four subdirectories + volume0/ + Introduction and credits + volume1/ + Installation and Operation + volume2/ + Programmers Manual. + volume3/ + PP user manual + +By default these documents use the a4.sty style to produce a4 paper +output. If you don't use a4 paper - create an empty file a4.sty in +each directory and this will disable this feature. diff --git a/doc/manual/book-changes.ms b/doc/manual/book-changes.ms new file mode 100644 index 0000000..01b40cf --- /dev/null +++ b/doc/manual/book-changes.ms @@ -0,0 +1,22 @@ +.TL +Differences between the 6.0 PP Manual and the book +.sp 2 +Implementing X.400 and X.500: +.br +The PP and Quipu systems +.LP +This is a summary of the differences between the PP 6.0 manual and the +book by Steve Kille. All references are to Volume1 of the PP 6.0 +manual uless explicitly stated. +.IP 1. +The Chapter entitled \fIAdditional Capabilites\fP which describes the +Fax interface and the ASN.1 filters has been added. +.IP 2. +A new line based console is described in the Chapter \fIManaging +PP\fP. +.IP 3. +A small number of new parameters can be tailored in the tailor file +and in the Make.defs file. +.IP 4. +Volume 3 has a new section on tools to maintain X.500 directory +distribution lists. diff --git a/doc/manual/make b/doc/manual/make new file mode 100755 index 0000000..6552bc1 --- /dev/null +++ b/doc/manual/make @@ -0,0 +1,10 @@ +#! /bin/sh +if [ -f ../../Make.defs ] +then + PATH=/usr/ucb:/bin:/usr/bin \ + exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} +else + PATH=/usr/ucb:/bin:/usr/bin \ + exec ${MAKECMD-make} -f Make.defs -f Makefile ${1+"$@"} +fi + diff --git a/doc/manual/ps/README b/doc/manual/ps/README new file mode 100644 index 0000000..f893715 --- /dev/null +++ b/doc/manual/ps/README @@ -0,0 +1,3 @@ +Postscript files are normally distributed separately. If this +directory is empty, retrieve the files specified in the COVER-LETTER. + diff --git a/doc/manual/texinputs/a4.sty b/doc/manual/texinputs/a4.sty new file mode 100644 index 0000000..1ce5d7a --- /dev/null +++ b/doc/manual/texinputs/a4.sty @@ -0,0 +1,23 @@ +% +% "a4" document style option. +% John Pavel, December 1986 +% +% Redefines the \textheight and \topmargin for A4 paper, as opposed to US paper. +% +% Adjusting \textheight will adjust position of the bottom of the page. +% Must preserve "(\textheight - \topskip) divides \baselineskip". +% \topskip always appears to be 10pt. +% So only add/subtract multiples of \baselineskip if you want shorter pages. +% +% \textwidth is not altered because A4 is narrower than US paper. +% +% +\topmargin 0 pt % Nominal distance from top of paper to top of page +\ifcase \@ptsize + % mods for 10 pt (\baselineskip=12pt) + \textheight 646 pt % Height of text (including footnotes and figures) +\or % mods for 11 pt (\baselineskip=13.6pt) + \textheight 649.2 pt % Height of text (including footnotes and figures) +\or % mods for 12 pt (\baselineskip=15pt) + \textheight 655 pt % Height of text (including footnotes and figures) +\fi diff --git a/doc/manual/texinputs/bcustom.bib b/doc/manual/texinputs/bcustom.bib new file mode 100644 index 0000000..8068fde --- /dev/null +++ b/doc/manual/texinputs/bcustom.bib @@ -0,0 +1,37 @@ +% BibTeX customization + +% people +@string{mtr = "Marshall T. Rose"} + +% places +@string{bbn = "Bolt, Beranek, and Newman, Inc."} +@string{ccitt = "International Telegraph and Telephone Consultative Committee"} +@string{cis = "Department of Computer and Information Sciences"} +@string{ee = "Department of Electrical Engineering"} +@string{ics = "Department of Information and Computer Science"} +@string{iso/iec = "International Organization for Standardization/International Electrotechnical Institute"} +@string{nic = "DDN Network Information Center"} +@string{nrtc = "Northrop Research and Technology Center"} +@string{rand = "The Rand Corporation"} +@string{sri = "SRI International"} +@string{twg = "The Wollongong Group"} +@string{uci = "University of California, Irvine"} +@string{ucl = "University College London"} +@string{udel = "University of Delaware"} + +% journals +@string{connexions = "ConneXions"} +@string{cn/isdn = "Computer Networks and ISDN Systems"} +@string{ccr = "Computer Communication Review"} +@string{ieeecom = "IEEE Transactions on Communications"} +@string{ieeecm = "IEEE Communications Magazine"} +@string{jsac = "IEEE Journal on Selected Areas in Communications"} + +% handbooks +@string{ddn = "DDN Protocol Handbook, + Volume One: \dod/ Military Standard Protocols, + DDN Network Information Center, SRI International"} + +% types +@string{idea = "IDEA"} +@string{rfc = "Request for Comments"} diff --git a/doc/manual/texinputs/captcont.sty b/doc/manual/texinputs/captcont.sty new file mode 100644 index 0000000..70f662e --- /dev/null +++ b/doc/manual/texinputs/captcont.sty @@ -0,0 +1,16 @@ +% SubStyle file to permit the use of captions in continuations of floats. +% +% \captcont is like \caption, except that it doesn't update the counter, and +% it doesn't make an entry in the list of figures or list of tables. + +\def\captcont{\@dblarg{\@captcont\@captype}} + +\long\def\@captcont#1[#2]#3{ +% \addcontentsline{\csname ext@#1\endcsname}{#1}{\protect\numberline{\csname +% the#1\endcsname}{\ignorespaces #2}} + \par + \begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} diff --git a/doc/manual/texinputs/dist-params.tex b/doc/manual/texinputs/dist-params.tex new file mode 100644 index 0000000..f79b704 --- /dev/null +++ b/doc/manual/texinputs/dist-params.tex @@ -0,0 +1,12 @@ +\def\ppversion/{6.0} +\def\isodevrsn/{7.0} +\def\ppdate/{December 20, 1991} +\def\uktarfile/{\verb|pp/pp-6.tar|} +\def\tarfile/{\verb|pp-6.tar|} +\def\tarsize/{4Mb} +\def\compresssize/{3Mb} +\def\compressfile/{\verb|pp-6.tar.Z|} +\def\ukcompressfile/{\verb|pp-6.tar.Z|} +\def\ukpsfile/{\verb|pp-6-ps-a4.tar.Z|} +\def\psfile/{\verb|pp-6-ps-us.tar.Z|} +\def\pssize/{1.5MB} diff --git a/doc/manual/texinputs/grindefs b/doc/manual/texinputs/grindefs new file mode 100644 index 0000000..0605a37 --- /dev/null +++ b/doc/manual/texinputs/grindefs @@ -0,0 +1,49 @@ +pepy|asn1|asn.1|ASN1|ASN.1|x409|x.409|X409|X.409:\ + :pb=^\d?\p\d?\:\:\=:tl:\ + :bb=\dBEGIN\d|{|\[|\(:be=\dEND\d|}|\]|\):\ + :cb=--:ce=--|$:sb="|':se="|':\ + :kw=ANY APPLICATION BEGIN BIT BITSTRING BOOLEAN\ + CHOICE COMPONENTS DEFAULT DEFINITIONS END\ + EXTERNAL FALSE IDENTIFIER IMPLICIT INTEGER\ + NULL OBJECT OCTET OCTETSTRING OF OPTIONAL\ + PRIVATE SEQUENCE SET STRING TRUE UNIVERSAL\ + MACRO NOTATION TYPE VALUE\ + ABSENT BY COMPONENT DEFINED ENCRYPTED\ + ENUMERATED EXPLICIT EXPORTS FROM IMPORTS\ + INCLUDES MIN MAX PRESENT REAL SIZE TAGS\ + WITH\ + ARGUMENT BIND ERROR ERRORS LINKED OPERATION\ + PARAMETER RESULT UNBIND\ + ABSTRACT AS CONSUMER INVOKES OPERATIONS PAIRED\ + PORT PORTS RECURRING REFINE SUPPLIER\ + VISIBLE [C] [S]\ + ATTRIBUTE CLASS CONTAIN EMPTY EQUALITY FOR\ + MATCHES MAY MULTI MULTIPLE MUST NUMBER\ + SINGLE SUBCLASS SUBSTRINGS SYNTAX USES\ + CONTEXT ELEMENT ELEMENTS INITIATOR REMOTE SERVICE\ + SYNTAXES\ + OBJECT-TYPE SYNTAX ACCESS STATUS\ + DECODER ENCODER PRINTER SECTIONS %{ %} [[ ]] << >>: + + +bnf:\ + :pb=^\d?\p\d?\:\:\=:tl:\ + :cb=--:ce=--|$:sb="|':se="|':\ + :kw=< >: + +tai|tailoring:\ + :pb=^\p:tl:cb=#:ce=$:sb=":se=":oc:id=-_:\ + :kw=chan prog type bptin bptout table info show\ + content-in content-out adr-order access sort adr\ + subtype chanout mta authlog normlog operlog tbl isodelog isode\ + cmddir tbldir quedir logdir loc_dom_mta loc_dom_site \ + loc_or postmaster bodypart pptsapd_addr chandir formdir \ + ppdbm pplogin file level slevel dlevel sflags dflags \ + size flags intable outtable inadr outadr in-info out-info \ + mtatable domain-norm insubadr outsubadr cost key drchan \ + maxproc auth-table conv probe trace: + +mf|mailfilter:\ + :pb=^\p:tl:cb=#:ce=$:sb="|/:se=\e"|\e/:id=\$\(\)-:\ + :bb={:be=}:\ + :kw=pipe ignore file if else exit unixfile: diff --git a/doc/manual/texinputs/grindefs.sty b/doc/manual/texinputs/grindefs.sty new file mode 100644 index 0000000..d069a44 --- /dev/null +++ b/doc/manual/texinputs/grindefs.sty @@ -0,0 +1,21 @@ +pepy|asn1|asn.1|ASN1|ASN.1|x409|x.409|X409|X.409:\ + :pb=^\d?\p\d?\:\:\=:tl:\ + :bb=\dBEGIN\d|{|\[|\(:be=\dEND\d|}|\]|\):\ + :cb=--:ce=--|$:sb="|':se="|':\ + :kw=ANY APPLICATION BEGIN BIT BITSTRING BOOLEAN\ + CHOICE COMPONENTS DECODER DEFAULT DEFINITIONS\ + EMPTY ENCODER END EXTERNAL FALSE IDENTIFIER\ + IMPLICIT INTEGER MACRO NOTATION NULL NUMBER\ + OBJECT OCTET OCTETSTRING OF OPTIONAL PRINTER\ + PRIVATE SECTIONS SEQUENCE SEQUENCEOF SET SETOF\ + STRING TAG TRUE TYPE UNIVERSAL USES VALUE\ + %{ %} [[ ]] << >>\ + ARGUMENT ERROR ERRORS OPERATION PARAMETER RESULT LINKED\ + ATTRIBUTE SYNTAX SINGLE MULTIPLE MATCHES FOR EQUALITY SUBSTRINGS\ + ABSTRACT CLASS SUBCLASS IMPORTS EXPORTS FROM MULTI WITH\ + MUST MAY CONTAIN: + +bnf:\ + :pb=^\d?\p\d?\:\:\=:tl:\ + :cb=--:ce=--|$:sb="|':se="|':\ + :kw=< >: diff --git a/doc/manual/texinputs/lcustom.tex b/doc/manual/texinputs/lcustom.tex new file mode 100644 index 0000000..5ae23b3 --- /dev/null +++ b/doc/manual/texinputs/lcustom.tex @@ -0,0 +1,350 @@ +% LaTeX customization + + +\makeatletter % for a little while + + +% plain TeX compatibility + +\def\oldstyle{\xdef\@oldstyle{\the\textfont\@ne}\mit\@oldstyle} + + +% PhD-TeX compatibility + +\def\showsummary{% + \begingroup + \def\note##1{% + \ifcase\value{##1}no ##1s\or + 1 ##1\else + \the\value{##1} ##1s\fi + }% + \typeout{LaTeX summary: \note{figure}, \note{table}, \note{footnote}.}% + \endgroup +} + +\def\smaller{\footnotesize} + + +% Float Support + +\def\topfraction{0.85} +\def\textfraction{0.20} +\def\floatpagefraction{0.85} +\def\dbltopfraction{0.85} +\def\dblfloatpagefraction{0.85} + +\def\@tagskipcommand{\vskip .5\baselineskip} + +% \tagfigure*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads TPIC output in file figureFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagfigure{\@ifstar{\@stagfigure}{\@tagfigure}} +\def\@tagfigure{\@ifnextchar[{\@@tagfigure}{\@@tagfigure[t]}} +\def\@stagfigure{\@ifnextchar[{\@@stagfigure}{\@@stagfigure[t]}} + +\def\@@tagfigure[#1]#2{% + \@@@tagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} +\def\@@stagfigure[#1]#2{% + \@@@stagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} + + +% \tagdiagram*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeX input in file diagramFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagdiagram{\@ifstar{\@stagdiagram}{\@tagdiagram}} +\def\@tagdiagram{\@ifnextchar[{\@@tagdiagram}{\@@tagdiagram[t]}} +\def\@stagdiagram{\@ifnextchar[{\@@stagdiagram}{\@@stagdiagram[t]}} + +\def\@@tagdiagram[#1]#2{\@@@tagfigure[#1]{\input diagram#2\relax}} +\def\@@stagdiagram[#1]#2{\@@@stagfigure[#1]{\input diagram#2\relax}} + +\def\@@@tagfigure[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@@stagfigure[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +% \tagtable*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FILE read LaTeX input in file tableFILE +% FLOAT float options +% CAPTION for list of tables +% LABEL for \ref and \pageref +\def\tagtable{\@ifstar{\@stagtable}{\@tagtable}} +\def\@tagtable{\@ifnextchar[{\@@tagtable}{\@@tagtable[t]}} +\def\@stagtable{\@ifnextchar[{\@@stagtable}{\@@stagtable[t]}} + +\def\@@tagtable[#1]#2#3#4{% + \begin{table}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table} +} + +\def\@@stagtable[#1]#2#3#4{% + \begin{table*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table*} +} + + +% Environments: + +% DESCRIBE - similar to DESCRIPTION, but indents extra on left margin of +% outer list + +\def\describe{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \ifnum\@listdepth=1 \advance\leftmargin by2em\fi + \let\makelabel\descriptionlabel}} +\let\enddescribe=\endlist + + +% Document style options: +% 10pt - Makes ten-point type the normal (default) type size +% draftnote - Customized draft option + +\@namedef{ds@10pt}{\def\@ptsize{0}} %%% for orthogonality + + +\newif\ifdraft \draftfalse + +\def\draftstring{{\ifdraft \tt Draft\fi}} + +\def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today\ with \fmtname\ v\fmtversion + \else + Draft \versiontag/ of \versiondate/ + \fi + \endgroup + \fi +} + +\def\versiontag/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}%6 + \versiontag/% +} +\def\versiondate/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}% + \versiondate/% +} + +\def\ds@draftnote{% + \drafttrue + \@ifundefined{ds@draft}{}{\ds@draft}% + \def\ps@plain{% + \let\@mkboth=\@gobbletwo + \def\@oddhead{\draftext\hfil}% + \def\@oddfoot{\draftstring\hfil\rm\thepage\hfil\draftstring}% + \def\@evenhead{\hfil\draftext}% + \let\@evenfoot=\@oddfoot + }% + \let\ps@@headings=\ps@headings + \def\ps@headings{% + \ps@@headings + \def\@oddfoot{\draftext\hfil}% + \def\@evenfoot{\hfil\draftext}% + }% +} + + +% Page Styles + +% \pagestyle{myfootings} similar to the myheadings command but also permits +% the user to define foot information as well as head information +% \markleftfoot{left_foot} specifies the foot for odd-numbered +% pages +% \markrightfoot{right_foot} specifies the foot for even-numbered +% pages +% N.B. DOES NOT USE MARKS TO ACCOMPLISH THIS, OWING TO CONFLICT WITH HEADING +% ROUTINES + +\def\ps@myfootings{\ps@myheadings} + +\def\markleftfoot#1{\def\@evenfoot{\hbox{}\sl#1\hfil}} +\def\markrightfoot#1{\def\@oddfoot{\hfil\sl#1\hbox{}}} + + +% \pagestyle{reprint} similar to plain page style in draft mode + +\let\reprintext=\draftext +\let\reprintstring=\draftstring + +\def\ps@reprint{% + \def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today + \else + Draft \versiontag/ + \fi + \endgroup + \fi + }% + \def\@oddhead{\reprintext\hfil\draftext}% + \def\@oddfoot{\reprintstring\hfil\rm\thepage}% + \def\@evenhead{\draftext\hfil\reprintext}% + \def\@evenfoot{\rm\thepage\hfil\reprintstring}% +} + + +% The Title + +\def\title#1{% + \gdef\@title{#1}% + \gdef\banner{% + \newpage\setcounter{page}{1}% + \begin{center}\Large#1\end{center}% + }% +} + + +% Miscellany + +\def\implies{\quad\supset\ } + +\def\tdots{\ldots\thinspace} + +\def\boxit#1{\fbox{\sc#1}} + +\def\note#1{\ifdraft\marginpar{\tt#1}\fi} + + +% Fractions (from The TUGboat v6 n1, 1985) + +\def\myfrac#1/#2{% + \leavevmode\kern.1em + \raise.5ex\mbox{\the\scriptfont\z@ #1}\kern-.1em + /\kern-.15em\lower.25ex\mbox{\the\scriptfont\z@ #2}% +} + + +% Trademarks... + +\input trademark + + +% Continuation Captions... + +\input captcont.sty + + +% Startup + +\xdef\today{% + \ifcase\month + \number\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\else + \number\month\fi + \space\number\day, {\noexpand\mit\number\year}% +} + +\begingroup + \count0=\time + \count1=\count0 + \divide\count0 by 60 + \count2=\count0 + \multiply\count0 by 60 + \advance\count1 by -\count0 + \ifnum\count2>11 + \ifnum\count2>12 \advance\count2 by -12\fi + \def\ampm{pm}% + \else + \ifnum\count2=0 \advance\count2 by 12\fi + \def\ampm{am}% + \fi + \xdef\daytime{% + \ifnum\count2<10 0\fi \the\count2:% + \ifnum\count1<10 0\fi \the\count1 + \ampm + }% +\endgroup + + +\makeatother % back to normal diff --git a/doc/manual/texinputs/networking.bib b/doc/manual/texinputs/networking.bib new file mode 100644 index 0000000..4076268 --- /dev/null +++ b/doc/manual/texinputs/networking.bib @@ -0,0 +1,1574 @@ +% ``Networking'' bibliography database for BiB-TeX + + +@techreport{ARP, + author = "David C. Plummer", + title = "{An Ethernet Address Resolution Protocol}", + type = rfc, + number = 825, + institution= nic, + address = sri, + month = sep, + year = 1982 +} + +@techreport{ARPA.MHS, + author = "Stephen E. Kille", + title = "{Mapping between X.400 and RFC822}", + type = rfc, + number = 987, + institution= nic, + address = sri, + month = jun, + year = 1986, + note = {Also available as UCL Technical Report number~120 + and Mailgroup Note number~19} +} + +@techreport{ARPA.mapping.MHS, + author = mtr, + title = "{Mapping Service Elements between ARPA and MHS}", + institution= nrtc, + month = nov, + year = 1985, + note = {Unpublished (superceded by IFIP WG6.5 report)} +} + +@techreport{Assigned.Numbers, + author = "Joyce K. Reynolds", + title = "{Assigned Numbers}", + type = rfc, + number = 1010, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@incollection{ARM, + author = "Michael A. Padlipksy", + title = "{A Perspective on the ARPANET Reference Model}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 5, + pages = {89--115}, + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as ARPA Internet Request for Comments + 871} +} + +@inproceedings{ASDC.DIPS, + author = "Jaime Delgado and Manuel Medina", + title = "{Use of the Abstract Service Definition + Conventions for Distributed Information + Processing Systems Specification}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{Building.Applications, + author = mtr, + title = "{Building Distributed Applications in an OSI + Framework}", + journal = connexions, + volume = 2, + number = 3, + month = mar, + year = 1988, + pages = {2--7} +} + +@inproceedings{Applications.Cookbook, + author = "Julian P. Onions and Marshall T. Rose", + title = "{The Application Cookbook}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@misc{CCITT.ACS.Service, + key = {CCITT}, + title = "{Association Control Service Definition for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.217} +} + +@misc{CCITT.ACS.Protocol, + key = {CCITT}, + title = "{Association Control Protocol Specification for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.227} +} + +@misc{CCITT.Directory, + key = {CCITT}, + title = "{The Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.500} +} + +@misc{CCITT.MHS, + key = {CCITT}, + title = "{Message Handling: System and Service Overview}", + year = 1988, + howpublished= ccitt, + note = {Recommendation X.400} +} + +@misc{CCITT.TP.Service, + key = {CCITT}, + title = "{Transport Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.214} +} + +@misc{CCITT.TP.Protocol, + key = {CCITT}, + title = "{Transport Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Service, + key = {CCITT}, + title = "{Session Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Protocol, + key = {CCITT}, + title = "{Session Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.225} +} + +@misc{CCITT.PP.Service, + key = {CCITT}, + title = "{Presentation Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.216} +} + +@misc{CCITT.PP.Protocol, + key = {CCITT}, + title = "{Presentation Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.226} +} + +@misc{CCITT.PP.Syntax, + key = {CCITT}, + title = "{Specification of Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.208} +} + +@misc{CCITT.PP.Encoding, + key = {CCITT}, + title = "{Specification of Basic Encoding + Rules for Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.209} +} + +@misc{CCITT.ROS.Service, + key = {CCITT}, + title = "{Remote Operations: Model, Notation and Service + Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.219} +} + +@misc{CCITT.ROS.Protocol, + key = {CCITT}, + title = "{Remote Operations: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.229} +} + +@misc{CCITT.RTS.Service, + key = {CCITT}, + title = "{Reliable Transfer: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.218} +} + +@misc{CCITT.RTS.Protocol, + key = {CCITT}, + title = "{Reliable Transfer: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.228} +} + +@book{Computer.Networks, + author = "Andrew S. Tanenbaum", + title = "{Computer Networks}", + publisher= {Prentice-Hall}, + series = {Prentice Hall Software Series}, + year = 1988, + note = {ISBN 0--13--162959--X} +} + +@techreport{Courier.BSD, + author = "Eric C. Cooper", + title = "{Writing Distributed Programs with Courier}", + institution= {Computer Science Division~---~EECS}, + address = {University of California, Berkeley}, + month = mar, + year = 1982 +} + +@techreport{DNS, + author = "Paul V. Mockapetris", + title = "{Domain Names --- Concepts and Facilities}", + type = rfc, + number = 1033, + institution= nic, + address = sri, + month = Nov, + year = 1987 +} + +@misc{DoD.OSI, + key = {DDN}, + title = "{The Department of Defense Open Systems + Interconnection (OSI) Implementation Strategy}", + month = may, + year = 1988, + note = {The MITRE Corporation} +} + +@misc{ECMA.ROS, + key = {ECMA}, + title = "{Remote Operations: Concepts, Notation and + Connection-Oriented Mappings}", + month = dec, + year = 1985, + note = {ECMA TR/31} +} + +@techreport{EON, + author = "Robert A. Hagens and Nancy E. Hall and + Marshall T. Rose", + title = "{Use of the DARPA/NSF Internet as a Subnet for + Experimentation with the OSI Network Layer}", + type = rfc, + number = 1070, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@techreport{EON.addressing, + author = "Ross Callon and Hans-Werner Braun", + title = "{Guidelines for the use of Internet-IP + addresses in the ISO Connectionless-Mode Network + Protocol}", + type = rfc, + number = 1069, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@techreport{FTP, + key = {FTP}, + author = {Jon B. Postel}, + title = "{File Transfer Protocol}", + type = rfc, + number = 959, + institution= nic, + address = sri, + month = oct, + year = 1985, + note = {See also \milstd/ 1780} +} + +@incollection{Gateways.Heffalumps, + author = "Michael A. Padlipksy", + title = "{Gateways, Architectures, and Heffalumps}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 10, + pages = {167--176}, + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as ARPA Internet Request for Comments + 875} +} + +@misc{GOSIP, + key = {USGOSIP}, + title = "{U.S.~Government Open Systems Interconnection + Profile (GOSIP)}", + month = aug, + year = 1988, + note = {U.S.~Federal Information Processing Standards + Publication~146} +} + +@misc{UK.GOSIP, + key = {UKGOSIP}, + title = "{U.K.~Government OSI Profile}", + month = jan, + year = 1988, + note = {Version~3.0} +} + +@article{Host.Multicasting, + author = "Stephen E. Deering", + title = "{Multicast Routing in Internetworks and + Extended LANs}", + journal = ccr, + volume = 18, + number = 4, + month = aug, + year = 1988, + pages = {55--64} +} + +@techreport{Interim.Addresses, + author = "Stephen E. Kille", + title = "{An interim approach to use of Network Addresses}", + type = "Research Note", + number = {RN/89/14}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@article{ISODE.Horizontal, + author = mtr, + title = "{ISODE: Horizontal Integration in Networking}", + journal = connexions, + volume = 1, + number = 1, + month = may, + year = 1987, + pages = {8--12} +} + +@techreport{IP, + key = {IP}, + author = {Jon B. Postel}, + title = "{Internet Protocol}", + type = rfc, + number = 791, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1777} +} + +@misc{IP.Requirements, + key = {NSF}, + title = "{Requirement for Internet Gateways~---~Draft}", + month = may, + year = 1986, + note = {ARPA Internet Request for Comments 985, prepared by + the Gateway Requirements Subcommitee of the National + Science Foundation's Network Technical Advisory Group, + David L.~Mills, chair} +} + +@misc{ISO.ALS, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Application Layer Structure}", + month = mar, + year = 1987, + howpublished= iso/iec, + note = {Draft Proposal 9534} +} + +@misc{ISO.ACS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Service Definition for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8649} +} + +@misc{ISO.ACS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~--~Protocol Specification for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8650} +} + +@misc{ISO.Directory, + key = {ISO}, + title = "{Information Processing Systems~---~Open + Systems Interconnection~---~The + Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= iso/iec, + note = {International Standard 9594-1} +} + +@misc{ISO.DLP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Data Link Service Definition}", + month = dec, + year = 1987, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8886--2} +} + +@misc{ISO.LAN, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802} +} + +@misc{ISO.LAN.LLC, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks~---~Logical Link Control}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802--2} +} + +@misc{ISO.LAN.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 over Local Area + Networks to Provide the OSI Connection-mode + Network Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8881} +} + +@misc{ISO.FTAM, + key = {ISO}, + title = "{Information Processing Systems~---~File + Transfer, Access, and Management}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8571} +} + +@misc{ISO.MOTIS, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~MOTIS~---~Message Handling: + System and Service Overview}", + month = nov, + year = 1988, + howpublished= iso/iec, + note = {Draft International Standard 8505-1} +} + +@misc{ISO.NP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service Definition}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348} +} + +@misc{ISO.NP.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 1: Connectionless-mode + Transmission}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 1} +} + +@misc{ISO.NP.Addressing, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 2: Network Layer Addresisng}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 2} +} + +@misc{ISO.NP.CLNP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol for providing the + Connectionless-mode Network Service and Provision + of Underlying Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {Consolidated Final Text of Draft International + Standard 8473} +} + +@misc{ISO.NP.X25, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 to Provide the + OSI Connection-mode Network Service}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8878} +} + +@misc{ISO.X25.PLP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~X.25 Packet Level Protocol}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8208} +} + +@misc{ISO.X25.LAPB, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~High-level Data Link Control + Procedures~---~Description of the X.25 + LAPB-compatible DTE Data Link Procedures}", + month = dec, + year = 1986, + howpublished= iso/iec, + note = {International Standard 7776} +} + +@misc{ISO.NP.IONL, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Internal Organization of + the Network Layer}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8648} +} + +@misc{ISO.NS.Principles, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 1: General Principles}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--1} +} + +@misc{ISO.NS.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 2: Provision and Support of + the connection-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--2} +} + +@misc{ISO.NS.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 3: Provision and Support of + the connectionless-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--3} +} + +@misc{ISO.PP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Service Definition}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8822} +} + +@misc{ISO.PP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Protocol Specification}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8823} +} + +@misc{ISO.PP.Syntax, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Abstract Syntax + Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8824} +} + +@misc{ISO.PP.Encoding, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Basic Encoding + Rules for Abstract Syntax Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8825} +} + +@misc{ISO.ASN1.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8824/DAD 1} +} + +@misc{ISO.BER.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1 Basic Encoding Rules}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8825/DAD 1} +} + +@misc{ISO.ROS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~1: Model, Notation and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-1} +} + +@misc{ISO.ROS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-2} +} + +@misc{ISO.RTS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~1: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-1} +} + +@misc{ISO.RTS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-2} +} + +@misc{ISO.SP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8326} +} + +@misc{ISO.SP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8327} +} + +@misc{ISO.SS.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 1: + Session Symmetric Synchronization for the + Session Service}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 1} +} + +@misc{ISO.SP.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 1: + Session Symmetric Synchronization for the + Session Protocol}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 1} +} + +@misc{ISO.SS.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 2} +} + +@misc{ISO.SP.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 2} +} + +@misc{ISO.TP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Service Definition}", + mon = jun, + year = 1985, + howpublished= iso/iec, + note = {International Standard 8072} +} + +@misc{ISO.TP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Protocol Specification}", + mon = jul, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8073} +} + +@misc{ISO.VT, + key = {ISO}, + title = "{Information Processing Systems~---~Virtual Terminal + Service: Basic Class}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 9040} +} + +@article{ISO.on.DDN, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{OSI Transport Services on top of the TCP}", + journal = cn/isdn, + volume = 12, + number = 3, + year = 1986, + note = {Also available as NRTC Technical Paper \#700.} +} + +@article{Internet.Architecture, + author = "Vinton G. Cerf and Edward A. Cain", + title = "{The DoD Internet Architecture Model}", + journal = cn/isdn, + volume = 7, + number = 10, + month = oct, + year = 1983, + pages = {307--318} +} + +@techreport{Internet.NM, + author = "Vinton G. Cerf", + title = "{IAB Recommendations for the Development of + Internet Network Management Standards}", + type = rfc, + number = 1052, + institution= nic, + address = sri, + month = apr, + year = 1988 +} + +@techreport{Internet.SMI, + author = "Marshall T. Rose and Keith McCloghrie", + title = "{Structure and Identification of Management + Information for TCP/IP based internets}", + type = rfc, + number = 1065, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@techreport{Internet.MIB, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Management Information Base Network Management + of TCP/IP based internets}", + type = rfc, + number = 1066, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@inproceedings{Layers, + author = "Danny Cohen and Jon B. Postel", + title = "{The ISO Reference Model and Other Protocol + Architectures}", + booktitle= {Proceedings of the IFIP Congress}, + year = 1983, + note = {Paris, France} +} + +@inproceedings{Management.TCP-IP, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + booktitle= "{Proceedings of the Digital Equipment Computer + Users Society}", + pages = {167--169}, + month = "Fall", + year = 1988 +} + +@article{Management.TCP-IP.Again, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {3--9} +} + +@misc{MHS, + key = {CCITT}, + title = "{Message Handling Systems: System Model-Service + Elements}", + month = oct, + year = 1984, + note = ccitt +} + +@misc{MHS.Elements, + key = {CCITT}, + title = "{Message Handling Systems: Basic Service Elements + and Optional User Facilities}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.401} +} + +@misc{MHS.Conversion, + key = {CCITT}, + title = "{Message Handling Systems: Encoded Information Type + Conversion Rules}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.408} +} + +@misc{MHS.Notation, + key = {CCITT}, + title = "{Message Handling Systems: Presentation Transfer + Syntax and Notation}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.409} +} + +@misc{MHS.RTS, + key = {CCITT}, + title = "{Message Handling Systems: Remote Operations and + Reliable Transfer Server}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.410} +} + +@misc{MHS.P1, + key = {CCITT}, + title = "{Message Handling Systems: Message Transfer Layer}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.411} +} + +@misc{MHS.P2, + key = {CCITT}, + title = "{Message Handling Systems: Interpersonal Messaging + User Agent}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.420} +} + +@misc{MHS.Teletex, + key = {CCITT}, + title = "{Message Handling Systems: Access Protocol for + Teletex Terminals}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.430} +} + +@misc{NBS.TP, + key = {NBS}, + title = "{Implementation Agreements Among Implementors of + OSI Protocols}", + month = may, + year = 1985, + note = {National Bureau of Standards} +} + +@techreport{NETBLT, + author = "David D. Clark and Mark L. Lambert and Lixia Zhang", + title = "{NETBLT: A Bulk Data Transfer Protocol}", + type = rfc, + number = 998, + institution= nic, + address = sri, + month = mar, + year = 1987 +} + +@manual{NFS, + title = "Network File System Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@misc{NRC.Report, + key = {NRC}, + title = "{Transport Protocols for Department of Defense Data + Networks}", + howpublished= {National Academy Press}, + month = feb, + year = 1985, + note = {Report to the Department of Defense and + the National Bureau of Standards by the Committee on + Computer-Computer Communication Protocols, Board on + Telecommunications and Computer Applications + Commission on Engineering and Technical Systems, + National Research Council, + C. Chaplin Cutler, chair + (Executive Summary available as ARPA Internet Request + for Comments 939)} +} + +@article{Netman.Demo, + author = "George Marshall", + title = "{The NetMan Demonstration at INTEROP '88}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {20} +} + +@article{NSFnet.Backbone, + author = "David L. Mills and Hans-Werner Braun", + title = "{The NSFNET Backbone Network}", + journal = ccr, + volume = 17, + number = 5, + month = aug, + year = 1987, + pages = {191--196} +} + +@techreport{Official.Protocols, + author = "{IAB}", + title = "{IAB Official Protocol Standards}", + type = rfc, + number = 1083, + institution= nic, + address = sri, + month = dec, + year = 1988, + note = {Internet Activities Board} +} + +@misc{OSI, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Basic Reference Model}", + mon = oct, + year = 1984, + note = {Interational Standard 7498} +} + +@misc{OSI.Implementors, + key = {NIST}, + title = "{Stable Implementation Agreements for Open + Systems Interconnection Protocols}", + month = dec, + year = 1988, + note = {Version 1, Edition 4} +} + +@article{OSI.POSIX, + author = mtr, + title = "{OSI Protocols within an openly available, + POSIX-conformant, Berkeley UNIX environment}", + journal = connexions, + volume = 2, + number = 10, + month = oct, + year = 1988, + pages = {11--13} +} + +@book{Open.Book, + author = mtr, + title = "{The Open Book: A Practical Perspective on Open + Systems Interconnection}", + publisher= {Prentice-Hall}, + year = 1989, + note = {(to appear)} +} + +@techreport{PSAP.on.TCP.old, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = idea, + number = 17, + institution= nic, + address = sri, + month = mar, + year = 1988 +} + +@techreport{PSAP.on.TCP, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = rfc, + number = 1085, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@article{Protocol.Conversion, + author = "Green, Jr., Paul E.", + title = "{Protocol Conversion}", + journal = ieeecom, + volume = {COM--34}, + number = 3, + month = mar, + year = 1986, + pages = {257--268} +} + +@techreport{QUIPU.Design, + author = "Stephen E. Kille", + title = "{The Design of QUIPU}", + type = "Research Note", + number = {RN/89/19}, + institution= {Department of Computer Science}, + address = ucl, + month = mar, + year = 1989 +} + +@inproceedings{QUIPU.Directory, + author = "Stephen E. Kille", + title = "{The QUIPU Directory Service}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@inproceedings{PP.MTA, + author = "Stephen E. Kille", + title = "{PP -- A Message Transfer Agent}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@techreport{RawPacket, + author = mtr, + title = "{Low Tech Connections in to the ARPA Internet: + The RawPacket Split-Gateway}", + number = 216, + institution= ics, + address = uci, + month = feb, + year = 1984 +} + +@techreport{RFC822, + author = "David H. Crocker", + title = "{Standard for the Format of ARPA Internet Text + Messages}", + type = rfc, + number = 822, + institution= nic, + address = sri, + month = aug, + year = 1982 +} + +@article{Session.Hints, + author = "Fausto Caneschi", + title = "{Hints for the Interpretation of the ISO + Session Layer}", + journal = ccr, + volume = 16, + number = 4, + month = aug, + year = 1986, + pages = {34--72} +} + +@techreport{Silly.Window, + author = "David D. Clark", + title = "{Window and Acknowledgement Strategy in TCP}", + type = rfc, + number = 813, + institution= nic, + address = sri, + month = jul, + year = 1982 +} + +@techreport{SMTP, + key = {SMTP}, + author = {Jon B. Postel}, + title = "{Simple Mail Transfer Protocol}", + type = rfc, + number = 821, + institution= nic, + address = sri, + month = aug, + year = 1982, + note = {See also \milstd/ 1781} +} + +@manual{SNA, + title = "{Systems Network Architecture Technical Overview}", + key = {IBM}, + organization= {International Business Machines, Incorporated, + Data Processing Division}, + address = {White Plains, New York}, + month = mar, + year = 1982, + note = {Document Number GC30--3073--0} +} + +@techreport{SGMP, + author = "James R. Davin and Jeffrey D. Case and Mark S. + Fedor and Martin L. Schoffstall", + title = "{A Simple Gateway Monitoring Protocol}", + type = rfc, + number = 1028, + institution= nic, + address = sri, + month = nov, + year = 1987 +} + +@inproceedings{SNA.convert.XNS, + author = "Kenneth O. Zoline and William P. Lidinksy", + title = "{An Approach for Interconnecting SNA and XNS + Networks}", + booktitle= "{Proceedings, Ninth Data Communications Symposium}", + pages = {184--198}, + organization= {ACM Special Interest Group on Communications}, + publisher= {IEEE Computer Society Press}, + month = sep, + year = 1985 +} + +@techreport{SNMP, + author = "Jeffrey D. Case and Mark S. Fedor and Martin L. + Schoffstall and James R. Davin", + title = "{A Simple Network Management Protocol}", + type = rfc, + number = 1067, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@article{SNMP.Design, + author = "Jeffrey D. Case and James R. Davin + and Mark S. Fedor and Martin L. Schoffstall", + title = "{Network Management and the Design of SNMP}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {22--26} +} + +@techreport{String.Addresses, + author = "Stephen E. Kille", + title = "{A string encoding of Presentation Address}", + type = "Research Note", + number = {RN/89/14}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@techreport{TCP, + key = {TCP}, + author = {Jon B. Postel}, + title = "{Transmission Control Protocol}", + type = rfc, + number = 793, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1778} +} + +@article{TCP.convert.ISO, + author = "Inge Groenbaek", + title = "{Conversion Between the TCP and ISO Transport + Protocols as a Method of Achieving Interoperability + Between Data Communication Systems}", + journal = jsac, + volume = {SAC-4}, + number = 2, + month = mar, + year = 1986, + pages = {288--296} +} + +@article{TCP.convert.OSI, + author = "Michael Witt", + title = "{Moving from DoD to OSI Protocols: A First Step}", + journal = ccr, + volume = 16, + number = 2, + month = {April/May}, + year = 1986, + pages = {1--7} +} + +@inproceedings{TCP.transition.ISO, + author = "Irene Hu", + title = "{Managing the Transition from TCP/IP to ISO + Protcols}", + booktitle= "{Proceedings, Uniforum 1987 Conference}", + pages = {59--74}, + organization= {/usr/group}, + month = jan, + year = 1987 +} + +@article{TCP.wars, + author = mtr, + title = "{Comments on ``Comments on `Congestion Control + in TCP/IP Internetworks'\,''}", + journal = ccr, + volume = 15, + number = 5, + month = {October/November}, + year = 1985, + pages = {2--9} +} + +@inproceedings{TCP.losing.MILSTD, + author = "Deepinder P. Sidhu and Thomas P. Blumer", + title = "{Some Problems with the Specification of the + Military Standard Transmission Control Protocol}", + booktitle= {Proceedings, Fourth International Workshop on Protocol + Specification, Testing, and Verification}, + editor = "Y.~Yemini and et.~al.", + pages = {375--381}, + organization= {IFIP WG 6.1}, + publisher= {North-Holland Publishing Company}, + month = jun, + year = 1985, + note = {Skytop Lodge, Pennsylvania} +} + +@inproceedings{RTT.Improve, + author = "Phil Karn and Craig Partridge", + title = "{Improving Round-Trip Time Estimates in + Reliable Transport Protocols}", + booktitle= "{Proceedings, SIGCOMM '87 Workshop}", + editor = "J. J. Garcia-Luna-Aceves", + pages = {2--7}, + organization= {ACM SIGCOMM}, + publisher= {ACM Press}, + month = aug, + year = 1987, + note = {Stowe, Vermont} +} + +@techreport{TELNET, + key = {TELNET}, + author = {Jon B. Postel}, + title = "{TELNET Protocol Specification}", + type = rfc, + number = 854, + institution= nic, + address = sri, + month = may, + year = 1983, + note = {See also \milstd/ 1782} +} + +@techreport{TP0.bridge, + author = "Julian P. Onions and Marshall T. Rose", + title = "{ISO-TP0 bridge between TCP and X.25}", + type = rfc, + number = 1086, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@article{Transition.and.Coexistence, + author = mtr, + title = "{Transition and coexistence for TCP/IP to OSI}", + journal = connexions, + volume = 2, + number = 12, + month = dec, + year = 1988, + pages = {2--5} +} + +@article{Transport.Bridges, + author = mtr, + title = "{Transport-level ``bridges'' from TCP/IP to OSI/ISO}", + journal = connexions, + volume = 2, + number = 1, + month = jan, + year = 1988, + pages = {2--6} +} + +@techreport{TSAP.on.TCP.old, + author = "Dwight E. Cass and Marshall T. Rose", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 983, + institution= nic, + address = sri, + month = apr, + year = 1986 +} + +@techreport{TSAP.on.TCP, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 1006, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@techreport{UDP, + key = {UDP}, + author = {Jon B. Postel}, + title = "{User Datagram Protocol}", + type = rfc, + number = 768, + institution= nic, + address = sri, + month = aug, + year = 1980 +} + +@misc{White.Book, + author = "{JNT}", + title = "{Transition to OSI Standards}", + howpublished= {U.K.~Joint Network Team}, + month = jul, + year = 1987, + note = {Final Report of the Academic Community OSI + Transition Group} +} + +@article{X.window, + author = "Robert W. Scheifler and Jim Gettys", + title = "{The X Window System}", + journal = tog, + volume = 5, + number = 2, + month = apr, + year = 1986, + pages = {79--109}, + note = {Special Issue on User Interface Software} +} + +@manual{XDR, + title = "External Data Representation Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@inproceedings{XDR.Comparison, + author = "Craig Partridge and Marshall T. Rose", + title = "{A Comparison of External Data Formats}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} diff --git a/doc/manual/texinputs/pp.bib b/doc/manual/texinputs/pp.bib new file mode 100644 index 0000000..4d4b06d --- /dev/null +++ b/doc/manual/texinputs/pp.bib @@ -0,0 +1,89 @@ +@string{nh = "North Holland Publishing"} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {5.0}, + author = mtr, + organization= twg, + month = mar, + year = 1989 +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{BIND, + title = "{Name Server Operations Guide for BIND}", + author = "Kevin J. Dunlap", + organization= "University of California, Berkeley", + note = "{BSD 4.3 Release}" +} + +@techreport{TSAP.on.TCP, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 1006, + institution= nic, + address = sri, + month = may, + year = 1987 +} +@techreport{POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{RFC1148, + author = "Stephen E. Kille", + title = "{Mapping between X.400(1988)/ISO10021 and RFC822}", + type = rfc, + number = 1148, + institution= nic, + address = sri, + month = jul, + year = 1989, +} +@techreport{RFC934, + author = "{Marshall T. Rose and Einar A. Stefferud}", + title = "{Proposed Standard for Message Encapsulation}", + type = rfc, + number = 934, + institution= nic, + address = sri, + month = jan, + year = 1985, +} + +@Inproceedings{IFIP.PP, + Author = { S.E. Kille }, + Title = { {PP} - A Message Transfer Agent }, + Publisher = nh, + Booktitle = { IFIP WG 6.5 Conference on Message Handling Systems + and Distributed Applications }, + Month = oct, + Pages = {115-118}, + Year = { 1988 } } + +@techreport{String.Addresses, + author = "Stephen E. Kille", + title = "{A string encoding of Presentation Address}", + type = "Research Note", + number = {RN/89/14}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} diff --git a/doc/manual/texinputs/sfwdoc.bib b/doc/manual/texinputs/sfwdoc.bib new file mode 100644 index 0000000..fb59687 --- /dev/null +++ b/doc/manual/texinputs/sfwdoc.bib @@ -0,0 +1,346 @@ +% ``Software'' bibliography database for BiB-TeX + + +@manual{AmSTeX, + author = "Michael Spivak", + title = "{Summary of \AmSTeX{}}", + month = sep, + year = 1983 +} + +@manual{BFLY.NRTC, + title = "{Using the BB\&N Butterfly at NRTC}", + author = "John L. Romine and Marshall T. Rose", + organization= nrtc, + month = may, + year = 1986 +} + +@manual{BibTeX, + author = "Oren Patashnik", + title = "{\BibTeX{}ing}", + month = may, + year = 1983 +} + +@manual{BSD.NET, + title = "{4.2BSD Networking Implementation Notes}", + author = "Samuel J. Leffler and William N. Joy and + Robert S. Fabry", + organization= {Computer Systems Research Group, + Computer Science Division}, + address = {Department of Electrical Engineering and Computer + Science, University of California, Berkeley}, + month = jul, + year = 1983 +} + +@book{C.Language, + author = "Brian W. Kernighan and Dennis M. Ritchie", + title = "{The C Programming Language}", + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + series = {Software Series}, + year = 1978 +} + +@manual{Emacs, + author = "James Gosling", + title = "{UNIX EMACS, UCI Version}", + month = may, + year = 1982 +} + +@manual{EtherTIP, + title = "{Using the Bridge CS/1 at NRTC}", + author = mtr, + organization= nrtc, + month = may, + year = 1986 +} + +@inproceedings{Face.Nation, + author = "Rob Pike and David L. Presotto", + title = "{Face the Nation}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {81--86}, + month = jun, + year = 1985, + note = {Portland, Oregon} +} + +@techreport{ISO.Environment, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{The ISO Development Environment at NRTC: User's + Manual}", + type = {Technical Paper}, + number = {\#702}, + institution= nrtc, + month = sep, + year = 1986 +} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {4.0}, + author = mtr, + organization= twg, + month = aug, + year = 1988 +} + +@book{LaTeXbook, + author = "Leslie Lamport", + title = "{\LaTeX{}: A Document Preparation System}", + publisher= {Addison-Wesley}, + address= {Reading, Massachusetts}, + year = 1985 +} + +@manual{MH.4, + title = "{Changes to the Rand MH Message Handling System: + MH.4}", + edition = {\mh4}, + author = mtr, + month = jul, + year = 1984, + note = {MH documentation set} +} + +@manual{MH.5, + title = "{Changes to the Rand MH Message Handling System: + MH.5}", + edition = {\mh5}, + author = mtr, + month = jan, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.6, + title = "{Changes to the Rand MH Message Handling System: + MH.6}", + author = mtr, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.ADM, + title = "{The Rand MH Message Handling System: + Administrator's Guide}", + author = mtr, + organization= ics, + address = uci, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.BB, + title = "{The Rand MH Message Handling System: + The UCI BBoards Facility}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.Beginners, + title = "{MH for Beginners}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.MM, + title = "{MH for MM Users}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@techreport{MH.POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{MH.XPOP, + author = mtr, + title = "{Post Office Protocol~---~Version 3: + Extended Service Offerings}", + type = rfc, + number = 1082, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@manual{MH.USR, + title = "{The Rand MH Message Handling System: + User's Manual}", + author = "Marshall T. Rose and John L. Romine", + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.TUT, + title = "{The Rand MH Message Handling System: + Tutorial}", + author = "Marshall T. Rose and Jerry N. Sweet", + month = may, + year = 1985, + note = {MH documentation set} +} + +@inproceedings{MMDF, + author = "David H. Crocker and E.S. Szurkowski and + David J. Farber", + title = "{An Internetwork Memo Distribution + Facility~---~MMDF}", + booktitle= "{Proceedings, Sixth Data Communications Symposium}", + pages = {18--25}, + month = nov, + year = 1979, + note = {Asilomar} +} + +@inproceedings{MMDFII, + author = "Douglas P. Kingston~III", + title = "{MMDFII: A Technical Review}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {32--41}, + month = jun, + year = 1984, + note = {Salt Lake City, Utah} +} + +@manual{PhDTeX, + author = "E. Timothy Morgan", + title = "{A Dissertation Style for \AmSTeX{}}", + month = sep, + year = 1984, + note = {Department of Information and Computer Science, + University of California, Irvine} +} + +@techreport{PIC, + author = "Brian W. Kernighan", + title = "{PIC --- A Graphics Language for Typesetting User + Manual}", + type = {Computing Science Technical Report}, + number = 85, + institution= {Bell Laboratories}, + address = {Murray Hill, New Jersey}, + month = mar, + year = 1982 +} + +@manual{SendMail, + title = "{SENDMAIL~---~An Internetwork Mail Router}", + author = "Eric Allman", + organization= {Britton-Lee, Inc.}, + address = {Berkeley, California}, + month = jul, + year = 1983 +} + +@manual{Slides, + title = "{Using \SLiTeX{} to Make Slides at NRTC}", + author = mtr, + organization= nrtc, + month = apr, + year = 1986 +} + +@manual{STREAMS, + key = {ATT}, + title = "{STREAMS Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@book{SVID, + key = {SVID}, + title = "{System V Interface Definition}", + publisher= {AT\&T Bell Laboratories}, + edition = {$2^{\underline{\mbox{\scriptsize nd}}}$}, + year = 1986 +} + +@book{TeXbook, + author = "Donald E. Knuth", + title = "{The \TeX{}book}", + publisher= {Addison-Wesley}, + address = {Reading, Massachusetts}, + year = 1983 +} + +@techreport{TeX.Roff, + author = "Michael Urban", + title = "{A Guide to \TeX{} for the Troff User}", + institution= {TRW Software Productivity Project}, + month = oct, + year = 1984 +} + +@misc{TeX.Trip, + author = "Donald E. Knuth", + title = "{A Test File for \TeX{}}", + month = jul, + year = 1983, + note = {Version 0.999} +} + +@manual{TLI, + key = {ATT}, + title = "{Network Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@manual{UCI.map, + title = "{The UCI RoadMap}", + author = mtr, + organization= nrtc, + month = jun, + year = 1986 +} + +@article{WEB.TUT, + author = "Donald E. Knuth", + title = "{Literate Programming}", + journal = {The Computer Journal}, + year = 1983 +} + +@manual{WEB.USR, + author = "Donald E. Knuth", + title = "{WEB USER MANUAL}", + year = 1983 +} diff --git a/doc/manual/texinputs/sfwmac.sty b/doc/manual/texinputs/sfwmac.sty new file mode 100644 index 0000000..3889ed8 --- /dev/null +++ b/doc/manual/texinputs/sfwmac.sty @@ -0,0 +1,66 @@ +% LaTeX support for writing UNIX-style documentation + + +% UNIX-style references + +\def\sfwFILfont{\sl} + +\def\@egaux#1#2#3{% + \def#1##1{% + #2\begingroup \tt \let\do=\@makeother \dospecials + \def\@tempa####1##1{####1\endgroup#3}\@tempa + }% +} + +\def\pgm#1{\mbox{\it#1}\index{#1}} % programs +\def\xpgm#1#2{\mbox{\it#1}\index{\noexpand\noexpand\noexpand#2{}}} +\def\man#1(#2){\xpgm{#1\/}{#1}(#2)} % manual entries +\@egaux\arg{`{}}{'{}} % arguments to programs +\@egaux\switch{`{}-}{'{}} % switches to programs +\def\file#1{\mbox{\sfwFILfont#1}\index{#1}} % filename + + +% Commonly used software systems + +\def\sfwPGMfont{\sf} + +\def\@sfwdef#1#2{\@sfwaux{#1/}{#2}} +\def\@sfwaux#1#2{\def#1{\mbox{#2}\index{\noexpand\noexpand\noexpand#1{}}}} + +\@sfwdef\EMACS{\sfwPGMfont EMACS} +\@sfwdef\INFO{\sfwPGMfont INFO} +\@sfwdef\MLisp{\sfwPGMfont MLisp} + +\@sfwdef\MH{\sfwPGMfont MH} +\def\mh#1{\mbox{\sfwPGMfont mh.#1}\index{mh.#1}} +\@sfwdef\Mail{\file{Mail/}} +\@sfwdef\context{\file{context}} +\@sfwdef\profile{\file{.mh\_profile}} +\@sfwdef\sequences{\file{.mh\_sequences}} +\def\whatnow/{\verb*"What now?"\index{whatnow}} + +\@sfwdef\MMDF{\sfwPGMfont MMDF} +\@sfwdef\MMDFI{\sfwPGMfont MMDF-I} +\@sfwdef\MMDFII{\sfwPGMfont MMDF-II} + +\@sfwdef\SendMail{\sfwPGMfont SendMail} +\@sfwdef\UUCP{\sfwPGMfont UUCP} + +\def\AmS{$\cal A$\kern-.1667em\lower.5ex\hbox{$\cal M$}\kern-.125em$\cal S$} +\@sfwaux\AmSTeX{\rm \AmS-\TeX} + +\@sfwaux\PhDTeX{\rm P\kern-.05em{\sc h\kern-.025em D}\kern-0.08em\TeX} + +\@sfwaux\LaTeX{\rm L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em\TeX} +\@sfwaux\BibTeX{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em\TeX} +\@sfwaux\SLiTeX{\rm S\kern-.06em{\sc l\kern-.035emi}\kern-.06em\TeX} + +\@sfwaux\NRTeX{\rm NR-\TeX} + +\@sfwdef\ROFF{\sfwPGMfont ROFF} + +\@sfwdef\SUMEX{\sfwPGMfont SUMEX} + +\@sfwdef\WEB{\sfwPGMfont WEB} + +\@sfwdef\TTYD{\sfwPGMfont TTYD} diff --git a/doc/manual/texinputs/tgrind.sty b/doc/manual/texinputs/tgrind.sty new file mode 100644 index 0000000..5177d05 --- /dev/null +++ b/doc/manual/texinputs/tgrind.sty @@ -0,0 +1,203 @@ +% LaTeX tgrind environment + +% Based on Van Jacobson's ``tgrindmac'', a macro package for TeX grinding +% Our job here is to simplify it quite a bit and make it conform to LaTeX + +\newif\ifcomment\newif\ifstring +\commentfalse\stringfalse +\newcount\linecount\newcount\linenext +\newbox\linesofar +\newdimen\TBwid +\newdimen\ts +\newbox\tbox + +\def\tgrind{% +\commentfalse\stringfalse +% Stuff we ignore for right now. +\let\Head=\@gobble +\def\File##1,##2,##3{} +\let\Proc=\@gobble +\let\ProcCont=\@gobble +% +% Each formfeed in the input is replaced by a "\NewPage" macro. If +% you really want a page break here, define this as "\vfill\eject". +\def\NewPage{\filbreak\bigskip} +% +% Each line of the program text is enclosed by a "\L{...}". We turn +% each line into an hbox of size hsize. If we saw a procedure name somewhere +% in the line (i.e., "procbox" is not null), we right justify "procbox" +% on the line. Every 10 lines we output a small, right justified line number. +\def\L##1{\par\hbox to\hsize{\CF\strut\global\advance\linecount by1 +##1\hss\linebox}} +% +\linecount=0 +\linenext=9 +\def\linebox{\ifnum\linecount>\linenext\global\advance\linenext by10 +\hbox{\sevrm\the\linecount}\fi} +% +% The following weirdness is to deal with tabs. "Pieces" of a line +% between tabs are output as "\LB{...}". E.g., a line with a tab at +% column 16 would be output as "\LB{xxx}\Tab{16}\LB{yyy}". (Actually, to +% reduce the number of characters in the .tex file the \Tab macro +% supplies the 2nd & subsequent \LB's.) We accumulate the LB stuff in an +% hbox. When we see a Tab, we grab this hbox (using "\lastbox") and turn +% it into a box that extends to the tab position. We stash this box in +% "\linesofar" & use "\everyhbox" to get \linesofar concatenated onto the +% front of the next piece of the line. (There must be a better way of +% doing tabs [cf., the Plain.tex tab macros] but I'm not not enough of a +% TeX wizard to come up with it. Suggestions would be appreciated.) +\def\LB{\CF\hbox} +\setbox\linesofar=\null +\everyhbox={\box\linesofar} +\def\Tab##1{\setbox\tbox=\lastbox\TBwid=1\wd\tbox\advance\TBwid by 1\ts +\ifdim\TBwid>##1\ts +\setbox\linesofar=\hbox{\box\tbox\space}\else +\setbox\linesofar=\hbox to ##1\ts{\box\tbox\hfil}\fi\LB} +% +% A normal space is too thin for code listings. We make spaces & tabs +% be in "\ts" units (which are the width of a "0" in the current font). +\setbox\tbox=\hbox{0} \ts=1\wd\tbox \setbox\tbox=\hbox{\hskip 1\ts} +\def\space{\hskip 1\ts\relax} +% +% Font changing stuff for keywords, comments & strings. We put keywords +% in boldface, comments in text-italic & strings in typewriter. Since +% we're usually changing the font inside of a \LB macro, we remember the +% current font in \CF & stick a \CF at the start of each new box. +% Also, the characters " and ' behave differently in comments than in +% code, and others behave differently in strings than in code. +\let\CF=\rm +\def\K##1{{\bf ##1}} % Keyword +\def\C{\it\global\let\CF=\it\global\commenttrue\relax} % Comment Start +\def\CE{\rm\global\let\CF=\rm\global\commentfalse\relax}% Comment End +\def\S{\tt\global\let\CF=\tt\global\stringtrue\relax} % String Start +\def\SE{\rm\global\let\CF=\rm\global\stringfalse\relax} % String End +% +% Special characters. +\def\{{\ifmmode\lbrace\else\ifstring{\char'173}\else$\lbrace$\fi\fi} +\def\}{\ifmmode\rbrace\else\ifstring{\char'175}\else$\rbrace$\fi\fi} +\def\!{\ifmmode\backslash\else\ifstring{\char'134}\else$\backslash$\fi\fi} +\def\|{\ifmmode|\else\ifstring{\char'174}\else$|$\fi\fi} +\def\<{\ifmmode<\else\ifstring<\else$<$\fi\fi} +\def\>{\ifmmode>\else\ifstring>\else$>$\fi\fi} +\def\/{\ifmmode/\else\ifstring/\else$/$\fi\fi} +\def\-{\ifmmode-\else\ifstring-\else$-$\fi\fi} +\def\_{\ifstring{\char'137}\else\underbar{\ }\fi} +\def\&{{\char'046}} +\def\#{{\char'043}} +\def\%{{\char'045}} +\def\~{{\char'176}} +\def\"{\ifcomment''\else{\tt\char'042}\fi} +\def\'{\ifcomment'\else{\tt\char'047}\fi} +\def\^{{\char'136}} +\def\${{\rm\char'044}} +% +\raggedright\obeyspaces%\let =\space% +} + +% \tagrind*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeXgrind input in file FILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagrind{\@ifstar{\@stagrind}{\@tagrind}} + +\def\@tagrind{\@ifnextchar[{\@@tagrind}{\@@tagrind[t]}} +\def\@stagrind{\@ifnextchar[{\@@stagrind}{\@@stagrind[t]}} + +\def\@@tagrind[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \vskip .5\baselineskip + \begin{minipage}\columnwidth\small + \begin{tgrind} + \input #2\relax + \end{tgrind} + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@stagrind[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \vskip .5\baselineskip + \begin{minipage}\textwidth\small + \begin{tgrind} + \input #2\relax + \end{tgrind} + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +\def\tgrindfile#1{% + \par\addvspace{0.1in} + \hrule + \vskip .5\baselineskip + \begin{footnotesize} + \begin{tgrind} + \input #1\relax + \end{tgrind} + \end{footnotesize} + \vskip .5\baselineskip + \hrule + \addvspace{0.1in} +} + + +% \tagrindfile{FILE}{CAPTION}{LABEL} + +\def\tagrindfile#1#2#3{% + \par\addvspace{0.1in} + \begingroup + \hrule + \vskip .5\baselineskip + \def\@captype{figure} + \begingroup + \setbox\z@=\hbox{#3}% + \ifdim\wd\z@>\z@ + \refstepcounter{\@captype} + \label{#3}% + \fi + \endgroup + \begin{tgrind}\footnotesize + \input #1\relax + \end{tgrind} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#3}% + \ifdim\wd\z@>\z@ + \@dblarg{\@caption\@captype}{#2}% + \else + \captcont{#2}% + \fi + \endgroup + \vskip 2pt + \hrule + \endgroup + \addvspace{0.1in} +} diff --git a/doc/manual/texinputs/trademark.tex b/doc/manual/texinputs/trademark.tex new file mode 100644 index 0000000..382ab1b --- /dev/null +++ b/doc/manual/texinputs/trademark.tex @@ -0,0 +1,82 @@ +% Trademarks... + +\def\gobble#1{} +\def\tradeORGfont{\sc} % used for organizations (e.g., ACM) +\def\tradeNAMfont{\sf} % used for names (e.g., Ada) + +\def\tradeorg#1{% + \tradeaux{#1}{\expandafter\gobble\string#1}\empty\tradeORGfont +} +\def\tradeorgn#1#2{% + \tradeaux{#1}{#2}\empty\tradeORGfont +} +\def\tradename#1#2#3{\tradeaux{#1}{#2}{#3}\tradeNAMfont} +\def\trademark#1#2{% + \tradeaux{#1}{\expandafter\gobble\string#1}{#2}\tradeNAMfont +} + +\def\tradeaux#1#2#3#4{% + \def#1/{\relax}% % in case #3 references #1 + \setbox0=\hbox{#3}% % when we make the \hbox + \ifdim\wd0>0pt + \gdef#1/{% + \tradeaux{#1}{#2}\empty{#4}% + #1/\footnote{#1/ is a trademark of #3.}% + }% + \else + \gdef#1/{{#4#2}}% + \fi +} + +\tradeorg\acm +\tradeorg\ansi +\tradename\Ada{Ada} + {the Department of Defense (\Ada/ Joint Program Office)} +\tradename\balance{Balance} {Sequent Computer Systems, Incorporated} +\tradeorg\bsd +\tradename\butterfly{Butterfly}{Bolt, Beranek, and Newman, Incorporated} +\tradeorg\ccitt +\tradename\cms{CMS} {International Business Machines, Incorporated} +\tradename\cpm{CP/M} {Digital Research Corporation} +\tradename\chrysalis{Chrysalis}{Bolt, Beranek, and Newman, Incorporated} +\tradename\decnet{DECnet} {Digital Equipment Corporation} +\tradeorgn\dod{DoD} +\tradename\dynix{DYNIX} {Sequent Computer Systems, Incorporated} +\tradename\ethernet{Ethernet} {the Xerox Corporation} +\tradename\eunice{Eunice} \empty +\tradename\exos{EXOS} {Excelan, Incorporated} +\tradename\ibmpc{IBM PC} {International Business Machines, Incorporated} +\tradename\ibmpcat{IBM PC/AT} {International Business Machines, Incorporated} +\tradeorg\ieee +\tradeorg\ifip +\tradename\iPSC{iPSC} {Intel Corporation} +\tradename\lattice{Lattice} {Lattice, Incorporated} +\tradename\locus{Locus} {Locus Computing Corporation} +\def\microvax/{$\mu$\vax/} +\def\microvms/{$\mu$\vms/} +\tradeorgn\milstd{MIL-STD} +\tradename\msdos{MS-DOS} {Microsoft Corporation} +\tradename\mvs{MVS} {International Business Machines, Incorporated} +\tradename\nfs{NFS} {Sun Microsystems, Incorporated} +\tradename\pcdos{PC-DOS} {International Business Machines, Incorporated} +\tradename\pcinterface{PC-Interface}% + {Locus Computing Corporation} +\tradename\pdp{PDP} {Digital Equipment Corporation} +\tradename{\tops20}{Tops20} {Digital Equipment Corporation} +\tradename\trustedmail{Trusted\ Mail}% + {Trusted Technologies, Incorporated} +\tradename\tseries{T-Series} {Floating Point Systems} +\tradename\ultrix{ULTRIX} {Digital Equipment Corporation} +\tradename\unibus{UNIBUS} {Digital Equipment Corporation} +\tradename\unix{UNIX} {AT\&T Bell Laboratories} +\tradename\vax{VAX} {Digital Equipment Corporation} +\tradename\vaxstation{VAXstation}% + {Digital Equipment Corporation} +\tradename\vm{VM} {International Business Machines, Incorporated} +\tradename\vms{VMS} {Digital Equipment Corporation} +\tradename\xenix{Xenix} {Microsoft Corporation} + +\def\xwindows/{% + \def\xwindows/{{\tradeNAMfont X \rm Window System}}% + \xwindows/\footnote{The \xwindows/ is a trademark of the Massachusettes Institute of Technology}% +} diff --git a/doc/manual/volume0/COVER-LETTER.aux b/doc/manual/volume0/COVER-LETTER.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/manual/volume0/COVER-LETTER.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/manual/volume0/COVER-LETTER.tex b/doc/manual/volume0/COVER-LETTER.tex new file mode 100644 index 0000000..9fe4ab0 --- /dev/null +++ b/doc/manual/volume0/COVER-LETTER.tex @@ -0,0 +1,10 @@ +\input lcustom +\documentstyle[11pt,sfwmac,a4]{article} +\begin{document} +\input{dist-params} + +\input{announce} +\input{contents} +\newpage +\input{distrib} +\end{document} diff --git a/doc/manual/volume0/COVER-TXT b/doc/manual/volume0/COVER-TXT new file mode 100644 index 0000000..73d8548 --- /dev/null +++ b/doc/manual/volume0/COVER-TXT @@ -0,0 +1,417 @@ + + + + + A N N O U N C E M E N T + + +The next release of PP will be available on December 20, 1991. This +release will be known as + + + PP 6.0 + + +PP is a Message Transfer Agent, intended for high volume message +switching, protocol conversion, and format conversion. It is targeted for +use in an operational environment, but is also be useful for investigating +message related applications. Good management features are a major +aspect of this system. PP supports the 1984 and 1988 versions of the +CCITT X.400 / ISO 10021 services and protocols. Many existing RFC 822 +based protocols are supported, along with RFC 1148bis conversion to +X.400. PP is an appropriate replacement for MMDF or Sendmail. +This is the second public release of PP, and includes substantial changes +based on feedback from using PP on many sites. + + + o PP is not proprietary and can be used for any purpose. The only + restriction is that suing of the authors for any damage the code may + cause is not allowed. + + + o PP runs on a range of UNIX and UNIX-like operating systems, + including SUNOS, Ultrix, and BSD. A full list of platforms on which + PP is know to run is included in the distribution. + + + o Current modules include: + + + - X.400 (1984) P1 protocol. + + - X.400 (1988) P1 protocol. + + - Simple mail transfer protocol (SMTP), conformant to host + requirements. + + - JNT mail (grey book) Protocol. + + - UUCP mail transfer. + + - DECNET Mail-11 transfer + + - Distribution list expansion and maintenance, using either a file + based mechanism or an X.500 directory. + + - RFC 822-based local delivery. + + - Delivery time processing of messages. + + - Conversion between X.400 and RFC 822 according to the latest + revision of RFC 1148, known as RFC 1148bis. + + - Conversion support for reformatting body parts and headers. + + - X-Window and line-based management console. + + - Message Authorisation checking. + + - Reformatting support for "mail hub" operation. + + - X.500-based distribution list facility using the QUIPU directory. + + + + 1 + + + + + - FAX interworking + + + o No User Agents (UAs) are included with PP. However, procedural + access to the MTA is documented, to encourage others to write or to + port UAs. Several existing UAs, such as MH, may be used with PP. + + + o It is expected that a Message Store to be used in conjunction with + PP (PPMS), and an associated X-Windows User Agent (XUA) will + be released on beta test in first quarter 92. + + + o The core routing of PP 6.0 is table based. DNS is used by the SMTP + channel. The next version of PP will support Directory Based + routing, which may use X.500 or DNS. + + + o PP 6.0 requires ISODE 7.0. + + + o X-Windows release X11R4 (or greater) is needed by some of the + management tools. PP can be operated without these tools. + + + o Although PP is not "supported" per se (but see later), it does have a + problem reporting address: + + + + RFC 822: PP-SUPPORT@CS.UCL.AC.UK + + + X.400: S=PP-Support; OU=CS; O=UCL; + PRMD=UK.AC; ADMD= ; C=GB; + + + + Bug reports (and fixes) are welcome. + + + o The discussion group PP-PEOPLE@CS.UCL.AC.UK is used as an + open forum on PP; Contact + PP-PEOPLE-REQUEST@CS.UCL.AC.UK to be added to this list. + + + o The primary documentation for this release consists of a three and a + half volume User's Manual (approx. 300 pages) and a set of UNIX + manual pages. The sources to the User's Manual are in LaTeX + format. + + +For more information, contact: + + + Steve Kille + Department of Computer Science + University College London + Gower Street + London + WC1E 6BT + England + + + + 2 + + + + +DISTRIBUTION SITES + + +NIFTP + + +If you run NIFTP over the public X.25 or over Janet, and are registered in +the NRS at Salford, you can use NIFTP with username "guest" and your +own name as password, to access UK.AC.UCL.CS to retrieve the file +pp/pp-6.tar. The file pp-6.tar.Z is the tar image after being run +through the compress program (approx 3Mb). + + + +FTP + + +If you can FTP to the Internet from outside Europe, then use anonymous +FTP to uu.psi.com [136.161.128.3] to retrieve the file pp-6.tar.Z in binary +mode from the isode/ directory. This file is the tar image after being run +through the compress program and is approximately 3Mb in size. + +If you can FTP to the Internet from Europe, then use anonymous FTP to +archive.eu.net [192.16.202.1] to retrieve the file pp-6.tar.Z in binary mode +from the network/isode/ directory. This file is the tar image after being +run through the compress program and is approximately 3Mb in size. + + + +EUROPE (tape and documentation) + + +For mailings in EUROPE, send a cheque or bankers draft and a purchase +order for 200 Pounds Sterling to: + + + Postal address: Department of Computer Science + Attn: Natalie May/Dawn Bailey + University College London + Gower Street + London, WC1E 6BT + UK + + +For information only: + + + Telephone: +44 71-380-7214 + Fax: +44 71-387-1397 + Telex: 28722 + Internet: natalie@cs.ucl.ac.uk + dawn@cs.ucl.ac.uk + + +Specify one: + + + 1. 1600bpi 1/2-inch tape, or + + + 2. Sun 1/4-inch cartridge tape. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + + 3 + + + + +EUROPE (tape only) + + +Tapes without hardcopy documentation can be obtained via the software +distribution service of the European UNIX User group (EUUG). The PP +6.0 distribution is called "EUUGD22 - PP (6.0)". + + + Postal address: EUUG Software Distributions + c/o Frank Kuiper + Centrum voor Wiskunde en Informatica + Kruislaan 413 + 1098 SJ Amsterdam + The Netherlands + + + For information only: + Telephone: +31 20-5924121 + (or +31 20-5929333) + Telex: 12571 mactr nl + Telefax: +31-20-5924199 + Internet: euug-tapes@cwi.nl + + +Specify one: + + + 1. 1600bpi 1/2-inch tape: 130 Dutch guilders. + + + 2. 800bpi 1/2-inch tape: 150 Dutch guilders. + + + 3. Sun 1/4-inch cartridge tape (QIC-24 format): 190 Dutch guilders. + + + 4. Sun 1/4-inch cartridge tape (QIC-11 format): 215 Dutch guilders. + + +If you require DHL, this is possible and will be billed through. Note that if +you are not a member of EUUG, then there is an additional handling fee of +300 Dutch guilders (please enclose a copy of your membership or +contribution payment form when ordering). Do not send money, cheques, +tapes or envelopes; you will be invoiced. + + + +NORTH AMERICA + + +For mailings in NORTH AMERICA, send a check for 375 US dollars to: + + + Postal address: University of Pennsylvania + Department of Computer and Information Science + Moore School + Attn: David J. Farber (PP Distribution) + 200 South 33rd Street + Philadelphia, PA 19104-6314 + U.S.A. + + + Telephone: +1 215-898-8560 + + +Specify one: + + + 1. 1600bpi 1/2-inch tape, or + + + + 4 + + + + + 2. Sun 1/4-inch cartridge tape. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + +AUSTRALIA and NEW ZEALAND + + +For mailings in AUSTRALIA and NEW ZEALAND, + + + 1. If you already have ISODE 7.0, send a cheque for 100 dollars + Australian to the following address. You will recieve only the PP + manuals and a PP tape. Clearly specify on the cheque and + order that you only want PP 6.0. + + + 2. If you do not have ISODE 7.0, send a cheque for 350 dollars + Australian to the following address. You will recieve a tape + containing both ISODE 7.0 and PP 6.0, together with manuals for + both ISODE 7.0 and PP 6.0. + + + + Postal address: CSIRO DIT + Attn: Andrew Waugh (ISODE Distribution) + 723 Swanston St + Carlton, 3053 + Australia + + +For information only: + + + Telephone: +61 3-282-2615 + Fax: +61 3-282-2600 + Internet: ajw@mel.dit.csiro.au + + +Specify one: + + + 1. 1600/3200/6250bpi 1/2-inch tape, or + + + 2. Sun 1/4-inch cartridge tape in either QIC-11, QIC-24 or QIC-150 + format. + + +The tape will be written in tar format and returned with a documentation +set. Do not send tapes or envelopes. Documentation only is the same price. + + + +FTAM on Janet or PSS + + +The source code is available by FTAM at the University College London +over X.25 using Janet (DTE 00000511160013), PSS (DTE +23421920030013) or IXI (DTE 20433450420113) with Transport +Selector 259 (ASCII encoding). Use the "anon" user-identity and retrieve +the file pp-6.tar. The file pp-6.tar.Z is the tar image after being run +through the compress program (3Mb). + + + + 5 + + + + +FTAM on the Internet + + +The source code is available by FTAM over the Internet at host +osi.nyser.net [192.33.4.10] (TCP port 102 selects the OSI transport +service) with Transport Selector 259 (numeric encoding). Use the "anon" +user-identity, supply any password, and retrieve pp-6.tar.Z from the +isode/ directory. This file is the tar image after being run through the +compress program and is approximately 3Mb in size. + + + +Online Postscript + + +For distributions via FTAM, the file service is provided by the FTAM +implementation in ISODE 5.0 or later (IS FTAM). +For distributions via either FTAM or FTP, there are additional files +available for retrieval, called pp-6-ps-a4.tar.Z and pp-6-ps-us.tar.Z +which are compressed tar images (1.5MB) containing the entire +documentation set in PostScript format, for A4 and US paper respectively. + + + +SUPPORT + + +A UK company has been set up to provide support for the ISODE, PP, +and associated packages: X-Tel Services Ltd. This company provides an +update service, general assistance and site specific support. This company +is closely associated with the development of PP. + + + Postal Address: X-Tel Services Ltd. + Nottingham University + Nottingham, NG7 2RD + UK + Telephone: +44 602-412648 + Fax: +44 602-790278 + Internet: support@xtel.co.uk + + + + 6 diff --git a/doc/manual/volume0/COVER-TXT.aux b/doc/manual/volume0/COVER-TXT.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/manual/volume0/COVER-TXT.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/manual/volume0/COVER-TXT.tex b/doc/manual/volume0/COVER-TXT.tex new file mode 100644 index 0000000..cfca899 --- /dev/null +++ b/doc/manual/volume0/COVER-TXT.tex @@ -0,0 +1,12 @@ +\input lcustom +\documentstyle[11pt,sfwmac,a4]{article} +\begin{document} +\input{dist-params} + +\raggedright\pretolerance=10000\tolerance=10000 +\def\pgm#1{#1} +\input{announce} +\input{contents} +\newpage +\input{distrib} +\end{document} diff --git a/doc/manual/volume0/Makefile b/doc/manual/volume0/Makefile new file mode 100644 index 0000000..89c01cb --- /dev/null +++ b/doc/manual/volume0/Makefile @@ -0,0 +1,125 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .pic .c .h .s .ry .py .bnf .make .web .tex .dvi .imp .ps + +.pic.tex:; tpic $< + +.c.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.h.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if $(TGRIND) -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.ry.tex:; sh -c 'if $(TGRIND) -d grindefs -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if $(TGRIND) -d grindefs -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.bnf.tex:; sh -c 'if $(TGRIND) -d grindefs -f -lbnf $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.make.tex:; sh -c 'if $(TGRIND) -f -lsrc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if $(LATEX) \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if $(DVI2PS) $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +######################################################################### +# End of extension rules +######################################################################### + +INPUTS = \ + bcustom.bib grindefs networking.bib sfwmac.sty \ + captcont.sty grindefs.sty pp.bib tgrind.sty \ + dist-params.tex lcustom.tex sfwdoc.bib trademark.tex \ + a4.sty + +############################################################# +# Here it is... +############################################################# + +all: volume0.dvi COVER-LETTER.dvi + +inst-all:; + +install: inst-all clean + +lint:; + +clean:; rm -f volume0.imp volume0.ps volume0.dvi volume0.log \ + volume0.blg _* \#* COVER-LETTER.txt COVER-LETTER.ps \ + COVER-LETTER.dvi COVER-TXT.log \ + COVER-TXT.dvi $(INPUTS) + +grind: volume0.dvi + true + dvisp $(DFLAGS) volume0 + +imp: volume0.imp + +ps: volume0.ps + +true:; + + +############################################################# +# volume0 +############################################################# + +# customization files, et. al., not included below +volume0.dvi: volume0.vrsn + +# volume0.bbl volume0.ind -- later + +volume0.vrsn: volume0.tex \ + $(INPUTS) \ + highlights.tex \ + real.tex dist-params.tex distrib.tex \ + version.sh + @version.sh volume0 + +$(INPUTS): + ln -s ../texinputs/$@ . + + +############################################################ +# COVER-LETTER +############################################################ + +COVER-TXT: COVER-TXT.dvi + dvi2tty COVER-TXT.dvi | sed 's/ffl/o /g' > $@ + +COVER-TXT.dvi: COVER-TXT.tex $(INPUTS) contents.tex \ + distrib.tex dist-params.tex announce.tex + +COVER-LETTER.dvi: COVER-LETTER.tex $(INPUTS) contents.tex \ + distrib.tex dist-params.tex announce.tex + +############################################################# +# miscellany +############################################################# + +bibtex:; bibtex volume0 + +preview: volume0.dvi \ + true + xdvi volume0.dvi + +index:; idx2ind -l volume0 + diff --git a/doc/manual/volume0/announce.tex b/doc/manual/volume0/announce.tex new file mode 100644 index 0000000..b34ba63 --- /dev/null +++ b/doc/manual/volume0/announce.tex @@ -0,0 +1,22 @@ +\begin{center} +\Large \bf A N N O U N C E M E N T +\end{center} + +The next release of PP will be available on \ppdate/. +This release will be known as +\begin{center} +PP \ppversion/ +\end{center} + +PP is a Message Transfer Agent, intended for high volume message +switching, protocol conversion, and format conversion. It is targeted +for use in an operational environment, but is also be useful for +investigating message related applications. Good management features +are a major aspect of this system. PP supports the 1984 and 1988 +versions of the CCITT X.400 / ISO 10021 services and protocols. Many +existing RFC~822 based protocols are supported, along with RFC~1148bis +conversion to X.400. PP is an appropriate replacement for MMDF or +Sendmail. + +This is the second public release of PP, and includes substantial +changes based on feedback from using PP on many sites. diff --git a/doc/manual/volume0/contents.tex b/doc/manual/volume0/contents.tex new file mode 100644 index 0000000..db06982 --- /dev/null +++ b/doc/manual/volume0/contents.tex @@ -0,0 +1,70 @@ + +\begin{itemize} +\item PP is not proprietary and can be used for any purpose. The only +restriction is that suing of the authors for any damage +the code may cause is not allowed. + +\item PP runs on a range of UNIX and UNIX-like operating systems, including + SUNOS, Ultrix, and BSD. A full list of platforms on which PP is know + to run is included in the distribution. + +\item Current modules include: + +\input{highlights} + +\item No User Agents (UAs) are included with PP. However, procedural access +to the MTA is documented, to encourage others to write or to port UAs. +Several existing UAs, such as MH, may be used with PP. + + +\item It is expected that a Message Store to be used in conjunction + with PP (PPMS), and an associated X--Windows User Agent (XUA) will + be released on beta test in first quarter 92. + +\item The core routing of PP \ppversion/ is table based. DNS is used + by the SMTP channel. The next version of PP will support Directory + Based routing, which may use X.500 or DNS. + +\item PP \ppversion/ requires ISODE \isodevrsn/. + +\item X--Windows release X11R4 (or greater) is needed by some of the +management tools. PP can be operated without these tools. + +\item Although PP is not ``supported'' per se (but see later), it does +have a problem reporting address: + +\begin{tabbing} + +RFC 822: \= PP-SUPPORT@CS.UCL.AC.UK \\ \\ + +X.400: \> S=PP-Support; OU=CS; O=UCL; \\ + \> PRMD=UK.AC; ADMD=\verb*| |; C=GB; \\ + +\end{tabbing} + + + + +Bug reports (and fixes) are welcome. + +\item The discussion group PP-PEOPLE@CS.UCL.AC.UK is used as an open forum +on PP; Contact PP-PEOPLE-REQUEST@CS.UCL.AC.UK to be added to this +list. + +\item The primary documentation for this release consists of a three and +a half volume User's Manual (approx. 300 pages) and a set of UNIX +manual pages. The sources to the User's Manual are in LaTeX +format. +\end{itemize} + +For more information, contact: +\begin{quote} +Steve Kille \\ +Department of Computer Science \\ +University College London \\ +Gower Street \\ +London \\ +WC1E 6BT \\ +England \\ +\end{quote} + diff --git a/doc/manual/volume0/distrib.tex b/doc/manual/volume0/distrib.tex new file mode 100644 index 0000000..cf20304 --- /dev/null +++ b/doc/manual/volume0/distrib.tex @@ -0,0 +1,206 @@ +\subsection*{DISTRIBUTION SITES} + +\subsubsection*{NIFTP} +If you run NIFTP over the public X.25 or over Janet, and are +registered in the NRS at Salford, you can use NIFTP with username +``guest'' and your own name as password, to access UK.AC.UCL.CS to +retrieve the file \uktarfile/. The +file \ukcompressfile/ is the \pgm{tar} image after being run through the +compress program (approx \compresssize/). + + +\subsubsection*{FTP} +If you can FTP to the Internet from outside Europe, then use anonymous +FTP to uu.psi.com [136.161.128.3] to retrieve the file \compressfile/ in +binary mode from the isode/ directory. This file is the \pgm{tar} image +after being run through the compress program and is approximately +\compresssize/ in size. + +\medskip +If you can FTP to the Internet from Europe, then use anonymous FTP to +archive.eu.net [192.16.202.1] to retrieve the file \compressfile/ in binary +mode from the network/isode/ directory. This file is the \pgm{tar} image +after being run through the compress program and is approximately +\compresssize/ in size. + + +\subsubsection*{EUROPE (tape and documentation)} + +For mailings in EUROPE, send a cheque or bankers draft and a purchase +order +for 200 Pounds Sterling to: +\[\begin{tabular}{ll} +Postal address:& Department of Computer Science\\ +& Attn: Natalie May/Dawn Bailey\\ +& University College London\\ +& Gower Street\\ +& London, WC1E 6BT\\ +& UK +\end{tabular}\] +For information only: +\[\begin{tabular}{ll} +\ Telephone:& +44 71--380--7214\\ +\ Fax:& +44 71--387--1397\\ +\ Telex:& 28722\\ +\ Internet:& \verb"natalie@cs.ucl.ac.uk"\\ +& \verb"dawn@cs.ucl.ac.uk" +\end{tabular}\] +Specify one: +\begin{enumerate} +\item 1600bpi 1/2--inch tape, or + +\item Sun 1/4--inch cartridge tape. +\end{enumerate} +The tape will be written in \pgm{tar} format and returned with +a documentation set. +Do not send tapes or envelopes. +Documentation only is the same price. + +\subsubsection*{EUROPE (tape only)} +Tapes without hardcopy documentation can be obtained via the software +distribution service of the European UNIX User group (EUUG). +The PP \ppversion/ distribution is called ``EUUGD22 - PP (\ppversion/)''. +\[\begin{tabular}{ll} +Postal address:& EUUG Software Distributions\\ +& c/o Frank Kuiper\\ +& Centrum voor Wiskunde en Informatica\\ +& Kruislaan 413\\ +& 1098 SJ Amsterdam\\ +& The Netherlands\\[0.1in] +For information only:&\\ +\ Telephone:& +31 20--5924121\\ + & (or +31 20--5929333)\\ +\ Telex:& 12571 mactr nl\\ +\ Telefax:& +31--20--5924199\\ +\ Internet:& \verb"euug-tapes@cwi.nl" +\end{tabular}\] +Specify one: +\begin{enumerate} +\item 1600bpi 1/2--inch tape: 130 Dutch guilders. + +\item 800bpi 1/2--inch tape: 150 Dutch guilders. + +\item Sun 1/4--inch cartridge tape (QIC-24 format): 190 Dutch guilders. + +\item Sun 1/4--inch cartridge tape (QIC-11 format): 215 Dutch guilders. +\end{enumerate} +If you require DHL, this is possible and will be billed through. +Note that if you are not a member of EUUG, +then there is an additional handling fee of 300 Dutch guilders +(please enclose a copy of your membership or contribution payment form when +ordering). +Do not send money, cheques, tapes or envelopes; +you will be invoiced. + + +\subsubsection*{NORTH AMERICA} +For mailings in NORTH AMERICA, +send a check for 375 US dollars to: +\[\begin{tabular}{ll} +Postal address:&University of Pennsylvania\\ +& \small Department of Computer and Information Science\\ +& Moore School\\ +& Attn: David J. Farber (PP Distribution)\\ +& 200 South 33rd Street\\ +& Philadelphia, PA 19104-6314\\ +& U.S.A.\\[0.1in] +Telephone:& +1 215--898--8560 +\end{tabular}\] +Specify one: +\begin{enumerate} +\item 1600bpi 1/2--inch tape, or + +\item Sun 1/4--inch cartridge tape. +\end{enumerate} +The tape will be written in \pgm{tar} format and returned with +a documentation set. +Do not send tapes or envelopes. +Documentation only is the same price. + + +\subsubsection*{AUSTRALIA and NEW ZEALAND} +For mailings in AUSTRALIA and NEW ZEALAND, + +\begin{enumerate} +\item If you already have ISODE \isodevrsn/, send a cheque for 100 + dollars Australian to the following address. You will + recieve only the PP manuals and a PP tape. {\bf Clearly specify + on the cheque and order that you only want PP \ppversion/.} +\item If you do not have ISODE \isodevrsn/, send a cheque for 350 + dollars Australian to the following address. You will + recieve a tape containing both ISODE \isodevrsn/ and PP + \ppversion/, together + with manuals for both ISODE \isodevrsn/ and PP \ppversion/. +\end{enumerate} + +\[\begin{tabular}{ll} +Postal address:& CSIRO DIT\\ +& Attn: Andrew Waugh (ISODE Distribution)\\ +& 723 Swanston St\\ +& Carlton, 3053\\ +& Australia +\end{tabular}\] +For information only: +\[\begin{tabular}{ll} +\ Telephone:& +61 3--282--2615\\ +\ Fax:& +61 3--282--2600\\ +\ Internet:& \verb"ajw@mel.dit.csiro.au" +\end{tabular}\] +Specify one: +\begin{enumerate} +\item 1600/3200/6250bpi 1/2--inch tape, or + +\item Sun 1/4-inch cartridge tape in either QIC-11, QIC-24 or QIC-150 format. +\end{enumerate} +The tape will be written in \pgm{tar} format and returned with a documentation set. +Do not send tapes or envelopes. +Documentation only is the same price. + +\subsubsection*{FTAM on Janet or PSS} +The source code is available by FTAM at the University College London over X.25 +using Janet (DTE \verb"00000511160013"), PSS (DTE \verb"23421920030013") +or IXI (DTE \verb"20433450420113") with +Transport Selector~\verb"259" (ASCII encoding). +Use the ``anon'' user-identity and retrieve the file \tarfile/. +The file \compressfile/ is the \pgm{tar} image after being +run through the compress program (\compresssize/). + +\subsubsection*{FTAM on the Internet} + +The source code is available by FTAM over the +Internet at host \verb"osi.nyser.net" \verb"[192.33.4.10]" +(TCP port~102 selects the OSI transport service) +with Transport Selector~\verb"259" (numeric encoding). +Use the ``anon'' user-identity, supply any password, +and retrieve \compressfile/ from the isode/ directory. +This file is the \pgm{tar} image after being run through the compress program +and is approximately \compresssize/ in size. + +\subsubsection*{Online Postscript} + +For distributions via FTAM, +the file service is provided by the FTAM implementation in ISODE~5.0 or later +(IS FTAM). + +For distributions via either FTAM or FTP, there are additional files +available for retrieval, called \ukpsfile/ and \psfile/ +which are compressed \pgm{tar} images (\pssize/) containing the entire +documentation set in PostScript format, +for A4 and US paper respectively. + +\subsection*{SUPPORT} + +A UK company has been set up to provide support for the ISODE, PP, +and associated packages: X-Tel Services Ltd. This company provides an +update service, general assistance and site specific support. +This company is closely associated with the development of PP. + +\[\begin{tabular}{ll} +Postal Address:& X-Tel Services Ltd.\\ +& Nottingham University\\ +& Nottingham, NG7 2RD\\ +& UK\\ +Telephone:& +44 602-412648\\ +Fax:& +44 602-790278\\ +Internet:& support@xtel.co.uk\\ +\end{tabular}\] diff --git a/doc/manual/volume0/highlights.tex b/doc/manual/volume0/highlights.tex new file mode 100644 index 0000000..02f5093 --- /dev/null +++ b/doc/manual/volume0/highlights.tex @@ -0,0 +1,23 @@ +\begin{itemize} +\item X.400 (1984) P1 protocol. +\item X.400 (1988) P1 protocol. +\item Simple mail transfer protocol (SMTP), conformant to + host requirements. +\item JNT mail (grey book) Protocol. +\item UUCP mail transfer. +\item DECNET Mail-11 transfer +\item Distribution list expansion and maintenance, using either a + file based mechanism or an X.500 directory. +\item RFC~822-based local delivery. +\item Delivery time processing of messages. +\item Conversion between X.400 and RFC~822 according to the latest + revision of RFC~1148, known as RFC~1148bis. +\item Conversion support for reformatting body parts and headers. +\item X-Window and line-based management console. +\item Message Authorisation checking. + +\item Reformatting support for ``mail hub'' operation. +\item X.500-based distribution list facility using the QUIPU + directory. +\item FAX interworking +\end{itemize} diff --git a/doc/manual/volume0/make b/doc/manual/volume0/make new file mode 100755 index 0000000..be14df3 --- /dev/null +++ b/doc/manual/volume0/make @@ -0,0 +1,11 @@ +#! /bin/sh + +if [ -f ../../../Make.defs ] +then + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../../../Make.defs -f Makefile ${1+"$@"} +else + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../Make.defs -f Makefile ${1+"$@"} +fi + diff --git a/doc/manual/volume0/real.aux b/doc/manual/volume0/real.aux new file mode 100644 index 0000000..5e356c1 --- /dev/null +++ b/doc/manual/volume0/real.aux @@ -0,0 +1,50 @@ +\relax +\citation{MHS} +\citation{CCITT.MHS} +\citation{RFC822} +\citation{ARPA.MHS} +\citation{RFC1148} +\citation{IFIP.PP} +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}Overview}{1}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}What is PP?}{1}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}The PP Documentation}{2}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}A Brief History of PP}{2}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.4}Etymology}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.5}Acknowledgements}{4}} +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {2}Using PP}{6}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.1}Conditions of Use}{6}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.2}Comments and Discussion}{6}} +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {3}Obtaining PP}{8}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\bibdata{bcustom,pp,networking} +\bibcite{MHS}{CCI84} +\bibcite{CCITT.MHS}{CCI88} +\bibcite{RFC822}{Cro82} +\bibcite{ARPA.MHS}{Kil86} +\bibcite{IFIP.PP}{Kil88} +\bibcite{RFC1148}{Kil89} +\bibstyle{alpha} +\global\@namedef{cp@real}{ +\setcounter{page}{13} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume0/real.tex b/doc/manual/volume0/real.tex new file mode 100644 index 0000000..dda90e6 --- /dev/null +++ b/doc/manual/volume0/real.tex @@ -0,0 +1,253 @@ +\input{dist-params} +\chapter {Overview} + +\section {What is PP?} + +PP is a message transfer agent (MTA), which supports a number of +message transfer protocols, including: + +\begin {itemize} +\item X.400 (1984) P1 \cite{MHS}. +\item X.400 (1988) / ISO 10021 P1 \cite{CCITT.MHS}. +\item A number of RFC~822-based protocols \cite{RFC822}. +\end {itemize} + +It is based on experience with previous MTAs, and has the following +aims: + +\begin {itemize} +\item Use for switching large volumes of messages in a service environment. +\item Management features, suitable for complex sites. +\item Protocol conversion facilities, particularly for mapping between +RFC~822 and X.400 according to RFC~987 \cite{ARPA.MHS}, +RFC~1148\cite{RFC1148} and RFC~1148bis. +\item Body part format conversion. +\item Support for development of advanced user agents, particularly those +wishing to use X.400 and/or multimedia capability. +\end {itemize} + +For a technical overview of PP, a number of papers are included in the +distribution, the paper by Kille is recommended +\cite{IFIP.PP}. PP is implemented in \pgm{C}, and runs on a range of +UNIX and UNIX-like operating systems. +The current release includes the following modules: + +\input{highlights} + + + +\section {The PP Documentation} + +This manual refers to PP version \ppversion/ of \ppdate/. + +The PP manual is divided into three volumes and this covering document, +which introduces PP and contains general +information relevant to all of the other volumes: + +\begin {description} +\item[Volume 1:] Installation and Operations. This describes all that is +needed to install PP and how to administer PP as part of an operational +service. +\item[Volume 2:] Programmer's Guide. This describes programming interfaces +for submission of messages into PP, and for channels which deliver messages +locally or remotely. +\item[Volume 3:] User's Guide. In general, PP should not be visible to the +end user. There are some associated tools, which are needed, and are +described in this volume. +\end {description} + +\section {A Brief History of PP} + +PP began in 1985, when several of us wished to produce a system to support +X.400. It was clear that MMDF (our favourite MTA at that time) was not going to be +extensible to do all that we wanted. Steve Kille had looked at the EAN MTA at the +end of 1984. Whilst this was an impressive development at the time, it did +not really meet our needs, although our initial plan was to use the OSI +layers from EAN. + +Two meetings were held in September 1985 to consider the possibilities of +future MTA development: + +\begin {itemize} +\item At CWI, discussion took place between: Doug Kingston (CWI/BRL), +Piet Beertma (CWI), Miriam Amos (DEC/UCB), Kevin Dunlap (DEC/UCB), +Daniel Karrenberg (Uni Dortmund), and Steve Kille. + +\item At UCL, discussion took place between: Phil Cockcroft (UCL), Doug +Kingston, Steve Kille, and Julian Onions. +\end {itemize} + +These meetings, and following messages, resulted in some of the +initial PP design. As a result of the second meeting, Phil Cockcroft +and Julian Onions started to write large chunks of code, and Steve +Kille wrote some small chunks of code. + +By April 1986, a system was starting to come together, which was being +called PP. Marshall Rose was starting work on his \pgm{ASN.1} tools, which +were clearly going to be a part of PP! In July, the mechanisms for +representing multimedia messages in the queue were designed and +evolved. + +By October 1986, it was time to design the QMGR fully. Steve Kille had been +at the infamous CCITT Directory meeting in Munich in February, and so +specified a QMGR design in the new ASDC (abstract service definition +conventions). Phil Cockcroft left UCL at the end of 1986, which was a big +loss to the effort. + +In February 1987, there was a basic system working, which talked SMTP +and X.400. Filling in the holes took much longer than we expected! +The first priority was to replace the shell script QMGR. Julian +Onions was then working on the ISODE ROS tools (ROSY and POSY), and so +it was decided to use ROS to implement the QMGR. The QMGR and the +tools proceeded in parallel. In 1988 Alina daCruz (UCL) rewrote the +access libraries, Pete Cowen (Nottingham) worked on a range of +formatting tools, and Bruce Wilford (UCL) redid all of the channel +binding and domain handling. Mike Roe (UCL) started work on LISP code +to produce a first cut at the 1988 X.400 protocol. Discussions with +Piete Brooks (Cambridge) led to the initial design of the JNT mail +channel. In October 1988, Steve Kille presented a paper on PP at the +IFIP WG 6.5 conference, but there was still no PP ready for release. +By the end of 1988, there was a PP which had been radically changed +and looked much more like the final system. + + +PP received its first public airing at CEBIT (Hannover Fair) in March 1989, +where it carried ODIF over X.400, and converted into Diamond format by +use of private conversion tools. It interworked with a number of +X.400(84) systems at this point. This was as a part of the ESPIRIT +PODA project. + + +In 1989, the X MTA Console (Pete Cowen) and authorisation (John +Taylor) were added in, and the internal structures fully upgraded to +X.400(88). PP 3.0 was cut in July 1989, and was used as the basis for +UK to full X.400 relaying. This system was released outside UCL and +Nottingham on a very selective basis. + +PP 4.0 was released at the very end of 1989 to 15 beta sites. Three more +beta releases were made during 1990 to an increasing number of beta sites. +During this time, the upgrade to RFC~1148 was made, and initial +implementations of P1(1988) and directory-based distribution lists (Colin +Robbins) added. + +PP 5.0, the first openly available release, was cut in September 1990. +As experience was obtained with PP 5.0, a bug-fix release known as PP +5.2 was released in February of 1991. This corrected a number of minor +problems with the 5.0 release. + +PP 6.0 was released on \ppdate/ +\section {Etymology} + +PP is not an acronym. There is no truth in the rumour that PP stands +for ``Postman Pat,'' a famous British postman. + +\section {Acknowledgements} + +PP funding has come from a number of sources. In particular the UK +Joint Network Team (JNT) has funded a significant part of the PP +development. Jim Craigie of the JNT has been helpful and encouraging +in this. The Alvey-sponsored COSMOS project funded a major part of +the initial development of PP. The Alvey-sponsored Locator project +funded work on PP to provide hooks for security features. Use of PP +as infrastructure in the ESPRIT PODA project has led to many +improvements in the current release. + +Prof. Peter Kirstein of University College London (UCL) and Dr. Hugh +Smith of Nottingham University have been particularly tolerant of the +excessive resources consumed by this development. + + +The major work of coding PP (apart from the authors) has been done by +Phil Cockcroft, Alina da Cruz, and John Taylor of UCL and Pete Cowen +of Nottingham University. Code has also been written by Adrian +Joseph, Mike Roe, Colin Robins, and Bruce Wilford of UCL. +Irene Hassel of UCL +helped to write documentation. John Andrews of UCL has helped to +bring PP into service at UCL. + +Piete Brooks of Cambridge Computer lab has been a faithful alpha test site, +and has contributed code to integrate UNIX-NIFTP and C-NRS. He has made +many useful comments and contributed a number of bugfixes. Andrew +Macpherson of STL has contributed a number of bugfixes and tools to help +Sendmail sites convert to PP. + +The ISODE from Marshall T. Rose of NYSERNet is an essential +component of PP. + +The character set conversion code is based on that provided by +Keld Simonsen of the Danish UNIX User Group. + +Useful comment and fixes have been provided by our beta test sites. +Particularly useful help has come from: Andrew Findlay of Brunel; Juha +Heinanen of FUNET; Simon Poole of EUnet; Ole Bj{\o}rn Hessen of University +of Oslo; George Michaelson of University of Queensland; and Peter Yee of NASA. + +\chapter {Using PP} + +\section {Conditions of Use} + +PP is an openly available suite of software. There are no +restrictions on its usage. The authors accept no liability resulting +from use of PP. + +\section {Comments and Discussion} + +Comments and problems on PP should be sent electronically to the PP +support mailbox. The RFC~822 form of this is: +\begin {quote} +\verb|pp-support@cs.ucl.ac.uk| +\end {quote} +Bug reports (and fixes) to this address are welcome. These reports +will be dealt with on a best-effort basis. + +The X.400 form is: + +\begin {center} +\begin {tabbing} +Organisation \= UCL \kill +Surname \> PP-Support \\ +Org Unit \> CS \\ +Organisation \> UCL \\ +PRMD \> UK.AC \\ +ADMD \> \verb*| | \\ +Country \> GB \\ +\end {tabbing} +\end {center} + +\pagebreak[4] + +If this is not possible, comments may be sent to: + +\begin {tabbing} +Postal Address: \= Steve Kille \\ +\> Department of Computer Science \\ +\> University College London \\ +\> Gower Street \\ +\> WC1E 6BT \\ +\> UK \\ \\ +Telephone: \> +44-1-380-7294 \\ +\end {tabbing} + + +There is an electronic discussion list: + +\begin {quote} +\verb|pp-people@cs.ucl.ac.uk| +\end {quote} + +All interested parties are encouraged to join this list by sending to: + +\begin {quote} +\verb|pp-people-request@cs.ucl.ac.uk| +\end {quote} + + +\chapter {Obtaining PP} + +The PP version \ppversion/ software may be obtained in the following +ways from these places: + +\input{distrib} + +\bibliography{bcustom,pp,networking} +\bibliographystyle{alpha} diff --git a/doc/manual/volume0/version.sh b/doc/manual/volume0/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/manual/volume0/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/manual/volume0/volume0.aux b/doc/manual/volume0/volume0.aux new file mode 100644 index 0000000..aa7329a --- /dev/null +++ b/doc/manual/volume0/volume0.aux @@ -0,0 +1,2 @@ +\relax +\@input{real.aux} diff --git a/doc/manual/volume0/volume0.bbl b/doc/manual/volume0/volume0.bbl new file mode 100644 index 0000000..2ef4d07 --- /dev/null +++ b/doc/manual/volume0/volume0.bbl @@ -0,0 +1,39 @@ +\begin{thebibliography}{CCI88} + +\bibitem[CCI84]{MHS} +{Message Handling Systems: System Model-Service Elements}, October 1984. +\newblock International Telegraph and Telephone Consultative Committee. + +\bibitem[CCI88]{CCITT.MHS} +{Message Handling: System and Service Overview}. +\newblock International Telegraph and Telephone Consultative Committee, 1988. +\newblock Recommendation X.400. + +\bibitem[Cro82]{RFC822} +David~H. Crocker. +\newblock {Standard for the Format of ARPA Internet Text Messages}. +\newblock Request for Comments 822, DDN Network Information Center, SRI + International, August 1982. + +\bibitem[Kil86]{ARPA.MHS} +Stephen~E. Kille. +\newblock {Mapping between X.400 and RFC822}. +\newblock Request for Comments 987, DDN Network Information Center, SRI + International, June 1986. +\newblock Also available as UCL Technical Report number~120 and Mailgroup Note + number~19. + +\bibitem[Kil88]{IFIP.PP} +S.E. Kille. +\newblock {PP} - a message transfer agent. +\newblock In {\em IFIP WG 6.5 Conference on Message Handling Systems and + Distributed Applications}, pages 115--118. North Holland Publishing, October + 1988. + +\bibitem[Kil89]{RFC1148} +Stephen~E. Kille. +\newblock {Mapping between X.400(1988)/ISO10021 and RFC822}. +\newblock Request for Comments 1148, DDN Network Information Center, SRI + International, July 1989. + +\end{thebibliography} diff --git a/doc/manual/volume0/volume0.major b/doc/manual/volume0/volume0.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/manual/volume0/volume0.major @@ -0,0 +1 @@ +1 diff --git a/doc/manual/volume0/volume0.minor b/doc/manual/volume0/volume0.minor new file mode 100644 index 0000000..8f92bfd --- /dev/null +++ b/doc/manual/volume0/volume0.minor @@ -0,0 +1 @@ +35 diff --git a/doc/manual/volume0/volume0.tex b/doc/manual/volume0/volume0.tex new file mode 100644 index 0000000..b4d0dc6 --- /dev/null +++ b/doc/manual/volume0/volume0.tex @@ -0,0 +1,56 @@ +% run this through LaTeX + +% SEK - this is a PP document, designed to be easy to convert to +% an ISODE Manual Section if we want to + +\input lcustom + +\documentstyle[11pt,sfwmac,tgrind,twoside,a4]{report} +% \documentstyle[11pt,draftnote,sfwmac,tgrind,twoside]{report} + +% \font\gross=t-rom at 2.5in +% SEK - must try to sort a portable way of doing this + +\pagenumbering{roman} + +\begin{document} + + +% \title{{\gross PP} \\ \vskip 2em +\title{{\Huge \bf The PP Manual} \\ \vskip 4em + } +\author{Steve Kille \\ +Department of Computer Science \\ +University College London \\ \and +Julian Onions \\ +X-Tel Services Ltd.} + +\date{\vskip-1.25em + \ifdraft \versiondate/\\ \tt Draft Version \versiontag/\else \today\fi} + +\maketitle +\newpage + +\thispagestyle{empty} +\setcounter{page}{0} +\mbox{} +\newpage + +\tableofcontents + +% \listoftables + +% \listoffigures + +\newpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi +\pagenumbering{arabic} + +\include{real} + +% \input volume0.ind + +\end{document} diff --git a/doc/manual/volume0/volume0.toc b/doc/manual/volume0/volume0.toc new file mode 100644 index 0000000..a5cf60c --- /dev/null +++ b/doc/manual/volume0/volume0.toc @@ -0,0 +1,10 @@ +\contentsline {chapter}{\numberline {1}Overview}{1} +\contentsline {section}{\numberline {1.1}What is PP?}{1} +\contentsline {section}{\numberline {1.2}The PP Documentation}{2} +\contentsline {section}{\numberline {1.3}A Brief History of PP}{2} +\contentsline {section}{\numberline {1.4}Etymology}{4} +\contentsline {section}{\numberline {1.5}Acknowledgements}{4} +\contentsline {chapter}{\numberline {2}Using PP}{6} +\contentsline {section}{\numberline {2.1}Conditions of Use}{6} +\contentsline {section}{\numberline {2.2}Comments and Discussion}{6} +\contentsline {chapter}{\numberline {3}Obtaining PP}{8} diff --git a/doc/manual/volume0/volume0.vrsn b/doc/manual/volume0/volume0.vrsn new file mode 100644 index 0000000..e3c6bf6 --- /dev/null +++ b/doc/manual/volume0/volume0.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.35}% + \gdef\versiondate/{Wed Dec 18 16:08:02 GMT 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/manual/volume1/Makefile b/doc/manual/volume1/Makefile new file mode 100644 index 0000000..5f56ecf --- /dev/null +++ b/doc/manual/volume1/Makefile @@ -0,0 +1,151 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .pic .c .h .s .ry .py .bnf .make .web .tex .dvi .imp \ + .ps .tai .sh .csh + +.tex.dvi:; sh -c 'if $(LATEX) \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.pic.tex:; tpic $< + +.tai.tex:; sh -c 'if $(TGRIND) -f -d $(GRINDEFS) -ltai $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.c.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.sh.tex:; sh -c 'if $(TGRIND) -f -lsh $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.csh.tex:; sh -c 'if $(TGRIND) -f -lcsh $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.h.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if $(TGRIND) -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.ry.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.bnf.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lbnf $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.make.tex:; sh -c 'if $(TGRIND) -f -lsrc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if $(WEAVE) $<; then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; $(DVIIMP) $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if $(DVI2PS) $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +######################################################################### +# End of extension rules +######################################################################### + +INPUTS = \ + bcustom.bib grindefs networking.bib sfwmac.sty \ + captcont.sty grindefs.sty pp.bib tgrind.sty \ + dist-params.tex lcustom.tex sfwdoc.bib trademark.tex \ + a4.sty + +############################################################# +# Here it is... +############################################################# + +all: volume1.dvi + +inst-all:; + +install: inst-all clean + +lint:; + +clean:; rm -f volume1.imp volume1.ps volume1.dvi volume1.log \ + volume1.blg _* \#* $(INPUTS) + +grind: volume1.dvi + true + $(DVISP) $(DFLAGS) volume1 + +imp: volume1.imp + +ps: volume1.ps + +true:; + + +############################################################# +# volume1 +############################################################# + +# customization files, et. al., not included below +volume1.dvi: volume1.vrsn + +volume1.vrsn: volume1.tex \ + $(INPUTS) \ + dist-params.tex \ + preface.tex \ + general.tex \ + install.tex \ + tablemakedefs1.tex \ + tablemakedefs2.tex \ + configure.tex \ + log-examp.tex chan-examp.tex table-examp.tex \ + tableinfo_expan.tex filt-examp.tex \ + shelfilt.tex \ + tables.tex \ + alias.tex \ + chantbl.tex domain.tex or.tex users.tex \ + or2rfc.tex rfc2or.tex lists-examp.tex \ + shell-examp.tex \ + tableauthreasons.tex rfc1148g.tex \ + x400links.tex \ + tablex400info1.tex tablex400info2.tex \ + exampleortbl.tex exampleortbl2.tex \ + chx400out.tex chanx400examp.tex \ + x400in-examp2.tex logx400-examp.tex \ + addon.tex \ + faxTable.tex faxtai.tex \ + asnfilter.tex \ + management.tex \ + console_tai.tex \ + tableconsole_accels.tex \ + tableconsole_mapping.tex \ + qfile.tex dreport.tex\ + appendix.tex \ + tailor.tex pp_start.tex pp_nightly.tex \ + x400tables.tex \ + qmgrproto.tex qmgrros.tex \ + volume1.ind \ + volume1.bbl \ + version.sh + @version.sh volume1 + + +$(INPUTS): + ln -s ../texinputs/$@ . + +############################################################# +# miscellany +############################################################# + +biblio:; bibtex volume1 + +preview: volume1.dvi \ + true + xdvi volume1.dvi + +index:; idx2ind -l volume1 diff --git a/doc/manual/volume1/addon.aux b/doc/manual/volume1/addon.aux new file mode 100644 index 0000000..5148e40 --- /dev/null +++ b/doc/manual/volume1/addon.aux @@ -0,0 +1,49 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {6}Additional Capabilities}{95}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {6.1}G3Fax capability in PP}{95}} +\newlabel{fax}{{6.1}{95}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.1.1}Fax Addressing}{95}} +\newlabel{sect:faxaddress}{{6.1.1}{95}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.1.2}The Fax Table}{96}} +\newlabel{sect:faxtable}{{6.1.2}{96}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {6.1}{\ignorespaces Example of Fax Table}}{97}} +\newlabel{fig:faxTable}{{6.1}{97}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.1.3}Fax Conversion}{98}} +\newlabel{sect:faxconv}{{6.1.3}{98}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The \unhbox \voidb@x \hbox {\string\pit\space hdr2fax} Filter}{98}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {6.2}{\ignorespaces Example Tailoring of Fax Channels}}{99}} +\newlabel{example:faxtai}{{6.2}{99}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The \unhbox \voidb@x \hbox {\string\pit\space ia52fax} Filter}{99}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.1.4}The Fax Transmission and Reception Channels}{100}} +\newlabel{sect:faxtrans}{{6.1.4}{100}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Panasonic Systemfax 250 Driver}{100}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Outbound Transmission Channel}{100}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Inbound Reception Daemon}{101}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Fujitsu dexNet200 Driver}{102}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {6.2}ASN.1 Filter}{102}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.2.1}Runtime Options}{102}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {6.3}{\ignorespaces Examples of the asn filter}}{103}} +\newlabel{fig:asn}{{6.3}{103}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {6.2.2}Tailoring}{103}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Tailoring Examples}{103}} +\global\@namedef{cp@addon}{ +\setcounter{page}{104} +\setcounter{equation}{0} +\setcounter{enumi}{3} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{6} +\setcounter{section}{2} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{3} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/addon.tex b/doc/manual/volume1/addon.tex new file mode 100644 index 0000000..df4df32 --- /dev/null +++ b/doc/manual/volume1/addon.tex @@ -0,0 +1,466 @@ +\chapter {Additional Capabilities} + +This chapter describes various units that may be added to PP to +provide specific functionality. +These units tend to provide new protocol functionality. + +\section {G3Fax capability in PP} \label{fax} + +This section describes PP's G3Fax capability and how to add it to the +configured system. +The G3Fax capability is divided into several components: +\begin{itemize} +\item Addressing +\item Tables +\item Conversion +\item Transmission and Reception +\end{itemize} +These are described below. + +\subsection {Fax Addressing} \label{sect:faxaddress} + +To enable an address to contain the information required for fax +delivery, PP recognises two specific X.400 domain defined attributes: +\begin{describe} + +\item[\verb+FAX+:] the value of this attribute is used to identify the +remote fax machine. +It can be the actual telephone number of the +machine (e.g. \verb-/FAX=+44 602 790278/-), in which case it is used +directly. +Or it can be a string +which is looked up in the \file{fax} table to get the required +information (e.g. \verb+/FAX=xtel/+) + +Note that the \verb+FAX+ attribute is compulsory. +The PP fax transmission channel will bounce the message if this +attribute is not present. + +Note also that the number may contain symbols like '\verb-+-' and +'\verb+P+'. +The meaning and processing of these symbols is specific to the driver +being used (see Section~\ref{sect:faxtrans}). + +\item[\verb+ATTN+:] the value of this attribute is a descriptive +string. +This string is printed on the +coverpage of the fax along with the key \verb+For the attention +of+. + +\end{describe} + +The \verb+FAX+ attribute identifies the remote fax machine and the +\verb+ATTN+ attribute gives an informative string for presentation on +the coverpage. +Note that the presence of one or both of these attributes is not +sufficient to route a message through PP for delivery via the fax +transmission channel. +Addresses will still have to be routed to the fax transmission +channel via the conventional PP routing tables (the \file{channel} table +and/or the the \file{users} table). + +\subsection {The Fax Table} \label{sect:faxtable} + +This section describes the format of the table used by the fax related +channels and filters. +As the table is shared by both the conversion filters and the +fax transmission channel, it is appropriate to describe the format and +contents of the table here. + +The general format of the table is the same as that of all PP tables. +That is: +\begin{quote}\begin{verbatim} +key:value +\end{verbatim}\end{quote} + +The table contains a mixture of delivery information and formating +information. +The main type of entry is of the form +\begin{quote}\begin{verbatim} +key: number,description +\end{verbatim}\end{quote} +Where +\begin{describe} + +\item[\verb+key+:] is the value of the domain defined attribute +\verb+FAX+ described in Section~\ref{sect:faxaddress}. + +\item[\verb+number+:] is the telephone number of the remote fax +machine. + +Any special symbol processing and meaning given to special values is a +specific to drivers and described in Section~\ref{sect:faxtrans} + +\item[\verb+description+:] is a string describing the remote site. +This description, if given, is printed on the coverpage by +\pgm{hdr2fax}. +\pgm{hdr2fax} maps the sequence ``\verb+\n+'' to a newline when printing +the string. +\end{describe} + +The fax table may also contain several hardwired keys used by the +conversion filters and the transmission channel. +These are: +\begin{describe} +\item[\verb+keyfont+:] the value is the name of a file containing the +font used by \pgm{hdr2fax} when printing out keys on the coverpage. + +\item[\verb+valuefont+:] the value is the name of a file containing +the font used by \pgm{hdr2fax} when printing out the values +associated with the keys. + +\item[\verb+textfont+:] the value is the name of a file containing the +font used by \pgm{ia52fax} for all text and by \pgm{hdr2fax} for any +subsiduary information it puts on the coverpage. + +\item[\verb+xstart+:] +\item[\verb+ystart+:] the values of these are used by \pgm{hdr2fax} to +identify the top left hand corner of the coverpage. +The values can be given in units, \verb+cm+ for centimetres or +\verb+in+ for inches. +If no unit is specified, the value is assumed to be in millimetres. + +\item[\verb+tab+:] the value is the minimum amount of space to leave +between the start of the \verb+key+ and the start of the \verb+value+ +on the coverpage. It can be specified with units in the same way as +\verb+xstart+ and \verb+ystart+. + +\item[\verb+coverpage+:] the value is the name of a file containing +the bitmap of a design which is used by \pgm{hdr2fax} as a backdrop to +the coverpage. + +\item[\verb+localOrg+:] the name and address of the local +organisation. +This is printed by \pgm{hdr2fax} on the coverpage. +Note that \verb+\n+ is mapped to a newline. + +\item[\verb+localNumber+:] the telephone number of the local +organisation. +This is printed on the coverpage by \pgm{hdr2fax}. + +\item[\verb+postscript+:] supplementary information which is printed +at the bottom of the coverpage by \pgm{hdr2fax}. +Note that \verb+\n+ is mapped to a newline. + +\item[\verb+int\_prefix+] the prefix required to phone international +numbers. + +\end{describe} + +Figure~\ref{fig:faxTable} shows an example fax table. + +\tagrind[hbtp]{faxTable}{Example of Fax Table}{fig:faxTable} + +\subsection {Fax Conversion} \label{sect:faxconv} + +This section describes the fax conversion facilities supplied with PP. +There are two filters: +\begin{description} +\item [\pgm{hdr2fax}:] which converts an RFC-822 header to a G3Fax +bodypart containing a coverpage. +\item [\pgm{ia52fax}:] which converts an ia5 bodypart to a G3Fax +bodypart with multiple pages. +\end{description} +Note that the size of the page produced is driven by the +\verb+FAXPAGESIZE+ macro from \file{Make.defs}. +If this macro is not defined, the filters will produce US size pages. +That is 216 mm wide by 273 mm high. +If \verb+FAXPAGESIZE+ equals \verb+-DA4+, the filters will produce A4 +size pages, 210mm wide by 297 mm high. + +These filters use fonts and bitmaps encoded in PP's own format. +There are two subsiduary tools which can be used to produce the +required format of fonts and bitmaps: +\begin{describe} +\item[\verb+xfontconv+:] this converts an X windows' font into PP's +format. +It is run as follows: +\begin{quote}\begin{verbatim} +xfontconv -font fontName -file fileName +\end{verbatim}\end{quote} +where \verb+fontName+ is the name of the required font which must be +present in the local X server and \verb+fileName+ is the name of the +file in which to place the PP encoded version of the font. + +\item[\verb+ximageconv+:] this converts an X windows' bitmap into PP's +format. +It is run as follows: +\begin{quote}\begin{verbatim} +ximageconv -in xbitmapFile -out fileName +\end{verbatim}\end{quote} +where \verb+xbitmapFile+ is the file containing the bitmap to convert +and \verb+fileName+ is the file in which to place the PP encoded +version of the bitmap. +\end{describe} + +\subsubsection {The \pgm{hdr2fax} Filter} + +The \pgm{hdr2fax} filter is used in conjunction with the general +filter controller \pgm{fcontrol}. +It produces a coverpage for a message, based on the information it is +passed via the tailored \verb+outinfo+ field and the information it +can glean from the RFC-822 header field. + +The coverpage is built up as a series of key/value pairs separated by +a set horizontal distance (\verb+tab+ see Section~\ref{sect:faxtable}). +These key/value pairs include To/value, From/value etc. + +The information passed via the \verb+outinfo+ field is standard and +as such the \verb+outinfo+ field should be tailored thus +\begin{quote}\begin{verbatim} +hdr2fax -table $(table) -from $(400sender) -to $(400recip) \ + -subject $(ua-id) -outmta $(outmta) +\end{verbatim}\end{quote} + +Although the \verb+outinfo+ is standard, you may omit or alter components +of the field if you wish. +This will result in the corresponding key/value pair being omitted +from the coverpage. +The only component which is compulsory is the \verb+-table+ component. +Note that the \verb+$(...)+ values will be expanded automatically by +\pgm{fcontrol}. + +The components of the \verb+outinfo+ field are: +\begin{describe} +\item[\verb+-table+:] the name of the fax table (see +Section~\ref{sect:faxtable}) +\item[\verb+-from+:] the originator of the message. +\item[\verb+-to+:] the recipient of the message. +\item[\verb+-subject+:] the subject of the message. +\item[\verb+-outmta+:] the pseudo mta to which this message is to be +delivered. +\end{describe} + +There is a further consideration concerning the tailoring of +\pgm{hdr2fax}. +\pgm{hdr2fax} produces a coverpage specific to one recipient of a message. +Therefore to ensure that each recipient gets a coverpage specific to +themself, the tailoring for the \pgm{hdr2fax} should have the variable +\verb+solo-proc+ set to \verb+yes+. + +Figure~\ref{example:faxtai} shows an example of how \pgm{hdr2fax} +should be tailored. + +\tagrind[hbtp]{faxtai}{Example Tailoring of Fax Channels}{example:faxtai} + +\subsubsection {The \pgm{ia52fax} Filter} + +The \pgm{ia52fax} filter is used, in conjunction with the general +filter controller \pgm{fcontrol}, to convert ia5 bodyparts into +multiple page g3fax bodyparts. + +The \verb+outinfo+ field needs to specify which font the filter should +use. +This can be +\begin{itemize} +\item either indirectly via the \verb+textfont+ specified in the fax table +(see Section~\ref{sect:faxtable}). In which case the \verb+outinfo+ field +should contain the component \verb+-table $(table)+. +\item or directly by specifying the name of the file containing the +font to be used. The \verb+outinfo+ field should contain the component +\verb+-font filename+ +\end{itemize} + +Figure~\ref{example:faxtai} shows an example of how \pgm{ia52fax} +should be tailored. + +\subsection {The Fax Transmission and Reception Channels} + \label{sect:faxtrans} + +This section describes the fax transmission and reception facilities +supplied with PP. +This code is divided into PP skeletons for an outbound fax channel and +an inbound fax daemon, and drivers that are written to use these +skeletons. +At present there are only two drivers written using these skeletons. +These drivers are for the following systems: +\begin{itemize} +\item the Panasonic Systemfax 250 +\item the Fujitsu dexNet200 +\end{itemize} +At the time of writing the inbound daemon is still in the beta stage. + +The inbound daemon receives an incoming fax, wraps it up into an x400 +message and sends it to a specified address. +The outbound channel transmits a message to the remote fax machine via +the local fax machine. + +With channel pairing, both these entities can be tailored as one +channel. +Figure~\ref{example:faxtai} shows an example of how these could be +tailored. +This example is written for the Panasonic Systemfax 250 driver. + +Before describing the details germane to the individual drivers, +the details germane to the PP skeletons are described. +The key data structure linking the skeletons and the drivers is the +structure \verb+FaxCtlr+. +The elements of this structure are mostly function pointers which +should be filled in by the driver code. +The structure contains other elements which mostly relate to the +inbound daemon. +These include: the address to send inbound faxes to; the subject to +attach to the message sent; and the channel to run as. + +In terms of tailoring, there is only one PP specific tailor element. +This is for the outbound channel and is the element \verb+confirm+. +If this element is set to \verb+always+, a positive delivery report +will be sent back to the originator of the message when the message +has been successfully transmitted. +If set to \verb+never+, positive delivery reports aren't sent. +The default action is not to send delivery reports. + +\subsubsection {The Panasonic Systemfax 250 Driver} + +\subsubsection{The Outbound Transmission Channel} + +The Panasonic Systemfax's outbound channel's behaviour can be altered +by several key/value pairs in the \verb+outinfo+ tailor field: +\begin{description} +\item[\verb+out=device+:] the outbound device on which to contact the +local fax machine. By default it will try to use \verb+/dev/faxout+ + +\item[\verb+prefix=number+:] the number to prepended to the remote fax +machine number. This is useful for a fax machine connected to an +internal network where a prefix is required to get external numbers. +If \verb+prefix+ is not present no number is prepended. + +\item[\verb+nattempts=number+:] the number of times the channel will +attempt to connect to the remote fax machine in one invocation. +The default is three times. +\item[\verb+sleep=numSecs+:] the number of seconds to sleep between +connection attempts. The default is 30 seconds. +\item[\verb+softcar=used+:] indicates that the software carrier detect +package is in place. +\end{description} + +The outbound channel's behaviour is also altered by the +fashion in which the recipient was addressed. +If the recipient was addressed directly via a telephone number, e.g +\verb+FAX=999+, and this value was not found in the fax table, then the +fax machine will generate a negative delivery report if it cannot +delivery the message in the first invocation (which consists of +\verb+nattempts+ connection attempts) providing that a connection with +the remote site is made. +If the value is found in the fax table, then the fax channel will not +bounce the message if the first invocation fails to transmit it. +Instead it will revert to the usual PP timeout method for nondelivery. + +The outbound channel contains special processing for the telephone +numbers of the remote machine. This is as follows: +\begin{itemize} + +\item If the number starts with the character \verb-+-, the international +prefix is prepended to the number. +The international prefix is stored in the fax table. + +\item Any ``\verb+P+'' characters in the number cause the fax transmission +channel to pause at those positions while dialing. + +\item If the number is zero, the fax channel will print the fax on the local +fax machine rather than send it to a remote fax. + +\end{itemize} + +\subsubsection {The Inbound Reception Daemon} + +The Panasonic Systemfax's inbound daemon`s behaviour can be altered by +several key/value pairs in the \verb+ininfo+ tailor field: +\begin{description} +\item[\verb+in=device+:] the inbound device on which to listen for +incoming fax. By default it will try to use \verb+/dev/faxin+. + +\item[\verb+master=address+:] the address to send incoming faxes to. +This will default to \verb+faxmaster+. + +\item[\verb+subject=string+:] the subject to append to the messages +encapsulating the incoming faxes. This defaults to the string +``Inbound fax message''. + +\item[\verb+softcar=used+:] indicates that the software carrier detect +package is in place. +\end{description} + +By default the inbound daemon will run as a channel named \verb+fax+. +This can be altered by the command line argument \verb+-c+ (e.g. +\verb+ps250d -c fax-in+) + +\subsubsection {The Fujitsu dexNet200 Driver} + +\section {ASN.1 Filter} + +The ASN.1 Filter \pgm{asn}, is used in conjunction with the +general filter controller \pgm{fcontrol}, and is located in the +\file{formdir} directory. + +It is a general body part conversion filter and can do +a variety of conversions depending on its specified options. These +options are: + +\begin{itemize} +\item Unpack ASN.1 encodings of bodyparts. +\item Perform a character set conversion on the body part. +\item Pack the body part into ASN.1 +\end {itemize} + +\subsection {Runtime Options} + +The \pgm{asn} filter can take a number of arguments. All of these are +optional. They are as +follows: +\begin{describe} +\item[\verb|-ia encoding|:] The type of ASN.1 decoding to be done on +input. If the encoding is specified as ``none'' no decoding will be +done (the default). + +\item[\verb|-oa encoding|:] The type of ASN.1 encoding to be done on +ouput. If ``none'' is specified no encoding will be done on output +(the default). + +\item[\verb|-is charset|:] The input character set. +\item[\verb|-os charset|:] The character set to be produced. If this +is the same as the \verb|-is| parameter, no conversion will be +performed. +\item[\verb|-x|:] Use X.408 encodings (the default). +\item[\verb|-m|:] Use Mnemonic encodings. +\item[\verb|-l|:] Add a trailing newline to each ASN.1 block decoded. +This should be used with care. +\end{describe} + +The character sets supported at present are: +\begin{describe} +\item[none:] Refers to no character set. +\item[ia5:] This is unencoded ascii text. +\item[generaltext:] The ISO general test format. +\item[motis-86-6937:] The MOTIS defined 6937 character set. +\item[teletex:] The T.61 character set. +\end{describe} + +\subsection {Tailoring} + +The following fields need to be set within the tailor file. +\begin {describe} +\item[\verb|prog|:] This should be set to the value \pgm{fcontrol}, as +this program is always run under \pgm{fcontrol}. +\item[\verb|bptin|:] This should be set to the inbound character set. +\item[\verb|bptout|:] This should be set to specified character set to +be produced. +\item[\verb|type|:] set to \verb|shaper|. +\item[\verb|conv|:] set to either \verb|conv| if the conversion is +reversible or \verb|loss| if the conversion looses information. +\item[\verb|cost|:] set this to a highish value (say 99) if +\verb|conv| is \verb|loss|. +\item[\verb|outinfo|:] set to the ASN.1 filter name \pgm{asn} followed +by its required options. +\end {describe} + +\subsubsection {Tailoring Examples} + +Figure~\ref{fig:asn} shows examples of tailoring the \pgm{asn} filter. +The first converts iso6937 format into ascii, this conversion is not +generally reversible, so \verb|loss| is specified. The second example +shows conversion of ia5 into iso6937. The third specifies a conversion +from iso6937 into teletex. + +\tagrind{asnfilter}{Examples of the asn filter}{fig:asn} + diff --git a/doc/manual/volume1/alias.tex b/doc/manual/volume1/alias.tex new file mode 100644 index 0000000..aa1d445 --- /dev/null +++ b/doc/manual/volume1/alias.tex @@ -0,0 +1,16 @@ +\small\begin{verbatim} +# sample aliases +# +mailgroup-request:alias Irene.Hassell +postmaster:alias Irene.Hassell +pp:alias postmaster +# +a.dacruz:synonym Alina.DaCruz +alina:synonym Alina.DaCruz +# +jpo:alias jpo@xtel.co.uk 822 +# +pc:alias "/I=P/S=Cowen/O=xtel/PRMD=X-Tel Services/ADMD= /c=gb/" x400 +# +f.bloggs:synonym f.bloggs@foo.bar 822 external +\end{verbatim} diff --git a/doc/manual/volume1/appendix.aux b/doc/manual/volume1/appendix.aux new file mode 100644 index 0000000..8567096 --- /dev/null +++ b/doc/manual/volume1/appendix.aux @@ -0,0 +1,38 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {A}Example of the Tailor File}{136}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{app:tailor}{{A}{136}} +\newlabel{tagrind:tailor}{{A.1}{136}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {A.1}{\ignorespaces An Example Tailor File}}{143}} +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {B}Example of the PP Start Script}{144}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{app:pp.start}{{B}{144}} +\newlabel{tagrind:pp.start}{{B.1}{144}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {B.1}{\ignorespaces An Example Start Script}}{144}} +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {C}Example of the PP Script Run Nightly}{145}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{app:pp.nightly}{{C}{145}} +\newlabel{tagrind:pp.nightly}{{C.1}{145}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {C.1}{\ignorespaces An Example Nightly Script}}{146}} +\global\@namedef{cp@appendix}{ +\setcounter{page}{147} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{0} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{1} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/appendix.tex b/doc/manual/volume1/appendix.tex new file mode 100644 index 0000000..87852a4 --- /dev/null +++ b/doc/manual/volume1/appendix.tex @@ -0,0 +1,21 @@ +\chapter {Example of the Tailor File}\label{app:tailor} + +What follows is a suggested layout for the pp runtime tailor file. +As the file is read in by most programs it is best if the number +of long comments is kept to a minimum. + +\tagrindfile{tailor}{An Example Tailor File}{tagrind:tailor} + +\chapter {Example of the PP Start Script}\label{app:pp.start} + +What follows is an example of a script which is run to start the PP +mail system. + +\tagrindfile{pp_start}{An Example Start Script}{tagrind:pp.start} + +\chapter {Example of the PP Script Run Nightly}\label{app:pp.nightly} + +What follows is an example of a script which is regularly run to keep +the PP mail system up to date. + +\tagrindfile{pp_nightly}{An Example Nightly Script}{tagrind:pp.nightly} diff --git a/doc/manual/volume1/argh.tex b/doc/manual/volume1/argh.tex new file mode 100644 index 0000000..7ab11a1 --- /dev/null +++ b/doc/manual/volume1/argh.tex @@ -0,0 +1,245 @@ +% argh.tex argument handler +\documentstyle [twoside,11pt]{article} +\title{Argument handler : argh} +\author{John Taylor} % Declares the author's name. +\date{11th January 1989} % no \date produces today's +\begin{document} % End of preamble and beginning of text. +\maketitle % Produces the title. + +This provides a simple method of automatically scanning the command line +to extract flags and their associated values. The calling program must +contain the line:\\ + +\verb+#include "argh.h"+\\ + +and must then initialise a structure array + \verb+arg+ as shown in this example : +\small +\begin{verbatim} +static struct argdef arg[] = { + +flag function type match + +"file", NULL, '1', 0, +"value", NULL, '2', 0, +"body", NULL, 'a', 0, +"all", NULL, '0', 0, +"group", NULL, '1', 0, +"lots", NULL, 'm', 0, +"zero", NULL, 'z', 3, +"nine", NULL, '9', -1 +"help", show_args, '0', 0, +"-", show_args, '0', 0, +"", NULL, '?', 0 +}; +\end{verbatim} +\normalsize +the last entry \verb+"", ...+ is mandatory + +where : + +\begin{tabular}{llp{3.5in}} +char & *flag & The command line flag to be preceded by FLAGCHAR + ( `-' by default ). \\ + +void & (*function)() & The name of any function to be called automatically + if one or more instances of the flag occur on the + command line. Parameters argc,argv and a pointer + to the appropriate flag structure are passed + in the call (*function)(). In the example + above, \verb+show_args+ (part of argh) is called if + either `--\,--' or `--help' is on the command line. + The function calls are invoked with \verb+call_args()+. \\ + +char & type & Specifies the type of flag and the way zero or more + arguments are to be associated with it. \\ + +&& 0 : lone ( no assoc. value ) \\ +&& 1 : valued : adjacent or next \\ +&& 2 : as v but takes 2 args \\ +&& 3 : as v but takes 3 args \\ + +&& \ldots\ etc. (up to 9) \\ + +&& m : 1 or more ( up to next flag ) \\ +&& z : as m but zero args allowed \\ + +&& a : valued : adjacent to flag (only) \\ +&& n : valued : next argument (only) \\ + +&& ? : dummy last entry ( can be any character ) \\ + + +int & match & Used internally by {\em argh\/} to calculate the minimum + length needed to uniquely identify each flag. + Flags are sorted ( using quick sort ) for this --- + the sort sequence is also used to display in \verb+show_args+. \\ + +&& Users may override this calculation by putting a + non-zero value in the match field: \\ + +&& $>0$ indicates match length to use \\ +&& $-1$ indicates exact match required \\ + +\end{tabular} + +The command line is processed by the call \verb+scan_args(argc,argv)+. + +If ADJARGS is set to TRUE, arguments may appear adjacent to the flag +if there is no ambiguity --- i.e., the whole flag is entered on the +command line. Alternatively, ( even if ADJARGS == FALSE ), the (first) +value to be associated with a flag may be introduced with EQUCHAR (`=' by +default). In the latter case, only sufficient of the flag to uniquely +distinguish it from other flags need be supplied. This is also true when +the (first) value follows as the next command line argument (i.e., separated +by white space). +ONECHARARGS may be set to TRUE in order to allow flags to be matched +by a single character followed by an adjacent argument as long as the +single character is an unambiguous abbreviation of the flag. Any other +partial matching would cause confusion and is disallowed.\\[2ex] + +To illustrate : ( flag sample ) + +\footnotesize +\begin{tabular}{ll} + -samplearg &complete match (adj) ok ( unless !ADJARGS )\\ + -sample arg &complete match (next) ok\\ + -sample=arg &complete match with = (adj) ok\\ + -sample= arg &complete match with = (next)\\ + &-- error -- ``value should be adjacent to `='\,''\\ + + -samarg &incomplete match (adj)\\ + &-- error -- ``ambiguous match''\\ + -sam arg &incomplete match (next) ok\\ + -sam=arg &incomplete match with =arg ok\\ + -sam= arg &incomplete match with = (next) arg\\ + &-- error -- ``value should be adjacent to `='\,''\\ + -sarg & single character match (adj) ok\\ + & provided ONECHARARGS == TRUE \&\& \\ + & there are no other `s' flags \\ + +\end{tabular} +\normalsize + +Linked lists are generated for each flag, accumulating command line arguments +in command line sequence. Where a flag takes zero arguments, the list item +points to the flag-invoking argument ( e.g., `-all' in the example above ). +Otherwise, each link item points to the next argv-specified value, after the +adjacent part has been skipped ( if necessary ). A `count' field contains +the total arguments taken from the command line. Thus if a 3-valued flag +were declared four times on the command line, and all expected arguments were +present, count would be set to 12. The function \verb+char *next_arg(flag,argv)+ +returns each argument in turn for a specified flag, NULL if there are no more. +To distinguish arguments gleaned from different sources, i.e., the +command line and an input file, a field {\em argsrc\/} is maintained in +the link record to record the setting of {\em argsource\/} in force +when the the argument was obtained. + +Any command line arguments that do not match any flag specifications accumulate +in the list pointed to by the dummy flag "". These are retrieved with +\verb+next_arg("",argv)+ calls.\\[2ex] + +Errors are reported as follows : + +\footnotesize +\begin{verbatim} +"argh! :" followed by : + + "unknown error\n", /* 0 */ + "flag %s not known\n", /* 1 */ + "flag %s ambiguous match\n", /* 2 */ + "invalid type for flag %s - fix source\n", /* 3 */ + "limit of %s argument instances - aborted\n", /* 4 */ + "flag %s value should be adjacent to '='\n", /* 5 */ + "flag %s (type adjacent) not followed by value\n", /* 6 */ + "flag %s - adjacent arguments not allowed without '='\n", /* 7 */ + "flag %s (type next) must use next argument\n", /* 8 */ + "flag %s (type next) has no next argument\n", /* 9 */ + "flag %s (type 0 valued ) should not have value\n", /*10 */ + "flag %s (type %s valued) has no value%s\n", /*11 */ + "flag %s (type %s valued) has only %s value%s\n", /*12 */ + "flag %s (type 1 or more) must have at least one value\n", /*13 */ + "duplicate flag %s in table - fix source\n", /*14 */ + "ambiguous flags %s and %s - fix source\n" /*15 */ +\end{verbatim} +\normalsize + +The following definitions are made : + +\footnotesize +\begin{verbatim} + +#define ARGHVER "argh v. 1.1" /* Version number */ +#define MAXARGS 50 /* Maximum argument instances provided for */ +#define MAXFLAGS 50 /* Maximum number of flags + needed to size sorting array argsort[] */ +#define FLAGCHAR '-' /* introduces a flag on command line */ +#define EQUCHAR '=' /* to separate a partial but + unambiguous flag from its value */ +#define MAXFLAGLEN 30 /* max flag length */ +#define VALIDTYPES "0123456789amnz" /* allowed flag types */ +#define ADJARGS TRUE /* allow adjacent args */ +#define ONECHARARGS FALSE /* allow unambiguous one-byte flags without EQUCHAR */ +#define ZEROCHECK FALSE /* test type '0' against next arg */ + +\end{verbatim} +\normalsize + +Note that an argument instance is the combination of one flag with one of the +associated values ( adjacent or not ) --- or an `other' argument.\\[2ex] + +\verb+show_args()+ displays argh analysis of command line : + +\begin{verbatim} +%program aaa bbb ccc -- -pr ddd eee -send -t fff + +argh v. 1.1 : 15 flags 11 command line arguments +others type ? match 1 count 3 : aaa bbb ccc +flag - type 0 match 1 count 1 : -- +flag body type z match 1 count 0 : +flag default type 1 match 1 count 0 : +flag file type z match 1 count 0 : +flag group type 1 match 1 count 0 : +flag help type 0 match 1 count 0 : +flag prompt type 2 match 1 count 2 : ddd eee +flag r type 0 match 1 count 0 : +flag send type 0 match 4 count 1 : -send +flag sent type 0 match 4 count 0 : +flag servant type 0 match 5 count 0 : +flag serve type 0 match 5 count 0 : +flag service type 0 match 5 count 0 : +flag tree type 1 match 1 count 1 : fff +flag value type 2 match 1 count 0 : +\end{verbatim} + +Note the calculated match lengths.\\[2ex] + +This version of argh expects to have a single command table whose +entries are flags i.e., values introduced on the command line with +FLAGCHAR ( `-' ). \\ + + +\end{document} +% remember : +% +% \documentstyle {article} {report} {book} +% \subsection and \subsubsection +% \ldots\ ``quote'' +% \$ \& \% \# \{ \} {\em italic\/} +% \begin{em} ... +% {\em Roman} +% \end{em} +% ``Mr.~Jones'' +% \mbox{\em itemnum\/} +% \footnote{This is an example of a footnote.} +% \( a_{1} > x^{2n} / y^{2n} > x' \) $x$ +% \[ x' + y^{2} = z_{i}^{2}\] +% \begin{quote} +% \begin{quotation} +% \begin{itemize} +% \item This is the first item of an itemized list. +% \begin{enumerate} +% \item This is the first ... +% \end{enumerate} +% \end{itemize} +% \end{document} % End of document. diff --git a/doc/manual/volume1/asnfilter.tai b/doc/manual/volume1/asnfilter.tai new file mode 100644 index 0000000..b2918e2 --- /dev/null +++ b/doc/manual/volume1/asnfilter.tai @@ -0,0 +1,22 @@ +chan iso6937toia5 + prog=fcontrol, + show="iso6937 -> ia5 conversion filter", + bptin=iso6937, bptout=ia5, + type=shaper, conv=loss, cost=99, + outinfo="asn -is iso_6937-2-add -os ccitt_x.408_ia5irv" + +chan ia5toiso6937 + prog=fcontrol, + show="ia5 -> iso6937 conversion filter", + bptin=ia5, bptout=iso6937, + type=shaper, conv=loss, cost=99, + outinfo="asn -is ccitt_x.408_ia5irv -os iso_6937-2-add + -ia ia5 -oa motis-86-6937" + +chan iso6937toteletex + prog=fcontrol, + show="iso6937 -> teletex conversion filter", + bptin=iso6937, bptout=ttx, + type=shaper, conv=loss, cost=99, + outinfo="asn -is iso_6937-2-add -os t.61-8bit + -ia motis-86-6937 -oa teletex" diff --git a/doc/manual/volume1/asnfilter.tex b/doc/manual/volume1/asnfilter.tex new file mode 100644 index 0000000..2adad0b --- /dev/null +++ b/doc/manual/volume1/asnfilter.tex @@ -0,0 +1,23 @@ +\File{asnfilter.tai},{12:11},{Dec 3 1991} +\L{\LB{chan iso6937toia5}} +\L{\LB{ prog=fcontrol,}} +\L{\LB{ show=\S{}\"iso6937 \-\> ia5 conversion filter\"\SE{},}} +\L{\LB{ bptin=iso6937, bptout=ia5,}} +\L{\LB{ type=shaper, conv=loss, cost=99,}} +\L{\LB{ outinfo=\S{}\"asn \-is iso\_6937\-2\-add \-os ccitt\_x.408\_ia5irv\"\SE{}}} +\L{\LB{}} +\L{\LB{chan ia5toiso6937}} +\L{\LB{ prog=fcontrol,}} +\L{\LB{ show=\S{}\"ia5 \-\> iso6937 conversion filter\"\SE{},}} +\L{\LB{ bptin=ia5, bptout=iso6937,}} +\L{\LB{ type=shaper, conv=loss, cost=99,}} +\L{\LB{ outinfo=\S{}\"asn \-is ccitt\_x.408\_ia5irv \-os iso\_6937\-2\-add }} +\L{\LB{ \-ia ia5 \-oa motis\-86\-6937\"\SE{}}} +\L{\LB{}} +\L{\LB{chan iso6937toteletex }} +\L{\LB{ prog=fcontrol,}} +\L{\LB{ show=\S{}\"iso6937 \-\> teletex conversion filter\"\SE{},}} +\L{\LB{ bptin=iso6937, bptout=ttx,}} +\L{\LB{ type=shaper, conv=loss, cost=99,}} +\L{\LB{ outinfo=\S{}\"asn \-is iso\_6937\-2\-add \-os t.61\-8bit }} +\L{\LB{ \-ia motis\-86\-6937 \-oa teletex\"\SE{}}} diff --git a/doc/manual/volume1/auth.tex b/doc/manual/volume1/auth.tex new file mode 100644 index 0000000..2073a7e --- /dev/null +++ b/doc/manual/volume1/auth.tex @@ -0,0 +1,244 @@ +\section{PP authorisation}\label{sect:auth} + +Authorisation is applied after address parsing and validation, to +establish whether the message is permitted to be transferred on a per +recipient basis. Address lookup may establish several possible +outbound channels for each recipient - authorisation selects one of +these after applying tests based on entries in the three authorisation +tables \file{auth.channel}, \file{auth.mta} and \file{auth.user}. + +\[\fbox{\begin{tabular}{l p{0.8\textwidth}} +\bf NOTE: & +It is intended that warnings may be sent to recipients and senders +regardless of the channels status. This functionality is not yet +available. +\end{tabular}}\] + +Access policy for channel pairs ( inbound + outbound ) determines how +the rights for the four entities : sender, recipient, sending MTA and +destination MTA are to be interpreted. ( `Rights' means one of the +four values in/out/both/none and a fifth value `unset' to indicate +that no table entry is present.) + +The intention is that one of these four may be shown to be authorising +the message ( i.e., willing to pay for it ). + +It should be noted that authorisation is not applied to delivery report +messages. + +\subsection{Access policy} +The access policy is one of the following: +\begin{describe} +\item[\verb|none|:] +Message may not be transferred + +\item[\verb|free|:] +No constraints on the four entities + +\item[\verb|block|:] +( i.e., ``blockable'' ) - at least one of the four must enable the +message by specifying `in' or `both' for the inbound channel and `out' +or `both' for the outbound channel. The message may not be +transferred if none of the four methods enable it. Therefore the +default is to not let messages through, the action on the configuration to +enable it. + +\item[\verb|negative|:] +Any one of the four may stop transfer by disabling the +message. This implies the default state is to let everything through, +and special cases are stopped by explicit configuration. + +\end{describe} + +When determining rights for a proposed transfer the following +algorithm is followed. +\begin{itemize} +\item Determine the inbound and outbound channels and look up +this pair in the \file{auth.channel}\index{auth.channel} file. + +If there is no entry in this file, take the default from the tailoring +variable as the access policy for the channel. + +\item If the access policy is free or none, then the message is +allowed through or rejected respectively. + +\item If the access policy is negative, check the mta and user +tables, \file{auth.mta} and \file{auth.user} to see if this route is +explicitly disabled. + +\item If the access policy is block, check the user and mta tables +to see if the route is explicitly enabled. +\end{itemize} + +\subsection{Table formats} +There are three tables associated with authorisation, plus the tailor +variables. The first of these tables is the \file{auth.channel} table. +This contains the overall policies for channel to channel relaying. +As the key, the table has the syntax + +\begin{quote}\small\begin{verbatim} + "->" +\end{verbatim}\end{quote} + +If no value is found for the above, then as a fall back the values +\begin{quote}\small\begin{verbatim} + "->" "*" +"*" "->" +\end{verbatim}\end{quote} +are checked in that order. + +The values that the table can have are as follows + +\begin{describe} +\item[\verb||:] Any of the above mentioned policies +(\verb|free|, \verb|block| etc.). + +\item[\verb|warnsender=|:] Send a warning message to the sender, +with text taken from the given file. + +\item[\verb|warnrecipient=|:] Send a warning message to the +recipient with text taken from the given file. + +\item[\verb|sizelimit=|:] Enforce the given size +limit on messages. No messages larger than this size will be relayed. +This is obeyed regardless of the overall policy of the channel. (i.e. +A channel may be marked as free with a sizelimit, and the sizelimit +will still be enforced.) + +\item[\verb|test|:] This setting modifies the checking procedure to +always allow the message through. However, all the checking is carried +out and the result is logged. This is useful to test out the results +of a setting for a while before fully applying them. +\end{describe} + +An example of this format might look like the following: +\begin{quote}\small\begin{verbatim} +822-local->pss:free +822-local->local:block +822-local->slocal:free +822-local->smtp:free, sizelimit=5000, warnsender=smtpwarnsender +822-local->janet:block, sizelimit=4000 +x400in84->x400out84:none +x400in84->local:free +822-local->x400out84:block, sizelimit=10000, warnsender=restriction +smtp->smtp:block, test +\end{verbatim}\end{quote} + +The next table is the mta policy table in file \file{auth.mta}. This +governs the policy for a given mta if the channel is not \verb|free| +or \verb|none|. The key used in this table is the source mta and +the destination mta. Each of these are looked up separately to +determine policies. + +The allowed values for this field are any of the following in a comma +separated list +\begin{describe} +\item[\verb|=|:] +This specifies for given channels what directions are allowed for this +mta. The possible directions are + \begin{describe} + \item[\verb|in|:] Allow inbound traffic for this channel. + \item[\verb|out|:] Allow outbound traffic for this channel. + \item[\verb|both|:] Allow both inbound and outbound + traffic for this channel. + + \item[\verb|none|:] Allow no access for this channel. + \end{describe} + +\item[\verb|default=|:] +This specifies the default directions that traffic can flow in the +absence of a particular channel being specified. + +\item[\verb|requires=|:] +This mta requires that the user being authorised to send to this +matches the given pattern. This is a standard regular expression as +specified in \man regex (3). + +\item[\verb|excludes=|:] +The mta requires that the user being authorised does not match the +given pattern. + +\item[\verb|bodypart-excludes=|:] +This specifies a list of bodyparts that the mta will not accept. +These bodyparts are taken from the list of standard bodyparts as +described in the Section~\ref{tai:bodypart}. + +\item[\verb|sizelimit=|:] +The mta will not relay messages larger than the given sizelimit. +\end{describe} + +An example of this table might look like the following: +\begin{quote}\small\begin{verbatim} +vs2.cs.ucl.ac.uk:default=both, smtp=out, x400out84=out, \ + 822-local=in, excludes="A.DaCruz.*" +localhost:default=in, x400in84=out, smtp=both, \ + 822-local=none, sizelimit=654321 +\end{verbatim}\end{quote} +(Lines are folded for readability) + +Finally, the user table is where both the recipient and originator are +looked up to determine access rights if none of the other tests proves +conclusive. The key is either the full normalized name of the user, or +if local, just the local part of the name. +The values may contain any of the following: +\begin{describe} +\item[\verb|=|:] +This specifies, much as for the mta, what directions are allowed for +this user. + +\item[\verb|default=|:] +This gives the default directions allowed for this user. + +\item[\verb|bodypart-excludes=|:] +A list of bodyparts that are not allowed to be sent to the user. + +\item[\verb|sizelimit=|:] +Disallow messages larger than this sizelimit. + +\end{describe} + +An example of the user authorisation table is: +\begin{quote}\small\begin{verbatim} +j.taylor@cs.ucl.ac.uk:default=both +/I=J/S=Taylor/OU=cs/O=ucl/PRMD=uk.ac/ADMD=gold 400/C=gb/:\ + bodypart-excludes=g3fax|dmd, sizelimit=100000, 822-local=both +a.dacruz@cs.ucl.ac.uk:default=both +s.kille@cs.ucl.ac.uk:default=both +p.cowen@computer-science.nottingham.ac.uk:default=both, \ + 822-local=in, x400out84=none +j.onions@computer-science.nottingham.ac.uk:default=both +\end{verbatim}\end{quote} + +\subsection{Statistical logging} + +Each line in the statistics log ( `stat' ) contains : +\begin{itemize} +\item a success indicator ( e.g., `ok' or `failed' ) +\item unique message id +\item inbound channel$\rightarrow$outbound channel +\item sender +\item sending MTA +\item recipient +\item destination MTA +\item message size +\item a diagnostic message +\end{itemize} + +Fields are space delimited and double quoted where necessary. + +The possible diagnostic messages are shown in Table~\ref{table:authmsg}. + +\tagtable{authreasons}{Authorisation Disagnostics}{table:authmsg} + +The \verb+(%s %s)+ fields above are filled in with inbound and outbound +rights i.e., in/out/both/none/unset + +Duplicate recipients are eliminated (second and subsequent) if there +is an exact match on the 822 or X400 address (as appropriate) NOT the +original entry. + +Channel binding is performed after all other tests have been passed - and +takes into account any body parts actually received but not specified in the +message header. + +Unsuccessful recipients are flagged to generate non-delivery reports. diff --git a/doc/manual/volume1/chan-examp.tai b/doc/manual/volume1/chan-examp.tai new file mode 100644 index 0000000..7a1c436 --- /dev/null +++ b/doc/manual/volume1/chan-examp.tai @@ -0,0 +1,19 @@ +chan 822-local prog=local, + show="Local 822 Delivery channel",type=both, + sort="user time",adr=822,adr-order=ukpref, + hdrout=822, bptout=ia5, content-out=822, + outtable=local,access=mts, drchan=dr2rfc + +chan x40084 prog=x400out84,show="X400 1984 channel", + type=both, adr=x400, adr-order=ukpref, + intable=x400in84, outtable=x400out84 + +chan qmgr-load prog=qmgr-load,show="Loading the QMGR", + type=qmgrload + +chan p2flatten prog=p2flatten,show="Structured body -> P2", + type=shaper,content-out=p2 + +chan g3faxtotxt prog=fcontrol,type=shaper,bptin=g3fax, + bptout=ia5,outinfo=f-fax2txt, + show="Fax -> Text mapper" diff --git a/doc/manual/volume1/chan-examp.tex b/doc/manual/volume1/chan-examp.tex new file mode 100644 index 0000000..63e45d7 --- /dev/null +++ b/doc/manual/volume1/chan-examp.tex @@ -0,0 +1,20 @@ +\File{chan\-examp.tai},{12:11},{Dec 3 1991} +\L{\LB{chan}\Tab{8}{822\-local prog=local,}} +\L{\LB{}\Tab{8}{show=\S{}\"Local 822 Delivery channel\"\SE{},type=both,}} +\L{\LB{}\Tab{8}{sort=\S{}\"user time\"\SE{},adr=822,adr\-order=ukpref,}} +\L{\LB{}\Tab{8}{hdrout=822, bptout=ia5, content\-out=822,}} +\L{\LB{}\Tab{8}{outtable=local,access=mts, drchan=dr2rfc}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{x40084 prog=x400out84,show=\S{}\"X400 1984 channel\"\SE{},}} +\L{\LB{}\Tab{8}{type=both, adr=x400, adr\-order=ukpref,}} +\L{\LB{}\Tab{8}{intable=x400in84, outtable=x400out84}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{qmgr\-load prog=qmgr\-load,show=\S{}\"Loading the QMGR\"\SE{},}} +\L{\LB{}\Tab{8}{type=qmgrload}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{p2flatten prog=p2flatten,show=\S{}\"Structured body \-\> P2\"\SE{},}} +\L{\LB{}\Tab{8}{type=shaper,content\-out=p2}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{g3faxtotxt}\Tab{24}{prog=fcontrol,type=shaper,bptin=g3fax,}} +\L{\LB{}\Tab{8}{bptout=ia5,outinfo=f\-fax2txt,}} +\L{\LB{}\Tab{8}{show=\S{}\"Fax \-\> Text mapper\"\SE{}}} diff --git a/doc/manual/volume1/chantbl.tex b/doc/manual/volume1/chantbl.tex new file mode 100644 index 0000000..0ec765d --- /dev/null +++ b/doc/manual/volume1/chantbl.tex @@ -0,0 +1,25 @@ +\small\begin{verbatim} +# +# +a.cs.uiuc.edu:a.cs.uiuc.edu(smtp) +# +bsec.abcy.uwist.ac.uk:bsec.abcy.uwist.ac.uk(gb-janet) +bt-gold:bt-gold(x400out84) +bte:bte(x400out84) +abcl.co.uk:ukc.ac.uk(gb-janet),ukc.ac.uk(gb-pss) +btvax.ulster.ac.uk:btvax.ulster.ac.uk(gb-janet) +bull:bull(x400out84) +bunny.ulcc.ac.uk:bunny.ulcc.ac.uk(gb-janet) +# +emu-france:emu-france(x400out84) +# +torch.co.uk:ukc.ac.uk(gb-janet),stl.stc.co.uk(gb-pss) +# +# These are resolved directly by the DNS - no relay +edu:(smtp) +gov:(smtp) +com:(smtp) +us:(smtp) +mil:(smtp) +org:(smtp) +\end{verbatim} diff --git a/doc/manual/volume1/chanx400examp.tex b/doc/manual/volume1/chanx400examp.tex new file mode 100644 index 0000000..92b6bd4 --- /dev/null +++ b/doc/manual/volume1/chanx400examp.tex @@ -0,0 +1,11 @@ +\begin{quote}\small\begin{verbatim} +#-*************************** +# +# -*** nasa ***- +us-nasa:us-nasa(x400out) +# +# -*** ucl ***- +gb-ucl:gb-ucl(x400out) +# +#-*************************** +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/chx400out.tex b/doc/manual/volume1/chx400out.tex new file mode 100644 index 0000000..6767ee3 --- /dev/null +++ b/doc/manual/volume1/chx400out.tex @@ -0,0 +1,43 @@ +\begin{quote}\footnotesize\begin{verbatim} +#-************************************** +# +# +# -*** UCL's default local entry ***- +# -*** this is different for every PP site ***- +# (lines folded for readability) +default:lpsap='"591"/Internet=bells',lmta="UK.AC.UCL.CS",lpass=" " +# +# +-*** NASA ***- +# +us-nasa:rmta="titan.arc.nasa.gov", + rpsap='"591"/Internet=128.102.128.5' +# +# -*** UCL ***- +gb-ucl:rmta="UK.AC.UCL.CS",rpass=" ", + rpsap='"591"/X121+23421920030080' +# +# -*** when pid is specified, the rpsap format below is used ***- +# +eg_site1:rmta="SiteName1", + rpsap='"999"/Int-X25(80)=23421234005004+PID+03010100' +# +# -*** when more than one network address is specified ***- +# -*** note the network addresses are seperated by '|' ***- +# +eg_site2:rmta="SiteName2", + rpsap='"400"/X121+23427351714799|X121+23428490013799' +# +# -*** when trynext is specified, the format below is used ***- +# +eg_site3:rmta="SiteName3",rpsap='"999"/X121+234212340050', + trynext="eg_site2" +# +# +au-manta:rmta="manta.cng.dit.csiro.au",rpass=" ", + rpsap='"591"/Int-X25(80)=50523343000180+PID+03010100|Internet=128.250.1.100' +# +# +# +#-************************************** +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/configure.aux b/doc/manual/volume1/configure.aux new file mode 100644 index 0000000..44bb67e --- /dev/null +++ b/doc/manual/volume1/configure.aux @@ -0,0 +1,84 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {3}Configuring PP}{16}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{tailoring}{{3}{16}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.1}The General Syntax of Tailor File Entries}{16}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.2}Variable Tailor File Entries}{17}} +\newlabel{variable-tai}{{3.2}{17}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.1}Mandatory Tailoring Variables}{17}} +\newlabel{tai:bodypart}{{3.2.1}{18}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.2}Optional Tailoring Variables}{18}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.3}Logging Tailor File Entries.}{21}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.1}{\ignorespaces Example of Log Tailoring}}{23}} +\newlabel{example:log}{{3.1}{23}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.1}Diverting Logging Streams}{23}} +\newlabel{sect:divlog}{{3.3.1}{23}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.4}Table Tailor File Entries}{24}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.5}Channel Tailor File Entries}{24}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.2}{\ignorespaces Example of Table Tailoring}}{25}} +\newlabel{example:table}{{3.2}{25}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.3}{\ignorespaces Example of Channel Tailor Entry}}{31}} +\newlabel{example:chan}{{3.3}{31}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.6}ISODE Runtime Tailoring}{32}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.6.1}Queue Manager Tailoring}{32}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.6.2}X.400 Tailoring}{32}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.7}Channel Pairing}{33}} +\newlabel{channel:pair}{{3.7}{33}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.8}Tailoring of Common Channels}{34}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.1}Submit}{34}} +\newlabel{sect:submit}{{3.8.1}{34}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.2}Protocol Channels}{34}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{SMTP channel}{34}} +\newlabel{sect:smtp}{{3.8.2}{34}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{X.400 inbound channel}{35}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{UUCP Channel}{36}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{{\string\psf\space DECnet} MAIL11 channel}{36}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.3}Filter Control and Common Filters}{37}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.4}{\ignorespaces Example of Filter Control Tailoring}}{38}} +\newlabel{example:fcontrol}{{3.4}{38}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.5}{\ignorespaces Simple Shell Script Filter}}{38}} +\newlabel{example:shellfilt}{{3.5}{38}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {3.1}{\ignorespaces Filter Control Expansion Macros}}{39}} +\newlabel{tab:expansions}{{3.1}{39}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{RFC\penalty \@M \ 822 Filter}{39}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{P2norm Filter}{41}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Body Part Deleting Filters}{42}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{ODIF filters}{42}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.4}The List Channel}{42}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.5}The RFC 1148 Channels}{43}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.6}Shaping Channels}{44}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{RFC 934 Channel}{44}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{P2flatten Channel}{44}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{P2explode Channel}{45}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.8.7}Miscellaneous Channels}{45}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Qmgrload Channel}{45}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Msg-Clean Channel}{45}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Debris Channel}{45}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Splitter Channel}{46}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Timeout Channel}{46}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Warning Channel}{46}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Dr2rfc Channel}{46}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {3.2}{\ignorespaces Warning expansion macros}}{47}} +\newlabel{table:warn}{{3.2}{47}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.9}How Channels Work}{48}} +\newlabel{chan-op}{{3.9}{48}} +\global\@namedef{cp@configure}{ +\setcounter{page}{50} +\setcounter{equation}{0} +\setcounter{enumi}{3} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{9} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{5} +\setcounter{table}{2} +} diff --git a/doc/manual/volume1/configure.tex b/doc/manual/volume1/configure.tex new file mode 100644 index 0000000..05b225e --- /dev/null +++ b/doc/manual/volume1/configure.tex @@ -0,0 +1,1865 @@ +\chapter {Configuring PP}\label{tailoring} + +This chapter is principally concerned with the \file{tailor} file and +how it is configured. The \file{tailor} file contains the runtime MTA +configuration information. This chapter describes how to construct +this information. + +The information in the \file{tailor} file may duplicate that in the +\file{Make.defs} in some cases. In these cases, the \file{tailor} file +settings will override the \file{Make.defs} settings. + +There are four basic types of entries in the \file{tailor} file: +\begin{itemize} +\item Variable entries. +\item Logging entries. +\item Table entries. +\item Channel entries. +\end{itemize} +The following sections describe how to construct these entries. +Appendix~\ref{app:tailor} contains a complete example \file{tailor} file. + +Since the construction of the information is complex, it is {\em +strongly } recommended to use \man ckconfig (8). +\pgm{ckconfig} applies several sanity checks to the information +contained in the \file{tailor} file and generally ensures that the +information represents a logically correct configuration. +\pgm{ckconfig} is described in Section~\ref{sect:ckconfig}. + +\section {The General Syntax of Tailor File Entries} + +A comment starts with an unescaped hash (\#) and finishes at the end +of the line. Other lines are split into components separated by white +space or commas (or both). A line may be extended onto the next line +by starting that next line with some white space. A field may be +enclosed by quotation marks (\verb+""+ or \verb|'field'|); this +disables special characters such as field delimiters. + +\section {Variable Tailor File Entries}\index{tailoring, variables} +\label{variable-tai} + +Variable entries take the form of a keyword and its value, +separated by white +space. Each key/value pair should be on a separate line and start in +the first column. For example: +\begin{quote}\small\begin{verbatim} +cmddir /usr/pp/cmds +tbldir /usr/pp/tables +\end{verbatim}\end{quote} + +There are a finite number of tailoring variables that can be +referenced in the \file{tailor} file. These tailoring variables are +divided into two types, mandatory tailoring variables and optional +tailoring variables. They are listed and described in the sections +below. + +\subsection{Mandatory Tailoring Variables}\index{tailoring, simple} +The following tailoring variables {\em must} be included in the +\file{tailor} file: + +\begin{description} +\item[\verb+loc\_dom\_mta+:]\index{loc\_dom\_mta} +This is the full domain name of the local mta. +It is used for trapping routing loops and so should be globally unique. +For example: \linebreak \verb+sheriff.cs.nott.ac.uk+. This is not +recognised as a local address by default. + +\item[\verb+loc\_dom\_site+:]\index{loc\_dom\_site} +This is the full domain name of the local site. This is used to reference the +site, and may refer to a group of MTAs collectively. For example: +\verb+cs.nott.ac.uk+. This variable should usually be present in the +domain table and marked as local in the \file{domain} table to ensure +that messages routed to this name are regarded as suitable for local +delivery. + +\item[\verb+loc\_or+:]\index{loc\_or} +This is the local O/R address defaults given in X.400 RFC~1148 +encoding form. It is used to fill in missing default components and +for tracing fields. it is not recognised as the local X.400 domain by +default, that must be marked in the \file{or} table. +For example: +\begin{quote}\begin{verbatim} +"/OU=CS/O=NOTT/PRMD=UK.AC/ADMD= /C=GB/" +\end{verbatim}\end{quote} +\pgm{Note}: If the name contains spaces or other special characters, it must +be quoted as above. + +\item[\verb+qmgrhost+:]\index{qmgrhost} +This is the name of the machine on which the QMGR is running. For +example, you could give the output of \man hostname (1) here. It is +used as an index either into the ISODE \file{isoentities} file, or to +search the X.500 directory for the application context. It is used by +\pgm{submit} to contact the qmgr. \pgm{Submit} caches the result of +the lookup in the file \file{qmgr-pa.cache} in the queue directory to +speed up the resolution process. If this variable is changed or the +details in the \file{isoentities} file or the X.500 directory are +altrered, this file should be removed. + +\item[\verb+postmaster+:]\index{postmaster} +This is the RFC~822 address of the local mail system administrator. +Typically of the form: \verb+Postmaster +. + + +\item[\verb+bodypart+:]\index{bodypart}\label{tai:bodypart} +This is a list of bodyparts that are recognised by the system. This +line may occur several times in the tailor file, each time appending +its arguments to the list of body parts. + +\item[\verb+headertype+:]\index{headertype} +This is a list of headers that are recognised by the system. This line +like the above line may occur several times each time appending to the +list. +Note that the common \verb+hdr.+ prefix is omitted from these values. + +\item[\verb+pptsapd\_addr+:]\index{pptsapd\_addr} +This is the address that the \pgm{pptsapd} listens on for incoming +connections. It is also used by the \pgm{qmgr} to call up the +\pgm{pptsapd} to start a channel. The default value is: +\verb|Internet=localhost+20001|. This is suitable if you are an +internet site, but not if you have just your own ethernet which is not +connected to the internet. In this case a more suitable value might be +\verb|LOCAL-ETHER=localhost+20001| or \verb|localHost=20001|. (See the +ISODE manual for more details on defining address communities.) + +This indicates that processes can communicate with the \pgm{pptsapd} +daemon via a TCP/IP connection to the local machine on Port 20001. +The address could just as easily be a remote machine name specifying +an X25 address or a real NSAP (e.g., \verb|Janet=0000210010297|). + +\end{description} + +\subsection{Optional Tailoring Variables} + +The tailoring variables in this section are less critical, having +defaults that are normally suitable. + +\begin{description} +\item[\verb+cmddir+:]\index{cmddir} +This is a directory and is the default place to find all the main PP +commands. It should be a fully qualified pathname, i.e., starting with +a forward slash. + +\item[\verb+tbldir+:]\index{tbldir} +This is the directory where all the table files are located and should +be a fully qualified pathname; it is used by +\verb+dbmbuild+\index{dbmbuild} to generate the hashed database and +for address lookups when tables are defined in +\verb+linear+\index{linear} mode. + +\item[\verb+quedir+:]\index{quedir} +This is the base directory for the PP queue. It should be a fully +qualified pathname. + +\item[\verb+logdir+:]\index{logdir} +This is the directory where log files will be written in by default. + + +\item[\verb+chandir+:]\index{chandir} +This is the directory where the executable channel programs are found. +It defaults to a directory called \file{chans} within the +\file{cmddir}. When defined, if it is a relative name, (i.e., not +starting with a forward slash) then it will be assumed to be a +subdirectory of the \file{cmddir}. + +\item[\verb+formdir+:]\index{formdir} +This is the directory where the simple programs run by the +\pgm{fcontrol} are found. Not usually tailored, it defaults to a +directory called \file{format} within the \file{cmddir}. +When it is defined, it is taken as +relative to the \file{cmddir} unless a full pathname is given. + +\item[\verb+dbm+:]\index{dbm} +This is the name of PP database. It is assumed to be +relative to the \file{tbldir} directory unless a full pathname is +given. The default is \file{ppdbm}. + +\item[\verb+pplogin+:]\index{pplogin} +This is the user id that most of the PP programs will run under. It +defaults to \file{pp} and should be a username found in the +\file{/etc/passwd} file. + +%%% \item[\verb+mboxname+:]\index{mboxname, mailbox, maildrop} +%%% This is the maildrop file used by the 822-local delivery channel for +%%% delivering local messages into users' home directories. The default +%%% is \file{.mail}. +%%% +%%% \item[\verb+mailfilter+:]\index{mailfilter} +%%% This is the mailfilter file used by the 822-local delivery channel +%%% (see {\em The PP Manual: Volume~3 -- Users Guide}). +%%% The default is \file{.mailfilter}. +%%% +%%% \item[\verb+sysmailfilter+:]\index{sysmailfilter} +%%% This is the mailfilter file the 822-local delivery channel uses if the +%%% user does not have one. +%%% The default is \file{/usr/local/lib/mailfilter}. +%%% +%%% \item[\verb+delim1+:]\index{delimiters}\index{mailbox}\index{maildrop} +%%% \index{delim1} +%%% This is the message delimiter appended to the maildrop file before +%%% each message. The default is \verb+"\001\001\001\001\012"+ i.e. four +%%% control-A's and a newline. (Beware, the {\em C} syntax \verb+\n+ +%%% does not work (yet)). +%%% +%%% \item[\verb+delim2+:]\index{delim2} +%%% This is the message delimiter appended to the maildrop file after +%%% each message. The default is +%%% \verb+"\001\001\001\001\012"+ i.e. four control-A's and a newline. + +\item[\verb+isode+:]\index{isode} +This variable allows the tailoring of any ISODE parameter specified in +the {\man isotailor (5)} file. However, the ISODE logging levels are +better handled by the \verb+isodelogs+ tailor line. + +\item[\verb+authchannel+:]\index{authchannel} +This gives the default policy for channel authorisation; it is in the +form of a \file{channel-auth} record (see Section~\ref{sect:auth}). +The default is +\verb+block+. This determines the policy for any inbound/outbound +channel pairing not explicitly entered in the channel authorisation +table \file{channel-auth}. + +\[\begin{tabular}{l p{0.7\textwidth}} +Note:& This feature is deprecated and will be removed in future. To +set a default authorisation policy, use a construct \verb|*->*| in the +\file{auth.channel} table. +\end{tabular}\] + +\item[\verb+authloglevel+:]\index{authloglevel} +This sets the level of authorisation logging. Three levels are defined: +\verb|low|, \verb|medium| and \verb|high|. These levels are now little +used and should probably not be set. + +\item[\verb+wrndfldir+:]\index{wrndfldir} +This is a directory to hold warning message files which can be sent +automatically to sender or recipients when authorisation fails or a +message is delayed in delivery. It may be a fully qualified pathname +starting with \verb+"/"+, or else is taken relative to the table +directory \file{tbldir}. + +The default is \verb+warnings+. + +\item[\verb+warninterval+:]\index{warninterval} +This is the time in hours after which to send a warning to the sender +of the message telling him or her that the message is stuck in the MTA. + +The default is 24 hours. + +\item[\verb+nwarnings+:]\index{nwarnings} +This is the maximum number of warnings to send. + +The default is two warnings. + +\item[\verb+returntime+:]\index{returntime} +This is the time in hours after which to expire an undelivered +message. By default, this time is doubled for low priority messages +and halved for high priority messages. However, these other values can +be overridden by specifying two other times in hours after the normal +return time, the first of these being the return time for high +priority messages and the second for low priority messages. + +The default normal time out is 72 hours, giving about a day for high +priority messages and just less than a week for low priority messages. +Messages that pass through the list channel are set to low priority. + +If you are expecting problems in delivery (e.g., around Christmas) +then it may be worth increasing this to some larger value temporarily. + +\item[\verb+lockstyle+:]\index{lockstyle} +This is the style of locking to be used when it is necessary to lock a file. +It may be one of the following: + +\[\begin{tabular}{| l | l |} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline\hline + \tt flock& Use the \man flock (2) system call. \\ + \tt fcntl& Use the \man fcntl (2) system call. \\ + \tt file& Use lock files that are created and removed.\\ + \tt lockf& Use the \man lockf (3) library call. \\ +\hline +\end{tabular}\] + +The default style is \verb+flock+ but may be changed if you have +doubts about the interaction of \man flock (2) and nfs. +This is a run time configuration variable, and it will depend on what +platform you are running as to whether all the above will be +supported. The file locking mechanism will always be available, though. + +\item[\verb+lockdir+:]\index{lockdir} +If the ``\verb+file+'' style of locking is to be +used, this is the directory to create the files in. It defaults to +\file{/tmp} and should be cleaned out at reboot time. It is ignored +otherwise. + +\item[\verb|maxloops|:]\index{maxloops} +This is a number indicating the number of times a +message may pass thorough this mta before being rejected. The default +is 5. + +\item[\verb|maxhops|:]\index{maxhops} +This is a number indicating the number of trace +fields a message may contain. If it has more than this number, the +message will be rejected as looping. The default is 25. + +\item[\verb|x400mta|:]\index{x400mta} +This is the name of this MTA in the X.400 world. It +defaults to the same as \verb|loc_dom_mta|. It may be tailored +differently if your MTA goes by a different name in the X.400 world. +It is only used for information, no use is made for any routing +purposes. It should therefore be a string that users will understand. + +\item[\verb|submit\_addr|:]\index{submit\_addr} +This is a list of comma-separated submit +addresses. By default a user interface program or channel will +directly invoke submit, but with this option it will call a submit +daemon. The specification is +\begin{quote}\begin{verbatim} + [ ":" ] +\end{verbatim}\end{quote} +The hostname is a TCP hostname, the port reference is either a number +or a port reference found in the services database. In this mode, +\pgm{submit} is usually run under \man inetd(8). See +Section~\ref{sect:submit} on page~\pageref{sect:submit} for more +details. The port defaults to \verb|4001| if not given, for no very +good reason. If it fails to contact \pgm{submit} it will attempt to do +a fork/exec of it as ususal. + +\item[\verb|dap\_user|:]\index{dap\_user} +This is an X.500 directory distinguished name +used when PP binds to the directory. It is useful to use this in +versions of ISODE greater than 6.8 to distinguish PP use of X.500 from +other users. There is no default for this, if this variable is empty +all directory binds will be anonymous. + +\item[\verb|dap\_passwd|:]\index{dap\_passwd} +A password to be used in conjunction with +the \verb|dap_user| variable in binding to the directory. It is not +necessary to set this variable normally, unless the directory entries +require an authenticated bind. + +\item[\verb|queuestruct|:]\index{queuestruct} +This is a variable used to control the structure of the queue. This is +only useful to change if you are expecting very large queues ($>$~2000 +messages in the queue at one time.) It takes two numbers. The first +number specifies the fan out of the queue. With a value of +\verb|100|, messages will be put in 100 sub-directories of the main +queue file. This cuts down the searching of the main directory but is +only useful for very large queues. The second optional number is the +level of sub-directories to create. By default this is one, indicating +an indirection of one directory. Again this parameter should not +be changed unless extremely large queues are expected (say $>$~50,000.) + +\item[\verb|fsync|:] This is a boolean variable which controls the use +of the \man fsync (2) call. Fsync is normally used when critical files +are written to before passing back a handshake. However, it can be +switched off by a value of \verb|no| if you consider that it is too +expensive. + +\item[\verb|diskuse|:] This parameter is used to limit the disk space +consumed by PP. There are two numbers, the first being the number of blocks +that should be free, the second being the percentage of the disk space +that should be free. Either of these can be effectively disabled by +setting them to \verb|0|. The disk that is checked is the partition +holding the queue (\verb|quedir|). + +\item[\verb|adminstration\_assigned\_alternate\_recipient|:] +\index{adminstration\_assigned\_alternate\_recipient} +This variable allows a undeliverable local address to be redirected to +the user given here. This needs to be used with care, as messages that +would normally be returned to the sender will be delivered to this +address. Possible uses of this feature might be to deliver all failed +messages to the postmaster for advice, or to deliver to a special +program that returns fuzzy matches. +\end{description} + +\section{Logging Tailor File Entries.}\index{tailoring, logs} +This section describes how to tailor the logging produced by PP. + +There are four main groups of logging; covering normal events, unusual +operational events, authorisation, and ISODE. By default, each group +will describe in a single file, the appropriate activities of all the +programs that provide logs. However, the \file{tailor} file may be used to +separate out logging on a per-program or per-channel basis (see +Section~\ref{sect:divlog} for more details). Thus, for +example, all normal activities may be logged in one file except +\pgm{submit} which may be logged in a different file, and at a different +level. + +All logging entries are comprised of a standard set of +key/value pairs, described below. + +\begin{describe} +\item[\verb+file=xxx+:]\index{log, file} +Set the log file to \verb+xxx+. This is either a fully qualified +filename, or more usually just a relative pathname which is taken +relative to the \file{logdir}. It defaults to one of \verb|norm|, +\verb|stat| or \verb|oper| depending on the log stream. + +\item[\verb+level=value+:]\index{log, level} +This adds to the logging levels the given value. Legal values are +\begin{describe} +\item[\verb+all+:] Enable all logging (this fills disks very quickly!). +\item[\verb+fatal+:] Enable reporting of fatal errors. +\item[\verb+exceptions+:] Report exceptional happenings. +\item[\verb+notice+:] Report interesting happenings. +\item[\verb+trace+:] Trace the programs flow (very detailed). +\item[\verb+debug+:] A full debugging trace. +\item[\verb+pdus+:] Show protocol data units. +\end{describe} +The last three levels are only available if PP was compiled with +\verb+PP_DEBUG+ defined to a suitable level. The value \verb|all| is +special, in that it sets all values. The other levels only set the +individual values (e.g., \verb+debug+ does not imply settings of any +other values). + +The default level is to enable \verb+notice+, \verb+exceptions+ and +\verb+fatal+. + +\item[\verb+dlevel=value+:]\index{log, dlevel} +This unsets a logging level. Legal values of this are the same as +the above. + +\item[\verb+sflags=value+:]\index{log, sflags} +This sets the logging flags to a given value; the value being one of: +\begin{describe} +\item[\verb+close+:] Close the log file after each entry is made. +\item[\verb+create+:] Create the log file if it doesn't already exist. +\item[\verb+zero+:] Zero the log file when it gets too big. +\item[\verb+tty+:] Log to the standard error as well as to the +file. This should be used only when debugging. +\end{describe} +The default is to \verb|create| new files. + +\item[\verb+dflags+:]\index{log, dflags} +This unsets one of the above levels for the log. + +\item[\verb+size+:]\index{log, size} +Set the maximum size in Kilobytes to which the log should be allowed +to grow. The default is not to limit the log size. What happens when +the logfile reaches the specified maximum is governed by the flags. If +\verb|zero| is not in force, logging will just stop. If \verb|zero| is +in force, then the log will be truncated and restarted. +\end{describe} + +There are currently four logging variables that can be specified +although there are several logging structures. + +The logging variables are: + +\begin{describe} +\item[\verb+normlog+:]\index{normlog} +This is the log where the bulk of the logging is done. + +\item[\verb+operlog+:]\index{operlog} +This is where urgent messages are logged. In the normal course of +events no entries should be made in this log unless something serious +has happened. + +\item[\verb+authlog+:]\index{authlog} +This indicates where authorisation tracing will be logged. + +\item[\verb+isodelog+:]\index{isodelog} +This line allows the tailoring of specific ISODE tracing levels. The +first argument is an ISODE logging level. The rest of +the line is interpreted as a normal log tailoring line. +Valid ISODE logging levels are: +\begin{describe} +\item[\verb+x25level+:] X.25 level (if used). +\item[\verb+compatlevel+:] Compatibility level. +\item[\verb+addrlevel+:] Addressing level. +\item[\verb+tsaplevel+:] Transport level. +\item[\verb+ssaplevel+:] Session level. +\item[\verb+psaplevel+:] Presentation structures. +\item[\verb+psap2level+:] Presentation level. +\item[\verb+acsaplevel+:] Association level. +\item[\verb+rtsaplevel+:] Reliable transfer level. +\item[\verb+rosaplevel+:] Remote operations level. +\end{describe} + +\end{describe} + +An example of logging tailoring is shown in Figure~\ref{example:log}. + +\tagrind[hbtp]{log-examp}{Example of Log Tailoring}{example:log} + +\subsection{Diverting Logging Streams}\label{sect:divlog} +By default, all the ISODE logging is directed at the normal log. + +Notice that for a given program or channel, the logging information +can be diverted. If a logging entry starts with the name of the +program (e.g., \verb|argv[0]| normally) then that line is specific to +that program; e.g.: +\begin{quote}\small\begin{verbatim} +submit normlog file=submit +\end{verbatim}\end{quote} +makes a \pgm{submit}-specific \verb+normlog+ tailoring entry. +Hence all logging from \pgm{submit} directed at the \verb+normlog+ will go +to the file \file{submit} instead of the file associated with +\verb+normlog+. The net result is that all the normal logging messages +from \pgm{submit} end up in the file \file{submit} in the log directory. + + +\section{Table Tailor File Entries}\index{tailoring, tables} + +This section describes how the tables of aliasing and addressing +information, referenced by \pgm{submit} and the channel programs, are +defined in the \file{tailor} file. + +Generally each table's entry is comprised of a line with several +key/value pairs. The line starts with the keyword \verb+tbl+ which is +followed by a string setting the default name for the table and the +plain text file in \file{tbldir}. Then come the key/value pairs, +described below. +\begin{describe} +\item[\verb+name=value+:]\index{table, name} +Name this table with the given value (to override the default -- see +above). This is included only for completeness as it is set by first +argument; it is not normally used. The name is used in all references +to the table. + +\item[\verb+file=value+:]\index{table, file} +The tables contents are found in the given file (to override the default). + +\item[\verb+show="value"+:]\index{table, show} +A descriptive string used when printing +messages about this table, mainly for logging purposes. It defaults +to the same as the table name. + +\item[\verb+flags=value+:]\index{table, flags} +A set of flags that specifies how this table +operates. It should be one of the following: + +\begin{describe} +\item[\verb+dbm+:]\index{table, dbm} +This table is stored in the database for fast +access (the default). + +\item[\verb+linear+:]\index{table, linear} +This table is searched with a linear pass through the file in +\file{tbldir} (this is slow, but does not require rebuilding the +database, and changes take immediate effect). Linearly searched files +are still built into the database. + +\end{describe} + +\item[\verb|override|:]\index{table, override} +This allows values in the table to be overriden, or indeed if the +table is small the whole table to be specified in the tailor file. +Each occurance of this keyword adds a new key/value pair to a list. +The format should be exactly the same as in a file with a key, a colon +character (\verb|:|) and a value. +\end{describe} + +An example of table tailoring is shown in Figure~\ref{example:table}. + +\tagrind[hbtp]{table-examp}{Example of Table Tailoring}{example:table} + +\section{Channel Tailor File Entries}\index{tailoring, channels} + +Channels are perhaps the most complex aspect of tailoring. There are +several types of channels. Input channels carry messages into the +system. Output channels carry messages out of the system. Reformatting +channels change the message structure in the queue. Finally there are +a few miscellaneous channels that do other jobs such as message deletion. + +The \file{channel tailor} file entries each consist of the keyword +\verb+chan+ followed by a value which, by default, names the channel +and the program associated with it; then comes a list of key/value +pairs which provides more information on the channel. + +A number of the values can be applied to a pair of channels +differently depending on whether the channel is being used in outbound +or inbound mode. Where the distinction is significant, there are +separate tailor variables prefixed by \verb|in| and \verb|out|. + +The key/value pairs consist of the following: +\begin{describe} +\item[\verb+name=value+:]\index{channel, name} +The name of the channel (overrides the default). +\item[\verb+prog=value+:]\index{channel, prog} +The program associated with this channel, i.e., the actual binary to +run (overrides the default). + +\item[\verb|key=values|:]\index{channel, key} +A list of keys (comma separated) by which this channel is known. This +can be used to map several logical channels onto one. See +Section~\ref{channel:pair} on channel pairing on +page~\pageref{channel:pair}. Note that a \verb|key| is an equally +valid way to refer to a channel. When referencing a channel, the first +match on \verb|key| or \verb|name| is taken. If specifying several +keys, the entier value should enclosed in quotes. + +\item[\verb+show="value"+:]\index{channel, show} +A descriptive string used in pretty printing. If this string starts +with the keywords \verb|with| or \verb|via| then this value is +included in \verb|Received| lines generated for RFC~822 messages. + +\item[\verb+type=value+:]\index{channel, type} +This parameter is {\em mandatory} and indicates the type of channel +this is. This {\em must} be set to one of the values shown below: + +\[\begin{tabular}{|l|p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Type of Channel}\\ +\hline + \tt in& An incoming channel.\\ + \tt out& An outgoing channel.\\ + \tt both& Both incoming and outgoing.\\ + \tt shaper& A reformatter that changes the shape of the message.\\ + \tt warn& A warning channel.\\ + \tt delete& A message deletion channel.\\ + \tt qmgrload& A queue manager loading channel.\\ + \tt debris& A debris collection channel.\\ + \tt timeout& A timeout channel.\\ + \tt split& A splitter channel.\\ +\hline +\end{tabular}\] + +\item[\verb+drchan=value+:]\index{channel, drchan} +This value must be set for outbound channels that cannot handle real +delivery reports - that is channels of type \verb|out| or type +\verb|both|.. At present, it is only the X.400 channels and the +X.400-based delivery channels that can handle delivery reports. Other +channels should set this to a suitable channel that can transform DRs +into suitable messages. Currently this should always +\pgm{dr2rfc}. + + +\item[\verb+content-in=value+:]\index{channel, content-in} +The content of this channel if it allows incoming messages. It is +normally either \verb+p2+, \verb+p22+ or \verb+822+. It should be +empty if the message is submitted in structured form (i.e. more than +one file) + +\item[\verb+content-out=value+:]\index{channel, content-out} +The content of this channel if it allows outgoing messages. Values are +as for \verb|content-in|. + +\item[\verb+cost=value+:]\index{channel, cost} +The cost of running this channel represented as a non-negative +integer. This is used in the reformatting calculations to decide the +best conversion path. The lowest cost route will be chosen, all other +things being equal. Costs are relative; a cost of 0, the default, +means that this channel essentially makes no changes to the message. +Higher costs make the channel less favourable. + +As a rule of thumb, any channel that makes a real change to a message +should have a positive cost. Thus \pgm{rfc822norm} channels should +have a small cost (e.g., 1) as they make small changes to the message. +A channel such as \pgm{P2toRFC} should have a larger cost (e.g., 10) +as this conversion should not be done unless needed. A channel that +removes a content type by \pgm{removebp} should be given a large cost +(e.g., 100) as this should only be run if there is no alternative. +However, a channel such as \pgm{p2flatten} should have a zero cost as +it makes no change to the message content, just combining it into one +file. + +\item[\verb+sort=value+:]\index{channel, sort} +This value is a series of keys that are used for sorting purposes by +the queue manager. The first key is the primary sort key and must be +either \verb+mta+, \verb+user+ or \verb|none|. The value \verb|none| +should only be used as a primary sort key for delivery channels. The +remaining keys are secondary sort keys and are taken in order. The +values for this field are any of those shown below: +\[\begin{tabular}{|l|p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt mta& Sort by destination MTA. This is the most common +primary sort key.\\ + \tt user& Sort by username. This is useful for local +deliveries. \\ + \tt priority& Sort by the priority of the message.\\ + \tt time& Sort by queued time.\\ + \tt size& Sort by the size of the message.\\ + \tt none& Don't attempt to sort\\ +\hline +\end{tabular}\] +By default, all outbound channels are sorted by \verb|mta| only. Local +channels should be sorted by \verb|user|. Reformatters and other +channels are normally sorted by \verb|none|. However, setting a +reformatter to \verb|mta| or \verb|user| allows multiple instances of +the same channel to run concurrently. + +\item[\verb+outinfo=value+/\verb+ininfo=value+:] +\index{channel, outinfo}\index{channel, ininfo} +This contains channel-specific information that can be used for a +variety of purposes. +For example, the \verb+outinfo+ field is used by the simple formatters +to give the real program to run. Typically a simple formatter is a +shell script or similar, with \pgm{fcontrol} indicated as the program. +In such cases the \pgm{fcontrol} program is then responsible for queue +manager interaction and it runs the program in the \verb|outinfo| field as a +subprocess. + +\item[\verb+inadr=value+/\verb+outadr=value+:]\index{channel, inadr} +\index{channel, outadr} +The type of addressing that is used by this channel. The value is +one of those below: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt x400& X.400 addressing\\ + \tt 822& rfc822 addressing\\ +%%% \tt any& any of the above two types\\ +\hline +\end{tabular}\] + +\item[\verb+adr=type+:]\index{channel, addr} +This assigns the given address format to both the \verb|inadr| and +\verb|outadr|. It is used for backwards compatability and as a short cut. + + +\item[\verb+insubadr=value+/\verb+outsubadr=value+:] +\index{channel, insubadr}\index{channel, outsubadr} +The type of subaddressing used by a channel, if appropriate. +Currently this is only relevant in conjunction with a definition of +\verb+inadr=822+ or \verb|outadr=822|. The value is one of those below: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt real.rfc822& normal rfc822 style addressing \\ + \tt real.rfc733& rfc733 style addressing \\ + \tt jnt& JNT style addressing \\ +\hline +\end{tabular}\] + +For inbound RFC~822 based channels, if \verb+insubadr+ is set to either +\verb+real.rfc733+ or \verb+jnt+ then \pgm{submit} will recognise +percentages as characters with routing properties. +If \verb+insubadr+ is not set to either of these, \pgm{submit} views +percentages as characters with no special properties. + +\item[\verb+subadr=type+:] \index{channel, subadr} +This variable sets both the \verb|insubadr| and \verb|outsubadr| +variables for a channel. + +\item[\verb+adr-order=value+:]\index{channel, adr-order} +The ordering of addresses on this +inbound channel. This is one of the following: +\[\begin{tabular}{|l|p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt usa& Internet style addressing is insisted upon.\\ + \tt uk& JNT style addressing is insisted upon.\\ + \tt usapref& Internet style addressing is preferred but both +types will be tried.\\ + \tt ukpref& JNT style is preferred but both types will be +tried. \\ +\hline +\end{tabular}\] +The default value is \verb|usa|. Normally only UK sites will need to +modify this variable. Note that this flag only affects the behaviour +of \pgm{submit}. + +\item[\verb+bptin=value+:]\index{channel, bptin} +A list of body parts that the channel accepts as input. +This must be one of the +types defined in the \verb|bodypart| tailoring item defined in +Section~\ref{tai:bodypart} on page~\pageref{tai:bodypart}. + +\item[\verb+bptout=value+:]\index{channel, bpout} +A list of body parts that the channel will output. The possible +values are the same as for those for bptin. + +\item[\verb|hdrin=value|/\verb|hdrout=value|:] +These variables are much the same as the \verb|bptin|/\verb|bpout| +variables but apply to the headers instead. + +\item[\verb+outtable=value+:]\index{channel, outtable}\index{channel, table} +A table associated with the outbound part of this channel. This is +used by the channel program, in a channel specific way. Not all +channels require this. + +\item[\verb|intable=value|:]\index{channel, intable} +A table associated with the inbound part of this channel. + +\item[\verb+mtatable=value+:]\index{channel, mtatable} +This is a table that is used in binding to the appropriate channel. See +Section~\ref{channel:pair} on page~\pageref{channel:pair} +on channel pairing for use of this feature. + +\item[\verb+mta=value+:]\index{channel, mta} +A destination MTA for this channel. If this is set, all messages will +be delivered to this MTA regardless of the destination MTA given in +the message. This is useful for relaying all messages for a given +channel via another MTA. + +\item[\verb+access=value+:]\index{channel, access} +The type of access this channel requires; only applicable to channels +of type \verb|in| and \verb|both|. The value is either \verb+mta+, in +which case the channel must be run by a trusted user-id, or else +\verb+mts+ in which case authentication of messages is enabled. The +default is \verb|mta|. + +\item[\verb+domain-norm=value+:]\index{channel, domain-norm} +The amount of domain normalisation of MTS addresses on inbound +channels. The value is one of those below (the default is +\verb+partial+): +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt full& all domains in an MTS address are normalised\\ + \tt partial& only the next hop of an MTS address is normalised\\ +\hline +\end{tabular}\] +With \verb|partial| local domains are recognised and skipped, so the +first non-local domain will be normalised. + +\item[\verb+maxproc=value+:]\index{channel, maxproc} +This is the maximum number of instances of the channel the QMGR is +allowed to run at any time. A value of \verb+0+ indicates that there +is no maximum to the number of instances the QMGR can run. The +default is \verb+0+. See Section~\ref{sect:qmgrmgr} for some discussion +on limiting channels in this way. + +\item[\verb+auth-table=value+:]\index{channel, auth-table} +This is a table which contains the authentication data for the channel +if it is an \verb+mts+ submission channel. The format is described in +Section~\ref{sect:authen} on page~\pageref{sect:authen}. + +\item[\verb|conv=value|:]\index{channel, conv} +This variable specifies what effect the channel has on a message. This +is used to check on conversion restrictions; in particular the X.400 +and RFC~1148 conversion semantics. It may take one of the following +values: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt none& channel does no conversion\\ + \tt 1148& channel does RFC 1148/987 header mappings\\ + \tt conv& channel does conversion without loss\\ + \tt loss& channel does conversion with loss\\ +\hline +\end{tabular}\] +The default value is \verb|none|. Channels that do mapping of P2 to +RFC~822 {\em headers} and the reverse should use the value \verb|1148| +to indicate that conversion can be carried out even in the presence of +the conversion-prohibited flag of X.400. This will allow messages with +header mappings and no body part conversions to go through an +RFC~1148/987 gateway. Channels that change formats without losing +information (except RFC~1148/RFC~987 channels) should be marked as +\verb|conv|. Channels which lose data (such as, say, G3Fax to Ia5) +should be marked as loss (they should also be given a high cost). + + +\item[\verb|probe=value|:]\index{channel, probe} +This variable states whether this channel can support X.400 style +probe messages. It has values \verb|y| and \verb|n|. The default is +\verb|n|. This should be set for X.400 channels. If submit determines +the channel cannot support probes it will return a delivery report. + +\item[\verb|trace=value|:]\index{channel, trace} +This variable tells \pgm{submit} what sort of trace element to +generate. This is only applicable to RFC~822-based protocols, and can +be set to either \verb|received| to generate Received lines or +\verb|via| for Via lines. The default is \verb|received|. + +\item[\verb|solo-proc=value|:]\index{channel, solo-proc} +If this variable is set to \verb|yes|, +\pgm{submit} ensures that messages processed +through this channel only have one recipient. +This may result in a message with multiple recipients being +resubmitted several times with one recipient each time. +This feature is useful for when the processing must be specific to one +recipient i.e. the \pgm{hdr2fax} filter (see +Section~\ref{sect:faxconv}). +By default, \verb+solo-proc+ is set to \verb|no|. + +Note this feature uses the \verb+splitter+ channel. +So such a channel must also be tailored. + +\item[\verb|bad-sender-policy=value|:] \index{channel, bad-sender-policy} +This can be set to one of the following keys to control the policy for +unroutable or unreplyable sender addresses. +\[\begin{tabular}{| l | l |} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline\hline + \tt strict& Generate delivery report (default).\\ + \tt sloppy& Artificially route on failure. \\ +\hline +\end{tabular}\] +It is STRONGLY recommended that the default policy is used. This will +fail messages that arrive with an unroutable or unreplyable sender +specification. If this is overridden, messages can easily be lost if +any failure occurs. + +If the \verb+sloppy+ mode is in effect, PP will attempt to route +failure messages for unroutable senders either via the inbound MTA or +if that fails to \verb+postmaster+. + +\item[\verb|check=value|:]\index{channel, check} +This variable sets the checking mode of the channel. Normally this +should be left as the default, which is strict checking. However, for +unusual cases it may be required to relax some of the constraints +normally imposed. Setting \verb|check| to \verb|sloppy| will reduce +the strictness of the checking to some extent. In particular it will +allow RFC~822 messages with no, or multiple \verb|Date| fields to be +accepted. + +\end{describe} + +An example of a channel tailoring is shown in +Figure~\ref{example:chan} and will help to make things a little clearer. +The descriptions above can be used to determine exactly what each +channel does. + +\tagrind[hbtp]{chan-examp}{Example of Channel Tailor Entry}{example:chan} +\clearpage + +\section {ISODE Runtime Tailoring} + +\subsection{Queue Manager Tailoring} +Information relating to the MTA, its QMGR, and their +addresses are normally obtained from the file +\file{isoentities} and take the general form: +\begin{quote}\small\begin{verbatim} +vs2 "pp qmgr" 1.17.6.2.1 #1001/Internet=vs2+18000 +\end{verbatim}\end{quote} + +The first field is the designator of the machine that the QMGR +is running on. It is usually the name of the machine. The second is +the QMGR service; this should not be changed. The same goes for the +other third field. The last field specifies the transport +selector that the QMGR listens on (1001 in this case) and the NSAP +address. In this case it is in internet form, with hostname \verb|vs2| +and TCP port number \verb|18000|. The QMGR uses this address to listen +on, \pgm{submit} uses the address to contact the QMGR as do mta +console programs such as \pgm{MTAconsole}. + +This information may also be obtained from the directory if the +directory nameserver is being used. A suitable +entry for addition to quipu might be: +\begin{quote}\begin{verbatim} +objectClass= top & applicationEntity & quipuObject +cn= pp qmgr +description= Submit to Qmgr +presentationAddress= \ + '1001'H/LOCAL-ETHER=lancaster.xtel.co.uk+18000 +supportedApplicationContext= 0.9.2342.60200172.201.1 +acl= +\end{verbatim}\end{quote} +The presentation address should be ammended to be correct for your +site, the {\verb|supportedApplicationContext|} +must not be altered however. + +\subsection{X.400 Tailoring} +If the X.400 is going to be used, then a definition of this must be +placed in the file \file{/etc/isoservices}. A suitable definition +might look like this: +\begin{quote}\small\begin{verbatim} +"tsap/p1" "591" /usr/lib/pp/chans/x400in84 +\end{verbatim}\end{quote} + +This shows the service name \verb|tsap/p1|, the transport selector +\verb+"591"+ and indicates the location of the program. You should use +a numeric IA5 form of TSEL for X.400(84) compliance. + +Alternatively, an entry can be added to the directory if the +\man iaed(8) is being used. Such an entry might look like the +following: +\begin{quote}\small\begin{verbatim} +objectClass= top & applicationEntity &\ + quipuObject & iSODEApplicationEntity +cn= x40084 +description= X.400 service (1984) +presentationAddress= "591"/LOCAL-ETHER=128.243.9.1|\ + Janet=00002100102999|\ + IXI=20433450210399 +supportedApplicationContext= 2.6.0.1.6 +execVector= /usr/lib//pp/cmds/chans/x400in84 +\end{verbatim}\end{quote} + +For more details of the formats of these files, see {\em The ISO +Development Environment: Users Manual}. + +\section{Channel Pairing}\label{channel:pair} + +Many of the channels within PP naturally fall into pairs. For +instance, it is usual to have an inbound X.400 channel and a +corresponding outbound X.400 channel. + +As this is a common occurence, one channel definition in the \file{tailor} +file can be used to define both channels. Such a channel should be +marked as type \verb|both|. Where both sides of the channel require a +parameter, such as a table, there is an explicit in and out value. + +Channel pairing can bring several benefits. If the QMGR knows about +paired channels, it can make some optimisations. When a message is +received for an MTA on the inbound side of a paired channel, it can, +if there are messages waiting to go out on that channel, assume that this +MTA has just come up and schedule a retry immediately (this feature is +planned for PP but not implemented in 6.0). + +A side effect of channel pairing can help with authorisation. An +incoming channel usually has a fixed name. However, if a number of +channels are defined in the tailor file with a \verb|key| of that +value, then all of these channels are potentially usable. In this +case, the MTA that the message was received in is looked up in each of +the associated \verb|mtatable| table. The first channel to match on +both key and the contents of the mtatable is chosen. Authorisation is +then done on this basis. One of the channels may not have an +\verb|mtatable| associated with it, in which case this is the default +channel to use. Note that this gives the first match, rather than the +best possible match of tables. + +The format of the \file{mtatable} is identical to the \file{domain} +table. However, the value on the RHS is only used in determining +matches. It must however be a legal value. + +As an example, consider a host on the internet which wishes to +authorise usage on the basis of whether the user is ``local'' or +``remote''. This might be achieved by the following: +\begin{quote}\small\begin{verbatim} +chan smtp-local key="smtp",mtatable=localhosts,... +chan smtp-internet key="smtp" +\end{verbatim}\end{quote} + +The incoming channel then claims to be ``smtp''. If the MTA the +message is received from is present in the localhosts table, then +\verb|smtp-local| is used as the channel, and authorisation done on +that basis. Otherwise it is assumed to be \verb|smtp-internet| and +potentially different authorisation is applied. + +On a smaller site, this same feature can be used to map many channels +onto one. For instance, the \pgm{greyin} channel selects one of +\verb|gb-janet| \verb|gb-pss| or \verb|ipss| depending on which +network the call originated. If this distinction is not important, all +three can be mapped to one channel by tailoring: +\begin{quote}\small\begin{verbatim} +chan gb-janet key="gb-pss,ipss",... +\end{verbatim}\end{quote} + +\section {Tailoring of Common Channels}\index{channel} + +Channels perform operations on messages. Intermediate channels for +reformatting and other manipulation are considered later. The +following terms apply to endpoint channels: + +\begin {description} +\item[outbound:] A channel which delivers messages out of PP. + +\item[inbound:] A channel which passes messages into PP +(through \pgm{submit}). + +\item[active:] A channel which is initiated by the QMGR. + +\item[passive:] A channel which is not initiated by the QMGR (typically by a +user or server). + +\end {description} + +The most common types of channel are passive inbound and active outbound. + +\subsection {Submit}\label{sect:submit} + +The \pgm{submit} program can run in a variety of modes. The original +and default mode is for incoming channels and user agents to directly +execute submit and communicate using \man pipe(2) interprocess +communication. + +As an alternative, if the \verb|submit_addr| variable is used, submit +can be run either from \pgm{inetd} or as a standalone daemon. +For example the +following \file{tailor} file entry +\begin{quote}\begin{verbatim} +submit_addr lancaster.xtel.co.uk:pp-submit +\end{verbatim}\end{quote} +might be combined with the following \file{inetd.conf} entry +\begin{quote}\begin{verbatim} +pp-submit stream tcp nowait pp + /usr/lib/pp/cmds/submit submit +\end{verbatim}\end{quote} + +Alternatively, submit with the \verb|-s| switch will run in standalone +server mode. A similar tailor line to above is required. In this mode, +submit will read the tailor file and contact the \pgm{qmgr} before +answering connections, thus being more efficient in some cases. + +\subsection {Protocol Channels} + +Protocol channels are channels that talk to the outside world. There +are a number of these supplied with PP. Those that have special +requirements or are optional are described here. + +\subsubsection {SMTP channel}\label{sect:smtp} +The \pgm{smtp} channel comes in two parts, the outbound channel and the +inbound daemon. The inbound daemon can have a number of arguments to +it, and can be run either under the control of \man inetd (8) or under +the standalone server \pgm{smtpd}. To configure it to run under +\pgm{inetd} the following entry in the file \file{/etc/inetd.conf} +might be appropriate (but see \man inetd.conf (5) for more details). + +\begin{quote}\small\begin{verbatim} +smtp stream tcp nowait pp \ + /usr/lib/pp/cmds/chans/smtpsrvr smtpsrvr smtp +\end{verbatim}\end{quote} + +If, however, you prefer to run a standalone smtp server, the command is +something like this (usually included in \file{pp.start}): + +\begin{quote}\small\begin{verbatim} +/usr/lib/pp/cmds/smtpd /usr/lib/pp/cmds/smtpsrvr smtp +\end{verbatim}\end{quote} + +The following arguments are supported by the \pgm{smtpd} program. +\begin{describe} + +\item[\verb|-p port|:] Specify a different TCP port to listen on when +running standalone. + +\item[\verb|-i maxcon|:] Set the maximum number of simultaneous smtp +connections that are supported. Only obeyed when running standalone. + +\item[\verb|-t timeout|:] Set a default timeout for use with the +nameserver. This is only used if the server is compiled with nameserver +support included. + +\end{describe} +The two mandatory arguments for \pgm{smtpd} are the name of a server +program to interpret the smtp protocol, and the name of a channel that +incoming messages will arrive on. + +Finally, the smtp server makes use of one additional tailoring +variable in the channel specification. If the \verb|ininfo| element +of the channel tailoring entry contains the string +{\verb|sloppy|\index{sloppy}} then any connection will be allowed. If +this is not the case, connections are only supported from hosts that +can be reversed translated (e.g., the IP number can be converted back +to a host name). + +The smtp outbound channel has only one special option. It can be +given a flag \verb|-p port| to tell it to connect to a different tcp +port other than the default. This can be set up by setting the tailor +entry to something like the following: + +\begin{quote}\small\begin{verbatim} +chan smtp-odd pgm="smtp -p 2001",show="Odd smtp"... +\end{verbatim}\end{quote} + + +\subsubsection {X.400 inbound channel} + +The X.400(84) inbound channel (\pgm{x400in84}) takes note of the +\verb|ininfo| part of the tailoring information. If this is set to the +string \verb|sloppy| then no checking of MTA name and password is done +for any connection incoming on that channel. Also, if the NSAP cannot +be found in the inbound table for this channel, the connection is +still allowed. + +X.400 inbound also has an optional flag; this is as follows: +\begin{describe} +\item[\verb|-c channelname|:] Claim to be the given channel name on +input. You may have a number of X.400 inbound channels, selected +initially by T-Selector or network address. If you wish to split up +traffic in this way, possibly for authorisation reasons, you should +set the channel name in this way in the \pgm{isoservices} file. By default +the channel is assumed to be the name of the program itself. However, +a better way to do this is through the channel pairing system. +\end{describe} + +\subsubsection {UUCP Channel}\index{channel, uucp} + +The uucp channel interfaces to the UUCP system. It uses the \verb|outinfo| +string of the channel to tailor the interface. This string is a key +value pair that can set various parameters. The key/value pairs are +separated by a comma. The possible keys are: +\begin{describe} +\item[\verb|uux|:] Set the \verb|uux| pathname and arguments. +This parameter must be present. + +\item[\verb|host|:] When constructing the uucp from line, use this +value as the host name. +\end{describe} +An example configuration might be: +\begin{quote}\small\begin{verbatim} +chan uucp-out prog=uucp-out,show="UUCP outbound channel", + type=out, adr=822,adr-order=ukpref,outtable=uucp + outinfo="uux=/usr/bin/uux - -r,host=nott-cs" +\end{verbatim}\end{quote} + +\subsubsection {\decnet/ MAIL11 channel}\index{channel, decnet} +The \pgm{decnet} channel implements the DECnet mail protocol. It is +currently only available for the Sun implementation of DECnet (Sunlink +DNI, V7.0 onward). The channel comes in two parts, the outbound channel +and the inbound server. The inbound server is run under the control of +the DECnet spawner (the DECnet equivalent of \pgm{inetd}) and will +require an entry of the form + +\begin{quote}\begin{verbatim} +27 MAIL /usr/lib/pp/cmds/chans/decnetsrvr +\end{verbatim}\end{quote} + +in the \file{dniserver.reg} configuration file. It is not possible to +pass any arguments into the server due to limitations of the +\pgm{dniserver}, so the server takes its tailoring from a channel with +the hardwired name of \verb|decnet-in|. + +The \pgm{decnet} outbound channel makes use of a number of tailoring +options. The \verb|outinfo| element of the channel tailoring entry +may be set to any combination of the following options. If more than +one option is selected then the options are separated by commas and +the whole string must be enclosed in quotes. + +\begin{description} +\item[\verb|strip|:] If this option is selected, all headers except +for To:, From: and Subject: will be stripped off and thrown away, +otherwise they will be moved into the message body. This is for the +benefit of VMS users who tend to be panicked by what they see as UNIX +style headers. + +\item[\verb|mrgate|:] +Select this option if the MTAs contacted by this channel are running +DECs mail router software. This makes a small but significant change +to the addresses presented to such sites. + +\item[\verb|map\_space|:] +This option enables the mapping of space to underbar in the incoming +channel and vice versa in the outgoing channel. This caters for sites +running All-in-One and/or mail router which have chosen to have mail +addresses with spaces in them. This can be specified in the +\verb|ininfo| and \verb|outinfo| variable. +\end{description} + +Note that incoming connections are only allowed from hosts for which a +reverse mapping exists in the DECnet database. There is no equivalent +of the \pgm{smtp} \verb|sloppy| option. + +\subsection {Filter Control and Common Filters} \index{filter control} + +Filters can be called via a special channel called \pgm{fcontrol}. +This channel can be used in a variety of guises to run various filters +on messages and, in particular, on the body parts within the messages. +It should only be used for filters where there is a one-to-one mapping +between incoming body parts and outgoing body parts; i.e., the contents +of the body parts, and possibly their names, may be altered by a +filter, but the structure of the message will remain the same. + +A filter reads an incoming body part from the standard input, does the +required filtering, and writes the outgoing body part to the standard +output. Any error or logging messages produced by the filter should +be written onto the standard error. \pgm{fcontrol} logs these messages +at the \verb+LLOG_NOTICE+ level. The filter should exit with a value +of \verb|0| to indicate success. Any other exit value is taken as +a temporary failure. + +To create a channel which runs a given filter, an entry has to be made +in the \file{tailor} file. The entry should be constructed in the normal way +with the following provisos: + +\begin{describe} + +\item[\verb+prog+:] This should contain the filename of the +filter controller, \pgm{fcontrol}. + +\item[\verb+outinfo+:] +The pathname of the filter's executable program should be placed in +the \verb+outinfo+ field, followed by any arguments that are to be passed +to the filter. If the given name is not a fully qualified pathname, +the filter controller assumes the executable to be under the +\file{formdir} directory. Arguments of the form \verb+$(key)+ will be +expanded to the entities described in Table~\ref{tab:expansions}. The +key is case independent. + +\item[\verb+bptin+/\verb+bptout+] +Filters should not change the structure of the message. \verb+bptin+ +should only contain one type of bodypart. This type is the bodypart +type that the filter converts. \verb+bptout+ should also only contain +one type of bodypart. This bodypart type is the result of the +filter's conversion. i.e., the filter converts bodypart \verb+bptin+ +into bodypart +\verb+bptout+. + +\item[\verb+hdrin+/\verb+hdrout+] +This fulfills the same type of function as \verb+bptin+/\verb+bptout+ +but for the headers of the messages. The header must be one of those +defined in \verb+headertype+. + +\item[\verb+type+] The type should be set to \verb|shaper|. + +\end{describe} + +\tagtable{info_expan}{Filter Control Expansion Macros}{tab:expansions} + +Example \file{tailor} file entries of filters running in conjunction with +\pgm{fcontrol} are shown in Figure~\ref{example:fcontrol}. + +\tagrind[hbtp]{filt-examp}{Example of Filter Control Tailoring}{example:fcontrol} + +Trivial filters such as voice to ia5 mappings can be done by a simple +shell script of the type shown in Figure~\ref{example:shellfilt}. + +\tagrind[hbtp]{shelfilt}{Simple Shell Script Filter}{example:shellfilt} + +Here are descriptions of some common filters run in conjunction with +\pgm{fcontrol}: + +\subsubsection {RFC~822 Filter}\index{rfc822norm} + +The filter \pgm{rfc822norm} is used in conjunction with the +general filter controller \pgm{fcontrol}, for dealing with RFC~822 and +related headers. It takes a generic RFC~822 header as input, and +outputs a ``normalised'' form. A normalised header is one in which +all addresses are fully qualified and are in the correct order. For +this reason, the \verb+hdrin+ and {\verb+hdrout+} fields in any +associated \file{tailor} file entry should be some extended version of +{\verb+822+}, e.g \verb+822-us+, {\verb+822-uk+}, etc. + +The filter affects the following fields of the RFC~822 header: + +\begin{itemize} +\item All of the addressing fields in RFC~822. +\item The Acknowledge-To field (JNT Mail). +\item Any invalid trace fields are replaced. +\end{itemize} + +The filter's behaviour may be altered by specifying various options. +These options are passed through \pgm{fcontrol} to the filter +by use of the \verb|outinfo| element of the channel structure. +One possible \verb|outinfo| string is as follows: +\begin{quote}\small\begin{verbatim} +rfc822norm -822 -striptrace -jntsender $(822sender) +\end{verbatim}\end{quote} + +The \pgm{rfc822norm} filter can be used in a variety of guises. +For example, in appendix~\ref{app:tailor} the combination of +\pgm{fcontrol} and \pgm{rfc822norm} appears twice, so +providing two different channels, \pgm{822touk} and \pgm{822tous}. + +The filter takes the following options: + +\begin{describe} + +\item[\verb+-822+:] Format source routes according to RFC~822. + +\item[\verb+-733+:] Format source routes with a ``\%'' notation (default). + +\item[\verb+-bigend+:] Format domains big--endian. + +\item[\verb+-littleend+:] Format domains little--endian (default). + +\item[\verb+-jnt+:] A combination of the \verb+-bigend+ option and the +\verb+-733+ option. + +\item[\verb+-striproutes+:] Removes any source routes (733 or 822) +from the \\ +header. This removal starts after the first valid domain in each address. + +\item[\verb+-stripdomain +:] Like -striproutes, except that only the +specified domain is stripped. + +\item[\verb+-striptrace+:] Remove all trace fields from the header. + +\item[\verb+-jntsender +:] This applies the rules of mailgroup note 15, +to ensure that the JNT Mail return path correctly identifies the P1 originator. +Typically, this will involve adding a Sender Field to the message, and +possibly modifying existing trace fields. + +\item[\verb+-msgid+:] This flag ensures the presence of a message id in +the message. +If there is no message id, the RFC~822 filter will create one and +append it to the header. + +\item[\verb+-full+:] This flag indicates that all domains in addresses +should be normalised. By default, only the next hop of an address is +normalised. + +\item[\verb+-percent+:] This flag indicates that the \verb+%+ +character should be treated as a routing character when parsing +addresses. If this witch is not in force, \verb|%| will be treated as +any other character. + +\item[\verb+-hidelocal +:] Apply a host-hiding heuristic to +``clean-up'' mail sent from other hosts on site which is going off site. +Pattern can be a simple domain or a domain with wildcard subdomains, +for example: +\begin{quote}\small\begin{verbatim} + *.icl.stc.co.uk +and + stl.stc.co.uk +\end{verbatim}\end{quote} +but not domains of the form +\begin{quote}\begin{verbatim} +frodo.*.co.uk +\end{verbatim}\end{quote} + +{\em Warning}: this flag should be used with care and should not normally be +required. + +\item[\verb+-changedomain +:] Change occurances of domain +\verb+from+ to domain \verb+to+. This flag is useful when running PP +as a gateway between two or more networks and a specific domain is +known by different names on different networks. +Note that this replacement may only work on normalised domains. +So to normalise all domains and guarantee the replacement, the +\verb+-percent+ should also be used. + +\item[\verb+-fold +:] This indicates the length for displaying +RFC~822 header fields. +The default value is 79; alternately with a value of -1 there will be +no folding. Whatever the value, folding will only occur at higher level +breaks, and not within an address. + +\item[\verb|-stripack|:] Strip \verb|Acknowledge-To| lines from the header. + +\item[\verb|-acks|:] If no \verb|Acknowledge-To| lines are present, generates +Acknowledge-To the the sender. + +\item[\verb|-exorcise|:] Changes domains not found in the table +specified by \verb|-valid_domains| to be routed via the domain +specified by \verb|-exorcise_domain| (defaulting as appropriate). + +\item[\verb|-exorcise\_domain domain|:] The domain to be added. This defaults +to \verb|loc_dom_site|. This also enables the \verb|-exorcise| switch. + +\item[\verb|-valid\_domains table|:] This is a table containing a list +of known domain references. It defaults to the \file{domain} table. +This also enables the \verb|-exorcise| switch. + +\item[\verb|-external|:] When normalising a local address, follow +\file{alias} table entries marked with +the qualifier \verb|external| (the default). + +\item[\verb|-internal|:] Don't follow \file{alias} table entires +marked with \verb|external| when normalising local addresses. + +\end{describe} + +\subsubsection {P2norm Filter}\index{p2norm} + +The filter \pgm{p2norm} can be used to +\begin{itemize} +\item normalise O/R addresses in X.400 P2 headers +\item and/or downgrade X.400 (88) P2 headers to X.400 (84) P2 +headers. +\end{itemize} + +The normalisation of O/R addresses consists of the replacing of +synonyms in the \file{or} table (e.g replacing +\verb+/PRMD=X-Tel Ltd/ADMD= /C=GB/+ with +\verb+/PRMD=X-Tel Services/ADMD= /C=GB/+) and the replacing of +local synonyms in the \file{aliases} table (e.g replacing +\verb+/S=pac/+ with \verb+/I=P/S=Cowen/+). + +The downgrading from X.400 (88) to X.400 (84) is done according to the +INTERNET draft ``X.400 1988 to 1984 downgrading'' written by +S.E.Hardcastle-Kille. + +The \pgm{p2norm} filter's behaviour may be altered by specifying +various command line options. +The possible options are as follows: +\begin{describe} +\item[\verb+-nonorm+:] don't normalise the O/R addresses in +P2 headers. By default, \pgm{p2norm} will normalise any addresses in +the headers. +\item[\verb+-downgrade+:] downgrade X.400 (88) headers to X.400 (84) +headers. +By default, \pgm{p2norm} will not downgrade the headers. +\item[\verb+-internal+:] don't follow \file{aliases} table entries +marked with the \verb+external+ qualifier. +\item[\verb+-external+:] follow \file{aliases} table entries marked +with the \verb+external+ qualifier. This is the default behaviour. +\end{describe} + +\subsubsection {Body Part Deleting Filters} + +In the \file{formdir} directory there is a general shell script that +can be run as a filter to remove body parts. It ignores its input and +writes out a short message indicating that the body part has been +removed. This can be used as a trivial filter in say, \verb|fax| to +\verb|ia5|, to indicate that a fax body part has been deleted. +The \verb|outinfo| string for such a channel might be: +\begin{quote}\small\begin{verbatim} +outinfo='removebp "Group 3 Fax"' +\end{verbatim}\end{quote} +An example \file{tailor} file entry for such a filter is shown in +Figure~\ref{example:fcontrol}. + +\subsubsection {ODIF filters} +There exist some filters that will convert between BBN Slate format +and ODIF. These filters are not publicly available as they were +developed under an ESPRIT PODA project. However, anyone interested in +these filters should contact Prof. Peter Kirstein +(P.Kirstein@cs.ucl.ac.uk). + +\subsection {The List Channel}\index{list} + +This channel should be tailored in a content independent fashion. +This means that the following fields should \verb+NOT+ be set: +\begin{quote}\begin{verbatim} +content-in +content-out +bptin +bptout +hdrin +hdrout +\end{verbatim}\end{quote} + +Note that it is not possible to mix different forms of addresses on +lists. This is because of the different meanings of symbols between +the different forms of addressing. For example, with an X.400 address +\verb+(a)+ is a printable string encoding of the \verb+@+ symbol but +with an RFC~822 address it is just a comment. This means that lists +with X.400 forms of addresses \verb+must+ only contain X.400 addresses +and must be expanded by a list channel that is tailored with +\verb+outadr=x400+. Similarly lists with RFC~822 forms of addresses +\verb+must+ only contain RFC~822 addresses and must be expanded by a +list channel that is tailored with \verb+outadr=822+. + +It may be necessary to set the field \verb+adr-order+ in the tailoring +for a list channel. The default for this field is \verb+usaonly+. If +you have some UK ordering of domains in your lists you should set +\verb+adr-order=ukpref+ or \verb+adr-order=usapref+. + +A valid content independent entry for the list channel is as follows: +\begin{quote}\small\begin{verbatim} +chan list prog=list,show="List channel",type=both, + table=list,drchan=dr2rfc,outadr=822 +\end{verbatim}\end{quote} + +The value of the \verb+outinfo+ field can alter the behaviour of the list +channel. +The values that can be set in the \verb+outinfo+ field are: +\begin{describe} +\item[\verb+dosublists+:] This enables the expansion of sublists +contained within a list. +This will improve performance if there are a number of nested lists +{\em BUT} this behaviour may cause problems with the sender field. +If a sublist is expanded, it will be submitted with the sender +relating to the main list and not relating to the sublist. +By default, the expansion of sublists is disabled. +\item[\verb+linked+:] +\item[\verb+notlinked+:] These two values indicate the mechanism used +for resubmitting the body of a message. +If the \verb+linked+ value is set, the body of the message is +resubmitted using the UNIX link facility. +This is more efficient in terms of speed and space. +If the \verb+notlinked+ value is set, the body of the message is +resubmitted by copying. +The default behaviour is \verb+linked+. +\end{describe} + +The list channel's basic function is to expand one recipient to many +by resubmission. The one recipient is the distribution list, the many +are the members of that list. On resubmission, the list channel +changes the originator of the message from the original address to the +address of the maintainer of the list. +The address of the maintainer is constructed using the defacto +standard of \verb+listname-request+. +As such this address must be a valid address -- usually an +\verb+alias+ entry in the \file{aliases} table. +If no such address is found, \verb+postmaster+ is used as the new +originator. + +\subsection {The RFC 1148 Channels}\index{rfc1148} + +The \pgm{P2toRFC} and \pgm{RFCtoP2} channels perform RFC~1148 conversions +on the headers of messages. +The tailoring of these channels is as with other channels with the +proviso that the \verb+conv+ entry is set to \verb+1148+. +Note also that the \verb+hdrin+ field should be set to have +\verb+ipn+ as well as either \verb+p2+ or \verb+p22+. +This enables the \pgm{P2toRFC} channel to recognise and map IPNs. + +Note that \pgm{P2toRFC} needs to compare OIDs and for this needs +QUIPU's OID tables to be present and correct. + +The output of the 1148 channels maybe be altered by use of the +\verb+outinfo+ tailor entry. + +With the \pgm{P2toRFC}, if the \verb+outinfo+ entry contains the string +\verb+uk+, all rfc822 addresses in the produced header will be output +in the uk order of domains. + +With the \pgm{RFCtoP2}, if the \verb+outinfo+ entry contains the string +\verb+rfc987+, the conversion from rfc822 to P2 will adhere to the +RFC~987 mapping rather than the RFC~1148. +Note that these mappings are very similar anyway. + +\subsection {Shaping Channels} + +Shaping channels alter the structure of the message. +This section describes tailoring requirements of the common shaping +channels. + +\subsubsection {RFC 934 Channel}\index{rfc934} + +The \pgm{rfc934} channel flattens an RFC~822 style message as +specified by RFC~934. The tailor file entry for such a channel should +be constructed with the following provisos: +\begin{describe} + +\item[\verb+type+:] This field should be set to \verb+shaper+ as the +channel alters the shape of the message. + +\item[\verb+content-out+:] This field should contain the value +\verb+822+ to indicate that it converts contents to RFC~822 format. +\end{describe} +Note that the \pgm{rfc934} channel only recognises three types of +bodyparts: RFC~822 headers, which it recognises as starting with the +string \verb+hdr.822+; text bodyparts, which it recognises as being of +the form \verb+n.ia5+ where \verb+n+ is a number; and forwarded +messages, which it recognises as being subdirectories. +If there is a bodypart in the message that it does not recognise, the +\pgm{rfc934} channel will fail. +The key strings \verb+hdr.822+ and \verb+ia5+ are hardwired into PP. +They can only be changed by editing the relevant entries in the file +\file{Lib/pp/static.c} within the source tree. + +\subsubsection {P2flatten Channel}\index{p2flatten} + +The \pgm{p2flatten} channel combines all the separate components of a +message into one file of \verb+p2+ or \verb+p22+, depending on how the +channel is tailored. The tailor file entry for such a channel should +be constructed with the following provisos: +\begin{describe} + +\item[\verb+type+:] This field should be set to \verb+shaper+, as the +channel alters the shape of the message. + +\item[\verb+content-out+:] This field should contain the content +that the channel outputs. +It should be either \verb+p2+ or \verb+p22+. +If it is set to \verb+p2+, \pgm{p2flatten} will output a file of \verb+p2+ +(i.e., a message suitable for transfer via X.400(84)). +If it is set to \verb+p22+, \pgm{p2flatten} will output a file of +\verb+p22+ (i.e., a message suitable for transfer via X.400(88)). + +\end{describe} + +\subsubsection {P2explode Channel}\index{p2explode} + +The \pgm{p2explode} channel explodes a \verb|p2| or \verb|p22| message into its +separate component bodyparts. The tailor file entry for such a +channel should be constructed with the following provisos: +\begin{describe} + +\item[\verb+type+:] This field should be set to \verb+shaper+ as the +channel alters the shape of the message. + +\item[\verb+content-in+:] This field should contain the inbound +content, either \verb+p2+ or \verb+p22+. + +\end{describe} + +\subsection {Miscellaneous Channels} + +Miscellaneous channels groups together the ``special'' channels +required by PP. This section describes tailoring requirements of +these ``special'' channels. + +\subsubsection {Qmgrload Channel}\index{qmgrload} + +The \pgm{qmgrload} channel is used to refresh the QMGR model of +the queue by reading the model stored on disc. The only proviso for +the tailor file entry of this channel is that the +\verb+type+ is set to \verb+qmgrload+. This channel takes note of the +\verb|outinfo| field in the \file{tailor} file. This, if present, should be +a number indicating how many messages to load into the QMGR at +one time. It defaults to 50 which is a sensible value for most sites. + +\subsubsection {Msg-Clean Channel}\index{msg-clean} + +The \pgm{msg-clean} channel is used by the QMGR to free the +storage associated with a message once all activity to do with that +message has finished. For the tailor file entry of this channel, +\verb+type+ is set to \verb+delete+. + +\subsubsection {Debris Channel}\index{debris} + +The \pgm{debris} channel is used by the QMGR to free any storage which +no longer is of interest to the mail system. The \file{tailor} file +entry of this channel should have \verb+type+ set to +\verb+debris+. + +The \pgm{debris} channel only removes files and directories which it +deems suitable for deletion and whose lasted modified times are +suitable ancient. The time interval after which a file is suitable +ancient may be specified in the \verb+outinfo+ field. +If not specified, the interval is set to the default value of three days. +If given, the interval must be specified as a string of the form +\verb+"4d 2h"+ which represents an interval of four days and two hours. +The time unit abbreviations recognised are: +\begin{tabular}{l l} +\tt s& seconds \\ +\tt m& minutes \\ +\tt h& hours \\ +\tt d& days \\ +\tt w& weeks \\ +\end{tabular} + +\subsubsection {Splitter Channel}\index{splitter} + +The \pgm{splitter} channel is used by \pgm{submit} to divide a multiple +recipient message into many single recipient messages. +This division is done via resubmission. A splitter channel has +a \verb|type| value of \verb|splitter|. + +\subsubsection {Timeout Channel}\index{timeout} + +The \pgm{timeout} channel is used to time messages out once they have been +around for a given time. The tailor file entry of this channel should +have \verb+type+ set to \verb+timeout+. + +\subsubsection {Warning Channel}\index{warning} + +The \pgm{warning} channel is used to send a message back to the +originator of a message, warning him or her that the message is +delayed and still awaiting delivery. +The tailor file entry for this channel should have \verb+type+ set to +\verb+warn+. +If the \verb+outinfo+ field has an entry of value +\verb+copy-to=address+ copies of any warning messages sent will also +be sent to the address specified. + +The \pgm{warning} channel sends back a message found in the +\file{warndir} directory. The file it sends back is of the either +\verb|warning.N| where \verb|N| is the number of the warning message +(usually either 1 or 2). If this file is not present it will send the +file \verb|warning| from that directory. + +The text of the file is subject to macro expansion. Strings of the +form \verb|$(key)| are expanded with value given in +Table~\ref{table:warn}. + +\tagtable{warn}{Warning expansion macros}{table:warn} + +\subsubsection {Dr2rfc Channel}\index{dr2rfc} + +The \pgm{dr2rfc} channel constructs receipt +notifications or error messages in the form of RFC~822 messages. +Once constructed these messages are then submitted to the QMGR +for return to the sender. +The channel's behaviour can be altered by various key/value pairs which +may appear in the \verb+outinfo+ entry of the channel's tailor entry. +These pairs are as follows: +\begin{describe} +\item[\verb|order=value|:] If the \verb|value| equals \verb|uk|, +\pgm{dr2rfc} produces UK-ordered domains in its output. +By default, \pgm{dr2rfc} produces US-ordered domains. + +\item[\verb|submit=value|:] This alters the method used to submit any +return of contents. +\verb+value+ can have one of two values - \verb+linked+ or +\verb+copy+. +If the value is \verb+linked+, \pgm{dr2rfc} will submit the return of +contents via the use of links wherever possible. +If the value is \verb+copy+, \pgm{dr2rfc} will copy the return of +contents on \pgm{submit}. +The default value is \verb+linked+. + +\item[\verb|admininfo=value|:] This determines whether verbose +adminstration information is included in positive delivery reports. +If the value is \verb+true+, adminstration information is included +with positive delivery reports. +By default, the adminstration information is omitted for positive +delivery reports. + +\item[\verb|return=value|:] This key/value pair tailors the amount of the +original message that will be submitted as return of contents. +If the value is \verb+all+, the whole of the original message is +returned. +By default, the return of contents is subject to the constraints +described below. +Otherwise the value must have the syntax of a number followed by a +letter (e.g., 10k or 2000l). +This provides an upperbound on certain aspects of the return of contents. +The letter must either be an \verb+l+ or a \verb+k+ indicating +which aspect is constrained. If both quantities are tailored, the +minimum value of either is taken. +\verb+l+ constrains the number of lines the return of contents can +contain. +\verb+k+ constrains the size of the return of contents (note that the +number before the letter is multiplied by 1000 to get the actual +constraint). +The default values for these constraints are 5k for the size and 10 +lines. +Note that return of contents is subject to availability and if +available the header of the original message is always returned +irrespective of any return of contents constraints. + +The \verb|return| key may have multiple occurances in the \verb|outinfo| +field, typically to constrain both the number of lines and the size of +the return of contents i.e. \verb|outinfo="return=10k return=4l"|. + +\end{describe} + +Note that \pgm{dr2rfc} uses QUIPU's OID tables to map to ``user +friendly'' representations of OIDs. + +\section{How Channels Work}\label{chan-op} + +The majority of channels work in the way described below. +This description may clarify the view one gets from examining the +logging produced by the \pgm{qmgr} and the channels. + +A channel is called by the QMGR. The QMGR first calls up the +\pgm{pptsapd} program and tells it what channel is required. The +\pgm{pptsapd} then fork's and exec's the appropriate channel passing +over the communication channel from the Qmgr. + +The QMGR then initialises the channel which informs the channel what +name it is (at this point the channel usually checks that this is +reasonable). Then the QMGR tells the channel to process a given +message and a set of recipients. All of the identified recipients +will be on the same MTA, or require the same conversion. The channel +will then attempt to do the work. After this it will update the queue +in the following way for each recipient: + +\begin {itemize} +\item If a conversion succeeded, it will increment the reformat counter. +\item If a delivery succeeded, it will set the status to DONE or DR, +dependent on whether a positive Delivery Report is needed. +\item If the operation failed permanently, it will set the status to +DR. +\item If the operation failed for some temporary reason, no change is +made to the message. +\end {itemize} + +If the status is set to DR, the DR should be generated before updating +the queue status. When the queue is updated, the QMGR should be +informed of the final status of each recipient. The returned value is +one of the following: +\begin{describe} +\item[success:] In this case the QMGR will schedule the next +designated channel to process the message. The current channel will be +given other messages to process if they are available. + +\item[messageFailure:] This is a soft failure associated with the +message. The QMGR will try the message again sometime in the future. +Other messages on this channel will be tried immediately. + +\item[mtaFailure:] This is a soft failure associated with the +destination mta. No more messages to this destination will be tried, +but messages to other destination may be tried on this channel. + +\item[messageAndMtaFailure:] This is a combination of both the above. +Other messages to this destination will not be tried, and in addition, +when they are retried this message will not be tried first (e.g., it +is suspected that this message may have caused the mta failure!) + +\item[positiveDR:] A positive delivery report was generated. The QMGR +will schedule the appropriate channels to return the report. + +\item[negativeDR:] The QMGR treats this exactly the same as above. +\end{describe} + +Once the response is received, the QMGR will give the channel +more work, or close it down. Connections to MTAs should be kept open, +the QMGR will attempt to sort the queue by MTA. + diff --git a/doc/manual/volume1/console_tai.tex b/doc/manual/volume1/console_tai.tex new file mode 100644 index 0000000..e780750 --- /dev/null +++ b/doc/manual/volume1/console_tai.tex @@ -0,0 +1,24 @@ +\small\begin{verbatim} + +#define default_mtsboth_chan \ + "mtsboth-chan:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_mta \ + "mtsboth-mta:age<2h,vol<1M,num<500,last<2h" +#define default_mtsboth_msg \ + "mtsboth-msg:age<2h,vol<1M" + +#define default_mtain_chan \ + "mtain-chan:last<2h" +#define default_mtain_mta \ + "mtain-mta:last<2h" +#define default_mtain_msg \ + "mtain-msg:last<2h" + +#define default_passive_chan \ + "passive-chan:age<20,vol<1M,num<10,last<20" +#define default_passive_mta \ + "passive-mta:age<20,vol<1M,num<10,last<20" +#define default_passive_msg \ + "passive-msg:age<20,vol<1M" + +\end{verbatim} diff --git a/doc/manual/volume1/domain.tex b/doc/manual/volume1/domain.tex new file mode 100644 index 0000000..90dbf98 --- /dev/null +++ b/doc/manual/volume1/domain.tex @@ -0,0 +1,8 @@ +\small\begin{verbatim} +*.edu:mta=nameserver +cs.nott.ac.uk:mta=cs.nott.ac.uk +computer-science.nott.ac.uk:norm+mta=cs.nott.ac.uk +*.fr:valid +*.co.uk:min=0 max=0 mta=co.uk|mta=server.co.uk +*:mta=nameserver +\end{verbatim} diff --git a/doc/manual/volume1/dreport.tex b/doc/manual/volume1/dreport.tex new file mode 100644 index 0000000..7cfe5db --- /dev/null +++ b/doc/manual/volume1/dreport.tex @@ -0,0 +1,13 @@ +\small\begin{verbatim} +Msgid string=DR020905-900816141523Z Country=gb Admin=" " Prmd=interspan +Trace mta="bells.cs.ucl.ac.uk" Country=gb Admin="gold 400" Prmd="uk.ac" + arrival="Thu, 16 Aug 1990 14:15:32 +0000" action=0 End-of-block +Trace Country=gb Admin=" " Prmd=interspan + arrival="Thu, 16 Aug 1990 14:15:23 +0000" action=0 End-of-block +Report-Hdr-End +Recip-No 1 +DR-Failure Unable-To-Transfer Unrecognised-ORName +Arrival-Time "Thu, 16 Aug 1990 14:14:59 +0000" +Reported-Recipient-End +Report-End +\end{verbatim} diff --git a/doc/manual/volume1/exampleortbl.tex b/doc/manual/volume1/exampleortbl.tex new file mode 100644 index 0000000..7ea3f7c --- /dev/null +++ b/doc/manual/volume1/exampleortbl.tex @@ -0,0 +1,41 @@ +\begin{quote}\footnotesize\begin{verbatim} +# A Truncated example of the UCL O/R Master Table +# +# -*** United Kingdom ***- +# +C$GB:valid +C$UK:alias C$GB +C$US:valid +ADMD$BTMHS.C$GB:valid +ADMD$ .C$GB:valid +ADMD$GOLD 400.C$GB:mta _DEFAULT_MTA_ +ADMD$GOLD-400.C$GB:alias ADMD$GOLD\ 400.C$GB +ADMD$ATTMAIL.C$US:mta _DEFAULT_MTA_ +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:valid +PRMD$AC\.UK.ADMD$GOLD 400.C$GB:alias PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB +PRMD$UK\.AC.ADMD$BTMHS.C$GB:alias PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB +PRMD$UK\.CO.ADMD$GOLD 400.C$GB:valid +PRMD$BDAC.ADMD$ .C$GB:mta _DEFAULT_MTA_ +PRMD$DTIIED.ADMD$GOLD 400.C$GB:mta _DEFAULT_MTA_ +O$UCL.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta _DEFAULT_MTA_ +# +# -*** australian sites ***- +C$AU:valid +ADMD$OTCDIA.C$AU:valid +ADMD$OTC.C$AU:valid +PRMD$EDU.ADMD$OTCDIA.C$AU:mta _DEFAULT_MTA_ +PRMD$DITMELPP.ADMD$OTC.C$AU:mta _DEFAULT_MTA_ +# +# -*** french sites ***- +C$FR:valid +ADMD$PTT.C$FR:mta _DEFAULT_MTA_ +ADMD$ATLAS.C$FR:mta _DEFAULT_MTA_ +PRMD$REUNIR.ADMD$ATLAS.C$FR:mta _DEFAULT_MTA_ +# +# -*** usa sites ***- +ADMD$UM.C$US:valid +ADMD$ATT.C$US:valid +PRMD$NREN.ADMD$UM.C$US:mta _DEFAULT_MTA_ +PRMD$ARC.ADMD$TELEMAIL.C$US:mta _DEFAULT_MTA_ +PRMD$WOLLONGONG.ADMD$ATT.C$US:mta _DEFAULT_MTA_ +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/exampleortbl2.tex b/doc/manual/volume1/exampleortbl2.tex new file mode 100644 index 0000000..6c8c5ff --- /dev/null +++ b/doc/manual/volume1/exampleortbl2.tex @@ -0,0 +1,43 @@ +\begin{quote}\footnotesize\begin{verbatim} +# A Truncated example of a +# UCL O/R Master Table after being edited by +# a PP Administrator +# +# -*** United Kingdom ***- +# +C$GB:valid +C$UK:alias C$GB +C$US:valid +ADMD$BTMHS.C$GB:valid +ADMD$ .C$GB:valid +ADMD$GOLD 400.C$GB:mta gb-ucl +ADMD$GOLD-400.C$GB:alias ADMD$GOLD\ 400.C$GB +ADMD$ATTMAIL.C$US:mta gb-ucl +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:valid +PRMD$AC\.UK.ADMD$GOLD 400.C$GB:alias PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB +PRMD$UK\.AC.ADMD$BTMHS.C$GB:alias PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB +PRMD$UK\.CO.ADMD$GOLD 400.C$GB:valid +PRMD$BDAC.ADMD$ .C$GB:mta gb-ucl +PRMD$DTIIED.ADMD$GOLD 400.C$GB:mta gb-ucl +O$UCL.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta gb-ucl +# +# -*** australian sites ***- +C$AU:valid +ADMD$OTCDIA.C$AU:valid +ADMD$OTC.C$AU:valid +PRMD$EDU.ADMD$OTCDIA.C$AU:mta au-goanna +PRMD$DITMELPP.ADMD$OTC.C$AU:mta au-manta +# +# -*** french sites ***- +C$FR:valid +ADMD$PTT.C$FR:mta fr-kwai +ADMD$ATLAS.C$FR:mta fr-kwai +PRMD$REUNIR.ADMD$ATLAS.C$FR:mta fr-reunir +# +# -*** usa sites ***- +ADMD$UM.C$US:valid +ADMD$ATT.C$US:valid +PRMD$NREN.ADMD$UM.C$US:mta us-destroyer +PRMD$ARC.ADMD$TELEMAIL.C$US:mta us-nasa +PRMD$WOLLONGONG.ADMD$ATT.C$US:mta us-wollongong +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/faxTable.tai b/doc/manual/volume1/faxTable.tai new file mode 100644 index 0000000..627418e --- /dev/null +++ b/doc/manual/volume1/faxTable.tai @@ -0,0 +1,18 @@ +#format information +keyfont: /fonts/bh-lucida-bold-r-normal-sans-26 +valuefont: /fonts/bh-lucida-medium-i-normal-sans-26 +textfont: /fonts/bh-lucida-medium-r-normal-sans-26 +xstart: 1.5in +ystart: 2.5in +tab: 2.5in +coverpage: /bitmaps/xtel.bm +int_prefix: 010 +localOrg: X-Tel Services Ltd,\nUniversity of Nottingham,\nUniversity Park,\nNottingham,\nNG7 2RD +localNumber: +44 602 790278 +postscript: This fax was automatically generated by PP software. +#recipient information +lancaster.xtel.co.uk: 0,A local print +nott: 783450,Computer Science,\nNottingham University +cripps: 588138,Cripps Computer Centre,\nNottingham University +ucl: 071 387 1397,UCL,\nGower Street,\nLondon WC1E 6BT +bobbies: 999,The Police Station diff --git a/doc/manual/volume1/faxTable.tex b/doc/manual/volume1/faxTable.tex new file mode 100644 index 0000000..90a4a67 --- /dev/null +++ b/doc/manual/volume1/faxTable.tex @@ -0,0 +1,19 @@ +\File{faxTable.tai},{16:28},{Sep 25 1991} +\L{\LB{\C{}\#format information}} +\CE{}\L{\LB{keyfont:}\Tab{16}{\/fonts\/bh\-lucida\-bold\-r\-normal\-sans\-26}} +\L{\LB{valuefont:}\Tab{16}{\/fonts\/bh\-lucida\-medium\-i\-normal\-sans\-26}} +\L{\LB{textfont:}\Tab{16}{\/fonts\/bh\-lucida\-medium\-r\-normal\-sans\-26}} +\L{\LB{xstart:}\Tab{16}{1.5in}} +\L{\LB{ystart:}\Tab{16}{2.5in}} +\L{\LB{tab:}\Tab{16}{2.5in}} +\L{\LB{coverpage:}\Tab{16}{\/bitmaps\/xtel.bm}} +\L{\LB{int\_prefix:}\Tab{16}{010}} +\L{\LB{localOrg:}\Tab{16}{X\-Tel Services Ltd,\!nUniversity of Nottingham,\!nUniversity Park,\!nNottingham,\!nNG7 2RD}} +\L{\LB{localNumber:}\Tab{16}{+44 602 790278}} +\L{\LB{postscript:}\Tab{16}{This fax was automatically generated by PP software.}} +\L{\LB{\C{}\#recipient information}} +\CE{}\L{\LB{lancaster.xtel.co.uk:}\Tab{24}{ 0,A local print}} +\L{\LB{nott:}\Tab{16}{783450,Computer Science,\!nNottingham University}} +\L{\LB{cripps:}\Tab{16}{588138,Cripps Computer Centre,\!nNottingham University }} +\L{\LB{ucl:}\Tab{16}{071 387 1397,UCL,\!nGower Street,\!nLondon WC1E 6BT}} +\L{\LB{bobbies:}\Tab{16}{999,The Police Station}} diff --git a/doc/manual/volume1/faxtai.tai b/doc/manual/volume1/faxtai.tai new file mode 100644 index 0000000..d4a1974 --- /dev/null +++ b/doc/manual/volume1/faxtai.tai @@ -0,0 +1,18 @@ +chan 822tofax prog=fcontrol,type=shaper, + hdrin=822-us,hdrout=g3fax, + outinfo="hdr2fax -table $(outtable) -from $(400sender) + -to $(400recip) -subject $(ua-id) -outmta $(outmta)", + outtable=fax, cost=20,solo-proc=yes, + show="hdr.822 -> g3fax mapper" + +chan ia5tofax prog=fcontrol,type=shaper, + bptin=ia5,bptout=g3fax, + outinfo="ia52fax -table $(outtable)",outtable=fax, + show="ia5 -> g3fax mapper" + +chan fax prog=G3Fax, show="Fax channel",type=both, + content-in=p22, maxproc=1, + hdrout=g3fax, bptout=g3fax, drchan=dr2rfc, + outtable=fax, sort="user time", + outinfo="out=/dev/faxout,confirm=always,softcar=used", + ininfo="in=/dev/faxin,softcar=used,master=faxmaster@xtel.co.uk" diff --git a/doc/manual/volume1/faxtai.tex b/doc/manual/volume1/faxtai.tex new file mode 100644 index 0000000..b91a215 --- /dev/null +++ b/doc/manual/volume1/faxtai.tex @@ -0,0 +1,19 @@ +\File{faxtai.tai},{12:11},{Dec 3 1991} +\L{\LB{chan 822tofax prog=fcontrol,type=shaper, }} +\L{\LB{ hdrin=822\-us,hdrout=g3fax,}} +\L{\LB{ outinfo=\S{}\"hdr2fax \-table \$(outtable) \-from \$(400sender)}} +\L{\LB{ \-to \$(400recip) \-subject \$(ua\-id) \-outmta \$(outmta)\"\SE{},}} +\L{\LB{ outtable=fax, cost=20,solo\-proc=yes,}} +\L{\LB{ show=\S{}\"hdr.822 \-\> g3fax mapper\"\SE{}}} +\L{\LB{}} +\L{\LB{chan ia5tofax prog=fcontrol,type=shaper,}} +\L{\LB{ bptin=ia5,bptout=g3fax,}} +\L{\LB{ outinfo=\S{}\"ia52fax \-table \$(outtable)\"\SE{},outtable=fax,}} +\L{\LB{ show=\S{}\"ia5 \-\> g3fax mapper\"\SE{}}} +\L{\LB{}} +\L{\LB{chan fax prog=G3Fax, show=\S{}\"Fax channel\"\SE{},type=both,}} +\L{\LB{ content\-in=p22, maxproc=1,}} +\L{\LB{ hdrout=g3fax, bptout=g3fax, drchan=dr2rfc,}} +\L{\LB{ outtable=fax, sort=\S{}\"user time\"\SE{},}} +\L{\LB{ outinfo=\S{}\"out=\/dev\/faxout,confirm=always,softcar=used\"\SE{},}} +\L{\LB{ ininfo=\S{}\"in=\/dev\/faxin,softcar=used,master=faxmaster@xtel.co.uk\"\SE{}}} diff --git a/doc/manual/volume1/filt-examp.tai b/doc/manual/volume1/filt-examp.tai new file mode 100644 index 0000000..498942f --- /dev/null +++ b/doc/manual/volume1/filt-examp.tai @@ -0,0 +1,11 @@ +chan 822touk prog=fcontrol,type=shaper, + hdrin=822,hdrout=822-jntmail, + outinfo="rfc822norm -jnt -jntsender $(sender) -fold 50" + +chan g3faxtotxt prog=fcontrol, type=shaper, bptin=g3fax, + bptout=ia5, outinfo='removebp "Group 3 Fax"', + show="Fax -> Text Mapper",cost=100,conv=loss + +chan dmd2odif prog=fcontrol, type=shaper, bptin=dmd, + bptout=odif, outinfo=f-dmd2odif, + show="Diamond -> Odif",cost=5,conv=conv diff --git a/doc/manual/volume1/filt-examp.tex b/doc/manual/volume1/filt-examp.tex new file mode 100644 index 0000000..a87d400 --- /dev/null +++ b/doc/manual/volume1/filt-examp.tex @@ -0,0 +1,12 @@ +\File{filt\-examp.tai},{12:11},{Dec 3 1991} +\L{\LB{chan 822touk prog=fcontrol,type=shaper,}} +\L{\LB{}\Tab{8}{ hdrin=822,hdrout=822\-jntmail,}} +\L{\LB{}\Tab{8}{ outinfo=\S{}\"rfc822norm \-jnt \-jntsender \$(sender) \-fold 50\"\SE{}}} +\L{\LB{}} +\L{\LB{chan g3faxtotxt prog=fcontrol, type=shaper, bptin=g3fax,}} +\L{\LB{}\Tab{8}{ bptout=ia5, outinfo=\'removebp \S{}\"Group 3 Fax\"\SE{}\',}} +\L{\LB{}\Tab{8}{ show=\S{}\"Fax \-\> Text Mapper\"\SE{},cost=100,conv=loss}} +\L{\LB{}} +\L{\LB{chan dmd2odif prog=fcontrol, type=shaper, bptin=dmd,}} +\L{\LB{}\Tab{8}{ bptout=odif, outinfo=f\-dmd2odif, }} +\L{\LB{}\Tab{8}{ show=\S{}\"Diamond \-\> Odif\"\SE{},cost=5,conv=conv}} diff --git a/doc/manual/volume1/general.aux b/doc/manual/volume1/general.aux new file mode 100644 index 0000000..1b2335b --- /dev/null +++ b/doc/manual/volume1/general.aux @@ -0,0 +1,42 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}General Considerations}{1}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Overview}{1}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}General Requirements}{1}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.1}Systems}{1}} +\citation{ISODE} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.2}Disk space}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.3}Communications Requirements}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.4}X Window System}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.2.5}QUIPU}{2}} +\citation{BIND} +\citation{TSAP.on.TCP} +\citation{MH6.5} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Specific Channel Requirements}{3}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.4}User Agents}{3}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.5}Compatibility with Older MTAs}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.5.1}MMDF}{3}} +\citation{POP} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.5.2}Sendmail}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.6}MTA Layout}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.7}Performance}{4}} +\global\@namedef{cp@general}{ +\setcounter{page}{5} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{2} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{1} +\setcounter{section}{7} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/general.tex b/doc/manual/volume1/general.tex new file mode 100644 index 0000000..b9c5661 --- /dev/null +++ b/doc/manual/volume1/general.tex @@ -0,0 +1,189 @@ +\chapter {General Considerations} + +\section {Overview} + +Before rolling the tape onto a disk, there are some general issues which it +is useful to consider. If you are planning to install PP on more than one +machine, you should read the latter parts of this chapter carefully. + +\section {General Requirements} + +\subsection{Systems} + +PP is designed to be portable to a wide range of \unix/ systems. +Configurations are given for the following systems: +\begin{itemize} +\item Sun 3 using SunOS 3.X. +\item Sun 3 using SunOS 4.X. +\item Sun 4 using SunOS 4.X. +\end{itemize} +It is also known to run on the following systems: +\begin{itemize} +\item Vax Ultrix. +\item Mips Ultrix. +\item CCUR 6000 RTU 6.0 +\item ICL DRS/6000 +\item NeXT +\item Olivetti LSX-3020 +\item Pyramid 9800 and MIS +\end{itemize} + +\subsection {Disk space} + +A fair amount of space must be made available for the system. The +figures given below are only a guide. + +The basic distribution tape contains sources amounting to around 7Mb. + +You will need approximately 40Mb of headroom extra to compile +everything, although you can do it in stages if you do not have that +much space. + +The installed binaries will take up somewhere around 20-30Mb. + +The routing table files plus local tables may take up about 1Mb if you +have a lot of connectivity. + +The \file{dbm} database built from these tables, perhaps another 1-4Mb. + +Of course you must also allow plenty of space for the mail passing through! + +This suggests that you should allow about 50Mb of space for building +everything, and when built, about 25Mb to run the system with whatever +room you feel reasonable for spooling of messages (phew!). + +This figure is less if your version of ISODE can make use of shared +libraries (e.g., SunOS). + +\subsection {Communications Requirements}\index{X25 access} + +PP uses OSI/ROS for its internal communication, using the ISODE +implementation of ROS and the lower layers\cite{ISODE}. It is assumed +that ISODE is installed and available on the system in question. ISODE +\pgm{ASN.1} tools are also required to build parts of PP. This version of +PP assumes ISODE version \isodevrsn/. + +\subsection {X Window System} +The system has a very useful monitoring tool which is written using +the \xwindows/ +which is used for managing the MTA as a whole. It is possible to run +an MTA without the console, but not so easily. The console depends on +X11 release 4 (or greater) and the Athena Widget set. It will not work under +earlier releases of X11. + +There are also present some small programs to do X-based alert of +new mail. These programs have the same X requirements. + +All binaries should work against X11 release 3 (or greater) servers. + +\subsection {QUIPU} +This release requires the \file{libdsap.a} library, but has no +requirements on the QUIPU X.500 directory service agent. There is a +list channel that utilises the directory but this is optional. Also +the X based alert utility has the ability to fetch photographs of the +user sending you mail from the directory. This feature can be disabled +though. Future releases of PP will require a QUIPU DSA. + +\section{Specific Channel Requirements} + +Some of the channels in PP have external dependencies. +\begin{describe} +\item[SMTP:] The Simple Mail Transfer Protocol channel requires the +use of TCP/IP. If the domain name server is to be used, then the +BIND\cite{BIND} resolver library must be provided (see +Table~\ref{tab:makedefs1} on page~\pageref{tab:makedefs1}). + +\item[JNT Mail:] This is integrated with the UNIX-NIFTP package, +available from Cambridge (UK) at the following address: +\begin{quote}\begin{verbatim} +Piete Brooks (pb@cl.cam.ac.uk) +Cambridge University Computer Laboratory, +Cambridge +ENGLAND +\end{verbatim}\end{quote} + +X.25 access is usually required for this channel. + +\item[X.400:] This uses the ISODE lower layers (both 1984 and 1988 +variants). For most services X.25, CONS, or CLNP is required to run +this channel, although it can be run over TCP/IP using +RFC-1006\cite{TSAP.on.TCP}. + +\item[UUCP:] This channel requires a working UUCP +installed on the given machine. + +\item[DECNET:] This requires the Sunlink DNI (version 7.0 or later) package. +\end{describe} + +\section{User Agents} + +This version of PP does not support any sophisticated user agents. It +provides a mail-sending interface of the same approximate +functionality of \pgm{/bin/mail}. It is strongly recommended that the +MH\cite{MH6.5} user agent is considered for use with PP. MH should be +configured with the SMTP transfer option which will connect to PP +though the SMTP protocol (configuration option \verb|mts send/smtp|). +This also allows PP to be accessed from hosts not running PP +directly but with SMTP connectivity. + +{\bf Warning:} MH should be compiled without the \verb|BERK| option. + +\section{Compatibility with Older MTAs} + +PP is designed as a replacement for \man sendmail(8) and MMDF. As such it is +capable of the majority of functions of both (and a great deal more). +However, there are some differences. + +\subsection{MMDF} +PP does not support the MMDF syntax that allows users to give an +address as \verb|user=string@host.domain|. + +\subsection{Sendmail} +PP does not deliver to sendmail style mailboxes by default. This can +be changed however (see Section~\ref{sect:local}). + +Some programs that send mail have compiled into them the +\pgm{sendmail} program. To deal with these, a fake sendmail is +provided that emulates most of the common sendmail options. + +As PP does not have sendmail's general rewriting rules, it can not in +general be programmed to ``fix up'' strange addresses. This applies +particularly to address formats such as DECnet and Xerox-style +addresses. To handle this sort of address an inbound channel should be +written that can parse these addresses and convert them to RFC-822 addresses. + +\section{MTA Layout} +Usually PP will support sites with many hosts. It is possible, but +not desirable, to run a copy of PP on each host. An MTA is defined +by the existence of a queue (spool area). Each queue should be managed +(in human terms) in order to guarantee good service. + +For this reason, the number of MTAs should be kept small, and other +mechanisms used for delivery to local hosts. Possibilities include: +\begin{itemize} +\item NFS. This simply consists of NFS-mounting (possible through use +of an automounter) the necessary files systems for delivery. +\item Remote access protocols. Use of services such as POP\cite{POP} +may be an alternative. +\item Delivery to a central place which is NFS-mounted by clients. +\end{itemize} +For these reasons, some of the PP utility programs may be accessed +remotely using \man rsh(1). + +A site with 1000 users and 100 hosts might consider installing +between one and four MTAs. Reasons for choosing MTAs might include: +\begin{itemize} +\item External communication links. +\item Large host with many users. +\item Fileservers used substantially for mail. +\item Separate administration domains. +\end{itemize} + +\section{Performance} + +PP is running on a Sun 4/330 at the nsfnet-relay.ac.uk mail hub, +moving around 15,000 messages a day between the UK and the US. +Experience from this and other sites has been fed back into the +development process, with the result that PP 6.0 performs better than +its predecessors. However, as is the case with any application, PP +could still benefit from more fine tuning. diff --git a/doc/manual/volume1/idx2ind b/doc/manual/volume1/idx2ind new file mode 100755 index 0000000..357a385 --- /dev/null +++ b/doc/manual/volume1/idx2ind @@ -0,0 +1,53 @@ +#! /bin/sh +: 'idx2ind - new LaTeX index converter - 11-Jul-88/JLR' + +L=%% +case x$1 in + x-l) L=""; shift ;; +esac + +for i +do + awk 'BEGIN {for (i = 97; i < 123; i++) # index letters "a" to "z" + printf "%c\n", i; exit}' |\ + cat - $i.idx |\ + sed \ + -e 's/ / /g'\ + -e 's/^\\indexentry{\(.*\)}{\([^}]*\)}$/\1 \2/'\ + -e 's/^\\verb\(.\)\(.*\)\1 \(.*\)$/\2 \3 \\verb\1\2\1/'\ + -e '/\\/!s/ *{}//'\ + -e '/,/{;s/^\(.*\) \(.*\)$/\1 \2 \1/;s/,/ /;}' |\ + sort -u -t" " +0fd -1 +1n |\ + awk -F" " ' +BEGIN {printf "\\begin{theindex}\\makeatletter\n" + printf "\\raggedright\n" + printf "\\def\\newindex#1{{\\huge\\hspace{-.5in}" + printf "\\parbox[t]{.5in}{\\makebox[.35in][c]{\\uppercase{#1}}}" + printf "\\vspace{-1.5ex}}}\n" + } +NF == 1 {x = $1; next} # NF=1: index letter + {n = $1} +NF == 3 {n = $3} # NF=3: special sort key +n == p {printf ", %s", $2; next} # another page number +p != "" {printf "\n"} # end of this item +x != "" {if (p != "") # index letter? + printf "\\indexspace\n" + printf "'$L'\\newindex{%s}\n", x + } + {x = s = ""; i = n; l = $2} # reset +/,/ {s = "sub" # sub-item + nf = split (i, a, ","); k = a[1]; i = a[2] + split (p, pk, ",") + if (pk[1] != k && pk[1] != k"{}") # should use substr... + {i = n; s =""} + else for (j = 3; j <= nf; j++) # add sub-sub-items + i = sprintf ("%s,%s", i, a[j]) + } + {printf "\\%sitem %s, %s", s, i, l} + {p = n} # save for next comparison +END {printf "\n\\end{theindex}\n" + }' > $i.ind + +done + +exit 0 diff --git a/doc/manual/volume1/install.aux b/doc/manual/volume1/install.aux new file mode 100644 index 0000000..673462f --- /dev/null +++ b/doc/manual/volume1/install.aux @@ -0,0 +1,45 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {2}Installing PP}{5}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.1}Compile Time Configuration}{5}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1.1}Make.defs}{5}} +\newlabel{Make.defs}{{2.1.1}{5}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {2.1}{\ignorespaces Make Variables That Should Be Set}}{6}} +\newlabel{tab:makedefs1}{{2.1}{6}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {2.2}{\ignorespaces Make Variables That Can Be Defaulted}}{7}} +\newlabel{tab:makedefs2}{{2.2}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1.2}h/config.h}{11}} +\newlabel{config.h}{{2.1.2}{11}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.2}Overview of Channels}{11}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.1}Mandatory Channels}{12}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.2}Optional Channels}{12}} +\citation{RFC1148} +\citation{RFC934} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.3}Example Configurations}{14}} +\newlabel{sect:example_configs}{{2.3}{14}} +\citation{MH6.5} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Local SMTP}{15}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{SMTP mail}{15}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Janet mail}{15}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.4}Configuration of User Agents}{15}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.5}Checking the Configuration of Your System}{15}} +\global\@namedef{cp@install}{ +\setcounter{page}{16} +\setcounter{equation}{0} +\setcounter{enumi}{3} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{1} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{2} +\setcounter{section}{5} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{2} +} diff --git a/doc/manual/volume1/install.tex b/doc/manual/volume1/install.tex new file mode 100644 index 0000000..f83ffcd --- /dev/null +++ b/doc/manual/volume1/install.tex @@ -0,0 +1,537 @@ +\chapter {Installing PP} + +This is a description of things to do when installing PP. The basic +information is described in \man pp-gen(8), but this section gives the +full details. It is recommended that you read this section before +compiling or installing the software. + +\section {Compile Time Configuration} + +Most of the definitions that have to be set before compiling PP are +given in \file{Make.defs} in the top level of the source tree, and +\file{config.h} in the \verb+h/+ directory. + +\subsection {Make.defs}\label{Make.defs} + +A number of \pgm{make} variables can be set. These variables come +in two classes. The first are variables that are truly site +specific. These are listed in Table~\ref{tab:makedefs1}. The second +class are variables that you can probably leave as the defaults. +These are listed in Table~\ref{tab:makedefs2}. For each entry a +reasonable default is given. + +\tagtable[hbpt]{makedefs1}{Make Variables That Should Be Set}{tab:makedefs1} + +\tagtable[hbpt]{makedefs2}{Make Variables That Can Be Defaulted}{tab:makedefs2} + +A number of these variables are important, so care must be taken when +configuring these variables. A description of each of these variables +is now given, however Tables +\ref{tab:makedefs1}~and~\ref{tab:makedefs2} give a good overview of +the variables. + +\begin{describe} +\item[\verb|CMDDIR|:]\index{CMDDIR} This is the directory into which +most of the PP core commands are placed. This is usually the directory +that contains subdirectories for channel and formatting programs. + +\item[\verb|CHANDIR|:]\index{CHANDIR} This directory is normally a +subdirectory of \verb|CMDDIR|. It contains all the channel programs +that PP knows about. + +\item[\verb|FORMDIR|:]\index{FORMDIR} This directory contains the +formatting programs that are run by \pgm{filtercontrol}. These can be +either binary executables or shell scripts. + +\item[\verb|TOOLDIR|:]\index{TOOLDIR} This directory is where a number +of miscellaneous tools are placed. These are useful programs that aid +in the day-to-day running of PP but are not usually used directly by the PP +system. + +\item[\verb|LOGDIR|:]\index{LOGDIR} This directory is where the +logging files are written to by default. These logs are used for a +variety of purposes, including debugging and statistics gathering. You +should allow for a reasonable amount of space. + +\item[\verb|TAILOR|:]\index{TAILOR} This specifies the location of +the PP tailor file. It is important you get this right. Almost +every PP variable can be changed in the PP tailor file, but +obviously the location of the PP tailor cannot. If you get this wrong, +you will need to relink all the PP binaries against an updated +\pgm{libpp.a}. + +\item[\verb|QUEDIR|:]\index{QUEDIR} This is the directory under which +the PP queue is maintained. As all messages sent are queued here, you +should allow enough room to handle all the mail you are likely to +receive. A busy site with just a day or two's network outage can +gather several megabytes of mail. + +\item[\verb|TBLDIR|:]\index{TBLDIR} This is the directory in which all +the PP routing tables and similar configuration files are kept. + +\item[\verb|LIBSYS|:]\index{LIBSYS} This variable contains all the +external libraries that you may require when building most of the PP +binaries. It should contain at least the \verb|ISODE| librarys +{\verb|-lisode|} and \verb|-ldsap| and possibly other libraries such +as the \man dbm (3) library and any machine specific libraries you may +need. + +\item[\verb|LIBRESOLV|:]\index{LIBRESOLV} This variable contains the +library for the bind domain name server (or equivalent). It is only +required if you are making use of the DNS (see Section~\ref{config.h}). +Leave it empty otherwise. + +\item[\verb|USRBINDIR|:]\index{USRBINDIR} This is a directory where +binaries that are used by users are placed. This includes a simple +mail interface, and some delivery time processors. + +\item[\verb|OPTIONALCHANS|:]\index{OPTIONALCHANS} +PP requires a certain core set of channels to operate at all, plus a +number which are used in all normal configurations. However, there are +a number of protocol and experimental channels which can be included +if required. This variable specifies +which of the optional channels and protocols you wish to support. +Currently this consists of a list made from the following: +\begin{describe} +\item[\verb|822-local|:] Basic RFC~822 delivery. +\item[\verb|lists|:] Support for distribution lists. +\item[\verb|grey|:] Support for JNT mail protocol (Grey book). +\item[\verb|shell|:] Support for delivery to programs. +\item[\verb|slocal|:] Support for structured local delivery (experimental). +\item[\verb|smtp|:] Support for the SMTP protocol. +\item[\verb|uucp|:] Support for the UUCP protocols (primitive). +\item[\verb|x40084|:] Support for the X.400 P1(1984) protocol. +\item[\verb|x40088|:] Support for the X.400 P1(1988) protocol. +\item[\verb|fax|:] Experimental fax delivery. +\item[\verb|decnet|:] Contributed \decnet/ MAIL11 channel. +\end{describe} + +\item[\verb|OPTIONALFILTERS|:]\index{OPTIONALFILTERS} +PP has a number of filters that can be used. Some are built by default; +others are only useful if you plan to support the given style of +content. Leave this empty initially if you are unsure; the defaults +are usually sufficient. + +\item[\verb|FAXDIRVERS|:]\index{FAXDRIVERS} +The PP fax channel can driver a number of FAX modems. This variable +should be configured if you are using the fax channel to specify the +particular driver(s) to use. + +\item[\verb|FAXPAGESIZE|:]\index{FAXPAGESIZE} +This macro alters the size of page the fax reformatter filters +produce. +If not defined the filters will produce US size pages, 216mm by 273mm. +If equal to \verb+-DA4+ they will produce A4 size pages, 210mm by +297mm. + +\item[\verb|MANDIR|:]\index{MANDIR} This is the directory under which +manual pages are placed. The installation process understands about +most layouts of manual pages, so this is usually a base directory. + +\item[\verb|MANOPTS|:]\index{MANOPTS} This variable configures the +style of manual pages to be installed. It can take the following +values: +\[\begin{tabular}{|l | l|} +\hline + \multicolumn{1}{|c|}{\bf Option} & + \multicolumn{1}{|c|}{\bf Format}\\ +\hline + \tt -bsd42 & man$<$N$>$/file \\ + \tt -bsd44 & cat$<$N$>$/file.O \\ + \tt -ros & man$<$N$>$/file -- using /etc/install\\ + \tt -sys5 & $<$a\verb+|+p\verb+|+u$>$\_man/man$<$N$>$/file\\ + \tt -local & manl/file.l\\ + \tt -l & man$<$N$>$/file.$<$N$>$l\\ + \tt -hpux & HP manual style\\ +\hline +\end{tabular}\] + +\item[\verb|NIFTPSRC|/\verb|NIFTPINTERFACE|:] These two variables +control the PP interfacing with the unix-NIFTP code. These variables +are ignored unless grey book mail is being installed. The variables +should be set to the source directory of the unix-NIFTP package, and +the particular interface the grey book channel will use. Suitable +interface settings include: +\begin{itemize} +\item sun (this is the only version currently in use.) +\item inet. +\item ubc. +\item dexpand. +\item x25b. +\item yorkbox. +\end{itemize} + + +\item[\verb|CC|:]\index{CC} The\pgm{C} compiler to use. The PP system has been +compiled with a number of \pgm{C} compilers. + +{\bf Warning: } If you wish to use the \pgm{gcc} compiler on +\verb|sparc|-based system, you must compile files making use of +\pgm{dbm}-style routines with \pgm{cc}. (The compiler will normally warn about +these files.) See \verb|OLDCC| below. + +\item[\verb|OLDCC|:]\index{OLDCC} The \pgm{C} compiler to use on dbm-related +files. This is to work around a problem with \pgm{gcc}; it should usually +be set to \pgm{cc}. + +\item[\verb|CCOPTIONS|:]\index{CCOPTIONS} This contains global \pgm{C} +compiler options. If your include files for \verb|ISODE| are in a non +standard place, a ``\verb|-I|'' flag or two may be necessary here. + +\item[\verb|LIBCCOPTIONS|:]\index{LIBCCOPTIONS} This contains global \pgm{C} +compiler options to use when compiling files to place in libraries. In +normal use this will be the same as \verb|CCOPTIONS|. + +\item[\verb|LDOPTIONS|:]\index{LDOPTIONS} This variable contains +global loader flags. It is normally empty or just contains the +``\verb|-s|'' flag. + +\item[\verb|PEPY|/\verb|POSY|/\verb|ROSY|/\verb|PEPSY|:] +\index{ROSY} \index{POSY} \index{PEPY}\index{PEPSY} +These variables are the +\pgm{pepy}, \pgm{posy}, \pgm{rosy} and \pgm{pepsy} programs. Normally +they just contain those names, but may be full pathnames if they are +not in the standard search path. + +\item[\verb|X11|:]\index{X11} If you have X11 then set this variable +to \pgm{true}. Leave it empty and no X-based programs will be compiled. + +\item[\verb|LIBX|:]\index{LIBX} The X11 libraries. This contains a +list of the X libraries necessary to compile the few X-based programs +in the distribution. This distribution is aligned to the X11R4 +release; it will {\em not} run under earlier versions of X. + +\item[\verb|APPDEFAULTS|:]\index{APPDEFAULTS} The application default +directory. This contains the directory in which to install the +application defaults for the various X-based programs. + +\item[\verb|LIBPHOTO|:]\index{LIBPHOTO} The \verb|ISODE| photo +library. This is required for the \pgm{xalert} program. Alternatively +you can set \verb|-DNOPHOTOS|\index{NOPHOTOS} in the \file{config.h} +file to compile this without photograph support. + +\item[\verb|LINT|:]\index{LINT} The \man lint (1) command. This is not +normally used unless you are doing development work. + +\item[\verb|LINTFLAGS|:]\index{LINTFLAGS} A list of global lint flags. +This variable is also not normally used unless development work is +being done. + +\item[\verb|PGMPROT|:]\index{PGMPROT} This is the default mode to +install programs as. Some programs need special modes, but these are +handled separately. + +\item[\verb|PPUSER|:]\index{PPUSER} This is the username that most PP +programs are installed under. It is usually \verb|pp|, but need not +be. + +\item[\verb|ROOTUSER|:]\index{ROOTUSER} The super user. + +\item[\verb|CHOWN|:]\index{CHOWN} The \man chown (8) program. This may +need to be a full pathname. + +\item[\verb|CHMOD|:]\index{CHMOD} The \man chmod (1) program. This is +normally ok as just \verb|chmod|. + +\item[\verb|BACKUP|:]\index{BACKUP} When PP installs a program, it +normally takes a copy of the existing program for safety. If you wish +this behaviour then you should set this variable to \man cp (1). If +not, setting it to something harmless like ``\verb|:|'' or \man +echo (1) which will disable this action. + +\item[\verb|INSTALL|:]\index{INSTALL} The command used to install a +new binary. This is normally either \man cp (1) or \man install (1). +\end{describe} + +\subsection {h/config.h}\label{config.h} + +The only other tailoring that should be done before compiling is +setting of \verb+#define+s in the file \file{h/config.h}. These affect the +more global options and there are very few of these. + +\begin{describe} +\item[\verb+DBM+/\verb+NDBM+:]\index{DBM}\index{NDBM} +One of these values must be defined. +It is {\em strongly} advised that you use \man ndbm (3) if you have it +at all; the \man dbm (3) routines can create havoc if you are using +another package that uses dbm too. If you are certain you don't have +\man ndbm (3) then use \man dbm (3) and add \verb+-ldbm+ to your +\verb+LIBSYS+ make variable. + +\item[\verb+PP\_DEBUG+:] This variable should be set to one of the following: +\[\begin{tabular}{|l | l|} +\hline + \multicolumn{1}{|c|}{\bf Level} & \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt PP\_DEBUG\_ALL& Include all debugging code\\ + \tt PP\_DEBUG\_SOME& Include basic debugging code\\ + \tt PP\_DEBUG\_NONE& Don't include any debugging code\\ +\hline +\end{tabular}\] + +\item[\verb+NAMESERVER+:]\index{NAMESERVER} If you wish to make use of +the BIND nameserver for the SMTP channels, you should define this. + +\item[\verb+HAS\_FSYNC+:]\index{HAS\_FSYNC} +This variable should be defined if your +system has the \man fsync (2) system call. This is defined for you if +the system is BSD based. + +\item[\verb+UKORDER+:]\index{UKORDER} +This variable should be defined if you want user tools to use UK +RFC-822 domain ordering by default. + +\item[\verb|VAT|:]\index{VAT} +This variable includes some minor extra features. +\end{describe} + +\section {Overview of Channels} + +This is a brief overview of the channels distributed with PP. +The binaries of these channels are installed in the \file{CHANDIR} +directory. + +\subsection {Mandatory Channels} + +The channels under this section must be installed with all +configurations of PP. +They are mostly ``housekeeping'' channels used by the \pgm{qmgr}. + +\begin{description} +\item[qmgrload:] +The \pgm{qmgr} maintains its own model of the queue, separate to the +master model stored under the \file{quedir} directory. The +\pgm{qmgrload} channel is used to initialise the \pgm{qmgr}'s model +when the \pgm{qmgr} starts up. When running, the \pgm{qmgr} +periodically uses \pgm{qmgrload} to check the consistency between its +model and reality. + +\item[msg-clean:] +After all work has been done on a message and that message is no +longer of interest to PP, the \pgm{qmgr} removes the message from the +\file{quedir} directory via the \pgm{msg-clean} channel. + +\item[trash:] +From time to time, the \pgm{qmgr} invokes the \pgm{trash} channel. +This channel hunts around the \file{quedir} directory for files and +directories that are no longer of interest to PP and removes them. + +\item[timeout:] +When a message has been in the queue for too long, the \pgm{qmgr} uses +the \pgm{timeout} channel to send a message back to its originator, +telling him or her that PP timed out the original message. + +\item[dr2rfc:] +The \pgm{dr2rfc} channel is used to construct delivery receipt +notifications or error messages for channels that cannot handle these +types of messages directly. It converts delivery reports into standard +RFC~822 messages which can then be sent back to the sender. + +\item[warning:] The \pgm{warning} channel is used to send warning reports +which informat senders of delay in delivering messages. + +\item[splitter:] The \pgm{splitter} channel is used by \pgm{submit} when +processing for a message has to be done on a per--recipient basis. +The \pgm{splitter} channel splits a multi--recipient message into +single recipient messages via resubmission. +\end{description} + +\subsection {Optional Channels} + +The channels under this section are optional. To see how they are +combined to produce various configurations see +Section~\ref{sect:example_configs}. + +\begin{description} +\item[822-local:] +The \pgm{822-local} channel is used to deliver messages to local users +in RFC~822 format. It can deliver by a number of methods. For more +details see Section~\ref{sect:local} on page~\pageref{sect:local} and +also {\em The PP Manual: Volume~3 -- Users Guide}. + + +\item[slocal:] +The \pgm{slocal} channel (structured local channel) should be used if local +users are to receive structured messages, that is, if the MTA is to +deliver messages made up of different parts, such as multi-media +messages, which cannot be appended to a single file but which must be +delivered as a directory of files. The \file{users} table will +indicate, for each user, whether \pgm{slocal} is an optional channel. + +\[\fbox{ +\begin{tabular}{l p{0.7\textwidth}} +\bf NOTE: & This channel is still experimental and not designed for an +operational configuration. +\end{tabular} +}\] + +\item[X400-84:] + +Inbound and outbound channels for handing X.400 P1(84) messages are +available. The channels will run over any media that ISODE can support +transport connections on. + +\item[X400-88:] + +Inbound and outbound channels for handing X.400 P1(88) messages are +available. The channels will run over any media that ISODE can support +transport connections on. This software should be considered as ``{\em +beta test}'' software in the current release. + +\item[SMTP:] + +An \pgm{smtp} channel is available for use over TCP/IP. It may be used +over networks such as a local Ethernet or WAN such as the DARPA +Internet. + +\item[JNT Mail:] +The JNT mail channel is used over X.25 networks, particularly in the U.K. +The unix-niftp package is used to provide the blue book file transfer +part of this. + +\item[UUCP:] +A channel that will interface with the UUCP protocols. + +{\bf Note:} This channel has not been tested extensively by the +developers. Others have reported that it is satisfactory, however. + +\item[\decnet/ MAIL11:] +A channel that implements the \decnet/ protocol. This is contributed +software. + +\item[p2explode:] +The \pgm{p2explode} channel is a restructuring channel that is used to +explode a general p2 message into its separate component bodyparts. +Note the same binary can explode p2(84) and p22(88). It is used +on an incoming X.400 message when the MTA needs to manipulate the +separate components of that message. + +\item[p2flatten:] +The \pgm{p2flatten} channel is a restructuring channel that is used to +combine all the separate components of a message into one p2 file. It +is the exact inverse of \pgm{p2explode}. + +\item[P2toRFC:] +The \pgm{P2toRFC} channel is a reformating channel that is used to +convert an X.400 style header encoded in \verb+p2(84)+ or +\verb+p2(88)+ to an RFC~822-style header. This conversion is +performed according to RFC~1148\cite{RFC1148} . + +\item[RFCtoP2:] +The \pgm{RFCtoP2} channel is a reformating channel that is used to +convert an RFC~822 style header to an X.400 style header encoded in +\verb+p2(84)+ or \verb+p2(88)+. +This conversion is done as described in RFC~1148. + +\item[rfc934:] +The \pgm{rfc934} channel flattens an RFC~822-style message which may +contain forwarded messages, into a flat RFC~822 message. The +flattening is done as described in RFC~934\cite{RFC934}. + +\item[list:] +The \pgm{list} channel expands a distribution list into its component +members. The original message is then sent to each of these members. +The channel uses the associated \file{list} table as described in +Section~\ref{sect:list} on page~\pageref{sect:list}. + +\item[dirlist:] +The \pgm{dirlist} channel expands a distribution list into component +members. It takes the list of members from the X.500 directory. + +\item[shell:] +The \pgm{shell} channel runs a specific process for the originator of +the message. This allows delivery of a message to a special process +rather than to a user. The mapping from the address the message is +sent to and the process to run is described by the \file{shell} table, +see Section~\ref{sect:shell} on page~\pageref{sect:shell}. + +\item[splitter:] +The \pgm{splitter} chanel is used in some instances to split a message +into separate messages with one recipient each. This allows some +specialist reformatting to be done. See details of the FAX driver for +an example. + +\item[fcontrol:] +The \pgm{fcontrol} channel is used to run various filters on the +bodyparts of the message. +These filters can only affect the contents of the bodyparts and cannot +affect the overall structure of the message. +The filters are usually installed in the \file{FORMDIR} directory. +\end{description} + +Here is a brief description of the filters distributed with PP: +\begin{describe} +\item[\verb+rfc822norm+:] The filter is used for conversion between various +styles of RFC~822 headers +. +\item[\verb+p2norm+:] The filter is used to normalise X-400 addresses +in P2 headers. It can also be used to downgrade X-400 (88) P2 +headers into X-400 (84) P2 headers. This downgrading is done according +to the INTERNET draft ``X.400 1988 to 1984 downgrading'' by S.E. +Hardcastle-Kille. + +\item[\verb+removebp+:] The filter is a simple shell script used to +replace bodyparts that the MTA cannot support. It removes the +indicated part and replaces it with a simple text message reflecting +this fact. +\end{describe} + +\section {Example Configurations}\label{sect:example_configs} + +This section gives some details about the example configurations +included in the distribution. These configurations should be looked on +as a sample first step to allow a working system to be installed +easily. This should then be evolved to meet local requirements. +To use one of these configurations, do the following. +\begin{enumerate} +\item Change to the \file{examples} directory. +\item Select one of the configurations shown below, and change into +that directory. +\item Read the \file{README} file, and carry out the instructions +given in there. +\end{enumerate} + +This should give you a {\em very basic} working system. + +\subsubsection{Local SMTP} +This configuration assumes a simple host doing local deliveries and +passing all other messages to another host. It requires the \pgm{smtp} +channel, the \pgm{822-local} channel and optionally the \pgm{list} +channel. + +\subsubsection {SMTP mail} +This configuration assumes a simple host doing SMTP relaying and local +delivery only. It is similar to the above, but can handle Internet +connectivity by use of the domain nameserver. + +\subsubsection {Janet mail} +This host is assumed to be on the Janet network and has local SMTP +capability. It is a skeleton only, as for proper operation, NRS data is +necessary to identify the necessary domain and routes. + +\section {Configuration of User Agents} + +PP is a message transfer agent, and does not contain a sophisticated +X.400 user agent. It is hoped that the interface documented in +Volume~2 of these manuals +will be useful in the development of new user agents or the +interfacing of existing UAs. The latter should be straightforward +for most RFC~822-based interfaces. + +MH\cite{MH6.5} can be used directly +with PP if compiled with the SMTP +transfer interface. + +PP provides a \pgm{/bin/mail} like interface. This should be installed +in the normal installation. It provides a simple way for submission of +RFC~822 messages, and allows a few flags to be set. Also provided is a +\man sendmail(8) emulation program that can be used to intercept those +programs that insist on calling sendmail directly (e.g., \man +cron(8)). + +\section {Checking the Configuration of Your System} + +Following installation, it is {\em strongly} recommended to use \man +ckconfig (8) to ensure that the PP directory structure is correct and +all the channel programs are correctly in place. +\pgm{ckconfig} is described in Section~\ref{sect:ckconfig}. diff --git a/doc/manual/volume1/lists-examp.tex b/doc/manual/volume1/lists-examp.tex new file mode 100644 index 0000000..e44ccf5 --- /dev/null +++ b/doc/manual/volume1/lists-examp.tex @@ -0,0 +1,11 @@ +\small\begin{verbatim} +# +# extract of `list' table +# +#Comment: -*- Example lists -*- +filelist:pac,file=/crg/pp/mainlist,a list with members in a file +strlist:pp|pac,p.cowen|j.onions|g.lunt,a list with members in line +mixedlist:jpo,j.onions|file=mixedlist,another list +# +\end{verbatim} + diff --git a/doc/manual/volume1/log-examp.tai b/doc/manual/volume1/log-examp.tai new file mode 100644 index 0000000..10d9c5b --- /dev/null +++ b/doc/manual/volume1/log-examp.tai @@ -0,0 +1,13 @@ +authlog level=notice, size=400 +operlog level=all, size=400 +normlog level=notice, size=400 + +submit normlog file=submit level=notice, size=400 +qmgr normlog file=qmgr level=notice, size=400 +x400in84 normlog file=x400in84 level=notice, size=400 +x400out84 normlog file=x400out84 level=pdus, size=400 + +isodelog compatlevel level=pdus +isodelog tsaplevel level=pdus +isodelog ssaplevel level=pdus +isodelog rtsaplevel level=pdus diff --git a/doc/manual/volume1/log-examp.tex b/doc/manual/volume1/log-examp.tex new file mode 100644 index 0000000..284cb2a --- /dev/null +++ b/doc/manual/volume1/log-examp.tex @@ -0,0 +1,14 @@ +\File{log\-examp.tai},{12:41},{Mar 25 1991} +\L{\LB{authlog}\Tab{16}{level=notice,}\Tab{32}{size=400}} +\L{\LB{operlog}\Tab{16}{level=all,}\Tab{32}{size=400}} +\L{\LB{normlog}\Tab{16}{level=notice,}\Tab{32}{size=400}} +\L{\LB{}} +\L{\LB{submit}\Tab{16}{normlog file=submit}\Tab{40}{level=notice, size=400}} +\L{\LB{qmgr}\Tab{16}{normlog file=qmgr}\Tab{40}{level=notice, size=400}} +\L{\LB{x400in84}\Tab{16}{normlog file=x400in84}\Tab{40}{level=notice, size=400}} +\L{\LB{x400out84}\Tab{16}{normlog file=x400out84}\Tab{40}{level=pdus, size=400}} +\L{\LB{}} +\L{\LB{isodelog compatlevel}\Tab{24}{level=pdus}} +\L{\LB{isodelog tsaplevel}\Tab{24}{level=pdus}} +\L{\LB{isodelog ssaplevel}\Tab{24}{level=pdus}} +\L{\LB{isodelog rtsaplevel}\Tab{24}{level=pdus}} diff --git a/doc/manual/volume1/logx400-examp.tex b/doc/manual/volume1/logx400-examp.tex new file mode 100644 index 0000000..9081a62 --- /dev/null +++ b/doc/manual/volume1/logx400-examp.tex @@ -0,0 +1,14 @@ +\begin{quote}\footnotesize\begin{verbatim} +2/ 7 15:41:38 x400in 22798 (#52 ) Starting x400in (via X400(84) inbound) +2/ 7 15:41:41 x400in 22798 (#52 ) Connection from +key='X121+5052334300018' mta='manta.cng.dit.csiro.au' password=' ' +2/ 7 15:41:41 x400in 22798 (#52 ) No information found in the +X.400 incoming tables +2/ 7 16:41:41 x400in 22799 (#52 ) x400in/main error: rts_decode_request +2/ 7 16:41:38 x400in 22799 (#52 ) Starting x400in (via X400(84) inbound) +2/ 7 16:41:41 x400in 22799 (#52 ) Connection from +key='"PHL"/X121+302049600717' mta='foo' password='foobar' +2/ 7 16:41:41 x400in 22799 (#52 ) No information found in the +X.400 incoming tables +2/ 7 16:41:41 x400in 22799 (#52 ) x400in/main error: rts_decode_request +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/make b/doc/manual/volume1/make new file mode 100755 index 0000000..be14df3 --- /dev/null +++ b/doc/manual/volume1/make @@ -0,0 +1,11 @@ +#! /bin/sh + +if [ -f ../../../Make.defs ] +then + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../../../Make.defs -f Makefile ${1+"$@"} +else + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../Make.defs -f Makefile ${1+"$@"} +fi + diff --git a/doc/manual/volume1/management.aux b/doc/manual/volume1/management.aux new file mode 100644 index 0000000..ea19ac4 --- /dev/null +++ b/doc/manual/volume1/management.aux @@ -0,0 +1,87 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {7}Managing PP}{104}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.1}QMGR}{104}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.1}Message Submission}{104}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.2}Queue Reading}{104}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.3}Active Channel}{104}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.4}Passive Channel}{105}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.5}Cleanups, Timeouts, Warnings and Debris}{105}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.1.6}QMGR Management and Tailoring}{105}} +\newlabel{sect:qmgrmgr}{{7.1.6}{105}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.2}MTA Console}{107}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.2.1}The MTA Console's Display}{107}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Monitor Mode}{108}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Control Mode}{108}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.2.2}Configuring The MTA Console}{108}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Totals Configuration.}{108}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Colour Configuration.}{109}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Static Connection Configuration.}{109}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Confirmation Configuration.}{109}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Heuristic Configuration}{109}} +\newlabel{sect:heur}{{7.2.2}{109}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Configuration of Timeouts and Retries.}{110}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.2.3}The Effect of the Mouse Buttons and Keys}{111}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {7.1}{\ignorespaces MTA Console Accelerators}}{114}} +\newlabel{tab:accelerators}{{7.1}{114}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.2.4}Badness}{114}} +\newlabel{sect:badness}{{7.2.4}{114}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Tailoring of Upperbounds}{114}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {7.2}{\ignorespaces Tailor File Entries to Console Keys.}}{115}} +\newlabel{tab:consolemapping}{{7.2}{115}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {7.1}{\ignorespaces Extract From the Console's Tailoring}}{116}} +\newlabel{example:console.tai}{{7.1}{116}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.3}LINEconsole}{116}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.3.1}LINEconsole Commands}{117}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.4}Lconsole}{118}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.5}Checkup Procedures}{121}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.5.1}ckchan}{121}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.5.2}ckconfig}{122}} +\newlabel{sect:ckconfig}{{7.5.2}{122}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.5.3}Checking of Addresses}{122}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Ckadr}{122}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Probes}{124}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.6}Dealing with Errors}{125}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.7}Managing Tables}{126}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{RFC 1148 Mapping Tables}{126}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Domain and Channel Tables}{127}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Generation of the domain table}{127}} +\newlabel{tablebuild:domain}{{7.7}{127}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Generation of the Channel Table}{129}} +\newlabel{tablebuild:channel}{{7.7}{129}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.8}Adding New Users and MTAs}{130}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.9}Adding Filters, Shapers + EITs}{131}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.9.1}Adding A New Encoded Information Type}{131}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.9.2}Adding a New Content Type}{131}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.10}The Day--to--Day Running of PP}{132}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.10.1}How to Start Up the PP System}{132}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.10.2}What to Run Each Night}{133}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.10.3}Saving Logs}{133}} +\newlabel{sect:logs}{{7.10.3}{133}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {7.11}Examining the PP Queue}{134}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.11.1}Delivery Reports}{134}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {7.11.2}Receipt Notifications}{134}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {7.2}{\ignorespaces Example of Address File}}{135}} +\newlabel{examp:qfile}{{7.2}{135}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {7.3}{\ignorespaces Example Delivery Report Format}}{135}} +\newlabel{examp:dr}{{7.3}{135}} +\global\@namedef{cp@management}{ +\setcounter{page}{136} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{2} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{7} +\setcounter{section}{11} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{3} +\setcounter{table}{2} +} diff --git a/doc/manual/volume1/management.tex b/doc/manual/volume1/management.tex new file mode 100644 index 0000000..b17c6fa --- /dev/null +++ b/doc/manual/volume1/management.tex @@ -0,0 +1,1746 @@ +\chapter {Managing PP} + +This chapter covers the +tools which allow the system administrator to keep up to date +with the status of the system and to take action to fix or avoid problems. +It also gives some guidance on what is entailed in daily maintenance of +the system, and how new users and MTAs may be added. + +\section{QMGR} + +The QMGR operates without ever reading the queue. The key ASN.1 +structure is MsgStruct. This is the ASN.1 representation of the +message as held by the queue manager. This is held in a sparse +matrix, initially sorted by channel, host/user, and priority. The +queue manager is not, inherently, a trusted process, as it does not +access the queue directly. The protocol is listed in +Appendix~\ref{qmgrros} in Figure~\ref{proto:qmgr}. + +\subsection{Message Submission} + +When \pgm{submit} is started, it asynchronously establishes an association +with the QMGR. When a message is submitted to the queue, a ROS +message is sent to the queue manager which will hold all of the +information needed by the QMGR. This allows the message to be +processed without the QMGR actually reading the queue. + +\subsection{Queue Reading} + +A ROS operation allows the queue to be read by calling up the +\pgm{qmgrload} channel. This is used at startup and for occasional +refresh of the queue. Note that when the queue is reread only new +messages are added, messages that are already known to the QMGR are ignored. + +\subsection{Active Channel} + +An active channel is invoked by the QMGR, which starts a ROS +association. The channel is synchronous. The first operation is +ChannelInitialise, which identifies the channel to the process (which +may act as several channels). Subsequent ChannelInitialise operations +serve to change the role of the channel. The ProcessMessage operation +allows the QMGR to control the channel, which will access the queue +directly. + +\subsection{Passive Channel} + +Passive channels have not yet been implemented. + +\subsection{Cleanups, Timeouts, Warnings and Debris} + +Message are deleted by the \pgm{msg-clean} channel. This is invoked +after all recipients have been processed. + +Messages are returned after a certain time by the QMGR invoking +the \pgm{timout} channel. This process creates a delivery report and +changes the status of the message to non-delivery. + +Message that have been in the queue for a long period may generate +warning messages to the originator. This is done via the \pgm{warning} +channel. + +Partially submitted messages and general debris are cleaned up quietly +by debris channel after being in the queue for a certain amount of +time. This channel is invoked at intervals. + +\subsection{QMGR Management and Tailoring}\label{sect:qmgrmgr} + +The QMGR is managed mostly through the MTA console interface. +However, there are several options you can give when starting up the +QMGR to change the mode of operation. These are listed here, in +approximate order of usefulness: + +\begin{describe} +\item[\verb|-m|:] This switch sets the default maximum number of +channels that can be run simultaneously. This parameter needs to be set +carefully (see below). + +\item[\verb|-c seconds|:] This switch sets the default time to cache a +channel that has failed. It defaults to 5 minutes. The cache value is +multiplied by 1.5 to obtain a delay for failed MTAs, and multiplied by +2 for failed messages. Successive failures will multiply this value up +to some maximum. + +\item[\verb|-D|:] This switch starts up the QMGR with all channels +disabled. This is most useful to allow controlled startup of +channels. Once started in this mode, channels can be gradually enabled +by use of appropriate management tools. + +\item[\verb|-d hours|:] This switch sets the time between successive +runs of the debris channel. This is the channel that removes +extraneous bits of messages, etc. Its default value is about six hours. + +\item[\verb|-l hours|:] This switch sets the time between successive +runs of the load channel. This channel is run at intervals to check +consistency between the image of the queue in memory and that on disk. + +\item[\verb|-t hours|:] This switch sets the time between successive +calls to the timeout channel. This channel is run at intervals to time +out messages that have been in the queue too long. + +\item[\verb|-C|:] Do not change directory to the queue directory. Stay +in the current directory. + +\item[\verb|-b|:] Do not run in the background, stay in the foreground. + +\item[\verb|-T file|:] Use this file as the pp \file{tailor} file. + +\item[\verb|-X|:] Turn up the debugging. + +\item[\verb|-s|:] Inhibit submission of messages. If this is set, the +QMGR will ignore all incoming messages. + +\item[\verb|-M|:] This flag allows the \pgm{msg-clean} channel to run +concurrently with the \pgm{qmgr-load} channel. There is a slight +possibility of a race condition occuring if this is enabled, which +may mean a message is not processed. The chance is slight however. If +your queues are reasonably small (say < 1000 messages normally) this +flag should not be used. If you have large queues commonly, the load +phase can take up to an hour, in which case allowing deletions during +this time is useful. +\end{describe} + +The QMGR also responds to various signals (where available). A +\verb|SIGTERM| signal will cause the QMGR to gracefully +shutdown. This is the same as QMGR control option. A \verb|SIGUSR1| +signal will increase the debugging level and a \verb|SIGUSR2| will +reset the level, or decrease it. All other signals default to their +normal actions. + +The loading on a given machine varies and it is controlled mainly +through the maximum number of channels variable. Consequently, it is +important to get this factor correct, otherwise response will suffer. + +The main adjustable parameter is the maximum number of channels that +can be run at any one time. This parameter should be set with care. It +can be set by the above-mentioned flag at QMGR start time, or can be +modified dynamically through the use of the MTA console. This +parameter should be used in conjunction with the per channel maximum +number of processes. The QMGR has a number of built in heuristics as +to how useful running several invocations of a channel at once is. +This can be overridden by the per-channel maximums, but these should be +used sparingly. Suitable cases for imposing a per-channel maximum are +the following: +\begin{itemize} +\item Channels which run very quickly. Such channels are usually +reformatters that do their job quickly. Allowing only one or two +instances of these channels can help loading in some cases. These +channels can create a large load on the machine as they have no external +influence and run as fast as the machine will let them. + +\item Special network channels. If you have a channel that uses a +dedicated resource, then this may be a candidate for setting a maximum +on. Such a resource might be a modem or a non-multiplexed line. +Clearly, if there is only one logical stream that a channel can use, +starting multiple instances of such a channel is pointless. +\end{itemize} + +Cases that should generally not have a per-channel maximum are the +following. +\begin{itemize} +\item Network channels. Unless you have an amazingly fast network +and instantaneous response from remote hosts, network channels do not +usually create too much load. They tend to be self-throttling, as they +spend much of their time waiting for I/O to complete or for response +from the remote host. + +\item QMGR special channels. Such channels as QMGR-load and timeout +are special to the QMGR and will only be invoked one at a time. +\end{itemize} + +The maximum number of channels defaults to three, which is a reasonable +number for a small machine that is doing other things besides mail. If +you are running a dedicated mail server you will probably get better +throughput with a larger number. However, it is worth spending some +time watching what happens and increasing and decreasing this number +via the MTA consoles to get a reasonable value. If you specify a value +of 10, for instance, you may end up just wiping out any trace of +performance on your machine, as the machine will just be thrashing +between processes. On the other hand, 10 channels talking to 300 baud +modems will probably not be noticeable. +Once you have determined a reasonable value, add this to your +pp.start script using the \verb|-m| switch detailed above. + +To begin with it is recommended that the default configuration with +no per-channel maxima is used and that it is run for a while before +adjustment is made. + +\section {MTA Console} + +The MTA console is a management tool that can be used to monitor +and/or control a QMGR. This tool uses the Athena widget set on top of +X11 release~4 (or greater). + +\subsection {The MTA Console's Display} + +The MTA console's display has two modes, the {\em monitor} mode +and the {\em control} mode. +Toggling between these modes is done via the appropriate button. + +The top section of the display is common to both modes. +This section contains a box within which the states of all the +channels are displayed. + +The {\em state} of an entity (channel, MTA or message) represents how +``bad'' that entity is, compared to the upperbound on ``badness'' +(maximum badness). +The badness of an entity can reflect various things like number of +messages on that entity or the age of the oldest message on that +entity. +Section~\ref{sect:badness} describes what badness represents, how +badness is calculated, and how this calculation can be tailored. + +\subsubsection {The Monitor Mode} + +The {\em monitor} mode provides a passive display of the overall state +of the QMGR. + +In this mode, the lower part of the display presents an ordered list +of the states of the channels. +The list is ordered on the basis of comparative badness. +The list is laid out vertically with the +worst state channel at the top. + +The states of the ``n worst state'' MTAs on each channel are displayed +to the right of the channel they are on. +They are ordered on the basis of comparative badness with the worst +state MTA being display directly to the right of the channel. +How many of the MTAs on a channel are actually displayed depends on +the heuristic being employed. +The MTA console has a number of possible heuristics. +These are described in Section~\ref{sect:heur}. + +\subsubsection {The Control Mode} + +The {\em control} mode allows the user to focus on particular +channels, MTAs or messages and control their passage through and their +behaviour in the QMGR. + +The amount of control the console can invoke depends on how the +console connected to the QMGR. +There are two types of connection the QMGR allows, unauthorised +and authorised. +With an authorised connection, the console can control the QMGR +by disabling entities, enabling entities and so on. +With an unauthorised connection, the console has no control over the +QMGR. +To get an authorised connection, the user has to specify a name and +password when he or she requests the connection. + +In the {\em control} mode, the lower part of the console's display presents +information on the entity the user has focused on and allows the user +to focus on other entities. + +\subsection {Configuring The MTA Console} + +This section details how the MTA console may be +configured by users to suit their own individual tastes. +There are three static mechanisms that can be used for this configuration: +\begin{enumerate} +\item command line arguments +\item user defaults +\item application defaults +\end{enumerate} +As well as these static mechanisms, the MTA console contains a +configuration menu. +This menu can be used dynamically to configure many of the options +described below. + +\subsubsection {Totals Configuration.} + +The MTA console displays the total number of messages and the total volume +of messages in the queue. +It also indicates how full the queue is by comparing these totals with +specific maximum values. +These maximum values can be statically tailored on the command line +(e.g., \verb+-number 1000000+ and \verb+-volume 100000000+) or in the X +defaults (e.g., \verb+MTAconsole.totalnumber: 1000000+ and +\verb+MTAconsole.totalvolume: 100000000+) +The values can also be tailored from the badness tailoring as +described in Section~\ref{sect:badness}. +The default values are, for volume of messages, 1000000 and, for number +of messages, 10000. + +\subsubsection {Colour Configuration.} + +On a colour screen the MTA console will display entities of +significantly different badness as different colours, with the colour +ranging from green for +entities with low badness to red for entities with high badness. +The number of colours the console will use can be statically tailored +from the command line (e.g., \verb+-ncolours 20+) or in the Xdefaults +(e.g., \verb+MTAconsole.ncolours 20+). +The console will use a range of 10 colours by default. + +\subsubsection {Static Connection Configuration.} + +The user must specify which QMGR to attempt to connect to. +Usually this is done dynamically from the connect popup. +However it can be done statically from the command line (e.g. +\verb+-Queue trellis+) or in the X defaults \\ +(e.g., \verb+MTAconsole.connectHost: trellis+). +If the QMGR to connect to is statically specified, the MTA console +will automatically attempt to open an unauthorised connection to the +specified QMGR. + +\subsubsection {Confirmation Configuration.} + +Certain of the MTA console's commands request confirmation via a +popup. +This feature can be turned off dynamically from the confirmation menu +or statically from the command line (e.g., \verb+-NoConfirm+) or in the +X defaults (e.g., \verb+MTAconsole.confirm: false+). + +\subsubsection {Heuristic Configuration} \label{sect:heur} + +When in monitor mode, the MTA console displays some of the MTAs on each +channel. +There are different heuristics that the console can use to decide +how many MTAs to display for each channel. +These heuristics are: + +\begin{description} +\item[\verb|channelonly|:] This heuristic shows only the information +about the channels and no per MTA information. This is useful when the +QMGR has many messages loaded into it and so refreshing the display +takes a while. + +\item [\verb+line based+:] This heuristic limits the display of MTAs +on each channel to a specific number of vertical lines. This number +can be tailored dynamically from the configuration menu or statically +on the command line (e.g., \verb+-downLines 6+) or in the X defaults +(e.g., \verb+MTAconsole.maxvert: 6+). The default value is 4. + +\item [\verb+percentage based+:] This heuristic displays a specific +percentage of the MTAs on each channel. The percentage to display is +calculated by multiplying the badness of the channel (expressed as a +percentage of the maximum badness) by a constant percentage. This +constant percentage can be tailored dynamically from the configuration +menu or statically on the command line (e.g. {\verb+-percent 70+}) or +in the X defaults (e.g. {\verb+MTAconsole.percentage: 70+}). The +default value for this constant is 50. + +There is a lower bound on the number of MTAs displayed using this +heuristic. +The MTA console will endeavour to ensure that the number of MTAs displayed +for each channel is at least the lower bound. +This lower bound can be tailored dynamically from the +configuration menu or statically on the command line (e.g. +\verb+-lowerbound 15+) or in the X defaults (e.g. +\verb+MTAconsole.lowerbound: 15+). +The default value for this lower bound is 20. + +\item [\verb+all+:] This heuristic instructs the MTA console in +monitor mode to display all the MTAs on each channel. + + +\end{description} + +The choice of heuristic can be changed dynamically from the +configuration menu or statically on the command line (e.g. +\verb+-heuristic all+) or in the X defaults (e.g. +\verb+MTAconsole.heuristic: all+). +The line-based heuristic is used by default. + +\subsubsection {Configuration of Timeouts and Retries.} + +There are various timeouts and retry intervals associated with the MTA +console. +These can be configured or disabled from the configuration menu and +are as follows: +\begin{description} + +\item[auto-refresh timeout:] If no activity occurs on the connection +between the MTA console and the QMGR during a specified interval, the +console will consult with the QMGR and automatically refresh the +information on display. +This particular timeout interval can also be configured on the command line +(e.g., \verb+-refresh 3m30s+) or in the X defaults (e.g. +\verb+MTAconsole.refresh: 3m30s+). +The default interval is 5 minutes. Note: to stop the console hogging +the QMGR's resources, a minimum value for this interval is enforced. +This minimum is 30 seconds. + +\item[inactive timeout] If the console is in {\em control} mode and no +user input has been received during a specified interval, the MTA +console automatically toggles to the {\em monitor} mode. +The default interval is 10 minutes. + +\item[reconnection retry interval] If the connection between the +MTA console and the QMGR breaks, the console will attempt to reconnect +to the QMGR. +After an unsuccessful reconnection attempt, the console will wait for +a specified time and then try to reconnect again. +The intervals between reconnection attempts increases in duration by a +specified increment up to a maximum interval. +The initial duration of the wait interval, the increment added to +the interval after each unsuccessful reconnection attempt and the +maximum interval can all be set dynamically from the configuration menu. +This menu can also disable the reconnection mechanism and/or the +increasing duration. + +\end{description} + +\subsection {The Effect of the Mouse Buttons and Keys} + +This section describes how a user can use the mouse buttons and the +keyboard to operate the MTA console. The following tables show the +effect of the command buttons that can be found on the +MTA console. + +\[\begin{tabular}{l p{0.6\textwidth}} + \multicolumn{2}{c}{\bf Top row of buttons} \\ + \multicolumn{1}{c}{\bf Button}& + \multicolumn{1}{c}{\bf Effect}\\ + \tt Refresh/Reconnect & Refresh the data or reconnect to the + QMGR. \\ + \tt quit & Exit the console program. \\ + \tt connect/disconnect & Connect to or disconnect from the QMGR. \\ + \tt control/monitor & Change between the two modes. \\ + \tt configuration & Set various parameters. \\ + \tt Qmgr control & Perform global QMGR control (only if authorised). \\ +\end{tabular}\] + +\[\begin{tabular}{l p{0.6\textwidth}} + \multicolumn{2}{c}{\bf Channel buttons} \\ + \multicolumn{1}{c}{\bf Button}& + \multicolumn{1}{c}{\bf Effect}\\ + \tt info & Display information about the channel. \\ + \tt ++ & Select next channel \\ + \tt -- & Select previous channel \\ + \multicolumn{2}{c}{If connected in authorised mode} \\ + \tt disable & Disable this channel. \\ + \tt enable & Enable this channel. \\ + \tt clear delay & Clear any delays on this channel. \\ + \tt add delay & Specify a delay. The channel will wait this + time before starting again. \\ + \tt downward force attempt & Invoke this channel now if + possible, clearing any delays and those + messages and MTAs waiting on this channel. \\ +\end{tabular}\] + +\[\begin{tabular}{l p{0.6\textwidth}} + \multicolumn{2}{c}{\bf MTA buttons}\\ + \multicolumn{1}{c}{\bf Button}& + \multicolumn{1}{c}{\bf Effect}\\ + \tt info & Display information on this MTA. \\ + \tt ++ & Select the next MTA \\ + \tt -- & Select the previous MTA \\ + \multicolumn{2}{c}{If connected in authorised mode} \\ + \tt disable & Disable this MTA. \\ + \tt enable & Enable this MTA. \\ + \tt clear delay & Clear any delays for this MTA. \\ + \tt add delay & Specify a delay before next retry. \\ + \tt force attempt & Clear any delays for this MTA, an + similarly for the channel this is on. \\ + \tt downward force attempt & Clear delays for this MTA and + those of any messages on this MTA. \\ +\end{tabular}\] + +\[\begin{tabular}{l p{0.6\textwidth}} + \multicolumn{2}{c}{\bf Message Buttons}\\ + \multicolumn{1}{c}{\bf Button}& + \multicolumn{1}{c}{\bf Effect}\\ + \tt info & Display information about this message .\\ + \tt ++ & Select next message \\ + \tt -- & Select previous message \\ + \tt show all & By default only information on ten messages is + shown. This button will show all messages on this + MTA/channel. \\ + \multicolumn{2}{c}{If connected in authorised mode} \\ + \tt freeze & Stop this message being delivered. \\ + \tt thaw & Allow this message to be delivered (this is the + opposite of freeze). \\ + \tt clear delay & Clear the next delivery attempt time. \\ + \tt add delay & Set a next delivery attempt time. \\ + \tt force attempt & Try and deliver the message now by clearing + all delays associated with this message.\\ +\end{tabular}\] + + +Here are the effects each button has when pressed within the MTA +console's display. It is based on a three-button mouse. Different +configurations are tailorable through the X defaults mechanism for +other hardware. +\begin{description} +\item[\verb+left hand button+:] If this button is pressed while the +cursor is over one of the many {\em command} buttons in the console, +that command is invoked. + +If the console is in monitor mode and the left-hand button is pressed +while the cursor is over the area occupied by the display of an entity, +the console toggles to control mode, focuses on that entity, and +displays information about the entities directly below it. +For example, if in monitor mode the left-hand button was pressed while the +cursor was over the area occupied by the channel \verb+x400out84+, +then the console would toggle modes, make \verb+x400out84+ the current +channel and display information about the MTAs currently on that channel. + +If the console is in control mode and the left-hand button is pressed +while the cursor is over the area occupied by the display of an +entity, then the console focuses on that entity and displays +information about the entities directly below it. +For example, if in control mode the left-hand button was pressed while +the cursor was over the area occupied by the channel \verb+x40084+, +then the console would make \verb+x40084+ the current channel and +display information about the MTAs currently on that channel. + +\item[\verb+middle button+:] If the console is in monitor mode and the +middle button is pressed while the cursor is over the area occupied by +the display of an entity, the console toggles to control mode and +focuses on that entity. + +If the console is in control mode and the middle button is pressed +while the cursor is over the area occupied by the display of an +entity, the console toggles the focus on that entity (i.e., if the focus +at that level is not on the entity, the focus is set on that entity. +However, if the focus is already on that entity, the focus is unset). + +\item[\verb+right button+:] This button has a similar effect in both +modes. +If it is pressed while the cursor is over the area occupied by the +display of an entity then the information displayed relating to that +entity is refreshed and redisplayed. +\end{description} + +There are various ``accelerators'' installed in the MTA console. +These are key presses that allow the user to invoke commands that +would otherwise have to be invoked by moving the cursor to a specific +area on the screen and then pressing one of the mouse buttons. The +accelerators installed in the console all provide alternative ways to +invoke some of the commands represented by {\em command} buttons. +Some have prerequisites for use. Table~\ref{tab:accelerators} shows +the accelerators, their prerequisites, and the commands they invoke. +This table has two modifier keys that must be held down together with +the other keys mentioned in the accelerator for that accelerator to +work -- the {\em Meta} key and the {\em Control} key. + +\tagtable{console_accels}{MTA Console Accelerators}{tab:accelerators} + +Several of the popups have various text boxes into which a user can +type. At any one instant only one of these boxes can have the +keyboard focus (the box with the keyboard focus gets the text the user +types in). This is indicated by the text box with the focus having a +border around it. All other text boxes will have no border. There +are accelerators installed in the MTA console to allow the user to +change the keyboard focus. The up arrow key when pressed will change +the focus to the box above the one currently with the focus. The down +arrow key when pressed will change the focus to the box below the one +currently with the focus. The tab key has the same effect as the down +arrow key. If the left-hand button on the mouse is pressed when the +cursor is over one of the text boxes, that text box gets the focus. + + +\subsection {Badness} \label{sect:badness} + +The {\em badness} of an entity (channel, MTA or message) is a value +used to compare the state of one entity with that of another. +This comparison is used throughout the MTA console to order the +displayed lists of entities, to choose which colour to display that +entity in, and so on. + +The badness of an entity is calculated from the sum of up to four +factors. +\begin{describe} +\item [\verb+number+:] The number of messages on an entity. +\item [\verb+volume+:] The volume of messages on an entity. +\item [\verb+age+:] For channel and MTA entities, this is the oldest +message on the entity. +For message entities, this factor is the age of the message itself. +\item [\verb+last+:] The last successful attempt on an entity. +\end{describe} + +Each factor has a specific upperbound and these upperbounds are +tailorable (this is described below). +In the badness summation, the factors are expressed in terms of +percentages of their respective upperbounds. +So if the upper bound on the number factor is represented as {\em +ub\_number} and similarly for the other factors then the badness +summation would be calculated as follows: +\begin{math} +(number/ub\_number)*100 + (volume/ub\_volume)*100 + (age/ub\_age)*100 ++ (last/ub\_last)*100 +\end{math}, +or, put more concisely, \(\sum^{factors}(factor/ub\_factor)*100\). + +\subsubsection {Tailoring of Upperbounds} + +When the console connects to a queue, it builds a database of +tailoring entries. +It can get the information for the database from any of three sources. +The file specified in the connect popup, the hardwired defaults and +the X defaults. +Entries in the file override equivalent entries in the defaults. +The file specified in the connect popup should be relative either to +the current directory, a full path name, or the home directory. + +An entry in this database has the form: +\begin{quote}\small\begin{verbatim} + ":" +\end{verbatim}\end{quote} + +The \verb+key+ is a tuple indicating which channel, or type of channel and +which type of entity on that channel the tailoring information in the +value relates to. +The channel or channel type and the entity are separated a~``\verb+-+''. +The entity must be one of: +\begin{quote}\small\begin{verbatim} +chan +mta +msg +\end{verbatim}\end{quote} +If the tailoring information is related to a specific channel, then +the channel's name must be before the~\verb+-+. +For example, if ``822local,'' ``x400in84,'' and ``p2explode'' are all +names of channels, then the following are valid keys that can be used +in the database: ``822local-chan,'' ``x400in84-mta,'' and +``p2explode-msg''. + +If the tailoring information is related to a type of channel then the +type of the channel appears before the~\verb+-+. +The type of a channel is constructed from the \verb+type+ of that channel +given in the \file{tailor} file and the \verb+access+ of that channel also in +the \file{tailor} file. +Table~\ref{tab:consolemapping} gives all the types of channels that can +be used in keys and how they are constructed. +Some +valid keys of this form are ``mtaboth-chan'', ``passive-msg'', +``internal-msg.'' + +When the console searches through the database, it searches first for +keys with the specific channel name in them (i.e., ``channelname-entity''). +If this fails, it searches for keys with the channel type in them +(i.e., ``channeltype-entity''). +This second search will never fail as there are default entries for all possible +channel types. + +\tagtable{console_mapping}{Tailor File Entries to Console Keys.}{tab:consolemapping} + +The \verb+value+ is a comma-separated list of expressions. +These expressions are of the form \verb+keyword /tmp/foo +info 822 >> /tmp/foo +list >> /tmp/foo +\end{verbatim}\end{quote} +The \verb+>+ symbol represents the overwrite operation, and the +\verb+>>+ symbol represents the append operation. + +\section{Lconsole} +The \pgm{lconsole} command is an alternative line based console. Both +versions of the line console will probably not be distributed in +future. This version may well be the default version if its +functionality is enhanced. + +The \pgm{lconsole} provides basic access to the qmgr. It allows all +the operations that may be achieved with the X based console, but does +not have such good facilities for displaying the data. It has a number +of commands that map onto the qmgr protocol. It may be run in +authorised or unauthorised mode. + +There are a few command line flags: +\begin{describe} +\item[\verb|-Q name|:] Contact the given QMGR. +\item[\verb|-u user|:] Use the given name to authenticate. A password +will be prompted for if not given. +\item[\verb|-p passwd|:] Connect with the given password. Use with +care! +\item[\verb|-b|:] Run in batch mode, little prompting is given in this +mode. +\end{describe} + +Additonal arguments on the command line, are taken as commands to +execute. This allows the the possibility of shell scripts top access +the queue status. + +All comamnds may be abbreviated to any unique string. The +\pgm{lconsole} has the following commands: +\begin{describe} +\item[\verb|channel|:] This command lists out all the channels with +their number of messages and reports by default. Normal channels are +printed as \verb|channel:msgs+reports|. Active channels have the +\verb|:| replaced by a \verb|*|. Channels that are disabled have the +\verb|:| replaced by \verb|!|. It an argument is given, then this is +taken as a regular expression to match a channel. Any channel matched +has its full details printed. + +\item[\verb|clear|:] This command clears a delay. The second argument +is one of the following: +\begin{describe} +\item[\verb|channel|:] The next argument is a channel from which +to remove the delay. +\item[\verb|mta|:] The next two arguments are a channel and an mta +from which the delay is removed. +\item[\verb|message|:] The next argument is a queue ID, followed by a +list of recipients numbers. For each recipient of the message, the +delay is removed. +\end{describe} + +\item[\verb|close|:] Close the connection to the QMGR. + +\item[\verb|decrease|:] Decrease the number of runnable channels. + +\item[\verb|delay|:] Set a specified delay for a given channel. +The second argument is one of: +\begin{describe} +\item[\verb|channel|:] The next argument is a channel followed by a +delay given in the same syntax as the \verb|MTAconsole|. +\item[\verb|mta|:] The next two arguments are a channel and an mta +follwed again by a delay specification. +\item[\verb|message|:] The next argument is a queue ID, followed by a +a delay time and then a list of recipients numbers. For each recipient +of the message, the delay is set. +\end{describe} + +\item[\verb|disable|:] This command disables a channel, mta or +message. The syntax is identical to the \verb|clear| command. +Additionally though, two other keys are recognised. \verb|disable all| +will disable all channels. \verb|disable submission| will disable +submission requests. + +\item[\verb|enable|:] This command is identical in syntax to +\verb|disable|, but with oppostire effect. + +\item[\verb|help|:] With no arguments, this lists out a list of valid +commands. With an argument, a one line summary of the specified +command is given. An argument of \verb|?| gives a one line summary of +all commands. + +\item[\verb|increase|:] Increase the number of runnable channels. + +\item[\verb|msg|:] Give details about a messages queued on a +channel/mta pair. The first argument is the channel (which may be a +regular expression), the second an MTA. An optional third argument +will print out full details on message queue id's matching that regular +expression. + +\item[\verb|mta|:] Display information about mtas associated with a +given channel. An optional second argument is a regular expression +which allows more detailed information about matching mta names. + +\item[\verb|open|:] Make a connection to a QMGR. The optional second +argument is the user to bind as. A password will be prompted for if a +user is given. + +\item[\verb|quit|:] Close any outstanding connections, and exit the +process. + +\item[\verb|rereadqueue|:] Forces the QMGR to initiate a re-read of +the queue on disk. + +\item[\verb|restart|:] Restarts the QMGR. + +\item[\verb|show|:] This allows messages matching certain criteria to +be displayed. The expression is of type key=value. The key may be any +unique abbreviation of the following: + +\[\begin{tabular}{| l | p{.6\textwidth}} +\hline + \multicolumn{1}{|c|}{\bf Key}& + \multicolumn{1}{|c|}{\bf Value}\\ +\hline + \tt channel & The channel the message is queued on.\\ + \tt contenttype & The content type of the message. \\ + \tt earlierthan & Messages older than this time.\\ + \tt eits & A list of encoded information types.\\ + \tt maxsize & The size of the message.\\ + \tt morerecentthan & Messages younger than this date. \\ + \tt mpduidentifier & The MPDU id of the message.\\ + \tt mta & The next hop MTA.\\ + \tt originator & The originator of the message.\\ + \tt priority & The priority of the message.\\ + \tt queueid & The queueid of the message.\\ + \tt recipient & The recipient of the message.\\ + \tt uacontentid & The UA content ID field.\\ +\hline +\end{tabular}\] + +\item[\verb|shutdown|:] Shuts down the QMGR. If an argument of +\verb|abort| is given then the QMGR is aborted and shuts down +immediately. + +\item[\verb|source|:] Read in a file containing a list of commands and +execute them. + +\item[\verb|status|:] Show the current status of the QMGR. + +\end{describe} + +Some of the commands will not be allowed if the user has not bound in +authorised mode. + +\section {Checkup Procedures} + +Additional procedures exist for querying the queue directly about the +status of the system. However, their prime importance is as development +tools; the consoles should be the main source of information for the system +administrator. + +\subsection {ckchan} + +The \pgm{ckchan} tool prints out information on the state of +currently active channels and is invoked as follows: + +\begin{quote}\small\begin{verbatim} +ckchan [-v] [-s] ... +\end{verbatim}\end{quote} +\pgm{ckchan} prints out information on the specified channels. +If no channels are specified, \pgm{ckchan} prints out information on +all the channels currently active. + +The presence of the \verb+-v+ flag on the command line instructs +\pgm{ckchan} to output a verbose form of information. + +If given a \verb|-s| flag, the program only shows a summary of the +information. + +Warning: on even a moderately-sized queue, this process runs fairly +slowly. + +\subsection {ckconfig}\label{sect:ckconfig} + +The \pgm{ckconfig} tool performs various checks on the +configuration of PP including confirmation that: +\begin{itemize} +\item All the required directories are in place and have appropriate +permissions. + +\item All the channels and filters described in the +\file{tailor} file reference programs in the appropriate directory +(\file{chndfldir}). + +\item All the tables described in the \file{tailor} file reference +files in the appropriate directory (\file{tbldir}). +\end{itemize} + +By default \pgm{ckconfig} will prompt for +correction of any configuration errors it identifies. + +\pgm{ckconfig}'s behaviour can be altered by the following command +line flags: +\begin{description} +\item[\verb+-f+:] ({\em force}) \pgm{ckconfig} will attempt +to automatically correct configuration errors. +\item[\verb+-v+:] ({\em verbose}) \pgm{ckconfig} will +display correct configuration information as well as displaying +configuration errors. +\item[\verb+-n+:] ({\em no execution}) \pgm{ckconfig} will perform all +its checks and report back the results. +No automatic correction will take place and the user will not be prompted +for corrections. + +\end{description} + +It is worth running this program at intervals and after every change +you make to PP. + +\subsection{Checking of Addresses} + +It is sometimes useful to check out addresses with and without the +whole system being invoked. To this end two utilities are provided. + +\subsubsection{Ckadr} + +PP provides a tool, \pgm{ckadr}, to check whether an address is +acceptable to the mail system. +Note that this tool does not do any of the PP authorization checks, +so an address may be acceptable to \pgm{ckadr}, but PP may still +refuse it due to authorisation criteria. + +If the address is acceptable, \pgm{ckadr} will display how the +address was parsed and how PP will deliver to this address. +For example: +\begin{quote}\small\begin{verbatim} +pac +Address parsing succeeded +pac -> (rfc822) p.cowen@cs.nott.ac.uk + -> (x400) + /I=p/S=cowen/OU=CS/O=NOTT/PRMD=UK.AC/ADMD=GOLD 400/C=GB/ +Delivered to sheriff.cs.nott.ac.uk by 822-local +\end{verbatim}\end{quote} + +If the address is not acceptable, \pgm{ckadr} will display how far +it got in the parse of the address and why it failed to find the +address acceptable. +For example: +\begin{quote}\small\begin{verbatim} +/S=foo/OU=CS/O=NOTT/PRMD=HOL/ADMD=GOLD 400/C=GB/ +Address parsing failed +Reason : Unknown PRMD HOL +Parsing gave this: +/S=foo/OU=CS/O=NOTT/PRMD=HOL/ADMD=GOLD 400/C=GB/ -> + (rfc822) foo@CS.NOTT.HOL.gold-400.gb +/S=foo/OU=CS/O=NOTT/PRMD=HOL/ADMD=GOLD 400/C=GB/ -> + (x400) /S=foo/OU=CS/O=NOTT/PRMD=HOL/ADMD=GOLD 400/C=GB/ +\end{verbatim}\end{quote} + +If \pgm{ckadr} is invoked with command line arguments (other than its +own command line flags), it will +attempt to parse these arguments as addresses. +Note that if any of the addresses have whitespace in them, they should +be quoted to avoid being split up into separate arguments. + +If \pgm{ckadr} is invoked with no command line arguments, it will +read from the standard input until the end of that input. +Each line of input is parsed as though it were an address. + +The behaviour of \pgm{ckadr} can be modified with the following +switches: +\begin{describe} +\item[\verb|-i inboundChan|] Sets all addressing characteristics based +on the inbound channel specified. +\item[\verb|-r|:] Treat all addresses as 822 format addresses. +This is the default behaviour. +\item[\verb|-x|:] Treat all addresses as X.400 format addresses. + +Note in most cases, \pgm{ckadr} will correctly parse an X.400 address +even if you say it is an 822 address and vice versa. +However there are some cases where this is not so, therefore be +careful when using \pgm{ckadr} and different formats of addresses. + +\item[\verb|-n|:] Check the address without expanding aliases. +\item[\verb|-p|:] Check the address and allow parsing of percent +symbols in the route. +\item[\verb|-a|:] Normalise all domains. +\item[\verb|-l|:] Normalise domains with the USA ordering +(\verb|l|ittlendian) preferred. +\item[\verb|-b|:] Normalise domains with the UK ordering +(\verb|b|igendian) preferred. +\item[\verb|-0|:] recognise USA domain ordering \pgm{only}. +\item[\verb|-1|:] prefer USA domain ordering. +\item[\verb|-2|:] recognise UK domain ordering \pgm{only}. +\item[\verb|-3|:] prefer UK domain ordering. + +The above values relate to the numerical values used +internally to specify which domain ordering to use. +By default, \pgm{ckadr} will recogise USA domain ordering ONLY. + +\end{describe} + +\subsubsection{Probes} +PP provides a tool, \pgm{probe}, which checks whether or not a +message would be acceptable either locally or to a remote mail system. + +A message probe attempts to transit the message transfer system +network to its destination. On arrival at its destination or at a +place where it can no longer be delivered (either because of errors or +because a gateway through which the network beyond does not support +probes is reached) a delivery report will always be returned. No +message is ever delivered to a recipient as a result of a message +probe. + +The returned delivery report informs of the future successful or +unsuccessful delivery of a message, having the same parameters as +those specified within the previously generated message probe. + +Within PP, the delivery report can be generated at either the remote +end or locally. The exact location of the generation will depend on +how the channels are specified within the PP \file{tailor} file. + +If an outbound channel supports message probes, then it should have +\begin{quote}\small\begin{verbatim} +probe=y +\end{verbatim}\end{quote} +specified as one of its parameters in the +\file{tailor} file. If this parameter is not specified than the +default +\begin{quote}\small\begin{verbatim} +probe=n +\end{verbatim}\end{quote} +is taken. If \verb|probe=y| is set against any +outbound channel, then the delivery reports are generated remotely +for any message probes outbound through that channel. +It is assumed that the remote sites, reached +via that outbound channel, will reply to the message probes. +If, however, the parameter is set to \verb|probe=n|, then the +delivery reports will be generated locally, and this fact is +recorded within the delivery report. + +Note that the information within a delivery report could sometimes +prove erroneous. For example, a remote recipient name (e.g James.Hacker) +in an X.400 address needs clarifying, but the outbound channel +associated with that recipient is set to \verb|probe=n|. If the X.400 +address is parsed correctly, then a successful delivery report is +generated locally, regardless of whether or not the name of the +recipient (e.g James.Hacker) is a valid one at the remote end. Thus +it is necessary that the probe parameters are set correctly in the +\file{tailor} file for \pgm{probe} to work correctly. + +Note also, that only the X.400 channels support message probes, +so any probing done of a non-X.400 site would have the delivery report +generated by a gateway. Thus an X.400 remote user probing a recipient at +a non-X.400 site, reachable via the local PP mail system, would have +a PP generated delivery report. Once again the information +within the delivery report could prove erroneous, if the remote +recipient's address is parsed correctly but the recipient name +is invalid. + +{\em Therefore for message probes to work absolutely correctly, +probing must be carried out between X.400 sites only.} + +The \pgm{probe} message generation program can be called in 2 ways: + +\begin{itemize} +\item With command line arguments. It will attempt to +parse the specified arguments before generating a message probe. + +\item Without command arguments. It will prompt on +standard output and read on standard input until all the information +has been received, before generating a message probe. +\end{itemize} + +With the following options: + +\begin{itemize} +\item[\verb|-t|:] Interprets the remaining arguments up to the next switch as +``To:'' Recipients. +\item[\verb|-s|:] Specifies the size (in bytes) of the future message. +\item[\verb|-e|:] Specifies one or more body part types within +the future message. The list of types should be separated +by a ``,''. +\item[\verb|-u|:] Specifies a user agent identifier. This should be a +maximum of 16 characters. +\item[\verb|-i|:] Requests implicit conversion. +\item[\verb|-a|:] Allows alternate recipients. +\end{itemize} + +\section {Dealing with Errors} + +To identify reasons for failure, it is necessary first to figure out +which program is failing. This is not always easy as there are many +programs involved in PP and at any one time, several of them may be +interacting. + +For a message submission that fails, it is rarely the inbound channel +that is the problem, though obviously this can be the case sometimes. +Most likely is that there is a problem in \pgm{submit}, so examining +the \pgm{submit} log is likely to be a good starting point. It is +also rare (but not unknown) that the problem is a bug in \pgm{submit}. The +most likely causes initially are that you have one of the following +wrong: +\begin{itemize} +\item The \file{tailor} file has things specified incorrectly. Most of the +common problems here are missing formatters, badly specified channels, +and missing directories. The \pgm{ckconfig} will help solve some of these. + +\item Another very likely cause is that the tables are wrong. This +can be checked to a degree by use of the \pgm{ckadr} program. This +allows addresses to be entered and the tables interrogated to determine +the actions for that address. If you alter the tables, do not forget to +run \pgm{dbmbuild} or else change the relevant table to linear mode. + +\item Worth checking, although less likely, is whether \pgm{submit} is installed +properly with the correct setuid bit on (it should be mode 4755 or similar). +\end{itemize} + +On outgoing channels, it is more likely either an error in one of the +channels, a queue file that is incorrect, or an inconsistency between +the QMGR and the queue on disc. + +If the QMGR is running but not delivering anything, check to +ensure the following: +\begin{itemize} +\item That the channels in question are enabled (check this via the MTA +\pgm{console} program). +\item That the \pgm{pptsapd} is running. +\item That the channel programs exist in the right place, with the +right modes (\pgm{ckconfig} will check most of these). +\end{itemize} +Remember, if you add channels or tables to the \file{tailor} file, +then you will need to restart both the QMGR and the +\pgm{pptsapd} programs. + + +If you wish to monitor the progress of the PP system through the logs +in a dynamic way, it may be worth using the \pgm{ntail} program +supplied in the \file{tools} directory. This program is much like +running the UNIX \man tail (1) command with the \verb|-f| flag on +several files at once. + +\section {Managing Tables} + +As described in Section~\ref{sect:tables}, there are a number of tables +that PP requires. For a site of any size, the generation of these +tables is likely to be substantially automated. Manual generation will +probably only be used by very small sites. +Local tables, such as \file{aliases}, \file{users}, \file{local channel}, +\file {list channel} or \file{authorisation} files +will come from local sources. The system manager +will be able to generate these easily. In the longer term, support for +local information by use of the OSI Directory is to be expected. + +For now, the tables needed for X.400 routing (the \file{or} table and X.400 +channel tables) must be manually generated. This is an indication of the +immaturity of this technology. + +\subsubsection {RFC 1148 Mapping Tables} + +RFC 1148 mappings should be global. Therefore, it is desirable to use +standard tables as far as possible. Two approaches are possible: + +\begin {enumerate} +\item UCL (and later the UK Gateway service at ULCC) will maintain and make +available RFC~1148 tables in PP format. FTAM will probably be the preferred +mode of access. + +\item There are scripts to take the RARE WG1 format tables and +generate PP format tables from these. The ambiguous and dubious +mappings are avoided by the simple expedient of ignoring all mappings +which relate to a single domain component. +\end {enumerate} + +The first method is preferred, until the RARE tables are updated at a +realistic interval (preferably on a continuous basis, which can be pulled +each day). + +\subsubsection {Domain and Channel Tables} + +There are some support tools to help generate +the \file{channel} and +\file{domain} tables, for domain-based information. +Note that the \file{channel} table is used for both X.400 and domain bindings. + +For \file{domain} and \file{channel} tables, it is important to understand the use +of these when defining mechanisms to build them. +The steps that +are taken for resolving a domain address are as follows: +\begin{enumerate} +\item Look up the domain of the address in the \file{domain} table. +Note: +\begin {itemize} +\item Domains are in US order. +\item There is a qualification on whether a given domain matches a +specific entry. This qualification is based on the number of +subdomains permitted for that entry. +\end {itemize} + +\item Look up the domain name derived from the domain table in +channel table. The RHS of +the channel table gives a list of host/MTA pairs which may be used. +If the MTA is null, the originally specified MTA will be used. +\end{enumerate} + + +Two basic strategies for generating these tables are described. + +\begin {describe} +\item[Internet:] This assumes that SMTP is used, in the context of domain +nameservers. The tables are used to identify a part of the domain tree +which will be passed to the SMTP channel. Use of DNS is confined to this +channel. + +\item[NRS:] Here, UK NRS tables are used to point valid NRS domains at JNT +Mail channels. +\end {describe} + +Simple sites will be able to use one of these strategies directly. More +complex sites will need to add additional information. + +\subsubsection{Generation of the domain table}\label{tablebuild:domain} + +When building a domain table, it is useful to start by building a variant +which only has entries for fully qualified domain names and the +partial domain names that are known. +The \pgm{abbrev} tool can be used to create the required +entries for abbreviated forms of domain names. + +The domain table is compiled from one or more sources: + +\begin{describe} +\item[Local Name:] +Your own domain name, and alternates are needed. For example: + +\begin{quote}\small\begin{verbatim} +cambridge.ac.uk:mta +cam.ac.uk:norm+mta=cambridge.ac.uk +\end{verbatim}\end{quote} + + +\item[NRS data:] +The NRS data can be converted directly into the PP domain format by +use of the \pgm{c-nrs} program\footnote{ To obtain a copy of this, +contact Piete Brooks at Cambridge Computer Laboratory (pb@cl.cam.ac.uk)}. +The file \file{pp.dmn} created by this program should then be +concatenated with the other generated domain data before being +processed by the \pgm{abbrev} tool. + +\item[Internet:] +A list of top level domains which you wish to be passed to the SMTP/DNS +channels should be given. For example: + +\begin{quote}\small\begin{verbatim} +*.edu:mta=edu +*.gov:mta=gov +*.com:mta +*.mil:mta +\end{verbatim}\end{quote} + +Note that to match with partial entries prefixed by \verb+*.+, unless +altered by the \verb+min+ key, there must be at least one subdomain. +Thus preventing \verb+edu+, +\verb+gov+, \verb+com+ and \verb+mil+ being recognised as valid +domains by themselves. + +\item[Other known domains:] +Other known domains (e.g., those associated with local UUCP links) +should be added in. For example: + +\begin{quote}\small\begin{verbatim} +iconet.uucp:mta +inset.uucp:mta +\end{verbatim}\end{quote} + +\end{describe} + +Once all the data has been collected, including all your local hosts +and domains, it should be passed through the \pgm{abbrev} program. +This arranges for all reasonable abbreviations of domains to be added. +An example input might be the following: + +\begin{quote}\small\begin{verbatim} +cs.nott.ac.uk:mta +cs.ucl.ac.uk:mta +stc.co.uk:mta +widget.uucp:mta +\end{verbatim}\end{quote} + +The syntax of the \pgm{abbrev} command is \verb|abbrev domainname...| and +it reads from the standard input and writes to the standard output. +One domain name should be the fully formed local domain. Other arguments +can be used to generate abbreviations for other domains. +When given the above as input and the command + +\begin{quote}\small\begin{verbatim} +abbrev cs.nott.ac.uk uucp +\end{verbatim}\end{quote} + +the output produced is + +\begin{quote}\small\begin{verbatim} +cs.nott.ac.uk:mta +cs.nott.ac:norm+mta=cs.nott.ac.uk +cs.nott:norm+mta=cs.nott.ac.uk +cs:norm+mta=cs.nott.ac.uk +cs.ucl.ac.uk:mta +cs.ucl.ac:norm+mta=cs.ucl.ac.uk +cs.ucl:norm+mta=cs.ucl.ac.uk +stc.co.uk:mta +stc.co:norm+mta=stc.co.uk +widget.uucp:mta +widget:norm+mta=widget.uucp +\end{verbatim}\end{quote} + +\subsubsection {Generation of the Channel Table}\label{tablebuild:channel} + +The channel table is also generated in two stages. The input is as follows. + +\begin{describe} +\item [Local domain:] +This is not needed. + +\item[NRS data:] The file \file{pp.chan} generated by the \pgm{c-nrs} +program is used directly. + +\item[Internet:] +The list of valid domains is given, with the channel indicated. +For example: + +\begin{quote}\small\begin{verbatim} +edu:(smtp) +gov:(smtp) +com:(smtp) +mil:(smtp) +\end{verbatim}\end{quote} + +\item [Private links:] +These should be added manually. For example: +\begin{quote}\small\begin{verbatim} +widget.uucp:widget.uucp(uucp) +\end{verbatim}\end{quote} +Note that the key ``widget.uucp'' must be the same on each side of the table. + +\item [Application relays:] +Known domains, reached indirectly, can be added. +For example: + +\begin{quote}\small\begin{verbatim} +foobar.uucp:widget.uucp() +\end{verbatim}\end{quote} + +This says that foobar.uucp is reached indirectly through widget.uucp. +\end{describe} + + +In the second stage, the program \pgm{tjoin} is run to collate and +reformat these input data into their final form. This stage is +essential if the input contains application or top-level relays, and +performs the following functions: + +\begin {itemize} +\item ``Unrolling'' application relays, so that the installed tables specify +the correct first hop. + +\item Where an MTA can be reached by multiple channels, sorting these into +the preferred order. A direct connection will always be preferred to an +application relay. +\end {itemize} + +\pgm{Tjoin} input allows the following syntaxes: +\begin{describe} +\item[mta:mta(channel):] Specifies to contact \verb|mta|, call +\verb|mta| using channel \verb|channel|. Both \verb|mta| parameters +should be the same +\item[mta:mta1():] To contact \verb|mta|, call \verb|mta1| using +the channel associated with \verb|mta1| which should be specified +elsewhere in the \file{channel} table. +This is the application relay format. +\item[mta:(channel):] To contact \verb|mta| call \verb|mta| using +channel \verb|channel|. This form is appropriate for domain nameservers. + +\end{describe} + +An example of the functions that \pgm{tjoin} does is shown here. +The input of +\begin{quote}\small\begin{verbatim} +stc.co.uk:(smtp) +uucp:uucphost.stl.stc.co.uk() +ac.uk:psshost.stl.stc.co.uk() +win.icl.stc.co.uk:erbert.uucp() +erbert.uucp:erbert.uucp(uucp) +psshost.stl.stc.co.uk:psshost.stl.stc.co.uk(smtp) +uucphost.stl.stc.co.uk:uucphost.stl.stc.co.uk(smtp) +\end{verbatim}\end{quote} + +would give as final output the table: + +\begin{quote}\small\begin{verbatim} +ac.uk:psshost.stl.stc.co.uk(smtp) +erbert.uucp:erbert.uucp(uucp) +psshost.stl.stc.co.uk:psshost.stl.stc.co.uk(smtp) +stc.co.uk:(smtp) +uucp:uucphost.stl.stc.co.uk(smtp) +uucphost.stl.stc.co.uk:uucphost.stl.stc.co.uk(smtp) +win.icl.stc.co.uk:erbert.uucp(uucp) +\end{verbatim}\end{quote} + +\section {Adding New Users and MTAs} + +To add new users to the tables is best done in an automated way, +generating the list from some master table perhaps or a system +database. + +To add a user, for example ``J.Soap'' with login id ``joe'' using +the local channel, the following is required: +\begin{enumerate} +\item Add an entry to the \file{alias} table to map ``joe'' into +``J.Soap.'' +\begin{quote}\small\begin{verbatim} +joe:synonym J.Soap +\end{verbatim}\end{quote} +This step is not required if you do not want to refer to +Joe other than by the UNIX login id. + +\item Add an entry to the \file{users} table to specify which +channel to deliver Joe's mail by. +\begin{quote}\small\begin{verbatim} +J.Soap:822-local +\end{verbatim}\end{quote} +If you run a number of MTAs locally, then add the machine name after +the channel. + +\item Add an entry to the local channel table to give the delivery details. +\begin{quote}\small\begin{verbatim} +J.Soap:joe +\end{verbatim}\end{quote} +Optionally add the home directory and the mailbox if required. + +\item To make the changes have immediate effect, run \pgm{dbmbuild}. +It is not necessary to restart any of the daemon programs. +\end{enumerate} + +\section {Adding Filters, Shapers + EITs}\index{tailoring, filters} + +\subsection{Adding A New Encoded Information Type} + +If you wish to add a new encoded information type, then some editing +of the \file{tailor} file is necessary. + +Suppose we wish to add a new body type ``binary'' which we want to be +able to submit and have converted to \verb|ia5| before transmission. + +\begin{enumerate} +\item Add a new body type to the list of body types in the +\file{tailor} file. +\begin{quote}\small\begin{verbatim} +bodypart binary +\end{verbatim}\end{quote} + +\item Now specify which outbound channels can handle such a body +part by adding this type to the \verb|bptout| list +associated with the channel. If no outbound channel will be delivering +this type then this step is unecessary. This is the case for \verb|binary|. + +\item To allow \pgm{submit} to work out how to convert from +\verb|binary| to \verb|ia5| it is necessary to add a new reformatting +channel, such as the following: +\begin{quote}\small\begin{verbatim} +chan bin2ia5 prog=fcontrol, type=shaper, bptin=binary, + bptout=ia5, outinfo="uuencode binary", + show="Binary -> Text" +\end{verbatim}\end{quote} +This specifies that to convert input bodypart type \verb|binary|, to output +body type \verb|ia5| the channel \pgm{fcontrol} should run the process +\verb|uuencode program| with standard input from the \verb|binary| body part +and standard output into the \verb|ia5| body part. + +In practise, it might be better not to call \pgm{uuencode} directly, +but wrap it up in a shell script; we could then print out some +preliminary remarks instructing the recipient how to unwrap the +binary part. + +\end{enumerate} +Now, when \pgm{submit} receives a message which has flagged that it +contains a body part of \verb|binary|, it will be able to convert that +part into \verb|ia5|, which most output channels can deal with. + +\subsection{Adding a New Content Type} +Adding a new content type for PP to relay is similar in style to +adding a new encoded information type. The steps that need to be taken +are dependent on whether conversion is involved or not. + +If no conversion is involved, then to add a new content type such as +\linebreak +\verb|p22-encrypted|, for instance, would simply consist of registering +that content type with an outbound channel. This is done by adding a +new channel with the +\linebreak +\verb|content-out| part set to +\verb|p22-encrypted|. In this case, \pgm{submit} will pass the message +straight through, unaltered, providing the recipient is reachable via +that channel. + +If conversion is required, then two things are necessary. The first is +to add a new unflattening channel which is capable of splitting the +message into component parts. Secondly, the component parts must be +able to be reformatted into whatever is required on the outbound channel. + +For example, suppose we have a new message content called +``whizbang''. This consists of a ``whizbang'' specific header and a +standard \verb|ia5| body part. To allow the type of mail to be input, +the following would be required. +\begin{itemize} +\item An exploder channel that can split up ``whizbang'' format mail +into its components. +\begin{quote}\small\begin{verbatim} +chan WBexplode prog=WBexplode,type=shaper, + content-in=whizbang, +\end{verbatim}\end{quote} +This channel is defined to split up the message into two +components, a file \verb|hdr.wb| and a body part \verb|1.ia5|. + +\item The new encoded information type \verb|hdr.wb| needs to be +registered in the tailor file +\begin{quote}\small\begin{verbatim} +headertype wb +\end{verbatim}\end{quote} + +\item The \verb|ia5| body part is okay as it stands, but to relay the +message to X.400 or RFC-822 the header will need converting, therefore +a filter to convert \verb|hdr.wb| into either \verb|hdr.822| or +\verb|hdr.p2| will be necessary. Only one need be written, because if +\pgm{submit} has a \verb|hdr.822| it can convert it to a \verb|hdr.p2| +using the \pgm{822top2} channel. Such a channel definition might look +like this: +\begin{quote}\small\begin{verbatim} +chan wbhdr-2-822 prog=wbto822,type=shaper,hdrin=wb, + hdrout=822, + show="WhizBang to 822 Header converter" +\end{verbatim}\end{quote} +\end{itemize} + +\section {The Day--to--Day Running of PP} + +\subsection {How to Start Up the PP System} + +Each time the UNIX machine is started up, the \file{rc.local} script +in your UNIX system is executed. An entry for PP should be placed in +\file{rc.local}. This entry should refer to a script which starts up +various programs related to the running of PP. Typically this script +is similar to \pgm {pp.start} (see appendix~\ref{app:pp.start}) which +starts up: +\begin{itemize} +\item QMGR: The queue manager which runs as the PP userID. +\item \pgm{pptsapd}: The PP TSAP Daemon which also runs as the PP userID. +\item \pgm{smtpsrvr} (optional): The SMTP listener which runs as the +superuser. This is only necessary if: + \begin{enumerate} + \item You are using the SMTP protocol. + \item You are not running SMTP from \pgm{inetd} (see + Section~\ref{sect:smtp} on page~\pageref{sect:smtp} + for details of this). + \end{enumerate} +\item \pgm{tsapd} (optional): is necessary if you are expecting +incoming X.400 messages. This is assumed to be part of the general +ISODE configuration; see +\linebreak +\man isode-gen (8) for details. +\end{itemize} + +Normally, these programs will run without interruption unless something +serious happens, such as the machine going down. But if necessary you +can always stop them by using the UNIX \pgm{kill} command. +You can restart them by running the script manually or by invoking +the programs separately, then letting them run in the background. + +\subsection {What to Run Each Night} + +In addition to running \pgm{pp.start} whenever the machine starts up, +there are other things you should run regularly, ideally each night. + +For example, if you build the PP tables from other sources, such as +the NRS database, local system databases or other external sources, +then running \pgm{dbmbuild} each night is a useful thing to do. + +All the nightly routines can be run from a shell script, +conventionally named something along the lines of \file{pp.night} (see +appendix~\ref{app:pp.nightly} for an example). + +The sequence of operations should be : +\begin{itemize} + \item Archive the day's logs and remove outdated logs (see + Section~\ref{sect:logs} on + \linebreak page~\pageref{sect:logs}). + \item Collect statistics. + \item Import new table source data files if necessary. + \item Build new tables. + \item \pgm{dbmbuild}. +\end{itemize} + +\subsection {Saving Logs}\label{sect:logs} + +Saving logs depends very much on the individual policies for each +site. For many cases the logs can just be set to truncate themselves +when a suitable size is reached. Alternatively, if you are more +concerned about keeping the information you should backup the logs +each night. Two important exceptions to these general rules above are +the \file{oper} log and the \file{stat} log. + +The \file{oper} log should under normal conditions be empty, or at +least very small. For this reason it is worth checking this overnight +and perhaps mailing it to the postmaster if it contains anything. + +The \file{stat} log can be processed to show statistics. There is a +program in the \file{tools} directory call \pgm{statp}. This program +processes the \file{stat} log file into a more structured format that +is suitable for processing with \man awk (1). A sample awk script is +supplied which shows the sort of output that can be produced from +this. + +\section {Examining the PP Queue} + +Occasionally there may be problems encountered by PP that cannot be +resolved by normal means, and it will be necessary to look at the +queue directory to find out what is going wrong. This section is a +brief guide to this. + +The PP Queue is stored under one directory, the \file{quedir} directory. +An item in the queue is contained within a subdirectory of \file{quedir} +with a unique name. +This subdirectory may contain the following: +\begin{describe} +\item[\verb|\file{addr}|:] a text encoded file containing information +corresponding approximately to P1 functionality. +\item[\verb|\file{base}|:] a directory which +contains the message as it arrived. +\item[\verb|\file{filter.number}:|] other directories +which contain transformed versions of the message content. +\item[\verb|\file{report.number}:|] files containing text +encoded delivery reports associated with the message. +\end{describe} +Of these components only the \file{addr} file must be present. + +Each message content is a (possibly degenerate) directory tree. This +hierarchy represents the structure of a message, with each body part being +represented by a single file. Subdirectories represent forwarded IP +messages. This structure is to allow for straightforward transformation of +messages. When a message is converted, the body parts not affected are +linked, rather than being copied. + +An example queue file is shown in Figure~\ref{examp:qfile}. + +\tagrind[hbtp]{qfile}{Example of Address File}{examp:qfile} + +\subsection {Delivery Reports} + +The basic operation of a channel is discussed in Section \ref{chan-op} +on page \pageref{chan-op}. Delivery Reports are text encoded, using a +format similar to that used for text delivery. Reports are stored as +files in the message directory, with name \verb+report.+, where n +is the PP number for the lowest recipient to which the DR refers. +Where a DR refers to multiple recipients, all except the lowest are +marked to done in the queue, and the first is marked to dliv. + +An example text-encoded delivery report is shown in +Figure~\ref{examp:dr}. + +\tagrind[hbtp]{dreport}{Example Delivery Report Format}{examp:dr} + +\subsection {Receipt Notifications} + +These are handled by the UA, and are thus beyond the scope of PP. +Mappings to RFC~822 are done according to RFC~1148. diff --git a/doc/manual/volume1/mu.aux b/doc/manual/volume1/mu.aux new file mode 100644 index 0000000..24c3436 --- /dev/null +++ b/doc/manual/volume1/mu.aux @@ -0,0 +1,30 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {E}Testing PP --- the MTS User Interface}{149}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {E.1}Overview}{149}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {E.2}User Input}{151}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {E.1}{\ignorespaces Summary of MU flags}}{152}} +\newlabel{mu:flags}{{E.1}{152}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {E.3}MU Internals}{152}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {E.1}{\ignorespaces io\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em} Interface}}{153}} +\newlabel{musub}{{E.1}{153}} +\global\@namedef{cp@mu}{ +\setcounter{page}{154} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{5} +\setcounter{section}{3} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{1} +\setcounter{table}{1} +} diff --git a/doc/manual/volume1/mu.tex b/doc/manual/volume1/mu.tex new file mode 100644 index 0000000..ebc8756 --- /dev/null +++ b/doc/manual/volume1/mu.tex @@ -0,0 +1,223 @@ +\chapter{Testing PP --- the MTS User Interface} + +A special user interface known as \pgm{mu} is +provided as a general tool to help test +\pgm{submit} and consequent operations in PP. +Setting defaults in the \file{mu.defaults} file allows a minimum +number of message-specific parameters to be provided. +It may be used to resubmit a modified text-encoded file taken from +the queue. + +\section{Overview} + +The message submission tool MU takes input from the command +line, from a defaults file \file{mu.defaults} if present in the +working directory, and +otherwise from the default command directory \verb+cmddfldir+ and then +any other files specified with \verb+-file+ flags. A full summary of +the flags to MU is given in Table~\ref{mu:flags} on +page~\pageref{mu:flags}. Any command line option may be placed on a +line within an input file. MU calls its command line parser +recursively when it encounters a line starting with \verb+`-'+ +(flagchar). Any line starting with \verb+`#'+ (commentchar) is +ignored. Otherwise, all lines are offered to the various +\pgm{submit} input routines in turn for incorporation into PP's +internal message structures ({\em prm\_vars\/}, {\em Qstruct\/} and +{\em addr\/}). Any line which returns an error code (\verb+rp_isbad+) +from all these routines is assumed to be in error. + +The input lines which specify assignments as specified in queue (5) may +be received in any sequence, and inputs may override earlier entries. +Any value may also be assigned on the (original) command line with +\verb+-value v1 v2 +\ldots up to the next flag. + +If input files are nested, input lines from the nested file are +processed before the remainder of the file containing the \verb+-file+ +specifier. The default file is parsed first (\file{mu.defaults} +unless overridden with a \verb+-default+ flag on the command line), +then any \verb+-file+ specified files from the command line, finally +\verb+-value+ specifications from the command line. Body part files +may be specified with \verb+-body+ commands, either on the command +line or embedded as with other commands.\\ + +MU uses PP's standard logging: additional logging messages generated by +--0 --1 --2 --3 flags are output to a channel (\verb+muout+) which defaults to \verb+stdout+ +unless flag \verb+-logfile+ is specified. Note that output may be rerouted +in the course of processing input files. The flag --5 allows +these messages to be appended to the nominated logfile, rather than +replacing it. \\ + +In addition to the llog\_trace and llog\_debug calls associated +with flags \verb+-0+ and \verb+-1+ shown below, there are some other +llog\_fatal and llog\_exceptions calls. Note that functions \verb+list_args+ +and \verb+show_args+ (in \file{argh.c}) do not generate llog events. +MU accepts a number of debug flags \verb+-0+, \verb+-1+ etc.; +currently these are used as follows:\\[2ex] + +\begin{tabular}{cp{3.5in}} + + flag & function\\[1ex] + -0 & Log to {\em muout} progress messages, and pplog(llog\_trace ...).\\ + -1 & Log to {\em muout} command files as they are processed, and pplog(llog\_debug ...).\\ + -2 & List to {\em muout} body part files as they are io\_tdata'ed.\\ + -3 & List to {\em muout} structures prior to \pgm{submit} io\_ calls.\\ + -4 & Abort prior to \pgm{submit} io\_ calls.\\ + -5 & Append to logfile rather than overwrite.\\[1ex] +\end{tabular} + +MU accepts \verb+-body+ part file names with any arbitrarily long pathname. +The full path is used: + +\begin{tabular}{lp{4.0in}} + +1. &To open the file and check its length. Two fatal errors are detected :\\ + +& a. \verb+unable to read body part %s+.\\ +& b. \verb+body part %s is null file+.\\ + +2.& To open the file in order to pass its contents to \pgm{submit} + with a series of {\em io\_tdata(buf,length)} calls. Again, failure + to open is reported:\\ + +& \verb+unable to open body part for reading %s+.\\ + +3.& To pass a name for \pgm{submit} to use in the queue. + \pgm{submit} generates a message directory to match the + supplied pathname. Thus:\\ + +& \verb+-body 4.ipm/hdr.822uk+ --- generates :\\ +& usr/spool/pp/queues/msg.annnnnn/base/4.ipm/hdr.822uk\\ +\end{tabular} + +If a reserved character ``*'' (filemarkchar) is embedded in the +\verb+-body+ pathname, MU strips all characters up to and +including the ``*' from the pathname before passing to \pgm{submit}. +This allows MU to distinguish between the path used to find the +file(s) and that required within the message. Thus: + +\begin{quote}\small\begin{verbatim} +-body nest1/nest2/*3.ipm/1.ia5 +\end{verbatim}\end{quote} +generates: +\begin{quote}\small\begin{verbatim} +/usr/spool/pp/queues/msg.annnnnn/base/3.ipm/i.ia5 +\end{verbatim}\end{quote} + +The ``*'' is removed for purposes (1) and (2) above. The character `*' +may also be placed in the pathname to a directory to truncate the +pathname passed on to \pgm{submit} from a \verb+-tree+ command; in +the same way as for \verb+-body+ specification. + +Because the line parsing routines used in MU are exactly those +in \pgm{submit} itself, any values/options which are acceptable to +\pgm{submit} will also be accepted by MU (but in any +sequence ). + +To illustrate : +\begin{quote}\small\begin{verbatim} +mu -- -0 -file test1 -body b1 /tmp/jtaylor/messdir/*b2 \ + -default new.defaults -value MsgiD Country=US +\end{verbatim}\end{quote} + +will read from \verb+"new.defaults"+, (processing any ``\verb+-flag+'' +specifiers it contains ), then from file \verb+"test1"+ finally +setting a new country \verb+US+ to override any file-specified value. +The \verb+-0+ flag turns on progress messages and ``\verb+--+'' will list +the flag table. During submission, files \verb+"b1"+ and \verb+"b2"+ +will be transmitted individually. + +\section{User Input} + +The reserved character ``\verb+$+'' (TOKENCHAR) is used to indicate that +the user should input a value to replace the ``\verb+$+'', unless the +line is a comment line or the ``\verb+$+'' is immediately followed by a +second to escape a real \verb+$+ symbol. The portion of the input +line up to and including the ``\verb+$+'' is displayed on screen, then a +carriage return delimited string is input to replace the ``\verb+$+''. +The substituted line is scanned for further unpaired ``\verb+$+'' +characters. When all have been replaced, if the flag \verb+-confirm+ +has been specified, the user input will be re-displayed awaiting user +confirmation or cancellation with ``\verb+y+'' or ``\verb+n+''. The line +is then offered to the \pgm{submit} input routines. Any error will +cause the input portions to be re-prompted {\em unless\/} the flag +\verb+-nofix+ has been specified, in which case MU will ignore +the error and continue. + +To allow repeated user input, for example, of multiple recipient +lines, another reserved character ``\verb+*+'' (repeatchar) may be +placed at the start of a line to indicate repetition. If this +character appears at the start of a line which contains no unpaired +``\verb+$+'' characters, an error + +\begin{quote}\small\begin{verbatim} +error : no TOKENCHAR(s) in REPEAT line - REPEATCHAR ignored +\end{verbatim}\end{quote} + +is reported. Otherwise, user input takes place as before, terminated +by a null input (just a carriage return) on any substitution field +in the line. Repeat lines are stripped of the ``\verb+*+'' character +before passing to the \pgm{submit} input routines. + +An example command line: +\begin{quote}\small\begin{verbatim} +mu -confirm -file a1 -nofix +\end{verbatim}\end{quote} +where file \verb+a1+ contains: +\begin{quote}\small\begin{verbatim} +# Start-of-MsgEnvPrm +-body hdr.822 +-body 2.ia5 +# $$ implies $ +-file level$$ +Message-type User-Mpdu +# $ symbols in comments are ignored +Inbound-channel 822-local +Inbound-host UK.AC.UCL.CS +Content-type $ +Encoded-info EncTypes=iA5Text +Priority $ +PerMsg-Flags disclose-recipients +PerMsg-Flags return-contents +MsgId string $ +Start-of-MsgEnvAddr +*Recip type=822 orig=$@uk.ac.ucl.$ End-of-addr +\end{verbatim}\end{quote} + +will prompt for \verb+Content-type+, \verb+Priority+, \verb+MsgId +string+, and two components from \verb+Recip+ lines until a null +input. Each input line must be confirmed with ``\verb+y+'', but any +errors will be disregarded. Section delimiters such as +\verb+Start-of-MsgEnvAddr+ are redundant, since MU accepts +control lines in any order, but are benign. + +\tagtable{muflags}{Summary of MU flags}{mu:flags} + +\section{MU Internals} + +MU uses the argument handling routine \verb+argh+ and can +therefore accept any unambiguous prefix for a flag specifier. (See +separate document.) + +MU has no knowledge of the significance of any input line +other than that it is valid for {\em txt2prm\/}, {\em txt2q\/} or {\em +txt2adr\/}. The one exception to this is that, to allow a recipient +to be specified before the originator, each potential address line is +tested against \verb+"Origs."+ (Because the originator is held in a +separate structure from the recipient list, and {\em io\_wadr\/} needs +to have \verb+AD_ORIGINATOR+ or \verb+AD_RECIPIENT+ passed to it +explicitly.) Second and subsequent \verb+"Origs"+ lines are treated +as errors. + +After processing all inputs, a sequence of procedure calls to are made +to \pgm{submit} the message (as outlined in Part IX). Thus +(summarised) : +\tagrind[hbp]{musub}{io\_ Interface}{musub} + +Each procedure call returns a status in the error structure +\verb+RP_Buf+ which is displayed as follows: + +\begin{quote}\small\begin{verbatim} +RP_ERROR error_number error_string. +\end{verbatim}\end{quote} + +Such errors abort the submission. diff --git a/doc/manual/volume1/musub.c b/doc/manual/volume1/musub.c new file mode 100644 index 0000000..1e5c4df --- /dev/null +++ b/doc/manual/volume1/musub.c @@ -0,0 +1,23 @@ +io_init(rp); /* initialisation */ +io_wprm(&prm,rp); /* write management parameters */ +io_wrq(&q,rp); /* per message parameters */ + +ap = ad_originator; /* originator */ +io_wadr(ap,AD_ORIGINATOR,rp); +ap = ad_recipient; +do { /* list of recipients */ + io_wadr(ap,AD_RECIPIENT,rp); + ap = ap->ad_next; + } while ( ap != NULL ); +io_adend(rp); /* terminate address list */ + +if((p=next_arg("body",argv)) != NULL) { + io_tinit(rp); /* prepare for body part(s) */ + do { + io_tpart(p,FALSE,rp); /* prepare one body part */ + loop_data(p); /* transmit with io_tdata() */ + io_tdend(rp); /* end one file */ + } while(p=next_arg("body",argv)); +} +io_tend(rp)); /* complete message */ +io_end(type); /* terminate session with submit */ diff --git a/doc/manual/volume1/musub.tex b/doc/manual/volume1/musub.tex new file mode 100644 index 0000000..ccef258 --- /dev/null +++ b/doc/manual/volume1/musub.tex @@ -0,0 +1,24 @@ +\File{musub.c},{17:06},{Jan 10 1989} +\L{\LB{io\_init(rp); \C{}\/* initialisation *\/\CE{}}} +\L{\LB{io\_wprm(\&prm,rp); \C{}\/* write management parameters *\/\CE{}}} +\L{\LB{io\_wrq(\&q,rp); \C{}\/* per message parameters *\/\CE{}}} +\L{\LB{}} +\L{\LB{ap = ad\_originator; \C{}\/* originator *\/\CE{}}} +\L{\LB{io\_wadr(ap,AD\_ORIGINATOR,rp);}} +\L{\LB{ap = ad\_recipient;}} +\L{\LB{\K{do} \{ \C{}\/* list of recipients *\/\CE{}}} +\L{\LB{ io\_wadr(ap,AD\_RECIPIENT,rp);}} +\L{\LB{ ap = ap\-\>ad\_next;}} +\L{\LB{ \} \K{while} ( ap != NULL );}} +\L{\LB{io\_adend(rp); \C{}\/* terminate address list *\/\CE{}}} +\L{\LB{}} +\L{\LB{\Proc{if}\K{if}((p=next\_arg(\S{}\"body\"\SE{},argv)) != NULL) \{}} +\L{\LB{ io\_tinit(rp); \C{}\/* prepare for body part(s) *\/\CE{}}} +\L{\LB{ \K{do} \{}} +\L{\LB{ io\_tpart(p,FALSE,rp); \C{}\/* prepare one body part *\/\CE{}}} +\L{\LB{ loop\_data(p); \C{}\/* transmit with io\_tdata() \/*}} +\L{\LB{ io\_tdend(rp); \/* end one file *\/\CE{}}} +\L{\LB{ \} \K{while}(p=next\_arg(\S{}\"body\"\SE{},argv));}} +\L{\LB{\}}} +\L{\LB{io\_tend(rp)); \C{}\/* complete message *\/\CE{}}} +\L{\LB{io\_end(type); \C{}\/* terminate session with submit *\/\CE{}}} diff --git a/doc/manual/volume1/or.tex b/doc/manual/volume1/or.tex new file mode 100644 index 0000000..cdcf9a4 --- /dev/null +++ b/doc/manual/volume1/or.tex @@ -0,0 +1,30 @@ +\small +\begin{verbatim} +# +# extract of `or' table +# +# -*** gb ***- +# +C$GB:valid +C$UK:synonym C$GB +ADMD$GOLD 400.C$GB:valid +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:valid +OU$NoOrg.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta NoOrg +# +# +# -*** sites connecting via gold 400 ADMD ***- +# +PRMD$DIGITAL.ADMD$GOLD 400.C$GB:mta bt-gold +PRMD$TELECOM GOLD.ADMD$GOLD\ 400.C$GB:mta bt-gold +OU$CS.O$UCL.PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB:local +# +# +# -*** france ***- +# +C$FR:valid +ADMD$PTT.C$FR:mta emu-france +ADMD$ATLAS.C$FR:mta emu-france +PRMD$BULLMTS.ADMD$ATLAS.C$FR:mta MYBULL +PRMD$DERIEUX.ADMD$ATLAS.C$FR:mta persona +# +\end{verbatim} diff --git a/doc/manual/volume1/or2rfc.tex b/doc/manual/volume1/or2rfc.tex new file mode 100644 index 0000000..aa602fb --- /dev/null +++ b/doc/manual/volume1/or2rfc.tex @@ -0,0 +1,19 @@ +\begin{quote}\small\begin{verbatim} +# +# -*** general GB ***- +# +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:ac.uk +ADMD$GOLD 400.C$GB:gold-400.gb +# +# -*** via gold 400 ADMD ***- +# +PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB:telecom-gold.gold-400.gb +PRMD$DIGITAL.ADMD$GOLD 400.C$GB:digital.gold-400.gb +# +# -*** france ***- +# +ADMD$ptt.C$fr:ptt.fr +PRMD$aristote.ADMD$ptt.C$fr:aristote.fr +PRMD$BULLMTS.ADMD$ATLAS.C$FR:bullmts.fr +# +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/pac.dvi b/doc/manual/volume1/pac.dvi new file mode 100644 index 0000000000000000000000000000000000000000..892fb61325f8ec67e657e2d6cbe9ecdedec4679f GIT binary patch literal 88296 zcmbTf37lM2nfKpzRR@Fs3W#iiG*Oa}bka!(5EG=y0+9e2(hv}lAs+&L_r&o1_w8MbrhEY2XVw@+{S&}oj8u-0RQjrIp^Gas~2GY^LgJH zQho0^&w2LkJokTEpZDfl{@<~$XyJcSzdYup-Pwy@TBwvqD&?1Uo_=~~N9VGR&Xub= zm!7ihZ9K6|k3HM}Jk9^?ZGCw8^4)u%eC5NB>}~x=`_G3@xpsH;RV^+1T8{p&_E)zY z{+W@M16XQK?{Lqq&ZQq-JD3?MXN%SS_H9@(Hok0d(mnhcP+KL4$6 z>#jcep7&&WhO(ux@s+LTxffc`{o@-(TMpQ_++Jww9WHh*o#-CSmFnq#d};5^_nzSP zsr6+`y~SM5t>^t9TdI`@v$c^*aimcwWowyyU#&En=h1RzSFO-*f89}ix^G>km@8Cx z+V-qfO4+`#+Yfs8t+sK`t@oZVT2C+kIIul^M7E>WJ(w-B82^9njz+fDlPTqTldsl# z8lyG$@FH!oyS6Via`)0#MX-aJ(opBpyE8+%Oo=mAU;f84CT#CT)$~ON*eiDfM6onB z_CABb|Fxd_&Ik0@YU*FJclQ;BGr9a&b>S~w?f-0>+20&G^7-u0SoP#bf9L*Q=PjYY ztzRgPRbSY%+5M@b+II1G&nbYJo%*wIRm}Rmdke#0peL8l_SI8&^lJqns8%k3>Y*Gc zC>myqa96fAoGq0y17JQ^N>ZW^q-2L|gO0H~4;D>d+tSi4Ox9CRe_Y7S43!GCOs$kH z8)+OVdJB$RxqL1^P|H-xgN0(Qlqu&5`C2aDUnmZ{{{|`#Zl<2z`>FoSaBgTcu}*m~ zQ?88^3!G#}t`9IXBO|O>s`cCqpOhOr8`*5Wc5%mwrAuoUEV;0n-g{*}!&!7Pzwm_{ zczJC-onCR;vSl@g{hB=l_WtMWEhAc~H#fJp*4r4&2=^tnffejvgPDey1?1+6wL)WO z-g8WZZ=N*!aB1Z`tj{B5iVXaDRVNjy}4gqjRiUc;L*l z#GLiE>yN!)Q|BvIeiw3j#dfRKy$OKZt3dP(GSR-3n zw7c5&<kCtFThmE`7fu5;-AM@82!fJLGMD z4gYkUUVX`jo(#W4g0W!Y%@d9S2Hf3AzAm2rUygZE0Q-FnZiKFRNL0@Ck4Bsc&cv3b z8muDZ*D`&5MOah}3JLhZGi-+^M7N38%1Z%qS+T!&ta{wOM+H`D(--gN-^&Dh`*J1+Rhqm*D$v8`%| zBn$9sZ#LTpj|)9RPC84g#>S8Nz_GjepXwz;kM5guLi?gyle8|4b}s$cA!B1>)$AM6 z6J7aw>USr5Kpm$5zr$`JkM7MB%emglP^Ksf4A-u#WpiL%8pBIlbehG&0Bah31UMAq zDJOO_92`Az5nw_O<)tQua#C75av8@4BOqX;n1gCg5P=N1;8zj& z1%D|zG74x9mJvx{1quaJA{PGDNF%@V;`sI1=_WdPG&eynl?d@+p7LNZ3l1@5g;FVp zJ*>gZ=wtBfMK~PI$u(zc^upaJh+{r*j4fUm?deziR?^Uwd@zuUrk9sRC2cZ&1DciS)mqfurgQpq={+FpfRt_4kp8DCRWkoy!=I1)H zxITM+=-j4Akp}}S4aN@gdx~Y}Fa{guL5>zqzhu=EBenoH+d*jWm(1bAr4*(>LZR3v zdB*D7lCr>lP1X^Wpo1`K3f&C(p5uGJgCVa4E8dt`B(!m2toofTRzVNFYK>PzP~%8ArMAasA9B=oY0<2ADob^jFd}N@R}YdW@`C193*9*Z2vvfc$Xu>v~IL#cLDVMXuoX24WlJaWU!n10(i>EHz1~D_W{!DJD z0#};FtO1L?tpu7QLr*Rg4_Uz~x^|n_&*}kg1wt7bf z+joXD8iJe*2M{0d$wHoZw&Y_>AU6)m6hR5jH00j5zgyg=M@TVf@yS)SiJgNv0@7Np zzm~%ojMx%r1oVON-llW5RND@C-EgCV@-f+g`W%~&F)0bUmIS^Q?C)3;5UK+}j z25Z|smY--BFOqJ_*rKf8QQdFhsa^1o<7frK4n(IPdkZ5u98E{29gsI$?7?$IMCKfM z*Et1+LsAF`+Jb5cH@BWXWNXODnsskeU=q@+Gs%y5QUx|6Feh4l(H7bi}Q=wOsSABp%A|ReSkolzB^S7xIhE&k_0cAAaX_?V9=7j)9Iv)z*E#*yfN~9?q0tQR5Vmw6;wz zv@hrwyM0E#=)!Ct84d(pHpk4kDX9Y5#i2rGa=1_fDSZvMTVq>)G27SPz;m(xI?r#@L<5Y&gym52mx&a8i%gCZ;81#Q~N%t0}~H-lS(l!1Hn}OCXn}(65ZdhU0~z z*Z=&oNfNk){OIt$=Ud(@q=S93`My8Oopo zob4^<26A~M!dveO={2#8ZDzQ4i(dbphgmdz$=t-EQoI8$H}$>sfW1eo4+4$=|4_+I|uaKg zP)OVO_0SbLjEXUOJ$>jKaSrrg$m&(+v@bbd=?SAg6#}zV`N(LKeIq;>D%j68$mf@p z6)_G1*U?+SuDj!zN9mH-dU7&|!~{%%CzIssjpdp-H>yd5ARoH9bb~C>@6V4jc0c&Y zWJ0QH6EGNN#&c^9&m>#KG?$w)xiRln+y3F6vy}hr&&ZS2v2`TMGZacv?}8~ym0=f* zS&0O^`>cbc5{~%x_maLjbQel;EnBMjA?avz{V(zY+KsLK3v9nUj!fKCpQZ=sZB{*^@`(mIqCJ;mCl0&j( za4I88-?+LGGMX8nd{a+-^kvRlY|3x^^4N*FLj>39zZ}yowPpBLnBtsc2|a1Rk)iA^ z)TOIrSY*YrdS2*HLWr;pu^D9QF&`M0C3Q8zYbd2q7`S#jB7<2A@ zdgbqa|JIh4{{H6;wzQ1D_P%wycaMK;#ou<{d!k%pzm2J53TC&@CAW1V%TfUw8X!~~ z3C3`hJyPYBjYVAbj&tDm?9dR8jucAX7kP$fM&iH4&-1eO%5?N)dW)4SR(T7gO;B$6 zOvk#+T7K6f`sXwJUCUfHQgEB-T>Rrq*lehyx6o19E*|%rjr7J3wJ+JYX7iFQYt|Na zX7fufSfdw~Y`*Zkb!#qO+?^$e$rhFUFD>a>$8WVIy=w+~mbBL-1Aevsj-H{yz(6U0 zrme$ocuR$j9`f@Nu)y;qjK>GR`D#hi$%wfvZwo5gSniVGC_OVGRn<-kzWf4|F zupx)VbOtmI!;KXzPCdQtJCVBZ-heZ92C&l(!Jv85`ig4$fkTPtNOvNnmXt4W@R#ZNgMT7Dv*)nE%o$mKrNX0zX zIlC>fES)mK9#=*R%cd(@V?B@}Ej(5|X8EZ;WnFE{tWmnmJOzl5L)(6FYl47QU?ko{ zTUklcS;hWhVYoJ(s0-S#|NBW~Fj7OXb9%>t=iu-WhE1#z?S$!*kPSydXPewZn*%0@pVc8-HYh>~p zvB6(do%7)@PNFF}+1!`>rJDoAAQbvND)c}?l?qx(s?U9*p{$e`c@n`plg)E!DKk!% zvx2X7dQCzaCbRB&wxE2Auu8-=u$>tp*A-=MAuA~T{Af4fsPwsxS^p@Y5l-vVxNexlfk^0 zzEriyds7h)8=DH=z?RV~9yXK_ZfE)%54&S~%@|ym=;<>veZ#qYN3dcOQZ+iK52UQ@ z=eO_+n^rvdTR~e}6|S(oG7?ff358vK`3J9c>d7-ZL1`cTCm6au%*KnC;@L;KTM=t9 zYh`S-frXf;-_-LEi)54%4lIwJl$S$w=%le~njP3wmP`3+ueN=6vzPiw{3(>t`Qgt( z(kt>bBQ%-HjU0Ahm=c^3BH+B|t&HOIonKg4FOZiX@VxEZNn|PZB3W&KfKsVPmnECx zNfOeuKYA4219%|yx+0kk+ln%hzu;R>$c5eXF~{mK1G%tY-sxMPs>grqdk*(?eq^6) z5kmVoD6;B?I9UP&Rq00c-FR~h%ZA>A@VGys6r!DOBYArgBi0^*A(dy#*~C7eZl3eSU(~M0R!@JV*3r>% zDeHdyTE!}-|NOGGZWW7Gwv)IhDP33o&TS_Uf6-DJFKt>Cx} zh-9qJdL{C~C;EIa!qV78;}pX}ree$7n2o_^hbB_rSjA_SKJir7`U zby)l@e<^#QA~GcH#Z0V1Z)W@KeNS*cZr8fg$m_$dj|9S`m@)%L> z3;f7`fhLwr&ATQREiDhx^~=DoNBwYznc=Q#+sZ>EX!W+0I~4OqNnifWCN&jp8om5% z?RA#=4y@cTUgC+-y1F#0&mTKz14f|XW8Fp7wp&MY!Bq~?!nZMrZJ{NFEW)S7LxuX&BcJG{f;J}1p#3Idy4TY= znip&F8>PhK)%MooCjvuIMS1y8FLH*#<+D`mqm)*Nc*goGiMYwWIzC}9Nmae=q!p21 z;q6E*qUfbk@^pH6$Cf7)+q<zpZ>O(OXN)aqpTQzdg0z z?|$b4{=&NTQJ6UX%D29ofd3n7R}k>e^gr^I5=n+Ph)GH(c|UWe7vda2(w|-Bs6;rZ z=zT|NSx0ZFqtZLnk?AG=hGtvJ*&W%Aa}lL%^RpwP#m=b@C)g%_SddO#cu@^nD+ZnV z2X@?yJm#_;n=|Ejjah(GMDGeOt5g8sW%Yb41{FK9#Z{$2m*_ZA!TYAWK8$&J-Dm#0 zDR^HtHF)1DG|nEpj~}z`ETfi7D)rp~w^_|gj-f~(55|>!7wt)1{;<;-rE-RNbCGLn zG(!rnO_v}E0$RW)#7I!aqOwS8L~2sa9hR7|*Y!pQb*{K8k`)OWSy(U8>0QH;=r~nH zS=v?Uq;Xx`;Cj7--mr6c?Wu~VRIh^;0JJ!e6$lPC9WU#M_z&_|b`P!y?Ys$FiF@L# zCGN#%AL>$FL%&!<$Bt+r+EtGmER{tg1m_2r?oN&qw!BQj^nM{zpHevZS zt7D*n!~oTnw{M{5`z1S8M%tw2B2~W+I@uzfL|i?SH-S<<;YWXgg*ZJP+$q*f-0h0z z>#Xs-$%VW8ZT6&+GPrPe^haI43qvcU_p_v)@~ifVmDt%vN(j%Yv9FJw*VL=8P z7kU&1v5Q$M*Dm20T%0pQJBWFiX5u0{cGxDT+_q$KejdI*LKXipHh%brpSD#d`J+fYVGTvpkayOs-_yuUHc4Hz zF_w9C6*&QTQMJat;XDP29pkMqHqLW;!RgVHa@CBPrStGHNPdS*oIK?@{aep3)L?L- z+xQffi6@j9viOiZ{gCf~B1HVuYNLjnKcAnoize0mkA0o?O}d0c;&cE_5(uqX>hnay znO*+B#S5&ACaHgkk;C;-~c5HwoFYfU*AY3#Kpoinv>U zC*g{QH@6tp4Tq^lhY1J|X?kOIJeIg!d4+c~PknA~=Aw(HyO~c~yD~oU{eP$a1nPrT zGzLm?Z;Lf{dG#O%eZ7l->*>$m7g-i>Z!Kc=U2Q}kw6VhbleBBCu`Vq_g(g~eRQF%@ zP&X7bw)TDvTZCX@Px{U0k}l%*4~nC-sygRgAEIT2f;P7j`m)yFljz}XWJ)C~UFeQN zUqhLBdqk0Gag+kUA0LEgg-y07(Zx?^5ZBa>sUotOoGJJ~E_wB09W%LF} zaEWdX=LB@8j~H2;S98`r6s29|GbA)C+z8} zrU%Lqyg^h$io%Dc!ijCjPJTNnA#LZEXH!BaCqd}{ZykqUpuqX)F0B|(r#0mkn+Rc|I&KlM0U4m6#aJa&P1;s74Dvf??2U_+;xvR zN4&t8bqXw2<`Dwu)WFL%mjrg1%GYuOnhzmYE6ETi&nOAeA=AfwAwHyJqCtuus|-UJ z^93|H-x6&Y5NmhB-zgVU=*{%h{K*o#`@W88VtChU@}4EH_@uUkC(9;=l*`mmM?sd1 z-6h}dmeMjZU-4#hZN&k;AOtQ#L1_4e&LK_+rlSeobxEcgQ_iU{f3UqADa%w8w(C!h zmqX^7PDFY6P6&NK=e#^Uk^mGTN;(Zv`7@U zXJN+#T>jo~@rdUeZQuHqPur1O-%>&_;y{W8U12`Cn*uiNkaWnMDGmy@-ulf=(f+~5 zaIUdGU(_F|Z6`Wv8)Wib2xcu!nIPto4WIO-!Hz4gsHc_}Cz4)~x$~BwF=w7fLW|6r zQ5+#MuCn$R40`E2jPz`^K5;&`NL2(3w4t?23xu6UM`Z?XzgD3GCng#(1q6aD%T8Tj z2(DGPjQ3((M5=m~JWNhjoACaz8RkepEQ`2iH3%&C3?)rPBp|61E}Y`!7=2PFEERo1 z(hKN5_Qoz5l+l_B0tRG6R_+AX)8pqNQ?7fBw3xpmDoy6w1-<1A&aJ&5ExR4#m>tE- zEfU#|pR0;RqC{jZ=B$3`dnZHHMYkB8m z-5v4B?K)y2v4vG3@Kx{2P7bMdH{{0|28kweCe|YB1GhT%@+k18yPi7e7$b8jSrVRi z`~G(O+jX!oz2WHJen8~D>k9^d2Ah$j4@o*%F4rb${S-2z;G~{Emm$yL}Br8&!H zSrLnH0TU*EQNRB8e%&oR_fvmWt3`xdWh3h8+FQ+eQQR9&HWS~k)8J3BC?ea&K8joy-!e+lHXZRzy6h`b8^JJ zHW0y%DIMWX9uBVnV}w?7v!^5cL*?O+1V`^Y()GN(mHo=-~_`nO6R@?0Y9yEBU)`GOeb+dW!Eu zfK1$Nv=ozH*>T|dx3fJS7TvDM9BNV63}K0mA_w(Tufe%OiMreaVi;u~s3(|sD~E)e zd3IMs2q&V+jK;SPcHSD9luI_|lC2nq3)?Kd^Y3Bsz&c3A#$WQ{vOtfPlr%7R%-`zk` z2Qpe(r!RM)Y(=B&vNv!%o|ns?imem&0Tf2lGT2zh#MV)Oqwiw;>!_M3b&TooOHGM@ zaUjl_2N#(iJoV*;^hr-SzFv=`pTGr{Fwmc-@BtXOB3q=ZQclG5)u*lfz~))keqi(T zwPk4hMexIJRXP-ko6k)#Af~*Kw5_v!!7M;DQMaDDIy)-}S7)b#P(}_cseg5LzK0;* zSxf;aBErnuBf-KNs;rPVYw>mCPhE+9+qd9tZa%#22R`gIwwxxo#v7HQ(y4u_OWN%- zRqP?L&2JEn%meWp3Una>fiBMf5&=)jv!^7#CnZ_|9nmGCC(UE^e|knNK(LoBTPC$< zxAtLD?f|7f@*pZ9%3w`hBJ>YL!8u{fAAZ^m*hvUoxhhmL{SnCa8rB4XnGV4)V|qU! z^Oi|Z)#(kwBPIb}v-~F4kX0|X{G*rE$Z-qzbP}3%VdWvOSn~n3x(^DzhDV6@lz6K5m0CYQ)ifHvMUXnh2=U+ z@WO|E?Q3`SqMny^()(dEe&7dfHG6gl;150aeiJi=na8xb{3mR|tz#u?quC(Hg!wT* zCzj`r{67XAG*Gr`-Esh_v+@<6z(2sEJMR_&whF{)SE&av*PAQTs}yI4LcIYFl)vR; ze@nzRWkD>k#@z?uUM+|d>#g7UmCGr}Bti7nM-4vP-8pR0hK4XO?NV?BW9)fS!ddB^DsrbfAbak~}ks7F3-&5=0Lut@%zDJ)`bix4>Rru^W4 zSp{hY@)Y!m6>8)_7JH|jDG>^XaRG1eY61GWVz~UhH)#oTIpk`aA6{Vom|8e3^PoRB z10<}msHI59#t)nPko^;uZT;@y85avDwIy}eT{#Plp_8gxY-Sy^?11=8U*9?n{3dRu zkOF59a`e3SM?l2)zdtp3Veya_4n8lfagRKJID-C#9Roe9ES#WG$xS9v7+O#L;$*!M zbx{X04fGH=r~bz#Yc%7*^^+n#sEfV|cl-@u0dSG>sSBN)?u4f-1LE=kla=idun;-!QWp*==C(AM7Uy~@8SyUClnLTThf)It{#di$@(2D1`-ex9MA z)tBDBF=~(1#a^A%AF3I-^;G6Q&#uP*>N>EaqVcSk1^B@@F{v|bkRSmSIPBpw4j^J;6D^OXgxE3reIHe#E_L#yB-h{AbB3~~CjKWDx ze0$*wF7)L0IR?g-$ghi22`e#kC;XgAfK){9U+?a}VUUklb&+fI3@xR)B)43-C9xaE z2AD(X*atdl^C0JFA>a6pzus%_kH7n*Z^Z483*Yq^?T|nIyW!pUF4P=@Rl}4@#80l* z&owvFx(JcVu6NO%X!-^Al*>rGU0hu1<%)D~Hu=2R!;<(@Uy73(tgz7COk8CRC+g)< zf5g(7z_BZfSLweTQ0_^+GZk8F(y0&pl;GpyKVQ|&(Udpl6ZtIZ6V57d@r%21h;ePZkX|O@-)2&!kV-gr)`K zO2CSO^v@~?fb-SbU|y?dT_cARO0nLs(x@eRwR3ZW7}JPDXj0yjPTeL-$UDP*r<0d> zdXhaFQs9kDxnaF3^6eWaPibXC1FH7Fuk9X0iqNA+|B6kBElTB}OeZV7T-zMUbWmB} z&QI*$DY)ypX#ZN z;vwS?3+|%b_d(SEIU5gaY0yOCjgOrRjZ{3-4o6Hz_Pha)Hl}WXreXsrds$>de9HmN ziZo~l)1uHdvZM%RWG98ixD6xV-N#5`5bvoahyzgw@)PuEM6;m`j)gb4au~j3ByU#G zq`6*^nRD5k@=)qj8KPkN;!>h>bUjL)GcXtYPto^gHmB4lal3slj54pMdJk^ZbMxRf z?>~zNH!bwnS#@==N&2TUy;Unb=fi$JVPO<$ei6HUr_D>oQ+Ic2OlV|7^t#Aho9rzP zbWGU}AAQo@-)i~;%iVrxd%J}c0u(|%GjmLX#zp;h$ls&_L7VmnG)3GzO)*U_sxvoc z22zP#IiPOso6{`^LPxXP2n}i8lUm&zj45q{KI;hv zcO1Bd-W#7`j#;`?DE1V%ivoQ9&=YRb(qx_+`3AK-z3^g?2Mi1Hpj}np&6OEZ&_9Lc zTR%SV%q%~%KGd2C-3E7-1HV|ppxkV!P=+#cQ`Mo9p7UwI{#={k>$$W;!xzyw5HMC9 z1Y_p>g}Qd8FVMhGh^(j18T3JeI0cRCkR~Jc+7-&cowGSIzJ@cIqL5Mdm(`*Ynm;Ee ztfzl^GZP|-z9K&}O0-n>Z){5rIMK6aPNsX~($0QSz~d$-i7U1@P(9e*@X0>^8hF#G z>kVFLg9+7jCF(bNEsoDnGXC0b$*-L(YSmNUBx}XB2MD*en)>G3tokC>WDOFGF5N9B zdKPOE;N?=hS5kgEO%C@pAIJONW+n0saq22L3pw(Pt<@a$*R5ef_0;u`g9}O;IVP=V ziUbqpn5%*~?0hk$GUQsn;9r+H*BYkyM(fs+bO@(WTw+(6c$0gZfi?6#ociI*q%Jsk zb{J;($cKGg0>3J6k{wAp|0H7qQlC+2r$4ek`+BGjJErcSvdE$-LbUb5q|zBpwo_%` z+U!B-u)U?_rt|;ok1ER#uE^4*JD(DkC=uDsK3Jvur{+lXX3(H!YG$f}nRc+?(I(Re zl|#FhCoxA6g_{a%&Q+C`ajuGV1UswO2}g+R3ZFrs<2^?r6b5tN93jkXwu2u~ ztbMJI-Y7RM6P{oZX0jh+$?s;ZJ+nvQJ!%Z2rl6QA<`Bx1`ol6y-^OwYr|@4r^_CC1 zmRFR)EMB_1CgfK3rXgD2rSFXW{06cZLZ@@!XH<)X7#+>Y3Pu3*#Rojm7%uCw>|o#U+ZP-S_PO?-%>idM0tH+{t8| zI?>UPQxo_rZ`~F3)~mOBO@m62GU14!Fi1SfO-i|o$xHLIw<-Ijr&wd!Y@b2k9^It^ zR>afNuoPbWupOxjZ+9lW*vD=4O3ZCLY-7ShX$*P@T$*_M7PIxECRX6raxglLn|$lN ze7h0gM5kD>2~=NQgupr9F=A!Eu%muGbr?8_7Q1ulX+E zzRchcZU`yo=c%R6L=7ZFvVK=v*~KC02#mUxWyQ$?$1AZ zKCNi0#uNr#@t&)pLcMMMx0`K;Z|HJ6nsaY{5gn~H> z&X9>)Wo77Da7jAyd9wMBNzjM`G2HY+B2*Tqvx*jIedOD^HB`$UtQ3_gFBX}CS1~Jl zNNuxH%n#BttW$C?)>H3$BfyYGv7R;*+&^BGxJ^%O0psVK4|1JM1p>J5y@F#YobgKy z^MxGTk0b6j0bx({5s>S(64_LepMYpXlL}1KadbeXg&Q<}6;JE*yvKZFP1Dz3EQxB$ z1+&bBry|z^bu&~|P``i?0Y}qJyr@rBHMB;60V}D&|46{=m!C3z(7U-jJ&nl3;pzL< z@N}hQx5UXq`uq1F33)UfTO@Jh+(L)@keQU1>tSL0`kVvb7Cu(snLQjn;Xf{U{XaVI zhmP{w|BWmEnhh9ox{#@<<@*39RL(7DuHwqXY4fNM$%_f?ic~iO&qSev z*9+$Cm~Lq9QY2B#dV_`};c5F}z{A8r$R1#fj<#E-vb~CB# zVDn`U{gyvsonKTz3GL~@@sz6`67Q~c2Sf&s-|rGjFY8N7?n#Y(aVG%-%u)x(U4uDl!ZkvBtQ@U zr~fwPF=hI+&36q$s5PntWA%4c%eb0Syj)pG8XPsUx;CNFK=`w_|BHTf?thr}ylqu` zbx!$bLdUj__Ue9T<`M&@RY|ka(lxu$?P0Wm(o$nCKj2m}SHcZws<-ZaaB{VS&~Z*Q zaZ`Y(x7JwtLOS(Y_gU^%y&~3*j;&G#h99B$~cLMP0^j zq*DSHyQ{6gf5Q*V?hK`%$O8dn|hqd6@|wU0rNCu#0-fI@e?9qA^M8>U8leBXJUA>iwo|3%f7zc3`elYjmB4Dk=+qEs8}>Y! z(WK#8nIUQS_Imm!-;I_>2h~p#e(Y0VKe-`nk?`eox6@dRzERzwXzhmKHc}4~PPydg}GJnF2w~?7ED$q6tYOY(uKWlNY1?(0bQF06rl%0n3!_ z8-v*X;V-g=KSE#)$)dtncTU5nHj)VlBxXTNc18WM2^Pd0w?6O!p2)}taTlEWGrbC@ z_@!9ijx{aIsvofZldW2=T^>GFAYH8N2N60)i1-1a)$GMMu~*zHH8SMu^RzHJCrz-c&U9dpJdN-`JE`Ne3Yb~{>*{?a1tp>aFd#dJI^NK3dlgTc?rI#ra%1!^Bl1Dq;}oi0WwPZ-b}si zV8-52;In$3or>I)mJS}Q@Eh&>ZP5L{t#1L0#DWjNaSWRk4(2_oIYW|jU>21xUTsRGdTWH;@F^m zsaQeNGiJJNk$&yt7Gl9X=t|=tEgFPI##!jO;9NeP5v1+wOG2 zW;ilU#h^g`uW~5<671xjW8LMH^i`kMjYCC7(Z%2BTF+J2Pe$*NG^Ni-^=XL%5{|aX z8I^@FJOggYFZDJXbhy+*nU+IuU4?kOikH5^G;(rXo@UIkdKIm4DjZ8%?@tG8-psh4 zeSdB$gDyIH-h}rp+8+8!H!Nv$U?u9oHJcQPCPY(88lDTp)7ruGs-rSY8HRKkV?^ud zjAmz}sgS^^`#`k<^K^*QorNKtp4hD3d|{`53Ci>*K1FX1F=CFKwNR1DM(pLGmKa6EzYrf*S1JqYw%EO_$!n<_N2dZgvgSNvr7JZJ~|@- zn~G3QnZ)k9<>i++%?5pf+fh$fYq;`K44#)_1fw{@_#&XU0RcFRQNyocz{42gCut%# zq(0+7LZ`g&YrizX4^B(#FTREaIX;YX6k-N3xm-6;Ey#*ky9w&VY~NoW%{62&5I z$M}UlS1I`^7#d$xn%I+ zF7m?{JVmo>>fy_cvWXK|^Q^utW>Z_jM?T2x7)Hjb$L>2pW|JS35F7KWJ0Zu{yZMWX zY(#3@bS3T}Gr(>O}v%J&RdEtyPD0?Gy$~K3dUl|j)h8%&u|Lj+H zBhKsT8*XqzV)wi5EMr+e`rIyxLnBUUQC!kMStd_^a6x}?uArx1J5GiM5_%Ky8GOL zD4V;x0fS$`msZXWR~EbX!V_KHo4U5l{*0aTtgV|io!7m^op1UJ=eZo2ZwWIoi;_TyHgJh9{SQ)-#cgAy*tZTnB zU9#NJH6qpt&A&{)>m{LizIp!T>6W~eDq?65UO%I!`>Dr~P!qSAA@||Ke)l}D8}G=) z>F8${gGtZxh6R0cB#7y(B?aZ<+_~`+2Rf|#rupM_Zc4jFS+z@R?ep8C>Fn(b+Cl3r zE${u_hr;CcXMEVta6jR4K2l_%F69vUfcEJsU9aE#W~oAVr^`y?cJo8_J8?NlNiY|M zDzuuS{}%k`Eo4qHCg@3EQ`qb52&>=GZ~a-AHT&?o>1s%M`B@>_foHYreM=^LU2m#$ zP(ORet@Wx`PZAywahS<4~1d7$vMW5z8hPos&JeUw7 zeG7)tjhonom}0^ zCfwusQAgo6lRg^;O{1JaZ9XX?-5xOG>6cq~{+0zICdS#jH%eoPahwsvGdXd9`zG;l zV;*J{Z_{vN^9B>&-jaD%9-fyEdHZ#V{84)EeoaFjGE*B@d~X;jrT9dy7bhb(O?izb zhI4M-dY4IXT_yF_H}19ymj!l`W+EZ^&5mhEk+>Z@gYpT5#QTNV!>&vejuUddH@?Iust zzvh>Q%OeYbKxVjyFtsDo(>vNxp}8d7>zVP_`2#(RFU#b!WxeaIsQ^U{WB^NdQHc~3Nb#`QSbySA*F;{=%sHZ&jr+5v4MHO$A z{#WzfJ(YZ(6AtzIeR-t$ho(h@m)Q2MivP2DQ9VXJpm)$UGC-FZjrTD+; zmyQ3y(4FuP8TI$tH`gxu>-Hw2e#%s%zSgPrXSeKhMy(8AU3=wov+UO`pT)9=?upZ^ zdtwW*^UamdqbiZ}`u?XqaUQ|HjT6ETr3?59OO{$u{sM-)Gl+}<(R_d#{mz$Py7=tN zd*-^DjQXb6b^GMLF3jyoue*vna|B6z?7_$X8a2X2sjT(saa~+qs*Y4%!vaiML`t2B zU`1SEMP?`w7{GN`$PY2CFV#WLLvD@rgoVH#-^3*+Oy${kd&wn>*)%p}-(pPn?rPI* zG?v$5p?2D2Y?EmauJ*elIcFgbs+i$)`w{yV&AxJUs0rW5tGlr}7Au9!&j%0mZigc7 zX)v;JJ@sGqjj_qaxx6=gt~rA-qv79-RKP5`;-tH5iU_&Osm3L7liXZQjV@vIIQcyz z%k&iYYQBD%rJwA_Vt+54FYXVk9{N7%InZ~qYZ9=LGWFErL;RPDYVqiQ1Un+YlnO0= z#QH6!>e0V;BTGq$=ytSBHpy{M>O|>|&FXV-#ZXa9o!7$wb~$|ZWrgI0YnMwVMVesRnycNKd!+a2b9R@sps2SS z!u!$BuNq5mSG$uieN4@Wlbbi|!$)$RF#qy*b}H}DZ-dy%i(oK%Xh}uT58{Mw5V7R) z*r6MGt&Hn3sOj5|^kz3ct82cL0hhwq^KF+1QqCx`nL|dE_tj9xXAjGwTht`UPKg_b z2W~YCIkY8jq1W83cu<)1;iU5IRB*DWH&igXu{g~Q_4MtJEAiLt(NK2+=OJ;*sJIgr zuJoBy6ELbo)e}2D#C@0aPcQd6rHK+A`f2E|r{D7P=LjUKNX-`kIKQH4mlc08U(u%9 z=_6|H+al2MvyTNR?dJ&AwJX}yr|`hRaHz}IVG6_DpddY_k^^cSd!j}e$ApteekkUl zn!CJKvQN&1(@#69d&+}t&zg=kZK7r>Yut7p$hEAvaTtce7jh(g$N{mI#{32P!$PeO z+(g(&L&uk)r|VjF)W+-^=g$C%m<_r&gi!CKSJPv6DoN%6RP?uDOP|~;DJHZO8&xWjM56gmX(MX#Z)f!PrEPL)nKpks~w?7z*x zW8_fWgBQ$GmxIfrSixN0&lcb1;PMYOmxOVRJAR#DrjYlEXgI?(f!EP3v~+as%W1|8 zF+QKDF=b$jah1?%{u!myDS_1QM`uw2P%rg+eYGu?eC_J=EA4La_8wjOi{erIcS^@w zl4^6|me74xYl1Aaxgwh9o^QQvb8;V01F#dMF!s`KApgOlhUkNPKFUxCSew*4iH}oS zO-Wj*tF))}i=S|Fdr(~}Iz#m4YO_YL;mxbQ4BKgRe6gefMINy{%$s;ZbpA6&F&xIj zrLRTQ(?fg@-U|w*HT|AHSRDu5^U`10weVo?rHi48xIIH8qnf1cD z?G4W4Xvvw<>;JjwOj6kEZw2NcV9uGFCSW!fJHttx&I-3L{laJQsod1>*SHv3lFzwq z?APztc*|$LyQG=-jUDj%7=aA;NddUlqnI~pSNeq$DoICwgFbXmt5^CJAF#Yq&<--% zR=I)z-cex2Uaa7FUg93W;-A7kHrj9FG?j4)-Xo@2Mblg_&7OP|Oc2LQ;r%$_k2LSg z9)GWQ#DWUzR#|21nNvZE2h5U-;LN^q$UmHKH{Fzb@Ftqrzuva?=Ahx8fBz+HmJGXD zE6#23Us6?2#M_wCSTeD=-1jz}`P{;fn+}>K{Ls}ewG7}h(O$MB_EeJ`dglByy`rSM zta5=yt_->Kmal$QQ518fy2kV5xiTnLC=7Nane2>D?ml;9`9WJ( zrx1T7bk8d0pPu~V-PNnH5+YChRdLfvQ@6J-kdMFki&r>E#bc@Axyi;QAaR9q?k)>; z@hwI_BUEr36Bbo&hg$9uu%E;YoDf8rP~9c3w?6*5xF!X+8dBt9G_K!5vjm*w3sw|s z6{}g9X)0b_D;_Jug`$^AT^Jj(Rf;C3X^sb^%PMISMIRwXA*=aBsJxedO^ha9wp}5F zdq09$Q_>^|iH^yc`DembcU@%GhdvcAK?tC2J^i=&j#ljJRAM+%b^q_p3qrsb!K-bX zFP_3}+P=mIwd@??xCmAX{onjI!Wm@@-MuV7Ah%S`FuYWz+SRK$4!vzW=?x7DYO@Zq z_I|Z#CaRu#`CStZ&3GSJAlATa>t|CFUI>UO&*T!9oaE55;q;8gC<^oL3(W9rbTcC| zwvo<1`&@sUIHWAW8Qm&GFp)I-z9#u^MvsJZO_UtvqQ~xR66y4t?w^dK^CrMph>@l7k5Q<6?q&Q?n3m>V=fQw5k}_BJT2Wc3VqS_^!no^%1QPiwPMy9 z8(7ksu#NheH6V{(I`=n_#Ge9P>56{MnaNMp!KLP>d!Yd3gLk`TKW!E_5?Esj%`F7X z8v6K!m%Hy&2^_z+@)Py+Zyxe}844rRfE?!MDkBJX)#QJMjZ=$p0@zVE6D^XO7Y`$| zzh5~LSgBm z^~?SR3Of<&t!>x8t(hgnjyB{;l_CbmIay!&toTdq*C zN_&(-LKz*bNvL9Azb&H1wXi+B;e13jnaUCpCJ+@UDde}Z55<$4q`WsQZ7R&hLJ$C< z32fgvYW%PpmhxaM8&)FkiEh+8Q5Mv%8-F3Xp8C~c#-8!A!8+r$eCTIgQFP>T=o}IC z-k>E6KmzOgRf)V)L+_nx959;HeN2PM!!|!b{1+OXk~u11bz>PVSrrua7SzO{`}|cd z^;T*$71YW#Q!-zRDS z^LG*T9U*_Q)vk>v5*ou>Z&wNMXbaOs3uu*k7@-}vN z*B#93O=V0umEd(`(*~%KpgiV_u-sm+r~7X-hbg=#fw*u3s9jr4_rFG_(fQXNtMM+$tI(s`;2s~kuJOa5vk)HcSZKq&%?uT)m^s(r%!p-7Id(-j-DJ!z$U@@30sNGP8)KF$kK-$ zgg!E%AxKk=XoU~bx}IB**0^c5AdRGkcaQ3+8{hB0sVcO2h>g{vlc2A$5H~Ls%DoBk zh}A1`Ng*x}DE~lite*alpSVY&(@j{F!E+rSmkrf}j&u54(&CEO(tu9FwaFK*fo(p{$!YvqTe8HOI zsbW#cppo))s}gcS^u{%7>uuK`+o{h;oJW(0z=`fzGeGm`Pd(x4fE>3(!1ae^-iJo> zc*jc$8nf-xMzOqyXPS(m4O9x3p#?2W(zwuHlGYgk$*UOtN>gf|x~}W#`TrbkWm&Wx zHLAWfE~0{%yXvVYk6dTkHB`4qY}vPqJ)iB_0i8sktb|N`meu(uCrch_9kvIazHs? z7fm@_HZr=Le%h&lO%&6-_zAZ~t#j$Jl?zP4>oOB2P`7O2>kV+yvW9jXD&z;4>7Vef zCFnLV)KvzoxJS#8jzI@W%ili5#TkCw`}B(vJ*eYDHuiNd9jMh~-jEJmsQT}w21cS@ z`)0-2XN6WwdqhXz(HVO{o4O;z$L{s?%#EdL)?BPsOm0uQRn;Xi4G@($W^4_e2G6V= zpK-${wMDLJ3|pgU$8-Q@?lf&WS6^-*SI!L0@bZk%H}`=iK{lj}Fj{x*JU;ZJ|6smf z0=taAh1EL}VR!mJ#_@PdKEDJbK%wKj__d%aKNMDLiVIa7#z(wtIb(T$#javv9}A z$(<#0B)yU%nvtq=elgk=jYsn9^3@CZxV-FinlcNtuki|AcT(e=8hb$Me+{3wI_tT4 zKzDRb_kfLll|{0V#)Nv9xALS=qnR`Qz(&Fy>%!8N z*{IW-$lW46Tt3{rr@n4U2~r}XCD-w#44Bd&-t$YidyV<9x^w;nr!szb&_z!1(OeQC z8jL8o-PVP-W~m8j3%gmPQU!jWxBl`jLPTZ0s5(Fzqnb{T=`9wBxe1L80>3JGC(V?4 z{8Z+LrQTi%UZ7h#_%&!;dna~Wa22?$<(y6bDHI!)rILrc4GP3cnA~^>kOH4o4*X;* zDK=EI%V^9LhN5SiM#|{0-e1(+pB^MIa9bKPhP!-_o20X|7 z`Xg~7i74)^MH0a-|LR6UKz8?$0Cr&0dg?d#;rh}+<9e4|W+6CQiVmX8lm8COQ|Is+ zsS*GV$kV6@ja{OrMY9x~7aP{+hW#!xO1)*bg@xaGos%r*l%R8Or74WtW&Y9`U;C}RGT>nO8`>JQW0wYaoEgNznUOJ{(SF69j zyUB$(ZK?uEo-8T-j36<0fI)I^*%^U9HokPu9H&nR?>d)`Rd+u9E20NtyRHhcEiRF3 z=@>ui+5?=@X!^b0HveGJT;D#G1lcD*QC-e8RC! zFH;_6;nT1c5bI+V2(ZyQL0NeKn#GgFpRwc#EKJInlsco{T%$QTpXd^tdz8;Yu1)4k z^!Yuj&P|-u<;Qr1+3&usK87Ls-h)j5V&BE-;IijB{sSpuQNGP(_#wm^S zE@)Lb3bJ;DR{gQ+SuZ@nDy>Fa_eVFfZLC_kX5WN$77}=e7g4VGf=ge10i7W@mfT|K zV%P{3_0(mbv=R~DaT>LVFGdA?z(}ate86j{erMH`lVjY~7ARU4A(?bmL*JTT z+jgO~mzJ2hq^X4orf?8O*KAATId;kAm%xTge3EntpRPtLKlV>bU}kD_ahhwii`QfgRsl`i5B*Y2Yjs<)Y;GV5veAk}Tzg^^7m88-U zU-d9)LHq25%Y~P+jJK;4>D^`!o*le_g01ZY)4tQY5ySxo_lFXd*w`Ct_btLjW+Hh; z;E!a0({WnPeSTgO#WWpp>;69J=-U6Vz$hj=WY{J$Rc4*N>SE1ATL}WoRg$75ia|qg z7_b5_`M1lW2&{9dk}2Im2&(C8TQ-wNDM$#IPxS2tE-31Dhw&rzV=+O6#Uc-N895@} z=Y(n>|I=I4nSDAVS42{~iT0Wwv`?JpESq7+;XtQw43$uR44yyYPyY~B=%?2?T7e1h zpjHJ`o_9PbKumQs3xQk-4?_=4gOux*?Y<8=rj)*@wvC@|e$Cr@Z@#0vz54W~U&^|) z*A{SN?v|EEetg=*;(GdyFTz^(8I8YYLMfFg5f5{j~x z87R8@YtksTo?Q>rwY6)Yf4%ih(Wj%R(>QNl>0v>}jMFe&GJKj)sp_br3(Bt=*k~<) ztemN*_Wwg*(pe2jI3e0HpRaP=i0=9ZZ9Eez6jAqydsiSnV6W?`M{Rhh zlel2qC0{cMkz%VpwOSXpyIYZvOwNJ!r>xS{HDhiHNN|^;#;WT^($scz1@h3dUto_j z_N1--3C;x7SO^p5T_N9w&2PMb_xYydnX)V2kmCoIiM}T2N>iTi0Kyr|Vot&=J?SD{ zVnew(E*Bj6I9f2)ETQk9>B5gbMEC=>YfN7O_@tMmz@$}Rk~v56ppT8b+T$UDIL((3 zJ*u{rF|x;*`!Go{dl{v5NS&;+J2rC@^)&5f3JnFB@BW&4Heu6=Hv485?P;A@)l1P# z4IBOy@6c3R^Ls^7xrM$6u}F<8B3^JKI~FZ=y?h{-XYCe{d%`)B%OAd9&6A*7nS1Ly zVt)m_M%EyJs41r+oE*$_oYbGXlZX~K8mU+gTh&n4$#&w4{T>a6@h=$kIz~8E>Q84n ze_49hLFLiS`hs*O=$zR?NO2K{k}d*ST3m$gx-YB9OV|L>DJAIBuL&nX?a3d~WNtWB zjNxI(lx!**Q(vMf**qDJ^vfTQ4AFI>)B93uU}K9N@LzGMdX*v_A2G!>Vk1lnisVCbZ*=bH`X`#l5S!mgH2`8A|`QFFvEawi+G| zKk{|D)_<~qX+qbAIQ8P5ulM#xx z+oL;}RaYU+Hh%a!PMsZ=_J!^4?y~wo_{YpZqKBvaS?`S>v6vhRSe<}3RX~pVw@^v0 zeN7&}zIq&@!fq!gQRE@C;tR&8RL&<{w=gve*K@qc3AXR~wSHV;uBn5oM@*FcY`1#C z)rcCS;}0d{&nS#Tr}jk(TYlzzKEIO9GO2RXyjecUz{O!cUw``%`D?;PJ2OQ>B!zuz zR`)YE*YEh%cYlHT7rGevj_o~xk9EdMWW3n0ZkVvJ})0chM zkDE;I`LpW`q*{RB+V_eX=g5pVTg+e3S3Amlu_>;WtXLshlk6?jxO-p*uBgU+7+ft#de^dfRuAgiQru+mrI z&R)ba7W?#hgL?Y?|Kh9iVE`1esb7Qov1wfb-6Y1oD2FHe_<{2`Duk-0e{y11HU0j# zVvpR{=G+c0_f$_^@}DlO^L-sAAF>P11aJw|V-C;ZvR2tIwvu=_1Lh~=6c_=(#_M}>9t~OT&&3ngq^7CCB=!8dkQExT8v1ThJ7ZRhdtsx{{ z7uSbafUt2bRO7oF1EOWyii(*Ge!|LYma7Dnqsl)ue7V=4vmz*eUJohES5IF$5Ahg8 z6Sx?g-|(TS@zSQK+?;d(FbqT1Rz5sma}%*@CV5^NF!IGO*es9rwj;l-&U!Y*NhJh^ zPi7Fr#Ek+LL=K%?HDgo480GhUqnS&&0;sf&!T{E97DkL9pDEd{E}vkXiYJe}MScuj%Ub`(+wGJK3>%Acdd zBe)8Yd8Puj*sfqMK7(Nut7Ma6)13IDJ+sP8mAp?3bK;LB_g8y)`X8A;V(TuFnNOHB z4JL{I$*^Z6VfxxOgT!qNiC_6-q-fUAJhIe3uTIQd{_suGYmigg>cLk$7!^_WwlogxaEEKmNb{efthP`oG#=-Esgw>i^H_9q!rH zx%A`b(hmK;=;5*5)mO~DxB30$KUkpm*9S35K2EKtr8NQoRj=I-J&N6rzSefHwmtmF z_-}vScdt`b)fe6L1$Og)wC@Uaz4B-K=AQefUF7F9yuhtP1=5U#S&= z1IC{XoYu!KeFku9Hk>F1>bXGD_O{;ZS`PZ-mn7*1$rI)G+*`>k&h>e!`M(8GbF8~{ ztIJ5}9-QcuvtfD(vl@6cxjZ7nVoqd|zen4SbUy30n>(NDUY_ttO=cURiS9+=mq=Gu zU$E&*(B12~sVBr}p8XO{T+pL-LoXaExh99={pngWxz{kW9G%{JwylPRO-7{AeLC}I z{#1uZKOc#L3{?9Ar*Z?S{Z9Um(V=i#NCJP-JtM_7#nF-nW|O3en)VA*56$)(Ovh=1wTo*p4zvK$Y|N_CV!RL7{w38CAIYaoAWMkwz`YU+=LWf zdjC`7Ak39Esg4s$2j4EFCzrfsEe-N>QhO{;7zlw}zEov>A{E7-RcEoR-Me{Ew;`*_}E03N0)>J>MAH#>W|@6nS*;{tc9Ea>8V5ej}Ge) zwc0|3Yp$||2tc@3Mh+}7o6{EZG7qrfv_9t|XnH7j+A@_hUY=N{_7($%j)7#ShB!;h zyIZhR7Z+=}yatTx4=b*oVR_4W`Z`L4${0GsmB{N$G}DQD&rwIZ%tY(s=O&2@Lq~O; z1O;5iQCN*@%cLEJu7e6foGXzM6f=!cSMMwZkeJ^QV2eM&;l6%2S0#w?BbVJ87}5_# zD6LsNqMKaBz>Rm2!?ILL+cysk8lvsrt_+W(lYLIqspKV*A||Yq9#C=7^(AqUxn$`Z zHY0!KljExh*`Lk|TBv3uG=`oqS7vtWrCv3(@4ga%SsHmHOcobXCPxCPAO zXs$GJOfbZyt784>kx!6*%kJXJN7r=|^Ouuj46&6e3E@je8)P$|{eS-TmD58jt0cfb z%35Z3>4H^u8akB{MB?h{+nx;AOyBn4bZnaU)Qqjrl|w3)mNpF=;Un9M+d-Tv+yRd> zVUd#eTr;$St*6k(&CFt%L3jbk@RQG6KJSose%etz{lp(azrtMhVaOD!Ok9R6HQX|$ z?kzveFoyIByPX!DZN+hx`>_fH@#Gn^Xxn?=9vGbJjw;#p%}C@{VO4oupd*k|VT?N;7xT6=_l{#Kf`v z^gON+?Mv&TgFW;_bTH+$(IM(VuvS!3clvayOV%ciz;;dPU(5c|jqsw={x(BHO7OTHgNp z-$ZGRH95K(Nuxv@)85swF0-~+xuS#O3REJqV@VRte2%u_B_(e{9>r~D+ZqtOH)R)B zLvBjftUP7K@@1VqPc|`slN#*A`QjA}uqJp(5#zS@WtzVqzhG?q*gN-H;_kk!6nCGk zu9r^TYEtJtEm>BT<*nThdm;^;RBqM>;1dB1|FPVnwFN|e2vv@#Z#?osxWsk4Hy}~J z12WNR*R@o$lZ)juu-ei-Iq5r3ui&sY2*l?mz&oiq0nH7z+fGudcl-13-7K3&V6v!j z87WzVJp5FX;D@}V)*|V9vNTd6<%lLhACJ0}DBV?}FZ;N=>%zU;Ug+n*zSrwTr#&H4 zA~AXf-zI#DW>0#>4-@8(GQ!1I595GUa2fO+D@baIb1!a-8uD_yD8=S6@WE_8jxeKc zpIG$;A(-ZLJs#|GTjtB&$#Ui>G+V^GS~G(N6&UAvpyVY=pSUd}jS}?gv#8pxYTK)h zl6tGRz3O@?SB+MSG$X&6l@-gQNd1me4xLPE!+}uURr96*^h_#l9qmg{l()?vn@O9& zOR#6O2rk4kC@*&dJ~H)IOZP!QPPNfUS6$Xo&Wv(v{mfYvR-9a3vT@C;_$Fevy|Cnh zt!sKqd>j!qw?x-$)>O8m?w06!%o<%w^7nX_tX(tEvt-pap|0@5r>0Y7V0nLL*HwI# z(P_p|e_CTX-ldB)eahv#*GO||85CZoqmOv7a>X-%?H(+3Y^Q>ieb(nj7y-RAn?F-i z0cjm6E-vZQM2UNWIFAm3tz!eOX5#uPEXFxD}tI zS@ZvpaZ_h3A2GO=Zkk5q4B^=Cp!-U<#3S|ETVOngt^)ee7oWWTe0pZ< zsnxG@l4BqW0uQ2;tgt+kwK}{1{9bTM?G%KxpS+%l53c=C`j3yXo5s=Ick|ek_ldno z+PqI)>f5}}es&L1Pkisz*}O=_&)kmc?DXBaTkNAg>bvpi-rEw+f(*W75Tfu#^zEOs zpZwHBo{K0T{4eiB6ZpYq{qCxy54|A-;jH2$AHM|$hNHj#xBi=E;WssU@!hs4lb|5v zXQx~1ZS;B+Y|N*cT9#|tTOd2e{7!CWa$VVav>as>_={Fu)zr@xboHo>mz#!L+^A3c zh>}J58gFvpqskstmTK5*# zz#L}1>G!Y}P!bJCe`Y7fcy~290NFUm0wfwhZnFjrjf|xzt`w##f72ak-(jweqM1 zSm@5{2;!)PJN9$)MeQz&8GnhQ_2c)tj0%l+N^4+nUi{`G!r7J~d^X%UP%oYPrvDTK zrP|?~ofg;V)_VfX>D>E~e2YdPP7_2b#gmjG#L?6mwa3s6B)qaUaJhI3DkxMnI!K3L zT}4Iz1vR@aXM^e-zv-`_SW|huW@4(uXLeZPsjJ$0`G&+!_14SZAqWJiX)_DE_&A{C z#hgA7+qVvcs6R(XZq8AUiwFpt=K}!jD-CA0!=gBN9y}#$5*HZYwi+L^$o0X>hH`z| zohuGLh5^$DedDhND%m#{8r+lq@XhlR*`5VzYp}ctj0u7BjcuaZV)LKdeHzU*q2k~D z=DWIdjdv%};hqK2qz5)rPxrmwIo)~$#FM;ns14_2ZWMzBLTsmYm&6z}JlG@O(GA)h z&(JmH&5)CETUmPBb-pQY38E^)`Dg+@;+JgW5(Uh)1rj;8Xh7(#`nTM=DMCd(H$SjA zab=v1e7-|7#f_Yp3xAsnx0Wb9sIIt0P+fR$KGIg-^ycq<>=3avbCD559Q%v)r9$ijW@01&A+F-udD;zc_#$$;&3Wnmmcx^6hQZXOL-SMicV2JjmB( z=r5r_yII;{K7lreTSD{M664`MvMCX3uiwSUt|1GrNmg4I+=)LhIf@2HAX6tQG~815 z;YeR)cz9H9R!tpiUhHf*0*`L#ICr}L#P>dSWUtEP3WFor{@%PRJxEx?TeiVETi4xd zonhrAxizIFr8VZBaRo`vWWk)tk^ir?Gl8$WEc1OxPTI1`Mao{bh|^ZGc5i9Qv=nH7 zw$KGZKunV~4b4VQLR+j0BZwPyPLCb~6;qMR6);!{Iy#7q%f~@rSj15g6oGML6gRF8 zDsaEQ=Xu}%`JXJM>ebJT>Hqxy@AACQ`|L|!S8EU^sV&pmC>g7+#iU4^xVpDDERrEE zX9$<4_*$}B-RRHLvZ#-8xqpBOYWLC3yq(>9r0w}D&!Wo6gv?&NYj`E8nC+5ZB-a!w zmz{1Lx2F^HLyY3U@Fg}o^T?$#f3;x#pnVAG(Ptbyby(4h1ih%4TF@1E`--l1Lh!0) zepf|8jVBd3KB3D9p@hDGI3Xz@eT5)TZb|WUA9W-33mNaD%&9xeZXpVhEac4A511;E zWEW(HUr#uxe*q%Lk3t?ejd5*=~8coPU+7&GmD-ukRmZ=X4<`^Y)u~3K4 zBD&8UMM$~oMz~@Qrx>x2fMJp-y1es8-%j*TIW{f$`Hx~+y>TK@*CH8YkZ5p$3Laih zhAyhrU5f=v4?|v5m9KIl(?~qB{RJ6XlCP@f2iZ{iv--jRS|Ur4I=#UV+(U%HgP~w; z9{yFDuoy{n(Ud`)AFCw&B8L{;tG{D-mZHLLSi7?@vJ71 zZlv%;=7IBRbp)jLof-fz-k24G_iN7>BLkj`qy;w4u6JD>B_o4&ap&5G%>IhoOD=*? zQ_Juz3FzG(XscV~X(FslmJYa@GE!0&V8=73R3E(bO1FWR|E@O)0%ueUab^IeEw}V- z>s3aBf5%df=nl1IL|#qg$LFA;NW2vfT)}?jPnjM;6Zg>Q9^%`zxi<%y7Nc$5k!v__ zr`)PH-novw*!T)hx4)P$jc9f~?Q(MR$QQbvnKO@Llf?xJfKqs&(mBxn0kClkCHY54jj9R=Tt>-MA;5hOp9 z)>L{gNX13hx^(Lhp>)6r&9gA!6rNgufBJwW0yp)i(|2+2jpN2mmLZ{K@%t}=0AN(P zX4=rVt4{V%xucfMyJi1tr+GL>X6ic#jk)0l3xYe~9X}fS^MAkR?hEAjw~Pp49Kw$T zz0ElwdrQgt7yV_X-e2j$r2-=2%LEl%^;|Mt23VT=y z&lE9@3r{bQg|nWq3pYq<;WDEKNd13bICo16cTuJT8;fm>n+p9G%EEdkSo74mJCbuo z<{w&m(pyuP4&wqaG&PoTlzzwJ0i*~SB~WSQ6JvpcDlA)c2nbHIRq>2PfoBSNigs12 zpt#8Ic;iK@&N+KUdvo)amaDF+4zGuqb={h$9k@?5Pn;koO(o!dmVAYtR^ZQ>-()P*y;?{1Yhgb4rw zlZ0xLr&DC!HtSUA+M6D-yOMd&5{-xA1b%vYf<6p}MJK>aFA^LO+b3g!D?8e@1Th(c z$yWlt;XrE2-d@{H|63pS={|9@P1oCted4J-#_`9@2l6nV6(CGevqI(*H=9=|*nRW6Md_*EyF)M=AiPGcmQr-GaStK7huD{J#WWO5}gL<3{?)S_Z! zqEY`Q5}7s)?{WLPt6R;T)EPPT2CMRFKW007iocv#cH3|8W(h2Wuk0XM{zduCZuOY(-I<{KnG&O8(pxYjc@R zx9iUFuhFl8D|9FH!Gjs2c30+uTLt#=&&~~kJ0Ayw=Nd*Uzw-~p2YMraiT4C-OxS5{ zmAN<5w?6J5<|s3u30B+clCQXQD!L-OS8}-_5>r>M5|Kd7ynCRd6-&u^KU@>popfQS zAwl*s%~5P0gIXwxfoavY91L7Ui4c}__?;`_SnWR6n-+~TRy#R9y{|Qx#SYo3m|21< zOUn+wYZw#v&}~|co)s#F?kEwwjp7Evg0%#R@5v#Pl!2)*jwaIlrTm(Z8A|+1hcQZ? zDcr%z2Po^XFAq4X*+zACQ(I?e^`@RKG0)guxW^mKNUjUebC)L1S?Cpg_c~p=Z@=Vm zDH{fkCeJdFDh#Ma5c;Iy9-s}5mnqX31&;|znAWL+s&d!g^YrO&#!P?D546fq16`&e zWhHT=bXK5Z%ns~r#@#Mp$pC%)3ZP+}FboQ<7YSnbdYtT^Kt25JVs@R(o4!FAMBGPYj~ z{<>&^oW%puh8X*j7j7FhwjFJ9PM#j09IG~@ zYly>qNAB&9KX2cb-~Oq%FaIsM7p#bzp^uCE`EX#>QGbc)U|78TSce&*keTx4 zl`EH@S*NPwQyR1VqLUEL1e$|eIbKeCWT3laYhIs##NDknk0~Pksy-D)%=WViKG(s{ z5V+!6f&55sZ;}tH+f_`WVSD{2pEj)J7RtZy4!!UBsG$g0coN!_l7HW{ZE>@ zQ%_=zi?A9#D`Y-!rG1GSXQ~W`)Z9k}i$1vu@ocms+p)irK2CPn{y`Wi5n>}lK2KrB zOY`ei=mFRJ%8tICZgW8fJ_vWt$@hiKD{u6A%&^p{Tl6T$@s~%T4*ou}i~l6T+>{ zF`KC;`QcFVKn#bag=VLz9nvo|S&b}&S3h5AyUbkpuc4J@#D?TGZJMB&7k@C`Zo_JP zQwDh7SFEfNT*N>8;ZloMR^wbtP8ff=%`MW<2c5nZuO`hx`cyV(lZX{ZbJb@q_eH;T zegYstKNw<+JY(defG5`?(O@Hr918WEx^lIN42XV}YYIBk5lv#*X!&7Jjzj%dgY9zE%dTA@3FA9WRjw3hc#d`JMitUsVUeh4BydC$QE$- zEF z?EKjw(t*H;efiIypPxv+M;Lia=cDfPLa}rL_pz0K2Xq{kCdX5iDah#z&Hf4%H_iz} zMV4@kZoDj`8u{~9W)I1Jq zS6zkkW3fq4P0N?$FJ4^Af%U`+d|Y}dky)pHltpv?QkJQyOk~zN(a~$Cx%YEM!@>n~ z>iB;PX69Eb)nedlR<32V_RI*}LDeD7EKJM;Vj@8o7HL8u6^`2XK6;`TgRIBW^(zF1 zil$HqM2Yg|FJ*Au!pz}I6)5b^6Mog0=?*mtU1CB}<)DR%!yr=V3Py{Ams!(@gk??n zca0H(KSF4c=eD?3>4Hph$@E9UJJdfR)^*0&!c6)t3?lSn4z%&$E-PfJ?oY~_T++oQ z6t-98%`EOR7F0CC1B1hsyQBMS(%Oo3C9?__#K^)VULt;kG69XDtAhrW_9t7SaR_Xobv|e==gj-FG{~nZrroaTUK<=p~#}6nNx$nsU-bCZ7dh z`{9JG>i7#4hb-gpr2}${Ji;2x^8P^alx4IwgRm3DE?T-Ez~6zKTXMM+Ic=tbFh2gx zo_3<8B!_&E>II{YTX1EV@7&|V6y1@E#qzDW;X!a^34tghL4@%E0S23Q>mm@2Vi!TU znX1|tifP*wVk~|nXd>%v-^`{FG8Gg@Y=P#y5(bB#h=5!FFk86aF&{kMJHMNu;V(?) z$X(xywo{rnG$*!Gc37w+PA8@EMr&B!6A0}mb|?h#dqSmgNy!AkRkr^soP^efc{6Q@ zzwL<0FD7&9>r#_y#r!ACx{;**Ci7;6zZ1+@G5_8$BMU;yijFOF;ie3#!t0VvmOnHj zy~%_Y?6NS!@&|uAdcr{k`91jCz08)&-19%OmHy-BjX{IRV)Z8VRjfY<9O&l3IIj6r zS)L@_3djZ!8t&Y>F@QMIv-H-+f#r)|7-w?^UPyv8n9;in2Uzjq%@ZDAu5$eapa(VE zDjr^Fn~R#GkzU)gVKsZkIg8sbk#r)}0wX%C78sjCqu@-8LI9$Y{XlU>;l`W;!vPiD zi0-0_W=D#O-WSP7$~qkpRNB0A0G5!BzxvJ;XS9g%8^138%?*O>!jLUF%nMcb$gaqh z96foqEutGOUx=o_c6I5Nu=iq3AU$+)WNCL&wBoYFWaH%#{{gCj{Hb$XKmf_}&5TZ! z(OWkLLMkEy2-mDw8x2!_>C>#%u6(JPeNGU=&)F9tyllV84@@YATUu&oZ#b#kWzjEk z6M^rFByQYJ#EuGCBCLF|= zStz>dhQShJ`d$m?<|iQ`7FK0CU{BxX978m>+F>zhE2^x=BCV2;h1w>_8vZ8qO6Op= zH;yf}__ia?NHQS1dRmJGhPf7nipOpa;Ym7@ND(U@`&hV8s0AR|Wx2TZXeblIFoPF= z^dN=fM2F-FTGLE|B1l@_EBjWI+ zZ~S^_apmj8VlK+uKlDi3h3+k_Tl}L5obZRgJZo=G_;dC@_HS^)GhJ}PPkOBBnzH|O zL0eK);icMt8PS!`)gF+=Cmwz>pZNKUR}HWC5F`QE2m?y3b&*wAd>8qX6vd0Uz_s4F zU)}z945jD5qsEZ#)}AzX$2Db#{Oj$-xgY4$+zVSU~uFf(0y)Owv%# z)GCE$<{J+iu1+RTO+w)ch8sJ%RdaYLPVT8`3SW4wxx<@dCNJ*1Wby#=sh2-Ttii8e zO}72tA3e^t9Y7v_D&2AZr2z5;;JOIH*e%m!O%hQvMJFu)f#ZT1Sm#?=I{YlslXDhR zA8Sewa0mZhw*3UV*Q@0vv`^!0t90-43@{s3OO-;h+e5PbV8K zUgExOszhND)#l?)l-KHjFS+hSx$z$}93FW_>r1>+&aj*(QCWNvewyag4QKkGN`(cu zRZ`reQ1MMt1)NPo3%sBrBGMwgkQH}B~Mq?_zI6*gz>kL!`UmRTqmCy=t+|@wu z;JwWyJIBV`-Ja}x9bnHiR3$DAQ6{oew3+mx9l%(j-+5@0lCP=%?IoI>nuW#b3|U#) z^BE00#K?)pZ8>!4%x9hwjoZ+c8~VokKHw-e?d|7IK;w@8_~-UU<1SfobSaHH>(9@; zcAyc{g$tJst4YFV6a$?*t?7zUaX%a0e(vy^wysccq)_p@FTi{AYOBq@^HwD{f(}Kh zCR{bX(j5R!W}~*-Hf_bxL+P2hT}eRCp?4m6P1&)tXD1}!h4X(g(%lm~TIZ%cIKaBX z3q}Y=t!q;2*R?LwpNyqaLNT1EOgUOhYHeXzDAP~@tt&l0M3IS{D5jr#i5u2sS+#A`mWMGhTF` zczeA<=D`YOgx2PlD)14<#?+aTg(4+3Kb{bF6d6tt&tmOUWzneh$6!k*h3S#TM2V>X zl2Ef$N|W7sH3UP_ObD$RM~&DdBK8UIyoCJq&MLQu1xYB;U!}-V11CzEW;vG10iiST zEg^*20h&xg`wN+GHc6lip zc6J%VizwGIKXyetci;4$!_J>T@7Y3H5u*cBgEWFV0X7|(Z6=w za@424V>S>4^k{V|%3#W0PzGZMDP)Qx4>^_4QH@<3+S8I{mnI+itYvjIOZ>@MOs7_b z{!{=!rByxo%#`C(AOl{)V%+VOrY2=&|HIsR;)fs=BN{{r3ygyX?&n~m1Sp~Ft1AUB`+xuUJYzr99*T}wk7wZ5>^Oj(74stPUg5PB0G zge5!66mhqj_lY6ca&PM55TbPca|xE`v!>vimJY=j6}BIyl)00|6(yuXMcs>R1oA?V zROqgzOi-naNwT6jC=ng5z4D%@N@Acv%lg6wSUIyH>BOPUl`5gdb;^jMjLqg* z&yPgnKisyp1AK~f$VNfloA(vQ7pejr6QKMa3C3EIoAxso{}@a;D7J-98u)FN0Q-5r*-~DRe3%_>O zzNxHisPS&%tA`$$^XKdD3aeZsJ9A^zK(?y7Q$~lzD)}6$s@<JZ8dn*T6_97 zx*wv7V3#Uf5$1tt>h7<(aMs)z3+iV!&YCxC&fM8}A?D1QRX=+=M9^ER*2wWfpVIJo zFAhXv3C16yenI{GxwCNh&2C5y(AS3ltS@|@)!()Lh}Ng96>8h`uJ4YwB8Hnimle&P zvvA=&4cOaT17Q&MZEEg{3!-L2*6K5OWroosj`p(5G9OFBf>X|GT7F9X?D_`&Td%># z)ax<7P1WefAJXZbk{|vN2^mvb-Jhb?xmA! z-Gc25%|(^dan9bIj!mi&F`nD;=qtQRj|&gwPkhbjgOJ&&E!5W;OuAHouQs8WP?PdK z(*K>?1t@(0g0ZmJJr37{n8IJ)39LuTWz0s}UWQJ5pW z)=)hy2msOOT{Kt*J6pK`g{d4Jgjq^~0d$w~LsMHpK@3L$utG&~40*BedG;g^C|tN{&A< z0sZ7qnIZPtuL7dJHpWtUfnQoxcZXI&mo-U0@&Ma}>>?^-zrFUW&hzPt3o&;VYqPk> zfx=M8oV$!=%bFtbny6JWxV+M(c!bx0XId=R;E&=tc^kvFcLvZu0=PZf3-Y|pnqKVb zh74L=x~;wXbVsi7&_9JfLRL~9C6H6_TJk7+sp$H7!R)_s-^AY&n0KjtZ+WZjKgvO zZew>kh$Kvi?Dd&%n05vr;^;;3A)vEQBS}GIn>kEgkT`3E0)Z~_PdJaj9I)Md^AgDp zeze7lFLW2mU%D~!(Nf9DCjoEaq@!EtVmqB-$#bMgl(N&XAh5u6rBaT1%_q?tSnkjV z(hRl180wRIWvCmP`$Er~s@ZeqF0866;hAu#`gt%BIOZacxv2_VbMuzw4rdi>Uwza$ zi5}H?3HRhPlO0NVXUX@9M`)P0pg#3I+%5HCQrfOcOm2xWxrSTkmN2=7`tiA(%d|55 zsAEy&b9VHMRa(=xX7*}$9LFafH#ePyqB064*(Xo_#a`5nx;|I_r+Z`e3Gb0rzv|P& zHba45z^_u~MktyJfbGalUG(B`WL#3p0wplXQcgIf;X}KO>Vbx)rul6+!(4NUFx8c? zJ0lKZ=HSpzLw8Y>iYO}THQaHX#X^oO)-Ym#BwTyU(Z!494MR~fEqHrXzP7gZQe|8V z&)aXhT~SBgizoSPdw#J(sv=`VdG^mzUwOoXMXEA;|5v0O64D)KPZ<#qh^OA4c6g83 zH65iIe%4moUP~*aIDqnHhu5yc=bPhm8Ar5S>_PHit)f1ja%$MVkyU*p_&VW^ypDvC zq$W<_KroZb{zHKCN-kz^g0O_4`Js@RdXv^lCRhC_$zl>MJlzK?$E$(tWUB|ez=8f< zJlaHcoP3)~s7M|1&b49LbC>$ma8OR4$Rf~&e8SxE=N#nN#PZI0)|FWAC~8KbM6Hi( zG%+YTM6`Qh2}DkQeOJ6JnL`S`(uU|(UxZUcNIa%T_J28?+em^Vc5+vKyx&>L(#I8o zn9D4^qoXxj=V6F~k162VP4KE3dL<9FB9nE@9;o=U?#J-`hWZwfk~=m>_CpdfrO5GP z#zO@-@l7x$x`&hdQph~;K|6Q&gV)Y5^NsoBdOEAG&s84wkv&~{V@K|!BmX=+Lyhw; zkO58=W7_gfgZwv_dEg&stYaJJofmLmWwVMwAwDe1O&WOjddvUVmFZh>7Qu*ZGbu1N zdFh&^6pogolUTt1O{vzxgNf0FK4iQfy&AEBlJPbrhx@9Ie=kIYa5}lRsc&Ol*$2u69Q1zRS`J6(?V#_-#IvX#*KYOy7>Ct;-u66Ce=`kv3K?bJtE8BrM+0 z?z~wgWGHcjqJ!uuA5>bR(q9ShROQ`XV&m;%}>waoA?i&|HjaBqknE z@9Xa~5pL&z*MN%7xWs@RU4E)q$F&U=o&;oX5l!0S_vXjZPWaUOXs?t2#H_m&^ZyAr zwP1U&#o=es{!D==L5nU`Hv8gFm%1e60!w5Hd=duDhDGW)HR`jN6uN$l1-4QfsjI{LB3Z{!MRj+&f6Z*9HG+<>HJ>0?--SQt8im65># z6MePHi2g-^TlVJpLEv7sZvyuzD<%-Qft)Ieq&T5N?bFBJFPG~}4?vLnpv*5loq8q0 z3u0%^sv?o|yIJ}DCbOHi620Vc#TZ3Z2H9Ax2?HR=KtDw#q4ZKeO6ZBXR6@}X%N055 zv^SW!Nyk#Cn2aXH4FKdxQtB9uiSSuDLaX(h?PR zy&!s#!Xf<{lCTeY~A_}I0;pIiA{qd z!&e7Wu%5PM!EkCBBX95l`WN8}b8zSs3l$$)C?f^{*y1*X)C#%yQIfNQft_t+C{po> zD<)WoFJ^&wZa~0{Opz=GXl0nfV~j^#9tUgj3vNmuV;0fmm>(}=k-N)2@MOWxZRqOh zj~7jY^FH=%OoQJ&zw7!~;LB=n0Zyyx$l~6nJxuqrU?D2emF!*)k(xKv>zC?geQzK#^2H6_pt1m*JbgyJmKaRJ2kG6e zaYC8Z?Xd{z_V(J&f$qJHBwS)OT^(E7T5Y7udwZ&r&uv}FZ`C1ALbg!7YuiPsIQ@(N zrOW@#kx~W4JB`G>1FCcRW-k`EqvzdZ$S%wK(f4cvOL_((PEgNLg~!pcL!u>on4n{E zdT|V-1m&};x%=E7DJsv6?#eJ1KDc$lbZa}~J%mxT)o2Tdn^)C;ad^gpnT5>D?_-VN zNA2~wDbFn{d1v8af6_ZL+@({T;oVm1Qz8r1$>880>n(C{30L?cpIau}2UemAz7na5kfF-QOB}?5mIfF%+xP;LaYIlIuf(~J9c3P;|eZIDp4tirCGFi2j zyr>>p;}0H}k64R_yY3MWAr&h?&^!+g+>}6y;st0w`987YFq=US!$Z~i1rDFBNr#-5 zwv(<^u6BtM8EfaRvl0d;e=aDImU*-zcgosN1}!pk^5=jw1~0^QiUg#f9fbb{d#R(Z(hQ zX`_PYY5h_d!O)3{`PC0c@ynFVLdBO)GH#dXna~^qOTd$eHc`LC(JJZ0M(|l z34^9?oe*h#;Y}qjiF_y6WfJk>LxAkvSF`Xn6039#x%)%Eo-z zt1;iqJ-aXg*uA1uVknSj2587ws@^4KXP^3+j`_IlOGB8hiUlBM* z&&XnQy(M*v$xvI8mqr)X$;lM+%xw?i&6cPa!Y(8}2J9CY`~o;AzVw!FmY{9L?Cabc z2-Z+RXjjGAS99K2U{N|SKa|{OKd7)?6U%mGE?Xf%guAK`7U=6Bi*)fAe6@f_Rnz=o^Z`g-8u$J5Iph=9`&xx>ZCcg=jIt7 z`pn8$n!Ar8vdclemjt;}Uuv`h(Exu7H2(j*vzu)Ra<-2hvW%(oHF~!F5s>=I_!wQZ$sY zqlN?XBgoBUPVlf=eCGH-m5=}kLZEtsl9d!GMtW-Y&O9NAIMpXJSyD*M4-HnwUDJvK zyeL(ARVyY3M3AVJED33grlI?|umGs^N!hB@^i^$Na&P+37eUC;cwk^!zg}-h9oWEx z+u*4YN&zt=EYhRHRma5x3#ittEgpno`q#8J z@rUrgrGoBp@4jZZ7+PCQQ_!$DbP(o|nBKPMhqG-V3e%kq65bdyss%&j6&GXGWk3 zlCB~O(r&d(_hL##J_qeVBDkzWE`ZDSU6l2K^#ddhCra~ZK*Z^}21>Tnq;6w^+6+a0fZ z_yP?-pbMJ{m8&03tmq&ad-U%VPt~5Eafu#O&5YgZc;@zMJsvPrNd@c$xPRqlpDEb{i?J_84g(qIW$f)7}Jyb+12Ev>OR0%=f?K-t%g;!3v!R;z!yJZwa{3%B-Q)d7w&=9k+lWxGd*{ddz++`)5AWuR z+v{fQo>xy5N3)E#FU%2p|niUC(jsY zzO18Fg{V5Wb#Gln!P)xlB9+y3s)aMqvZ1cC7lR5m`1AAv@4W#&IJD^YJ79yCW-Ck0 z)y@P{=IXVNyM;|4DZ#jbM z(9(cQYD6v7<%m})#3X_nGxBbTyQF8cnmpw%S-z$!PfRmH&FB%*luNu8+V-LD*8rJIgI8+SMZPisdr_0B|5BAE29Tykf2sDO>Y z>>gY)R*2|Mide&KTYCmT8{`Y_H9~^LwI<~Q%pf0JnvAx5fO?|b143=@rp#Q?N)184 z>t^FBU%r*(UNdqTnN^smIugLY@J*PQ!^`57-C8BMiK$d=O}<^O5J(_LsW>-_qM8bi zJa9LfG}Zhj)v<0SKIe+3ejyJ5HN;;3J4qmX)B#PU{%@GTY@;!p-$4^Z$U;TUzjM7U z43;$+JL?l;)eYDv|GQY5v5GvD55ib1<;9nSZA1)t#y>`_Gkym53UiW-3QD$RcUAQM zT2|hkLFz>l?uP3WBjdKgDAx=ckK{+McQ*)J=?o%z+&V~A;>2B zud2kf?`?f|xSWtD9sby}I=I>HI3ipm?@)H+lUQ=K$Oz(?u;D_*Z}4Qo@OxCbO>Cxj zNA8$sZzc~WQ~tdBoRXqBiQ8$=oK7dbV^*ot$-V(d+G&w*8DBL17WN20cV*_y#$*aK z)iJA|Y`=aPL)D(8e-n3dFnXJ;jh0kDZ0Xz`{e*FQaHM(5=D}e)n%XJyHa5~QIxl1V z3@`7>ytf>Huw2Zg+wWq-7+FE=!ED==I?BH0&cR^Sr=1#Ox{E(MXnWSVu%-c&hA?;{ z8JhuJT3PD zem^@sz@(F^s&6biAUtG%>^5Gle7S7;qV&`L4xU!@-dTTk`f0Y4r~CU7iX+$(ruY(y zPi+YYeC@ldc9)^H+yD7;XZ=27BfM_oMq60i#D4blsAtY9d0J*qr{3F}e)>|`es8{| J{AvB?{{agRq@n-- literal 0 HcmV?d00001 diff --git a/doc/manual/volume1/pp_nightly.sh b/doc/manual/volume1/pp_nightly.sh new file mode 100644 index 0000000..65ea612 --- /dev/null +++ b/doc/manual/volume1/pp_nightly.sh @@ -0,0 +1,46 @@ +#! /bin/sh + +PATH=/crg/pp/bin:/crg/pp/cmds/tools:/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/5bin: +export PATH +# +# Shell script run nightly to collect up things etc. +# +set -x +cd /crg/pp +L=logs +T=tables +STATDIR=/crg/pp/logs/statistics + +exec 1> $L/pp-nightly.log 2>&1 + +freespace . 2000 || { echo NO space left on device; exit 1; } + +#Save the stats files +if [ -f $L/stat ] +then + DATE=`date +%h-%d.%T` + [ -d $L/tmp ] || mkdir $L/tmp + mv $L/stat $L/tmp/stat.$DATE +fi + +# And then once a week... +if [ `date +%w` -eq 0 ] +then + YDATE=`date "+%h-%d-%y` + [ -d $STATDIR ] || mkdir $STATDIR + if pstat $L/tmp/* /dev/null | bin/stat.awk > $STATDIR/stats.$YDATE + then + echo 'Sucessful - removing old files' + rm $L/tmp/* + fi +fi + +# This should be first building command, as it updates the DERFIL2 file +echo 'building the PP tables' +(cd tables; make install) + +# update the niftp stuff +echo 'building the niftp database' +(cd niftp; make ) + +echo UPDATE complete diff --git a/doc/manual/volume1/pp_nightly.tex b/doc/manual/volume1/pp_nightly.tex new file mode 100644 index 0000000..4be5b9f --- /dev/null +++ b/doc/manual/volume1/pp_nightly.tex @@ -0,0 +1,47 @@ +\File{pp\_nightly.sh},{14:28},{Jun 12 1990} +\L{\LB{\C{}\#! \/bin\/sh}} +\CE{}\L{\LB{}} +\L{\LB{PATH=\/crg\/pp\/bin:\/crg\/pp\/cmds\/tools:\/usr\/local\/bin:\/usr\/ucb:\/bin:\/usr\/bin:\/usr\/5bin:}} +\L{\LB{export PATH}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# Shell script run nightly to collect up things etc.}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{set \-x}} +\L{\LB{cd \/crg\/pp}} +\L{\LB{L=logs}} +\L{\LB{T=tables}} +\L{\LB{STATDIR=\/crg\/pp\/logs\/statistics}} +\L{\LB{}} +\L{\LB{exec 1\> \$L\/pp\-nightly.log 2\>\&1}} +\L{\LB{}} +\L{\LB{freespace . 2000 \|\| \{ echo NO space left on device; exit 1; \}}} +\L{\LB{}} +\L{\LB{\C{}\#Save the stats files}} +\CE{}\L{\LB{if [ \-f \$L\/stat ]}} +\L{\LB{then}} +\L{\LB{}\Tab{8}{DATE=`date +\%h\-\%d.\%T`}} +\L{\LB{}\Tab{8}{[ \-d \$L\/tmp ] \|\| mkdir \$L\/tmp}} +\L{\LB{}\Tab{8}{mv \$L\/stat \$L\/tmp\/stat.\$DATE}} +\L{\LB{fi}} +\L{\LB{}} +\L{\LB{\C{}\# And then once a week...}} +\CE{}\L{\LB{if [ `date +\%w` \-eq 0 ]}} +\L{\LB{then}} +\L{\LB{}\Tab{8}{YDATE=`date \S{}\"+\%h\-\%d\-\%y`}} +\L{\LB{}\Tab{8}{[ \-d \$STATDIR ] \|\| mkdir \$STATDIR}} +\L{\LB{}\Tab{8}{if pstat \$L\/tmp\/* \/dev\/null \| bin\/stat.awk \> \$STATDIR\/stats.\$YDATE}} +\L{\LB{}\Tab{8}{then}} +\L{\LB{}\Tab{16}{echo \'Sucessful \- removing old files\'}} +\L{\LB{}\Tab{16}{rm \$L\/tmp\/*}} +\L{\LB{}\Tab{8}{fi}} +\L{\LB{fi}} +\L{\LB{}} +\L{\LB{\# This should be first building command, as it updates the DERFIL2 file}} +\L{\LB{echo \'building the PP tables\'}} +\L{\LB{(cd tables; make install)}} +\L{\LB{}} +\L{\LB{\# update the niftp stuff}} +\L{\LB{echo \'building the niftp database\'}} +\L{\LB{(cd niftp; make ) }} +\L{\LB{}} +\L{\LB{echo UPDATE complete}} diff --git a/doc/manual/volume1/pp_start.csh b/doc/manual/volume1/pp_start.csh new file mode 100644 index 0000000..46ac242 --- /dev/null +++ b/doc/manual/volume1/pp_start.csh @@ -0,0 +1,20 @@ +#! /bin/csh -f + +cd /usr/pp/pp/lib/chans +if [ -f smtpd -a -f smtpsrvr ]; then + (./smtpd `pwd`/smtpsrvr smtp > /dev/null 2>&1 ) & echo -n ' smtp' +fi + +cd /usr/pp/pp/lib/tools +su pp + +cd /usr/pp/pp/lib +echo -n ' pp.startaspp : ' +if ( -f pptsapd ) then + echo -n ' pptsapd ' + pptsapd >& /dev/null & +endif +if ( -f qmgr ) then + echo -n ' qmgr ' + qmgr >& /dev/null & +endif diff --git a/doc/manual/volume1/pp_start.sh b/doc/manual/volume1/pp_start.sh new file mode 100644 index 0000000..7990e2d --- /dev/null +++ b/doc/manual/volume1/pp_start.sh @@ -0,0 +1,22 @@ +#! /bin/sh + +# SMTP running under inetd +#cd /usr/pp/pp/lib/chans +#if [ -f smtpd -a -f smtpsrvr ]; then +# (./smtpd `pwd`/smtpsrvr smtp > /dev/null 2>&1 ) & +# echo -n ' smtp' +#fi + +cd /usr/pp/pp/lib +su pp < /dev/null 2>&1 +fi +if [ -f qmgr ]; then + echo -n ' qmgr ' + qmgr > /dev/null 2>&1 +fi +echo '.' +EOF diff --git a/doc/manual/volume1/pp_start.tex b/doc/manual/volume1/pp_start.tex new file mode 100644 index 0000000..ad63297 --- /dev/null +++ b/doc/manual/volume1/pp_start.tex @@ -0,0 +1,23 @@ +\File{pp\_start.sh},{18:00},{Dec 4 1989} +\L{\LB{\C{}\#! \/bin\/sh}} +\CE{}\L{\LB{}} +\L{\LB{\C{}\# SMTP running under inetd}} +\CE{}\L{\LB{\C{}\#cd \/usr\/pp\/pp\/lib\/chans}} +\CE{}\L{\LB{\C{}\#if [ \-f smtpd \-a \-f smtpsrvr ]; then}} +\CE{}\L{\LB{\C{}\#}\Tab{8}{(.\/smtpd `pwd`\/smtpsrvr smtp \> \/dev\/null 2\>\&1 ) \& }} +\CE{}\L{\LB{\C{}\#}\Tab{8}{echo \-n \' smtp\'}} +\CE{}\L{\LB{\C{}\#fi}} +\CE{}\L{\LB{}} +\L{\LB{\K{cd} \/usr\/pp\/pp\/lib}} +\L{\LB{su pp \<\ \/dev\/null 2\>\&1 }} +\L{\LB{\K{fi}}} +\L{\LB{\K{if} [ \-f qmgr ]; \K{then}}} +\L{\LB{}\Tab{8}{echo \-n \S{}\' qmgr \'\SE{}}} +\L{\LB{}\Tab{8}{qmgr \> \/dev\/null 2\>\&1}} +\L{\LB{\K{fi}}} +\L{\LB{echo \S{}\'.\'\SE{}}} +\L{\LB{EOF}} diff --git a/doc/manual/volume1/pptables.aux b/doc/manual/volume1/pptables.aux new file mode 100644 index 0000000..61b2467 --- /dev/null +++ b/doc/manual/volume1/pptables.aux @@ -0,0 +1,22 @@ +\relax +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.1}{\ignorespaces Example of the byhand file}}{55}} +\newlabel{example:byhand}{{5.1}{55}} +\global\@namedef{cp@pptables}{ +\setcounter{page}{57} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{5} +\setcounter{section}{4} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{1} +\setcounter{table}{1} +} diff --git a/doc/manual/volume1/pptables.tex b/doc/manual/volume1/pptables.tex new file mode 100644 index 0000000..e69de29 diff --git a/doc/manual/volume1/preface.aux b/doc/manual/volume1/preface.aux new file mode 100644 index 0000000..07b89e3 --- /dev/null +++ b/doc/manual/volume1/preface.aux @@ -0,0 +1,21 @@ +\relax +\citation{IFIP.PP} +\global\@namedef{cp@preface}{ +\setcounter{page}{9} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{0} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/preface.tex b/doc/manual/volume1/preface.tex new file mode 100644 index 0000000..9078aaa --- /dev/null +++ b/doc/manual/volume1/preface.tex @@ -0,0 +1,18 @@ +% -*- Latex -*- + +\preface + +This volume describes the installation and general operation of the PP +software. More details about its history, development and objectives +can be found in {\em PP Manual} introduction pages. + +There are several PP related papers in the directory \file{doc}. +In particular, a general overview of PP can be found in the +paper~\cite{IFIP.PP}. + +A guide to writing programs that interact with PP is given in {\em PP +Volume 2: Programmer's Guide}. + +A guide to the user-visible parts of PP can be found in {\em PP Volume +3: Users Guide}. + diff --git a/doc/manual/volume1/program.tex b/doc/manual/volume1/program.tex new file mode 100644 index 0000000..a6edd12 --- /dev/null +++ b/doc/manual/volume1/program.tex @@ -0,0 +1,76 @@ +% -*- LaTeX -*- +% run this through LaTeX + +% SEK - this is a PP document, designed to be easy to convert to +% an ISODE Manual Section if we want to + +\input lcustom + +\documentstyle[11pt,draftnote,sfwmac,tgrind,twoside]{report} + +\makeindex + +\newcount\volnum +\volnum=2 + +\pagenumbering{roman} + +\begin{document} + +\title{{\Huge PP} \\ + {\huge User's Manual}\vskip 1.5em + \LARGE\sl Volume 2: Programmers Guide} +\author{Julian Onions \\ Nottingham University} + + +\date{\ifdraft \versiondate/\\ \tt Draft Version \versiontag/\else \today\fi} + +\maketitle +\newpage + +\thispagestyle{empty} +\setcounter{page}{0} +\mbox{} +\newpage + +\tableofcontents +\footnotetext[0]{\hskip -\parindent +This document (version \versiontag/) +was \LaTeX set \today\ with \fmtname\ v\fmtversion.} + +\listoftables + +\listoffigures + +% \include{preface} + +\newpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi +\pagenumbering{arabic} + +% \part {Introduction} +% \include{introduction} + +% \part {Programming PP} +\include{general} +\include{submission} +\include{channels} +\include{delivery} + +% \bibliography{bcustom,sfwdoc,networking} +% \bibliographystyle{alpha} + +\input program.ind + +\clearpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi + +\typeout{you can usually ignore the message about Label(s) may have changed} + +\end{document} diff --git a/doc/manual/volume1/qfile.tex b/doc/manual/volume1/qfile.tex new file mode 100644 index 0000000..e29d6cd --- /dev/null +++ b/doc/manual/volume1/qfile.tex @@ -0,0 +1,37 @@ +\small\begin{verbatim} +Start-of-MsgEnvPrm +Message-type User-Mpdu +Message-size 84 +Number-warnings 000 +Warning-interval 24 +Return-interval 72 +Encoded-info EncTypes="hdr.822,ia5" +alt-recip-allowed true +cont-return true +Ua-id Test +pp-cont-corr "Subject: Test, To: pac" +content-corr 04165375626a6563743a20546573742c20546f3a20706163 none +Inbound-channel smtp +Inbound-mta "xtel.co.uk" +MsgId string="lancaster..123:25.08.91.15.53.50" Country=GB Admin=" " + Prmd="X-Tel Services" +Trace Country=GB Admin=" " Prmd="X-Tel Services" + arrival="Wed, 25 Sep 1991 16:53:49 +0100" action=0 End-of-block +Trace mta="lancaster.xtel.co.uk" Country=GB Admin=" " + Prmd="X-Tel Services" + arrival="Wed, 25 Sep 1991 15:53:50 +0000" action=0 End-of-block +Queued-time "Wed, 25 Sep 1991 15:53:51 +0000" +Start-of-MsgEnvAddr +Origs rno=000 status=done reform-done=000 reform-list="822tous|822tous.1" + outchan=dr2rfc outmta="lancaster.xtel.co.uk" ext-id=0 resp=false + mta-rreq=basic usr-rreq=basic type=822 eits="ia5,hdr.822-us" + content=822 orig="pp@xtel.co.uk" + x400="/I=P/S=Pat/O=XTEL/PRMD=X-Tel Services/ADMD= /C=GB/" + rfc="P.Pat@xtel.co.uk" end-of-addr +Recip rno=001 status=pend reform-done=001 reform-list="822tous|822tous.1" + outchan=822-local outmta="lancaster.xtel.co.uk" ext-id=1 + resp=true mta-rreq=basic usr-rreq=basic type=822 + eits="ia5,hdr.822-us" content=822 orig=pac + x400="/I=p/S=cowen/OU=x400/O=XTEL/PRMD=X-Tel Services/ADMD= /C=GB/" + rfc="p.cowen@x400.xtel.co.uk" end-of-addr +\end{verbatim} diff --git a/doc/manual/volume1/qmgrproto.aux b/doc/manual/volume1/qmgrproto.aux new file mode 100644 index 0000000..be21db9 --- /dev/null +++ b/doc/manual/volume1/qmgrproto.aux @@ -0,0 +1,26 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {F}QMGR Protocol}{154}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{qmgrros}{{F}{154}} +\newlabel{proto:qmgr}{{F.1}{154}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {F.1}{\ignorespaces QMGR ROS}}{163}} +\global\@namedef{cp@qmgrproto}{ +\setcounter{page}{164} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{6} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{1} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/qmgrproto.tex b/doc/manual/volume1/qmgrproto.tex new file mode 100644 index 0000000..64af145 --- /dev/null +++ b/doc/manual/volume1/qmgrproto.tex @@ -0,0 +1,5 @@ +\chapter {QMGR Protocol}\label{qmgrros} + +This appendix contains the ASN.1 description of the QMGR protocol. + +\tagrindfile {qmgrros}{QMGR ROS}{proto:qmgr} diff --git a/doc/manual/volume1/qmgrros.ry b/doc/manual/volume1/qmgrros.ry new file mode 100644 index 0000000..f805154 --- /dev/null +++ b/doc/manual/volume1/qmgrros.ry @@ -0,0 +1,527 @@ +-- qmgr.ry - Qmgr operation definitions + +Qmgr +DEFINITIONS ::= +BEGIN + +IMPORTS MPDUIdentifier FROM QmgrP1; + +-- EXPORTS everything + + +-- PORTS +qmgr-use OBJECT + PORTS { newmessage[S], + readmsginfo[S], + msginfo[C], + channelinitialise[C], + processmessage, + channelbegin[S], + readqueue[C], + channelread[S], + channelinfo[C], + channelcontrol[S], + mtaread[S], + mtainfo[C], + mtacontrol[S], + qmgrstatus[S], + readchannelmtamessage[S] } ::= id-pt-qmgr-use + + +activeChannel OBJECT + PORTS { channelinitialise, + processmessage [S] } + ::= id-pt-activeChannel + +passiveChannel OBJECT + PORTS { processmessage[S], + channelbegin[C] } + ::= id-pt-passiveChannel + +submitProcess OBJECT + PORTS { newmessage[C] } + ::= id-pt-submitProcess + +queueReadProcess OBJECT + PORTS { readqueue[S] } + ::= id-pt-queueReadProcess + +managementUA OBJECT + PORTS { processmessage[C], + readmsginfo[C], + msginfo[S], + channelread[C], + channelinfo[S], + channelcontrol[C], + mtaread[C], + mtainfo[S], + mtacontrol[C], + qmgrstatus[C], + readchannelmtamessage[C] } + ::= id-pt-managementUA + +-- OPERATIONS + + -- new message arrived + -- Submit -> QMGR +newmessage OPERATION + ARGUMENT MsgStruct + RESULT NULL + ERRORS { congested, protocol } + ::= 0 + + -- read a message + -- Console -> QMGR + -- QMGR -> QMGR +readmsginfo OPERATION + ARGUMENT ReadMessageArgument + RESULT MsgList + ERRORS { congested, protocol } + LINKED {msginfo} + ::= 1 + + -- QMGR -> Console + -- Incremental update +msginfo OPERATION + ARGUMENT MsgList + ::= 10 + + -- processes a message + -- QMGR -> Channel +processmessage OPERATION + ARGUMENT ProcMsg + RESULT DeliveryStatus + ERRORS { congested, protocol } + ::= 2 + + -- start up a channel + -- Channel -> QMGR +channelbegin OPERATION + ARGUMENT FilterList + -- type of message requested + RESULT FilterList + -- what you are going to get + ERRORS { congested, protocol } + ::= 3 + + -- read the entire queue + -- QMGR -> Q reader +readqueue OPERATION + ARGUMENT NULL + RESULT MsgList + ERRORS { congested, protocol } + ::= 4 + + -- read a channel + -- Console -> QMGR + -- get info at channel level +channelread OPERATION + ARGUMENT UTCTime + RESULT ChannelReadResult + ERRORS { congested, protocol } + LINKED {chaninfo} + ::= 5 + + -- QMGR -> Console + -- Incremental update +chaninfo OPERATION + ARGUMENT ChannelReadResult + -- info on ALL channels + ::= 11 + + -- control a channels behaviour + -- Console -> QMGR +channelcontrol OPERATION + ARGUMENT ChannelControl + RESULT PrioritisedChannelList + ERRORS { congested, protocol, noSuchChannel, illegalOperation, + authenticationFailure} + ::= 6 + + -- read about a mta + -- Console -> QMGR +mtaread OPERATION + ARGUMENT MtaRead + RESULT PrioritisedMtaList + ERRORS { congested, protocol, noSuchChannel } + LINKED {mtainfo} + ::= 7 + + -- QMGR -> Console + -- Incremental update +mtainfo OPERATION + ARGUMENT PrioritisedMtaList + ::= 12 + + -- control a mta + -- Console -> QMGR +mtacontrol OPERATION + ARGUMENT MtaControl + RESULT MtaInfo + ERRORS { congested, noSuchChannel, mtaNotInQueue, + authenticationFailure} + ::= 8 + + -- control a message + -- Console -> QMGR +msgcontrol OPERATION + ARGUMENT MsgControl + RESULT NULL + ERRORS { congested, protocol, noSuchChannel, mtaNotInQueue, + authenticationFailure} + ::= 13 + + -- QMGR -> Channel (process) +channelInitialise OPERATION + ARGUMENT Channel + RESULT NULL + ERRORS { congested, protocol, noSuchChannel} + ::= 9 + +qmgrControl OPERATION + ARGUMENT QMGRControl + RESULT NULL -- always works + ERRORS { congested, protocol, authenticationFailure} + ::= 14 + +readChannelMtaMessage OPERATION + ARGUMENT MsgRead + RESULT MsgList + ERRORS { congested, protocol, noSuchChannel, mtaNotInQueue } + ::= 15 + +qmgrStatus OPERATION + ARGUMENT NULL + RESULT QmgrStatus + ERRORS { congested, protocol } + ::= 16 +-- ERRORS + + -- congestion at the responder +congested ERROR + ::= 0 + + -- unknown channel +noSuchChannel ERROR + ::= 1 + + -- unknown operation +illegalOperation ERROR + ::= 2 + + -- operation on mta makes no sense +mtaNotInQueue ERROR + ::= 3 + + -- error in the protocol +protocol ERROR + ::= 4 + +authenticationFailure ERROR + ::= 5 + +-- Bind Arguments + +BindArgument ::= CHOICE { -- structure used in association request + noAuthentication [0] NULL, + weakAuthentication [1] WeakAuthentication + } + +WeakAuthentication ::= SEQUENCE { + username [0] IA5String, + passwd [1] IA5String OPTIONAL + } + +BindResult ::= SEQUENCE { + result[0] ENUMERATED { -- result from the association request + acceptedLimitedAccess(0), -- accepted limited access + acceptedFullAccess(1) -- accepted full access + }, + information[1] IA5String OPTIONAL, + version[2] IA5String OPTIONAL + } + + +BindError ::= SEQUENCE { + reason[0] ENUMERATED { + badCredentials(0), -- dont know this person + congested(1) -- some system problem + }, + information[1] IA5String OPTIONAL + } + +-- DATA TYPES + +Mta ::= IA5String + +Channel ::= PrintableString + +Priority ::= ENUMERATED {low(0), normal(1), high(2)} + -- Internal priorities COULD be different + -- to external ones + +UAContentId ::= PrintableString + +ContentType ::= PrintableString + +EncodedInformationTypes ::= SEQUENCE OF PrintableString + +QID ::= PrintableString + +User ::= IA5String + -- QMGR just sees users as strings. + -- This is 822 or /= X.400 syntax + -- The caller must get the right form! + + +ReadMessageArgument ::= SEQUENCE { + filters FilterList, + interval UTCTime OPTIONAL + -- interval for control of the LINKED operation + } + +MsgList ::= SEQUENCE { + msgs SEQUENCE OF %[ type_Qmgr_MsgStructList %] + MsgStruct, + deleted SEQUENCE OF %[ type_Qmgr_QidList %] QID OPTIONAL + } + +ProcMsg ::= SEQUENCE { + qid QID, + users UserList, + -- if USER 0, do all outstanding DNs + channel Channel -- Channel to apply + -- must be same for each user! + -- Warning and Expiry channels have "special" behaviour +} + +Control ::= CHOICE { + stop [0] NULL, + start [1] NULL, + cacheClear [2] NULL, + cacheAdd [3] UTCTime } + +ChannelControl ::= SEQUENCE { + channel [0] Channel, + control [1] Control + } + +MtaControl ::= SEQUENCE { + channel [0] Channel, + mta [1] Mta, + control [2] Control + } + +MsgControl ::= SEQUENCE { + qid [0] QID, + users [1] UserList, + control [2] Control + } + +UserList ::= SEQUENCE OF RecipientId + +RecipientId ::= INTEGER + +MsgStruct ::= SEQUENCE { + messageinfo [0] PerMessageInfo, + recipientlist [1] SEQUENCE OF %[ type_Qmgr_RecipientList %] + RecipientInfo + -- only recipients with responsibility bit set + -- AND originator (recipient 0) + -- The originator is needed for DRs + } + + +PerMessageInfo ::= SEQUENCE { + queueid [0] QID, + mpduiden [1] MPDUIdentifier, + originator [2] User, + contenttype [3] ContentType OPTIONAL, + eit [4] EncodedInformationTypes OPTIONAL, + priority [5] Priority, + size [6] INTEGER, + -- size in bytes + age [7] UTCTime, + warnInterval [8] INTEGER, + numberWarningsSent [9] INTEGER, + expiryTime [10] UTCTime, + deferredTime [11] UTCTime OPTIONAL, + uaContentId [12] UAContentId OPTIONAL, + errorCount [13] INTEGER OPTIONAL, + inChannel [14] Channel OPTIONAL + } + +ProcStatus ::= SEQUENCE { + enabled [0] BOOLEAN, + lastAttempt [1] UTCTime OPTIONAL, + cachedUntil [2] UTCTime OPTIONAL, + lastSuccess [3] UTCTime OPTIONAL + } + +RecipientInfo ::= SEQUENCE { + user [0] User, + id [1] RecipientId, + mta [2] Mta, + channelList [3] SEQUENCE OF %[ type_Qmgr_ChannelList %] Channel, + channelsDone [4] INTEGER, + -- Number of channels processed + -- If EQUAL to the number of channels, + -- this implies DN is still pending + procStatus [4] ProcStatus OPTIONAL, + info [5] IA5String OPTIONAL } + + +FilterList ::= SEQUENCE OF Filter + +Filter ::= SEQUENCE { + contenttype [0] ContentType OPTIONAL, + eit [1] EncodedInformationTypes OPTIONAL, + -- message must have only specified types + priority [2] Priority OPTIONAL, + -- messages of this priority and above + moreRecentThan [3] UTCTime OPTIONAL, + earlierThan [4] UTCTime OPTIONAL, + maxSize [5] INTEGER DEFAULT 0, + -- size in bytes + originator [6] User OPTIONAL, + recipient [7] User OPTIONAL, + channel [8] Channel OPTIONAL, + mta [9] Mta OPTIONAL, + queueid [10] QID OPTIONAL, + mpduiden [11] MPDUIdentifier OPTIONAL, + uaContentId [12] UAContentId OPTIONAL } + +ChannelReadResult ::= SEQUENCE { + channels [0] PrioritisedChannelList, + load1 [1] INTEGER DEFAULT 0, + load2 [2] INTEGER DEFAULT 0, + currchans [3] INTEGER DEFAULT 0, + maxchans [4] INTEGER DEFAULT 0} + +PrioritisedChannelList ::= SEQUENCE OF PrioritisedChannel + +PrioritisedChannel ::= SEQUENCE { + channel ChannelInfo, + priority Priority } + +ChannelInfo ::= SEQUENCE { + channel [0] Channel, + channelDescription [1] PrintableString, + oldestMessage [2] UTCTime, + numberMessages [3] INTEGER, -- not including DRs + volumeMessages [4] INTEGER, -- bytes + numberActiveProcesses [5] INTEGER, + status [6] ProcStatus, + numberReports [7] INTEGER, + direction [8] BITSTRING { + inbound (0), -- supports inbound traffic + outbound (1) -- supports outbound traffic + -- both bits on => does both + -- both bits off is internal + }, + chantype [9] ENUMERATED { + mta (0), -- is an MTA level channel + mts (1), -- is an MTS level channel + internal (2), -- is an internal channel (formatter etc) + passive (3) -- responding channel? + }, + maxprocs [10] INTEGER DEFAULT 0, + numberMtas [11] INTEGER DEFAULT 0 + + } + +MtaRead ::= SEQUENCE { + channel Channel, + time UTCTime OPTIONAL + } + +MsgRead ::= SEQUENCE { + channel Channel, + mta Mta, + time UTCTime OPTIONAL + } + +PrioritisedMtaList ::= SEQUENCE OF PrioritisedMta + +PrioritisedMta ::= SEQUENCE { + mta MtaInfo, + priority Priority } + +MtaInfo ::= SEQUENCE { + channel [0] Channel, + mta [1] Mta, + oldestMessage [2] UTCTime, + numberMessage [3] INTEGER, -- not DRs + volumeMessages [4] INTEGER, + status [5] ProcStatus, + numberDRs [6] INTEGER, + active [7] BOOLEAN DEFAULT FALSE, + info [8] IA5String OPTIONAL + } + +DeliveryStatus ::= SEQUENCE OF IndividualDeliveryStatus + + +IndividualDeliveryStatus ::= SEQUENCE { + recipient [0] RecipientId, + status [1] ENUMERATED { + -- The QMGR should treat the following + -- as successful. In the latter cases + -- a DR is processed in conjuction + -- with a different recipient + success (0), + successSharedDR (1), + failureSharedDR (2), + + -- The next set are treated by the + -- QMGR as now having to send a DR + negativeDR (3), -- negative DR + positiveDR (4), -- positive DR + + + -- the final set are different types + -- of transient failure, needing + -- different QMGR retry strategies + messageFailure (5),-- temp failure on the Message (e.g. + -- protocol temp reject) + mtaFailure (6), -- MTA failure (e.g. couldn't connect) + mtaAndMessageFailure (7) -- Both (e.g. connection bust) + }, + info[2] IA5String OPTIONAL + } + + +QMGRControl ::= SEQUENCE { + op [0] QMGROp + } + +QMGROp ::= ENUMERATED { + abort (0), + gracefulTerminate (1), + restart (2), -- as if from cold + rereadQueue (3), -- but don't discard current information + disableSubmission (4), -- Don't let processes submit + enableSubmission (5), + disableAll (6), + enableAll (7), + increasemaxchans(8), + decreasemaxchans(9) } + + +QmgrStatus ::= SEQUENCE { + boottime UTCTime, + messagesIn INTEGER, + messagesOut INTEGER, + addrIn INTEGER, + addrOut INTEGER, + opsPerSec INTEGER, -- * 100 + runnableChans INTEGER, -- * 100 + msgsInPerSec INTEGER, -- * 100 + msgsOutPerSec INTEGER, -- * 100 + maxChans INTEGER, + currChans INTEGER, + totalMsgs INTEGER, + totalVolume INTEGER, + totalDrs INTEGER + } +END diff --git a/doc/manual/volume1/qmgrros.tex b/doc/manual/volume1/qmgrros.tex new file mode 100644 index 0000000..a0239d5 --- /dev/null +++ b/doc/manual/volume1/qmgrros.tex @@ -0,0 +1,528 @@ +\File{qmgrros.ry},{12:38},{Mar 25 1991} +\L{\LB{\C{}\-\- qmgr.ry \- Qmgr operation definitions}} +\CE{}\L{\LB{}} +\L{\LB{Qmgr }} +\L{\LB{\Proc{DEFINITIONS}DEFINITIONS ::=}} +\L{\LB{BEGIN}} +\L{\LB{}} +\L{\LB{IMPORTS MPDUIdentifier FROM QmgrP1;}} +\L{\LB{}} +\L{\LB{\C{}\-\- EXPORTS everything}} +\CE{}\L{\LB{}} +\L{\LB{}} +\L{\LB{\C{}\-\- PORTS}} +\CE{}\L{\LB{qmgr\-use \K{OBJECT}}} +\L{\LB{ PORTS \{ newmessage[S],}} +\L{\LB{}\Tab{16}{readmsginfo[S],}} +\L{\LB{}\Tab{16}{msginfo[C],}} +\L{\LB{}\Tab{16}{channelinitialise[C],}} +\L{\LB{}\Tab{16}{processmessage,}} +\L{\LB{}\Tab{16}{channelbegin[S],}} +\L{\LB{}\Tab{16}{readqueue[C],}} +\L{\LB{ channelread[S],}} +\L{\LB{}\Tab{16}{channelinfo[C],}} +\L{\LB{}\Tab{16}{channelcontrol[S],}} +\L{\LB{}\Tab{16}{mtaread[S],}} +\L{\LB{}\Tab{16}{mtainfo[C],}} +\L{\LB{}\Tab{16}{mtacontrol[S],}} +\L{\LB{}\Tab{16}{qmgrstatus[S],}} +\L{\LB{}\Tab{16}{readchannelmtamessage[S] \} ::= id\-pt\-qmgr\-use}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{activeChannel \K{OBJECT}}} +\L{\LB{}\Tab{8}{ PORTS \{ channelinitialise, }} +\L{\LB{}\Tab{24}{processmessage [S] \}}} +\L{\LB{}\Tab{8}{::= id\-pt\-activeChannel}} +\L{\LB{}} +\L{\LB{passiveChannel \K{OBJECT}}} +\L{\LB{}\Tab{8}{ PORTS \{ processmessage[S],}} +\L{\LB{}\Tab{8}{ channelbegin[C] \}}} +\L{\LB{}\Tab{8}{::= id\-pt\-passiveChannel}} +\L{\LB{}} +\L{\LB{submitProcess \K{OBJECT}}} +\L{\LB{ PORTS \{ newmessage[C] \}}} +\L{\LB{}\Tab{8}{::= id\-pt\-submitProcess}} +\L{\LB{}} +\L{\LB{queueReadProcess \K{OBJECT} }} +\L{\LB{ PORTS \{ readqueue[S] \}}} +\L{\LB{}\Tab{8}{::= id\-pt\-queueReadProcess}} +\L{\LB{}} +\L{\LB{managementUA \K{OBJECT} }} +\L{\LB{}\Tab{8}{ PORTS \{ processmessage[C],}} +\L{\LB{}\Tab{8}{ readmsginfo[C],}} +\L{\LB{}\Tab{24}{msginfo[S],}} +\L{\LB{}\Tab{8}{ channelread[C],}} +\L{\LB{}\Tab{24}{channelinfo[S],}} +\L{\LB{}\Tab{24}{channelcontrol[C],}} +\L{\LB{}\Tab{8}{ mtaread[C],}} +\L{\LB{}\Tab{24}{mtainfo[S],}} +\L{\LB{}\Tab{8}{ mtacontrol[C],}} +\L{\LB{}\Tab{24}{qmgrstatus[C],}} +\L{\LB{}\Tab{24}{readchannelmtamessage[C] \}}} +\L{\LB{}\Tab{8}{::= id\-pt\-managementUA}} +\L{\LB{}} +\L{\LB{\C{}\-\- OPERATIONS}} +\CE{}\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- new message arrived}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Submit \-\> QMGR}} +\CE{}\L{\LB{newmessage OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MsgStruct}} +\L{\LB{}\Tab{8}{RESULT NULL}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{::= 0}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- read a message}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> QMGR}} +\CE{}\L{\LB{readmsginfo OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT ReadMessageArgument}} +\L{\LB{}\Tab{8}{RESULT MsgList}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{LINKED \{msginfo\}}} +\L{\LB{}\Tab{8}{::= 1}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Console}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Incremental update}} +\CE{}\L{\LB{msginfo OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MsgList}} +\L{\LB{}\Tab{8}{::= 10}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- processes a message}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Channel}} +\CE{}\L{\LB{processmessage OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT ProcMsg}} +\L{\LB{}\Tab{8}{RESULT DeliveryStatus}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{::= 2}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- start up a channel}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Channel \-\> QMGR}} +\CE{}\L{\LB{channelbegin OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT FilterList}} +\L{\LB{}\Tab{24}{\C{}\-\- type of message requested}} +\CE{}\L{\LB{}\Tab{8}{RESULT FilterList}} +\L{\LB{}\Tab{24}{\C{}\-\- what you are going to get}} +\CE{}\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{::= 3}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- read the entire queue}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Q reader}} +\CE{}\L{\LB{readqueue OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT NULL}} +\L{\LB{}\Tab{8}{RESULT MsgList}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{::= 4}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- read a channel}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- get info at channel level}} +\CE{}\L{\LB{channelread OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT UTCTime}} +\L{\LB{}\Tab{8}{RESULT ChannelReadResult}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{LINKED \{chaninfo\}}} +\L{\LB{}\Tab{8}{::= 5}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Console}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Incremental update}} +\CE{}\L{\LB{chaninfo OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT ChannelReadResult}} +\L{\LB{}\Tab{24}{\C{}\-\- info on ALL channels}} +\CE{}\L{\LB{}\Tab{8}{::= 11}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- control a channels behaviour}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{channelcontrol OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT ChannelControl}} +\L{\LB{}\Tab{8}{RESULT PrioritisedChannelList}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, noSuchChannel, illegalOperation,}} +\L{\LB{}\Tab{16}{authenticationFailure\}}} +\L{\LB{}\Tab{8}{::= 6}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- read about a mta}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{mtaread OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MtaRead}} +\L{\LB{}\Tab{8}{RESULT PrioritisedMtaList}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, noSuchChannel \}}} +\L{\LB{}\Tab{8}{LINKED \{mtainfo\}}} +\L{\LB{}\Tab{8}{::= 7}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Console}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Incremental update}} +\CE{}\L{\LB{mtainfo OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT PrioritisedMtaList}} +\L{\LB{}\Tab{8}{::= 12}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- control a mta}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{mtacontrol OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MtaControl}} +\L{\LB{}\Tab{8}{RESULT MtaInfo}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, noSuchChannel, mtaNotInQueue,}} +\L{\LB{ }\Tab{16}{authenticationFailure\}}} +\L{\LB{}\Tab{8}{::= 8}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- control a message}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- Console \-\> QMGR}} +\CE{}\L{\LB{msgcontrol OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MsgControl}} +\L{\LB{}\Tab{8}{RESULT NULL}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, noSuchChannel, mtaNotInQueue,}} +\L{\LB{ }\Tab{16}{authenticationFailure\}}} +\L{\LB{}\Tab{8}{::= 13}} +\L{\LB{}} +\L{\LB{}\Tab{32}{\C{}\-\- QMGR \-\> Channel (process)}} +\CE{}\L{\LB{channelInitialise OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT Channel}} +\L{\LB{}\Tab{8}{RESULT NULL}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, noSuchChannel\}}} +\L{\LB{}\Tab{8}{::= 9}} +\L{\LB{}} +\L{\LB{qmgrControl OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT QMGRControl}} +\L{\LB{}\Tab{8}{RESULT NULL \C{}\-\- always works}} +\CE{}\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, authenticationFailure\}}} +\L{\LB{}\Tab{8}{::= 14}} +\L{\LB{}} +\L{\LB{readChannelMtaMessage OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT MsgRead}} +\L{\LB{}\Tab{8}{RESULT MsgList}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol, noSuchChannel, mtaNotInQueue \}}} +\L{\LB{}\Tab{8}{::= 15}} +\L{\LB{}} +\L{\LB{qmgrStatus OPERATION}} +\L{\LB{}\Tab{8}{ARGUMENT NULL}} +\L{\LB{}\Tab{8}{RESULT QmgrStatus}} +\L{\LB{}\Tab{8}{ERRORS \{ congested, protocol \}}} +\L{\LB{}\Tab{8}{::= 16}} +\L{\LB{\C{}\-\- ERRORS}} +\CE{}\L{\LB{}} +\L{\LB{}\Tab{24}{\C{}\-\- congestion at the responder}} +\CE{}\L{\LB{congested ERROR}} +\L{\LB{}\Tab{8}{::=}\Tab{24}{0}} +\L{\LB{}} +\L{\LB{}\Tab{24}{\C{}\-\- unknown channel}} +\CE{}\L{\LB{noSuchChannel ERROR}} +\L{\LB{}\Tab{8}{::=}\Tab{24}{1}} +\L{\LB{}} +\L{\LB{}\Tab{24}{\C{}\-\- unknown operation}} +\CE{}\L{\LB{illegalOperation ERROR}} +\L{\LB{}\Tab{8}{::=}\Tab{24}{2}} +\L{\LB{}} +\L{\LB{}\Tab{24}{\C{}\-\- operation on mta makes no sense}} +\CE{}\L{\LB{mtaNotInQueue ERROR}} +\L{\LB{}\Tab{8}{::=}\Tab{24}{3}} +\L{\LB{}} +\L{\LB{}\Tab{24}{\C{}\-\- error in the protocol}} +\CE{}\L{\LB{protocol ERROR}} +\L{\LB{}\Tab{8}{::=}\Tab{24}{4}} +\L{\LB{}} +\L{\LB{authenticationFailure ERROR}} +\L{\LB{}\Tab{8}{::= }\Tab{24}{5}} +\L{\LB{}} +\L{\LB{\C{}\-\- Bind Arguments}} +\CE{}\L{\LB{}} +\L{\LB{BindArgument ::= CHOICE \{}\Tab{32}{\C{}\-\- structure used in association request}} +\CE{}\L{\LB{}\Tab{8}{noAuthentication [0] NULL,}} +\L{\LB{}\Tab{8}{weakAuthentication [1] WeakAuthentication}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{WeakAuthentication ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{username [0] IA5String,}} +\L{\LB{}\Tab{8}{passwd [1] IA5String OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{BindResult ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{result[0] ENUMERATED \{}\Tab{40}{\C{}\-\- result from the association request}} +\CE{}\L{\LB{}\Tab{24}{acceptedLimitedAccess(0), \C{}\-\- accepted limited access}} +\CE{}\L{\LB{}\Tab{24}{acceptedFullAccess(1)}\Tab{48}{ \C{}\-\- accepted full access}} +\CE{}\L{\LB{}\Tab{16}{\},}} +\L{\LB{}\Tab{16}{information[1] IA5String OPTIONAL,}} +\L{\LB{}\Tab{16}{version[2] IA5String OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{BindError ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{reason[0] ENUMERATED \{}} +\L{\LB{}\Tab{24}{badCredentials(0),}\Tab{48}{\C{}\-\- dont know this person}} +\CE{}\L{\LB{}\Tab{24}{congested(1)}\Tab{48}{\C{}\-\- some system problem}} +\CE{}\L{\LB{}\Tab{16}{\},}} +\L{\LB{}\Tab{16}{information[1] IA5String OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{\C{}\-\- DATA TYPES}} +\CE{}\L{\LB{}} +\L{\LB{Mta ::= IA5String}} +\L{\LB{}} +\L{\LB{Channel ::= PrintableString}} +\L{\LB{}} +\L{\LB{Priority ::= ENUMERATED \{low(0), normal(1), high(2)\}}} +\L{\LB{}\Tab{24}{\C{}\-\- Internal priorities COULD be different}} +\CE{}\L{\LB{}\Tab{24}{\C{}\-\- to external ones}} +\CE{}\L{\LB{}} +\L{\LB{UAContentId ::= PrintableString}} +\L{\LB{}} +\L{\LB{ContentType ::= PrintableString}} +\L{\LB{}} +\L{\LB{EncodedInformationTypes ::= SEQUENCE OF PrintableString}} +\L{\LB{}} +\L{\LB{QID ::= PrintableString}} +\L{\LB{}} +\L{\LB{User ::= IA5String}} +\L{\LB{}\Tab{24}{\C{}\-\- QMGR just sees users as strings.}} +\CE{}\L{\LB{}\Tab{24}{\C{}\-\- This is 822 or \/= X.400 syntax}} +\CE{}\L{\LB{}\Tab{24}{\C{}\-\- The caller must get the right form!}} +\CE{}\L{\LB{}\Tab{24}{}} +\L{\LB{}} +\L{\LB{ReadMessageArgument ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{filters FilterList,}} +\L{\LB{}\Tab{16}{interval UTCTime OPTIONAL}} +\L{\LB{}\Tab{24}{\C{}\-\- interval for control of the LINKED operation}} +\CE{}\L{\LB{}\Tab{16}{\}}} +\L{\LB{}} +\L{\LB{MsgList}\Tab{8}{::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{msgs SEQUENCE OF \K{\%}[ type\_Qmgr\_MsgStructList \K{\%}]}} +\L{\LB{}\Tab{24}{MsgStruct,}} +\L{\LB{}\Tab{16}{deleted SEQUENCE OF \K{\%}[ type\_Qmgr\_QidList \K{\%}] QID OPTIONAL}} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}} +\L{\LB{ProcMsg ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{qid QID,}} +\L{\LB{}\Tab{8}{users UserList,}} +\L{\LB{}\Tab{24}{\C{}\-\- if USER 0, do all outstanding DNs}} +\CE{}\L{\LB{}\Tab{8}{channel Channel \C{}\-\- Channel to apply}} +\CE{}\L{\LB{}\Tab{16}{\C{}\-\- must be same for each user!}} +\CE{}\L{\LB{}\Tab{16}{\C{}\-\- Warning and Expiry channels have \"special\" behaviour}} +\CE{}\L{\LB{\}}} +\L{\LB{}} +\L{\LB{Control ::= CHOICE \{}} +\L{\LB{}\Tab{16}{stop [0] NULL,}} +\L{\LB{}\Tab{16}{start [1] NULL,}} +\L{\LB{}\Tab{16}{cacheClear [2] NULL,}} +\L{\LB{}\Tab{16}{cacheAdd [3] UTCTime \}}} +\L{\LB{}} +\L{\LB{ChannelControl ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{channel [0] Channel,}} +\L{\LB{}\Tab{16}{control [1] Control }} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}} +\L{\LB{MtaControl ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{channel [0] Channel,}} +\L{\LB{}\Tab{16}{mta [1] Mta,}} +\L{\LB{}\Tab{16}{control [2] Control }} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}} +\L{\LB{MsgControl ::= SEQUENCE \{}} +\L{\LB{}\Tab{16}{qid [0] QID,}} +\L{\LB{}\Tab{16}{users [1] UserList,}} +\L{\LB{}\Tab{16}{control [2] Control}} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}} +\L{\LB{UserList ::= SEQUENCE OF RecipientId}} +\L{\LB{}} +\L{\LB{RecipientId ::= INTEGER}} +\L{\LB{}} +\L{\LB{MsgStruct ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{messageinfo}\Tab{24}{[0] PerMessageInfo,}} +\L{\LB{}\Tab{8}{recipientlist}\Tab{24}{[1] SEQUENCE OF \K{\%}[ type\_Qmgr\_RecipientList \K{\%}]}} +\L{\LB{}\Tab{32}{RecipientInfo}} +\L{\LB{}\Tab{24}{\C{}\-\- only recipients with responsibility bit set}} +\CE{}\L{\LB{}\Tab{24}{\C{}\-\- AND originator (recipient 0)}} +\CE{}\L{\LB{}\Tab{24}{\C{}\-\- The originator is needed for DRs}} +\CE{}\L{\LB{}\Tab{8}{\}}} +\L{\LB{}\Tab{24}{}} +\L{\LB{}} +\L{\LB{PerMessageInfo ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{queueid}\Tab{24}{[0] QID,}} +\L{\LB{}\Tab{8}{mpduiden}\Tab{24}{[1] MPDUIdentifier,}} +\L{\LB{}\Tab{8}{originator}\Tab{24}{[2] User,}} +\L{\LB{}\Tab{8}{contenttype}\Tab{24}{[3] ContentType OPTIONAL,}} +\L{\LB{}\Tab{8}{eit}\Tab{24}{[4] EncodedInformationTypes OPTIONAL,}} +\L{\LB{}\Tab{8}{priority}\Tab{24}{[5] Priority,}} +\L{\LB{}\Tab{8}{size}\Tab{24}{[6] INTEGER,}} +\L{\LB{}\Tab{24}{\C{}\-\- size in bytes}} +\CE{}\L{\LB{}\Tab{8}{age}\Tab{24}{[7] UTCTime,}} +\L{\LB{}\Tab{8}{warnInterval}\Tab{24}{[8] INTEGER,}} +\L{\LB{}\Tab{8}{numberWarningsSent [9] INTEGER,}} +\L{\LB{}\Tab{8}{expiryTime }\Tab{24}{[10] UTCTime,}} +\L{\LB{}\Tab{8}{deferredTime}\Tab{24}{[11] UTCTime OPTIONAL,}} +\L{\LB{}\Tab{8}{uaContentId}\Tab{24}{[12] UAContentId OPTIONAL,}} +\L{\LB{}\Tab{8}{errorCount}\Tab{24}{[13] INTEGER OPTIONAL,}} +\L{\LB{}\Tab{8}{inChannel}\Tab{24}{[14] Channel OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{ProcStatus ::= }\Tab{16}{SEQUENCE \{}} +\L{\LB{}\Tab{8}{enabled}\Tab{24}{[0] BOOLEAN,}} +\L{\LB{}\Tab{8}{lastAttempt}\Tab{24}{[1] UTCTime OPTIONAL,}} +\L{\LB{}\Tab{8}{cachedUntil}\Tab{24}{[2] UTCTime OPTIONAL,}} +\L{\LB{}\Tab{8}{lastSuccess}\Tab{24}{[3] UTCTime OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{RecipientInfo ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{user}\Tab{16}{ }\Tab{24}{[0] User,}} +\L{\LB{}\Tab{8}{id}\Tab{24}{[1] RecipientId,}} +\L{\LB{}\Tab{8}{mta}\Tab{24}{[2] Mta,}} +\L{\LB{}\Tab{8}{channelList}\Tab{24}{[3] SEQUENCE OF \K{\%}[ type\_Qmgr\_ChannelList \K{\%}] Channel,}} +\L{\LB{}\Tab{8}{channelsDone [4] INTEGER,}} +\L{\LB{}\Tab{32}{\C{}\-\- Number of channels processed}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- If EQUAL to the number of channels, }} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- this implies DN is still pending}} +\CE{}\L{\LB{}\Tab{8}{procStatus }\Tab{24}{[4] ProcStatus OPTIONAL,}} +\L{\LB{}\Tab{8}{info}\Tab{24}{[5] IA5String OPTIONAL \}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{FilterList ::= SEQUENCE OF Filter}} +\L{\LB{}} +\L{\LB{Filter ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{contenttype}\Tab{24}{[0] ContentType OPTIONAL,}} +\L{\LB{}\Tab{8}{eit}\Tab{24}{[1] EncodedInformationTypes OPTIONAL,}} +\L{\LB{}\Tab{24}{\C{}\-\- message must have only specified types}} +\CE{}\L{\LB{}\Tab{8}{priority}\Tab{24}{[2] Priority OPTIONAL,}} +\L{\LB{}\Tab{24}{\C{}\-\- messages of this priority and above}} +\CE{}\L{\LB{}\Tab{8}{moreRecentThan}\Tab{24}{[3] UTCTime OPTIONAL,}} +\L{\LB{}\Tab{8}{earlierThan}\Tab{24}{[4] UTCTime OPTIONAL,}} +\L{\LB{}\Tab{8}{maxSize}\Tab{24}{[5] INTEGER DEFAULT 0,}} +\L{\LB{}\Tab{24}{\C{}\-\- size in bytes}} +\CE{}\L{\LB{}\Tab{8}{originator}\Tab{24}{[6] User OPTIONAL,}} +\L{\LB{}\Tab{8}{recipient}\Tab{24}{[7] User OPTIONAL,}} +\L{\LB{}\Tab{8}{channel}\Tab{24}{[8] Channel OPTIONAL,}} +\L{\LB{}\Tab{8}{mta}\Tab{24}{[9] Mta OPTIONAL,}} +\L{\LB{}\Tab{8}{queueid}\Tab{24}{[10] QID OPTIONAL,}} +\L{\LB{}\Tab{8}{mpduiden}\Tab{24}{[11] MPDUIdentifier OPTIONAL,}} +\L{\LB{}\Tab{8}{uaContentId}\Tab{24}{[12] UAContentId OPTIONAL \}}} +\L{\LB{}} +\L{\LB{ChannelReadResult ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channels}\Tab{24}{[0] PrioritisedChannelList,}} +\L{\LB{}\Tab{8}{load1}\Tab{24}{[1] INTEGER DEFAULT 0,}} +\L{\LB{}\Tab{8}{load2}\Tab{24}{[2] INTEGER DEFAULT 0,}} +\L{\LB{}\Tab{8}{currchans}\Tab{24}{[3] INTEGER DEFAULT 0,}} +\L{\LB{}\Tab{8}{maxchans}\Tab{24}{[4] INTEGER DEFAULT 0\}}} +\L{\LB{}} +\L{\LB{PrioritisedChannelList ::= SEQUENCE OF PrioritisedChannel}} +\L{\LB{}} +\L{\LB{PrioritisedChannel ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channel}\Tab{16}{ChannelInfo,}} +\L{\LB{}\Tab{8}{priority Priority \}}} +\L{\LB{}} +\L{\LB{ChannelInfo ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channel}\Tab{24}{[0] Channel,}} +\L{\LB{}\Tab{8}{channelDescription [1] PrintableString,}} +\L{\LB{}\Tab{8}{oldestMessage}\Tab{24}{[2] UTCTime,}} +\L{\LB{}\Tab{8}{numberMessages}\Tab{24}{[3] INTEGER, \C{}\-\- not including DRs}} +\CE{}\L{\LB{}\Tab{8}{volumeMessages}\Tab{24}{[4] INTEGER,}\Tab{40}{\C{}\-\- bytes}} +\CE{}\L{\LB{}\Tab{8}{numberActiveProcesses [5] INTEGER,}} +\L{\LB{}\Tab{8}{status}\Tab{24}{[6] ProcStatus,}} +\L{\LB{}\Tab{8}{numberReports [7] INTEGER,}} +\L{\LB{}\Tab{8}{direction}\Tab{24}{[8] BITSTRING \{}} +\L{\LB{}\Tab{16}{inbound (0),}\Tab{32}{\C{}\-\- supports inbound traffic}} +\CE{}\L{\LB{}\Tab{16}{outbound (1)}\Tab{32}{\C{}\-\- supports outbound traffic}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- both bits on =\> does both}} +\CE{}\L{\LB{}\Tab{32}{\C{}\-\- both bits off is internal}} +\CE{}\L{\LB{}\Tab{16}{\},}} +\L{\LB{}\Tab{8}{chantype}\Tab{24}{[9] ENUMERATED \{}} +\L{\LB{}\Tab{16}{mta (0),}\Tab{32}{\C{}\-\- is an MTA level channel}} +\CE{}\L{\LB{}\Tab{16}{mts (1),}\Tab{32}{\C{}\-\- is an MTS level channel}} +\CE{}\L{\LB{}\Tab{16}{internal (2),}\Tab{32}{\C{}\-\- is an internal channel (formatter etc)}} +\CE{}\L{\LB{}\Tab{16}{passive (3)}\Tab{32}{\C{}\-\- responding channel?}} +\CE{}\L{\LB{}\Tab{16}{\},}} +\L{\LB{}\Tab{8}{maxprocs}\Tab{24}{[10] INTEGER DEFAULT 0,}} +\L{\LB{}\Tab{8}{numberMtas}\Tab{24}{[11] INTEGER DEFAULT 0}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{MtaRead ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channel Channel,}} +\L{\LB{}\Tab{8}{time UTCTime OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{MsgRead ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channel Channel,}} +\L{\LB{}\Tab{8}{mta Mta,}} +\L{\LB{}\Tab{8}{time UTCTime OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{PrioritisedMtaList ::= SEQUENCE OF PrioritisedMta}} +\L{\LB{}} +\L{\LB{PrioritisedMta ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{mta MtaInfo,}} +\L{\LB{}\Tab{8}{priority Priority \}}} +\L{\LB{}} +\L{\LB{MtaInfo ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{channel}\Tab{24}{[0] Channel,}} +\L{\LB{}\Tab{8}{mta}\Tab{24}{[1] Mta,}} +\L{\LB{}\Tab{8}{oldestMessage}\Tab{24}{[2] UTCTime,}} +\L{\LB{}\Tab{8}{numberMessage}\Tab{24}{[3] INTEGER, \C{}\-\- not DRs}} +\CE{}\L{\LB{}\Tab{8}{volumeMessages}\Tab{24}{[4] INTEGER,}} +\L{\LB{}\Tab{8}{status}\Tab{24}{[5] ProcStatus,}} +\L{\LB{}\Tab{8}{numberDRs}\Tab{24}{[6] INTEGER,}} +\L{\LB{}\Tab{8}{active}\Tab{24}{[7] BOOLEAN DEFAULT FALSE,}} +\L{\LB{}\Tab{8}{info}\Tab{24}{[8] IA5String OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{DeliveryStatus ::= SEQUENCE OF IndividualDeliveryStatus}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{IndividualDeliveryStatus ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{recipient [0] RecipientId,}} +\L{\LB{}\Tab{8}{status}\Tab{16}{ [1] ENUMERATED \{}} +\L{\LB{}\Tab{32}{ \C{}\-\- The QMGR should treat the following}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- as successful. In the latter cases}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- a DR is processed in conjuction}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- with a different recipient}} +\CE{}\L{\LB{}\Tab{16}{success (0),}} +\L{\LB{}\Tab{16}{successSharedDR (1),}} +\L{\LB{}\Tab{16}{failureSharedDR (2),}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{32}{ \C{}\-\- The next set are treated by the}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- QMGR as now having to send a DR}} +\CE{}\L{\LB{}\Tab{16}{negativeDR (3), \C{}\-\- negative DR}} +\CE{}\L{\LB{}\Tab{16}{positiveDR (4),}\Tab{32}{ \C{}\-\- positive DR}} +\CE{}\L{\LB{}\Tab{32}{ }} +\L{\LB{}} +\L{\LB{}\Tab{32}{ \C{}\-\- the final set are different types}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- of transient failure, needing}} +\CE{}\L{\LB{}\Tab{32}{ \C{}\-\- different QMGR retry strategies}} +\CE{}\L{\LB{}\Tab{16}{messageFailure (5),\C{}\-\- temp failure on the Message (e.g. }} +\CE{}\L{\LB{}\Tab{24}{ }\Tab{32}{ \C{}\-\- protocol temp reject)}} +\CE{}\L{\LB{}\Tab{16}{mtaFailure (6),}\Tab{32}{ \C{}\-\- MTA failure (e.g. couldn\'t connect)}} +\CE{}\L{\LB{}\Tab{16}{mtaAndMessageFailure (7) \C{}\-\- Both (e.g. connection bust)}} +\CE{}\L{\LB{}\Tab{16}{\},}} +\L{\LB{}\Tab{8}{info[2] IA5String OPTIONAL}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{QMGRControl ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{op [0] QMGROp}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{QMGROp ::= ENUMERATED \{}} +\L{\LB{}\Tab{8}{abort (0),}\Tab{24}{}} +\L{\LB{}\Tab{8}{gracefulTerminate (1),}} +\L{\LB{}\Tab{8}{restart (2),}\Tab{24}{\C{}\-\- as if from cold}} +\CE{}\L{\LB{}\Tab{8}{rereadQueue (3), \C{}\-\- but don\'t discard current information}} +\CE{}\L{\LB{}\Tab{8}{disableSubmission (4), \C{}\-\- Don\'t let processes submit}} +\CE{}\L{\LB{}\Tab{8}{enableSubmission (5),}} +\L{\LB{}\Tab{8}{disableAll (6),}} +\L{\LB{}\Tab{8}{enableAll (7),}} +\L{\LB{}\Tab{8}{increasemaxchans(8),}} +\L{\LB{}\Tab{8}{decreasemaxchans(9) \}}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}} +\L{\LB{QmgrStatus ::= SEQUENCE \{}} +\L{\LB{}\Tab{8}{boottime }\Tab{24}{UTCTime,}} +\L{\LB{}\Tab{8}{messagesIn }\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{messagesOut }\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{addrIn}\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{addrOut}\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{opsPerSec }\Tab{24}{INTEGER,}\Tab{40}{\C{}\-\- * 100}} +\CE{}\L{\LB{}\Tab{8}{runnableChans }\Tab{24}{INTEGER,}\Tab{40}{\C{}\-\- * 100}} +\CE{}\L{\LB{}\Tab{8}{msgsInPerSec }\Tab{24}{INTEGER,}\Tab{40}{\C{}\-\- * 100}} +\CE{}\L{\LB{}\Tab{8}{msgsOutPerSec }\Tab{24}{INTEGER,}\Tab{40}{\C{}\-\- * 100}} +\CE{}\L{\LB{}\Tab{8}{maxChans }\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{currChans }\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{totalMsgs}\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{totalVolume}\Tab{24}{INTEGER,}} +\L{\LB{}\Tab{8}{totalDrs}\Tab{24}{INTEGER}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{END}} diff --git a/doc/manual/volume1/rfc1148g.tex b/doc/manual/volume1/rfc1148g.tex new file mode 100644 index 0000000..31b2cba --- /dev/null +++ b/doc/manual/volume1/rfc1148g.tex @@ -0,0 +1,4 @@ +\small\begin{verbatim} +ca:O$ubc.PRMD$cdn.ADMD$telecom\.canada.C$ca +uk:OU$CS.O$UCL.PRMD$UK\.AC.ADMD$ .C$GB +\end{verbatim} diff --git a/doc/manual/volume1/rfc2or.tex b/doc/manual/volume1/rfc2or.tex new file mode 100644 index 0000000..5691855 --- /dev/null +++ b/doc/manual/volume1/rfc2or.tex @@ -0,0 +1,21 @@ +\begin{quote}\small\begin{verbatim} +# +# extract of `rfc2or' table +# +gold-400.gb:ADMD$GOLD 400.C$GB +# +# -*** via gold 400 ADMD ***- +# +telecom-gold.gold-400.gb:PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB +digital.gold-400.gb:PRMD$DIGITAL.ADMD$GOLD 400.C$GB +# +# +# -*** france ***- +# +fr:PRMD$fnet.ADMD$ptt.C$fr +ptt.fr:ADMD$PTT.C$Fr +aristote.fr:PRMD$aristote.ADMD$PTT.C$Fr +bullmts.fr:PRMD$BULLMTS.ADMD$ATLAS.C$FR +derieux.fr:PRMD$DERIEUX.ADMD$ATLAS.C$FR +# +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/shelfilt.sh b/doc/manual/volume1/shelfilt.sh new file mode 100644 index 0000000..5d13b8c --- /dev/null +++ b/doc/manual/volume1/shelfilt.sh @@ -0,0 +1,11 @@ +#! /bin/sh + +# +# Voice -> IA5 conversion filter +# + +echo "********************" +echo "There was a voice body part here, which was" +echo "removed in the conversion process" +echo "********************" +exit 0 diff --git a/doc/manual/volume1/shelfilt.tex b/doc/manual/volume1/shelfilt.tex new file mode 100644 index 0000000..48f88dc --- /dev/null +++ b/doc/manual/volume1/shelfilt.tex @@ -0,0 +1,12 @@ +\File{shelfilt.sh},{09:32},{Dec 5 1989} +\L{\LB{\C{}\#! \/bin\/sh}} +\CE{}\L{\LB{}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# Voice \-\> IA5 conversion filter}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{}} +\L{\LB{echo \S{}\"********************\"\SE{}}} +\L{\LB{echo \S{}\"There was a voice body part here, which was\"\SE{}}} +\L{\LB{echo \S{}\"removed in the conversion process\"\SE{}}} +\L{\LB{echo \S{}\"********************\"\SE{}}} +\L{\LB{\K{exit} 0}} diff --git a/doc/manual/volume1/shell-examp.tex b/doc/manual/volume1/shell-examp.tex new file mode 100644 index 0000000..5bdd06c --- /dev/null +++ b/doc/manual/volume1/shell-examp.tex @@ -0,0 +1,10 @@ +\small\begin{verbatim} + +##################### extract of `shell' table #################### +# +nullshell:pac,60,sh -c "/bin/cat > /dev/null" +usefulshell:jpo,,usefulshellprog $(ua_id) +lynx:pp,0|solo,/usr/ucb/lpr -Plynx +# +\end{verbatim} + diff --git a/doc/manual/volume1/shellfilt.sh b/doc/manual/volume1/shellfilt.sh new file mode 100644 index 0000000..5d13b8c --- /dev/null +++ b/doc/manual/volume1/shellfilt.sh @@ -0,0 +1,11 @@ +#! /bin/sh + +# +# Voice -> IA5 conversion filter +# + +echo "********************" +echo "There was a voice body part here, which was" +echo "removed in the conversion process" +echo "********************" +exit 0 diff --git a/doc/manual/volume1/table-examp.tai b/doc/manual/volume1/table-examp.tai new file mode 100644 index 0000000..3f0f161 --- /dev/null +++ b/doc/manual/volume1/table-examp.tai @@ -0,0 +1,9 @@ +tbl aliases show="Aliases: mapping -> local id", + flags=dbm,file=local-aliases +tbl domain show="Mapping domain key ->full domain/MTA", + flags=dbm,override="xtel.co.uk:local" +tbl or show="Mapping O/R Address -> MTA",flags=dbm +tbl or2rfc show="RFC 987: X.400 -> RFC 822",flags=dbm +tbl rfc2or show="RFC 987: RFC 822 -> X.400",flags=dbm +tbl channel show="Binding MTA -> Channels",flags=dbm +tbl auth.qmgr show="Qmgr authorisation",flags=linear diff --git a/doc/manual/volume1/table-examp.tex b/doc/manual/volume1/table-examp.tex new file mode 100644 index 0000000..adc5fd3 --- /dev/null +++ b/doc/manual/volume1/table-examp.tex @@ -0,0 +1,10 @@ +\File{table\-examp.tai},{16:06},{Nov 19 1991} +\L{\LB{tbl}\Tab{8}{aliases}\Tab{16}{show=\S{}\"Aliases: mapping \-\> local id\"\SE{},}} +\L{\LB{}\Tab{16}{flags=dbm,file=local\-aliases}} +\L{\LB{tbl}\Tab{8}{domain}\Tab{16}{show=\S{}\"Mapping domain key \-\>full domain\/MTA\"\SE{},}} +\L{\LB{}\Tab{16}{flags=dbm,override=\S{}\"xtel.co.uk:local\"\SE{}}} +\L{\LB{tbl}\Tab{8}{or}\Tab{16}{show=\S{}\"Mapping O\/R Address \-\> MTA\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{or2rfc}\Tab{16}{show=\S{}\"RFC 987: X.400 \-\> RFC 822\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{rfc2or}\Tab{16}{show=\S{}\"RFC 987: RFC 822 \-\> X.400\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{channel}\Tab{16}{show=\S{}\"Binding MTA \-\> Channels\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{auth.qmgr show=\S{}\"Qmgr authorisation\"\SE{},flags=linear}} diff --git a/doc/manual/volume1/tableauthreasons.tex b/doc/manual/volume1/tableauthreasons.tex new file mode 100644 index 0000000..0ee0f61 --- /dev/null +++ b/doc/manual/volume1/tableauthreasons.tex @@ -0,0 +1,30 @@ +\[\begin{tabular}{|p{0.9\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Failure Reasons} \\ +\hline\hline + unknown error\\ + access policy: none \\ + negative: in-MTA (\%s \%s) sender (\%s \%s) out-MTA (\%s \%s) recip + ((\%s \%s) \\ + block: in-MTA (\%s \%s) sender (\%s \%s) out-MTA (\%s \%s) recip (\%s + (\%s) \\ + inbound MTA regex : \%s does not include sender \\ + inbound MTA regex : \%s excludes sender \\ + outbound MTA regex : \%s does not include recipient \\ + outbound MTA regex : \%s excludes recipient \\ + message size \%s exceeds channel limit \%s \\ + message size \%s exceeds mta limit \%s \\ + message size \%s exceed user limit \%s \\ + illegal body part : \%s ( mta restriction ) \\ + illegal body part : \%s ( user restriction ) \\ + channel bind failed \\ + duplicate recipient eliminated \\ +\hline\hline + \multicolumn{1}{|c|}{\bf Success Reasons} \\ +\hline\hline + access policy: free\\ + negative: in-MTA (\%s \%s) sender (%s %s) out-MTA (%s %s) recip + ((\%s \%s) \\ + block: in-MTA (\%s \%s) sender (\%s \%s) out-MTA (\%s \%s) recip (\%s + (\%s) \\ \hline +\end{tabular}\] diff --git a/doc/manual/volume1/tableconsole_accels.tex b/doc/manual/volume1/tableconsole_accels.tex new file mode 100644 index 0000000..885d398 --- /dev/null +++ b/doc/manual/volume1/tableconsole_accels.tex @@ -0,0 +1,18 @@ +\[\begin{tabular} {|l|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Accelerator} & + \multicolumn{1}{|c|}{\bf Command} & + \multicolumn{1}{|c|}{\bf Prerequiste} \\ +\hline + Meta + R & Refresh &\\ + Meta + Q & Quit &\\ + Meta + D & Disconnect &\\ + Meta + C & Connect &\\ + Meta + M & Toggle Modes &\\ + Meta + F & Configuration &\\ + Return & Ok & A popup must be on display\\ + Control + C & Notok & A popup must be on display \\ + Meta + H & Toggle Heuristic & The configuration popup must be on display \\ + Meta + A & Toggle Authorisation & The connect popup must be on display \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tableconsole_mapping.tex b/doc/manual/volume1/tableconsole_mapping.tex new file mode 100644 index 0000000..310925d --- /dev/null +++ b/doc/manual/volume1/tableconsole_mapping.tex @@ -0,0 +1,26 @@ +\[\begin{tabular} {|l|l|l|} +\hline + \multicolumn{2}{|c|}{Tailor File Values} & \\ + \cline{1-2} + \multicolumn{1}{|c|}{type} & + \multicolumn{1}{|c|}{access} & + \multicolumn{1}{|c|}{Key} \\ +\hline + in & mts & mtsin \\ + out & mts & mtsout \\ + both & mts & mtsboth \\ + in & mta & mtain \\ + out & mta & mtaout \\ + both & mta & mtaboth \\ + in & & mtsin \\ + out & & mtsout \\ + both & & mtsboth \\ + shaper & & internal \\ + warn & & internal \\ + delete & & internal \\ + qmgrload & & internal \\ + debris & & internal \\ + timeout & & internal \\ +\hline +\end{tabular}\] + diff --git a/doc/manual/volume1/tableinfo_expan.tex b/doc/manual/volume1/tableinfo_expan.tex new file mode 100644 index 0000000..4c8dd9b --- /dev/null +++ b/doc/manual/volume1/tableinfo_expan.tex @@ -0,0 +1,35 @@ + +\[\begin{tabular} {|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Key} & + \multicolumn{1}{|c|}{\bf Expansion} \\ +\hline + \tt sender & + the address of the sender of the message (original format) \\ + \tt 822sender & + the address of the sender (rfc822 format) \\ + \tt 400sender & + the address of the sender (x400 format) \\ + \tt recip & + the address of the recipient of the message (original format) \\ + \tt 822recip & + the address of the recipient (rfc822 format) \\ + \tt 400recip & + the address of the recipient (x400 format) \\ + \tt qid & + the queue id of the message (e.g., msg.a000000) \\ + \tt ua-id & + the user agent id of the message \\ + \tt p1-id & + the P1 id of the message \\ + \tt outtable & + the outbound table associated with this channel (if any)\\ + \tt intable & + the inbound table associated with this channel (if any)\\ + \tt outmta & + the destination mta \\ + \tt confirm & + if confirmation of deliver is requested, this value is +set to ``yes'' else ``no''. \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tablemakedefs1.tex b/doc/manual/volume1/tablemakedefs1.tex new file mode 100644 index 0000000..240550d --- /dev/null +++ b/doc/manual/volume1/tablemakedefs1.tex @@ -0,0 +1,46 @@ +\[\begin{tabular}{| l | l | p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Variable} & + \multicolumn{1}{|c|}{\bf Example} & + \multicolumn{1}{|c|}{\bf Description} \\ +\hline + \tt TAILOR& \tt /usr/lib/pp/tailor& + Location of the pp tailor file\\ + \tt CMDDIR& \tt /usr/lib/pp&Directory for PP basic commands\\ + \tt CHANDIR& \tt /usr/lib/pp/chans& + Directory for channel programs\\ + \tt FORMDIR& \tt /usr/lib/pp/format& + Directory for the simple + formatting channels\\ + \tt TOOLDIR& \tt /usr/lib/pp/tools& + Directory for miscellaneous + shell scripts and debugging tools\\ + \tt LOGDIR& \tt /usr/lib/pp/logs& Directory for PP logs\\ + \tt QUEDIR& \tt /usr/spool/pp& + Location of the PP queue directory\\ + \tt TBLDIR& \tt /usr/lib/pp/tables& + The directory containing the + table files\\ + \tt LIBSYS& \tt -ldsap -lisode& + External libraries required - must + include ISODE and DSAP\\ + \tt LIBRESOLV& \tt -lresolv& Resolver library for bind (empty + if nameserver not required) \\ + \tt USRBINDIR& \tt /usr/local/bin& + Directory for user binaries\\ + \tt OPTIONALCHANS&\tt list 822-local smtp & + List of optional channels you require \\ + \tt OPTIONALFILTERS&\tt ascii2fax & List of optional filters\\ + \tt MANDIR& \tt /usr/local/man& + Directory to place manual + pages under \\ + \tt MANOPTS& \tt -bsd42& Manual page installation + options\\ + \tt NIFTPSRC& \tt /usr/src/niftp& + Directory containing the +source to unix-niftp package. (Only required if you wish to run grey +book mail). \\ + \tt NIFTPINTERFACE&\tt sun& Niftp interface being used +(restrictions as above)\\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tablemakedefs2.tex b/doc/manual/volume1/tablemakedefs2.tex new file mode 100644 index 0000000..eb7b9b5 --- /dev/null +++ b/doc/manual/volume1/tablemakedefs2.tex @@ -0,0 +1,38 @@ +\[\begin{tabular}{| l | l | p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Variable} & + \multicolumn{1}{|c|}{\bf Default} & + \multicolumn{1}{|c|}{\bf Description} \\ +\hline + \tt CC& \tt cc& The \pgm{C} compiler to use\\ + \tt CCOPTIONS& \tt -O& \pgm{C} compiler options\\ + \tt LIBCCOPTIONS&\tt -O& \pgm{C} compiler options specific + to library files \\ + \tt OLDCC& \tt cc& Other cc if gcc is used\\ + \tt LDOPTIONS& \tt -s& Loaded options\\ + \tt PEPY& \tt pepy& The \pgm{pepy} ASN.1 parser/compiler\\ + \tt POSY& \tt posy& The \pgm{posy} stub generator\\ + \tt ROSY& \tt rosy& The \pgm{rosy} remote + operations stub generator \\ + \tt PEPSY& \tt pepsy& The \pgm{pepsy} program \\ + \tt X11& \tt true& Does the system have X11? \\ + \tt LIBX& \tt -lXaw -lXmu -lXt -lX11& + The X11 libraries - may need -lXext + for X11R4\\ + \tt LINT& \tt lint& The \man lint (1) command\\ + \tt LINTFLAGS& \tt -hbuz& Lint flags\\ + \tt PGMPROT& \tt 755& Program protection mode\\ + \tt PPUSER& \tt pp& The user id PP will run as\\ + \tt ROOTUSER& \tt root& The user id for privileged channels\\ + \tt CHOWN& \tt chown& The \man chown(8) command\\ + \tt CHMOD& \tt chmod& The \man chmod(1) command\\ + \tt BACKUP& \tt cp& A command to back up the old +binary\\ + \tt INSTALL& \tt cp& A command to install a new +binary\\ + \tt LIBPHOTO& \tt -lphoto& + The quipu photo library\\ + \tt FAXDRIVERS& \tt dexNet200& The fax modem to compile\\ +\hline +\end{tabular}\] + diff --git a/doc/manual/volume1/tablemuflags.tex b/doc/manual/volume1/tablemuflags.tex new file mode 100644 index 0000000..ff491e6 --- /dev/null +++ b/doc/manual/volume1/tablemuflags.tex @@ -0,0 +1,22 @@ +\[\begin{tabular}{ll} +Flag & Purpose\\[1ex] + +default & override mu.defaults\\ +file & input from file(s)\\ +value & command line specification of value\\ +body & body part file name(s)\\ +tree & directory name(s)\\ +confirm & wait for y/n after \verb+$+ substitution\\ +nofix & ignore errors resulting from user input\\ +logfile & re-route output messages to file\\ +help & list flag table analysis\\ +-- & same as --help\\ +! & dummy next flag to terminate sequence ( future use )\\ +0 & debug (see above)\\ +1 & debug\\ +2 & debug\\ +3 & debug\\ +4 & debug\\ +5 & debug\\ + +\end{tabular}\] diff --git a/doc/manual/volume1/tables.aux b/doc/manual/volume1/tables.aux new file mode 100644 index 0000000..ad36645 --- /dev/null +++ b/doc/manual/volume1/tables.aux @@ -0,0 +1,89 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {4}PP Tables}{50}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{sect:tables}{{4}{50}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.1}Basic Operation of the Tables}{50}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.2}The General Syntax of Table Entries.}{51}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.3}The Aliases Table}{51}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.1}{\ignorespaces Example of Alias Table}}{52}} +\newlabel{example:alias}{{4.1}{52}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.4}The Users Table}{53}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.2}{\ignorespaces Example of Users Table}}{54}} +\newlabel{example:users}{{4.2}{54}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.5}The Domain Table}{54}} +\newlabel{table:domain}{{4.5}{54}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.3}{\ignorespaces Example of Domain Table}}{57}} +\newlabel{example:domain}{{4.3}{57}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.6}The O/R Address Table}{59}} +\newlabel{sect:ortables}{{4.6}{59}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.7}The Channel Table}{60}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.4}{\ignorespaces Example of Or Table}}{61}} +\newlabel{example:or}{{4.4}{61}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.5}{\ignorespaces Example of Channel Table}}{62}} +\newlabel{example:channel}{{4.5}{62}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.8}Supporting Multiple Organizations on One MTA}{63}} +\newlabel{sect:multihub}{{4.8}{63}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.9}RFC 1148 Mapping Tables}{65}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.9.1}The O/R to RFC\penalty \@M \ 822 Table}{65}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.6}{\ignorespaces Example of or2rfc Table}}{65}} +\newlabel{example:or2rfc}{{4.6}{65}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.9.2}The RFC\penalty \@M \ 822 to O/R table}{65}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.7}{\ignorespaces Example of rfc2or Table}}{66}} +\newlabel{example:rfc2or}{{4.7}{66}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.9.3}The Known RFC\penalty \@M \ 1148 Gateway Table}{66}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.8}{\ignorespaces Example of RFC\penalty \@M \ 1148 Gateway Table}}{66}} +\newlabel{examp:rfc1148g}{{4.8}{66}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.10}PP Authorisation}{66}} +\newlabel{sect:auth}{{4.10}{66}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.10.1}Access Policy}{67}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.10.2}Table Formats}{67}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Channel Authorisation}{68}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {4.1}{\ignorespaces Warning Message Macro Expansions}}{69}} +\newlabel{tab:warnexp}{{4.1}{69}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{MTA authorisation}{69}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{User Authorisation}{70}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.11}Authentication}{70}} +\newlabel{sect:authen}{{4.11}{70}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.11.1}Submit Authentication}{71}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.11.2}QMGR Authentication}{71}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.12}The 822 Local Table}{73}} +\newlabel{sect:local}{{4.12}{73}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.13}The X.400 (1984/1988) Outbound Table}{74}} +\newlabel{tab:X.400(84)out}{{4.13}{74}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.9}{\ignorespaces Example of X.400 Outbound Channel Table}}{76}} +\newlabel{example:x400out}{{4.9}{76}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.14}The X.400 (1984/1988) Inbound Table}{76}} +\newlabel{tab:X.400(84)in}{{4.14}{76}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.10}{\ignorespaces Example of X.400 inbound Channel table}}{77}} +\newlabel{example:x400in}{{4.10}{77}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.15}The List Table}{77}} +\newlabel{sect:list}{{4.15}{77}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.11}{\ignorespaces Example of List Table}}{78}} +\newlabel{example:lists}{{4.11}{78}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.16}The Shell Table}{78}} +\newlabel{sect:shell}{{4.16}{78}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {4.2}{\ignorespaces Shell Channel Expansion Macros}}{79}} +\newlabel{tab:shellexp}{{4.2}{79}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.16.1}Statistical Logging}{79}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {4.12}{\ignorespaces Example of Shell Table}}{80}} +\newlabel{example:shell}{{4.12}{80}} +\global\@namedef{cp@tables}{ +\setcounter{page}{81} +\setcounter{equation}{0} +\setcounter{enumi}{3} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{4} +\setcounter{section}{16} +\setcounter{subsection}{1} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{12} +\setcounter{table}{2} +} diff --git a/doc/manual/volume1/tables.tex b/doc/manual/volume1/tables.tex new file mode 100644 index 0000000..46e2d11 --- /dev/null +++ b/doc/manual/volume1/tables.tex @@ -0,0 +1,1616 @@ +\chapter {PP Tables}\label{sect:tables} + +This chapter describes the purpose and syntax of the various tables +used by PP. +There are five basic tables used by PP, the \file{aliases} table, the +\file{users} table, the \file{domain} table, the \file{channel} +table and the \file{or} table. How these are combined and used to +deliver and route messages is described below. + +There are also a set of tables containing authorisation information +and a family of tables that provide mappings between X.400 O/R names +and RFC~822 domain names. Specific channels may also have their own +tables containing the information they require. + +\section{Basic Operation of the Tables} + +When a message arrives, \pgm{submit} uses the \file{domain}, +\file{or}, \file{users}, \file{aliases} and \file{channel} tables to +identify delivery routes for the addresses in the message. +The \file{or2rfc}, \file{rfc2or} and \file{rfc1148gate} tables are +used to convert between X.400 style addresses and RFC-822 style +addresses and vice versa. + +The parsing of an address proceeds as follows: + +\begin{itemize} + +\item An address arrives in one particular form -- either an X.400 +style address or an RFC-822 style address. + +\item The address is normalised via the appropriate table -- the +\file{or} table for X.400 style addresses, the \file{domain} table for +RFC-822 style addresses. + +\item There are three possible outcomes of the normalisation +process. + +\begin{enumerate} +\item The address is unrecognised +\item The address is recognised as a remote address. +\item The address is recognised as a local address. +\end{enumerate} + +\item If the address is recognised as a remote address, routing +information to the remote site is accessed via the \file{channel} +table. + +\item If the address is recognised as local, the local address is +first looked up in the \file{aliases} table. + +If an entry is found in +this table, the parsing process recurses with the value found in the +\file{aliases} table. + +If no entry is found in the \file{aliases} table, routing information +for the local address is accessed via the \file{users} table. + +\item Having done the normalisation of the address and accessed the +routing information for that address, the address is converted into +the other style of address (i.e. X.400 style addresses are converted to +RFC-822 style and vice versa) This conversion is done according to +RFC-1148 and use the \file{or2rfc}, \file{rfc2or}, and +\file{rfc1148gate} tables. + +Note both styles of addresses are kept by PP. Also this conversion +between styles is always possible. + +\item At this stage PP has parsed one style of address. If this +parsing has resulting in routing information for that address, the +address is valid. However the address +still has to pass the authorisation stage before \pgm{submit} accepts it. + +If the parsing does not result in routing information, the address +is not valid in that form. PP then switches to the other style of +address and attempts to parse that form. + +There is a failure point. This occurs when PP decides all avenues and +styles of addresses have been followed. +\end{itemize} + +The tool \pgm{ckadr} can be used to check the action of parsing on +various address. + +\section {The General Syntax of Table Entries.} + +In general, entries in the tables are in the form: +\begin{quote}\small\begin{verbatim} + ":" +\end{verbatim}\end{quote} +The only special character is \verb|:| which if it appears on the LHS +must be preceded by a backslash ``$\backslash$'' to escape it. All other +characters are copied verbatim. However, some tables undergo further +processing and may need other escape sequences. + +The purposes and details of the various tables now follow. + +\section {The Aliases Table}\index{tables, alias} + +The \file{aliases} table governs the handling of aliases for +user names. It is used for several reasons. These include: +\begin{itemize} +\item Mapping non-users to usernames. (e.g., ``postmaster'' to some +``user''). +\item Redirecting users who have moved (e.g., ``fred'' to ``fred@foo.edu''). +\item Rewriting users addresses (e.g., ``jpo'' to ``j.onions''). +\item Mapping aliases. (e.g., ``list-request'' to ``j.onions''). +\end{itemize} +Entries in this table are constructed as follows: + +\begin{quote}\begin{verbatim} + ":" +\end{verbatim}\end{quote} + +The \verb+type+ +describes the user name or address. This may be one of: + +\begin{describe} +\item[\verb+synonym+:] +a new address, this name replaces the original +value. +\item[\verb+alias+:] +a new address is given, but in some cases this name does {\em not} +replace the original value. Aliases are not expanded for originators +of messages whereas synonyms are. +Aliases are also not expanded in the normalisation of addresses in +message headers. +Aliases, when expanded, add a redirect history element to the appropriate +recipient of the message. +Note this happens in the envelope but need not happen in the header. +\end{describe} + +The \verb|| is an address. It can be local or remote. + +The \verb|| gives the interpretation of the value. By +default this is assumed to be a local user. However, full addresses can +be specified with the appropriate qualifier. These are: + +\begin{describe} +\item[\verb+822+:] +a remote RFC~822 user address is specified. +\item[\verb+x400+:] +a remote X400 user address is specified. + +\item[\verb|external|:] If this qualifier is present the name will not +be lookup up again in the \file{aliases} file. This can be used for +complex mappings. +This qualifier is explained by example in Section~\ref{sect:multihub} +\end{describe} + +The format is best illustrated by a sample extract of the table as +shown in Figure~\ref{example:alias}. + +\tagrind[hbtp]{alias}{Example of Alias Table}{example:alias} + +The table includes an entry for a local alias \verb+mailgroup-request+. +The value \verb+Irene.Hassell+ is used as a key for a further search +in the \file{aliases} table, +but will not replace the alias in the message header; +if no match is +found, and since the entry is of type \verb|alias| with no qualifiers, +the address is +assumed to be a local one and is used for accessing the \file{user} +table. Also, if a local submission arrives from +\verb|mailgroup-request| then checking and authorisation will be done +on the basis of \verb|mailgroup-request| rather than +\verb|Irene.Hassell|. + +The next entries indicate that \verb+a.dacruz+ and \verb+alina+ are +both synonyms for \verb+Alina.DaCruz+. Here, the user's address will +be converted to Alina.DaCruz, and this value will be used in future +table searches. + +An entry is given for a remote RFC~822 user, \verb|jpo|. The value of +\linebreak +\verb|jpo@xtel.co.uk| is parsed as an RFC~822 +address. + +Then follows an entry for a remote X400 user, \verb|pc|. The value +\begin{quote}\small\begin{verbatim} +"/I=P/S=Cowen/O=XTel/PRMD=X-Tel Services/ADMD= /c=gb/" +\end{verbatim}\end{quote} +would be parsed as X.400 address. The quotes +({\tt "}) are needed as the entry contains a space which is a +field separator. + +Finally, the entry \verb|f.bloggs| is an external synonym. The address +\verb|f.bloggs| will be replaced by \verb|f.bloggs@admin.foo.bar| +for the originating address and further lookups of the \file{aliases} +table will be disabled. +It will not be replaced in recipient addresses to which delivery is being +attempted. +It may or may not be replaced for addresses in message headers +depending on the tailoring. +This is explained in greater detail in +Section~\ref{sect:multihub}. + +\section{The Users Table}\index{table, users} + +The \file{users} table determines the local delivery channel for a +particular local user. It is formatted in the form: + +\begin{quote}\begin{verbatim} + ":" [ ] + ["," [ ] ...] +\end{verbatim}\end{quote} + +\begin{describe} +\item[\verb+Channel+:] specifies the name of a local delivery channel +on \verb+mta+. + +\item[\verb+Mta+:] is the local machine on which the mailbox resides. +If no MTA is indicated, the channel may be used for delivery by any +MTA using these tables. If an MTA is present and is not the local +machine (\verb|loc_dom_mta|) then the message will be sent to that MTA +by an appropriate channel and the channel parameter is effectively +ignored - the normal routing tables will be used to reach that host. +This should only be used for internal shuffling between several MTAs +that are responsible for one domain. + +\end{describe} + +A user can have several channels for local delivery. +For example, in Figure~\ref{example:users} \verb+John.Taylor+ can have +his mail delivered either by the \pgm{822-local} channel or by the +\pgm{slocal} channel. +Which of these two channels is actually used for delivery depends on +the format of the message being delivered. +This allows a user to have, for instance, X.400 format mail delivered +by one channel, and RFC~822 mail by another channel. + +\tagrind[hbtp]{users}{Example of Users Table}{example:users} + +Figure~\ref{example:users} illustrates how the various local users +will receive mail +and on which machines their mailboxes reside. +An entry for a distribution list is also shown, and the entry for +\verb+info-server+ shows the \pgm{shell} channel rather than a local +delivery channel. + +\section {The Domain Table}\index{table, domain}\label{table:domain} + +The \file{domain} table is used by \pgm{submit} +\begin{itemize} +\item to derive a fully-qualified +domain from any aliases or short-form names; +\item and to obtain a pointer to +the routing information for that domain. +\end{itemize} +See +Section~\ref{tablebuild:domain} on page~\pageref{tablebuild:domain} for a +description of how to go about constructing this table. + +Entries in the domain table are encoded in the form: + +\begin{quote}\small\begin{verbatim} + ":" {"|" } + ::= ["=" ] {[["="]]} +\end{verbatim}\end{quote} + +\subsection*{Left Hand Side (LHS) Constructions} + +\verb+LHS+ has two possible constructions: +\begin{describe} + +\item[\verb+dmn+] +This construct is used for exact matches. No subdomains are allowed in +this entry. This effectively sets \verb+min=0+ and \verb+max=0+ and +cannot be altered. + +\item[\verb+*.dmn+] +This construct is used to specify partial domain matches. +Unless altered by the \verb+min+ and \verb+max+ keys described later, +constructs of this form will match domains with at least one +subdomain (i.e., \verb+min=1+ and \verb+max=*+). + +Note that an entry of \verb+*+ with no domain components specified at +all, represents the \verb+default domain+. If the \verb+default +domain+ is present in the \file{domain} table, then any top level +domains which are not matched in the table, are matched by this +\verb+default domain+ entry. + +\end{describe} + +\subsection*{Qualified Entries} + +Each qualified entry may have several \verb+key=value+ components. +The keys have two uses: to provide the information associated with the +entry; and secondly to aid in matching the LHS. +The possible types of \verb+key+ and what their values represent are +as follows: +\begin{describe} + +\item[\protect{\verb|max=|}:] +This specifies the maximum number of subdomains for the entry. +A value of \verb+*+ indicates that the maximum number of subdomains +should not be used when testing for a match. +Effectively setting the maximum number of subdomains to infinity +This is the default value for \verb+max+ on non-exact match entries. + +\item[\protect{\verb|min=|}:] +This specifies the minimum number of subdomains for the entry. +As with the \verb+max+ value above, a value of \verb+*+ indicates that +the minimum restriction should not be used when testing for a match. +Effectively \verb|min=0|. The default value for \verb+min+ is \verb+1+. + +\item[\protect{\verb+norm=+}:] +This identifies the fully-qualified domain name. +If \verb++ isn't specified, the fully-qualified domain name +is taken as \verb+LHS+ (without the \verb+*.+ wildcard prefix if present). + +\item[\protect{\verb+mta=+}:] +This provides a pointer to where the routing information for this +domain is stored the \file{channel} table. +If \verb++ isn't specified, the pointer is taken as +\verb+LHS+ (without the \verb+*.+ wildcard prefix). + +\item[\protect{\verb|norm+mta=|}:] +This key is a combination of the \verb+mta+ and +\verb+norm+ keys described above (i.e. \verb|norm+mta=| is +the same as \verb|norm= mta=|). + +\item[\protect{\verb|mta+norm=|}:] +This key is identical to the \verb|norm+mta| key described above. + +\item[\protect{\verb+synonym=+}:] +This identifies a synonym. The \verb|LHS| key is replaced by +\verb++ and parsing continues by looking for the new +\verb|LHS| in the domain table. + +If the \verb++ is prefixed with the wildcard symbol +\verb+*.+, the new \verb|LHS| is constructed from \verb++ +and the subdomains that a wildcard represents in the original +\verb+LHS+. For example a domain of \verb|foo.bar.zz| matching an +entry of \verb|*.zz:synonym=yy| would result in a table lookup of +\verb|foo.bar.yy|. +Note that this is only applicable to partial \verb+LHS+ entries. + +\item[\protect{\verb+local=+}:] +This indicates that \verb|LHS| is local. Any host that needs to be +recognised as local should have this keyword - this includes +{\verb|loc_dom_site|}. With no {\verb||}, this indicates +that \verb|LHS| is a local reference whose information is contained in +the default tables \file{aliases} and \file{users}. With a +\verb|| specified, this indicates separate local alias +and user tables. This feature is used when one MTA is supporting +multiple local organisations, each with its own user and alias tables. +This is described more fully in Section~\ref{sect:multihub}. + +\item[\verb+valid+:] +This is shorthand for the entry \verb+norm=LHS+ +e.g \verb+*.fr:valid+ is the +same as \verb+*.fr:norm=fr+. +It implies that the domain is known but not routable directly. This +may be used to indicate the domain is valid and may be used for +RFC~1148 mappings. It may also be used to stop use of the default +route. If a top level domain has an entry in the \file{domain} table, +it will not be routed via the default route. +\end{describe} + + +\subsection*{Domain table lookup} + +The right hand side of a \file{domain} table entry is a sequence of +qualified entries. +The qualification is based upon the number of subdomains below the key +being looked up (i.e. the number of domain components the wildcard +prefix \verb+*.+ represents). + +For example, take the domain ``1.2.3.xtel.co.uk''. +When attempting to look this domain up in the table, several different +keys may be used in the following order: +\begin{itemize} +\item ``1.2.3.xtel.co.uk'' the exact match, +\item ``*.1.2.3.xtel.co.uk'' where the number of subdomains is zero, +\item ``*.2.3.xtel.co.uk'' where the number of subdomains is one (i.e. +\verb|*| represents ``1'') +\item ``*.3.xtel.co.uk'' where the number of subdomains is two (\verb|*| +represents ``1.2'') +\item and so on. +\end{itemize} + +PP will take the qualified entries in turn and choose the first one +whose restrictions on the number of subdomain components is met by the +number of subdomain components actually present. +The restrictions for an entry are set by the \verb+min+ and \verb+max+ keys. + +Note that all occurances of domain references in the +\file{domain} table must be specified in US order (littleendian). +If the appropriate flag is set, the routines accessing the +\file{domain} table will ``do the right thing'' for UK ordering. + +\subsection*{Domain lookup results} + +As mentioned above, the \file{domain} table is used to provide two +items: +\begin{enumerate} +\item The fully-qualified domain name. + +If a match is found in the table then this is always provided. +If it is not explicitly provided by the \verb+norm+ key or a +combination containing that key, then it is implicitly provided as the +left hand side of the entry matched (i.e. the key used to index the +\file{domain} table) +For example with the entry +\begin{quote}\begin{verbatim} +xtel.co.uk:local +\end{verbatim}\end{quote} +The fully-qualified name is \verb+xtel.co.uk+. +If the left hand side is a partial domain construct, the prefix +\verb+*.+ is omitted from the fully-qualified name. + +If any subdomains exist they are prepended to the fully-qualified name +to reconstruct the full domain. +For example with the entry +\begin{quote}\begin{verbatim} +*.gb:norm=uk +\end{verbatim}\end{quote} +and the address \verb+xtel.co.gb+, the fully-qualified name produced +from the table would be \verb+uk+. +After the re-addition of the subdomains, this would become +\verb+xtel.co.uk+. + +\item The pointer to the routing information. + +The pointer into the \file{channel} table may be omitted. +In which case the fully-qualified domain name has been derived but no +routing information associated with it. +This is useful when you wish to normalise the domain in message +headers but you do not wish to deliver mail to that domain. +It is also of use when the route to that domain is specifically an +x400 route and as such the pointer to the routing information is +specified in the \file{or} table described in +Section~\ref{sect:ortables}. + +\end{enumerate} + +\subsection*{Examples} + +Figure~\ref{example:domain} contains several examples entries. + +\tagrind[hbtp]{domain}{Example of Domain Table}{example:domain} + +The entries in this figure imply the following actions: +\begin{itemize} + +\item The \verb|*.edu| entry will match all domain names with the most +significant component of \verb|edu| and at least one subdomain. Thus, +the hosts \verb|ucbarpa.berkeley.edu|, \verb|prep.ai.mit.edu| and +\verb|foo.edu| would all be matched by this entry. However an address +of \verb|user@edu| would not be matched. + +The fully-qualified domain name is constructed with the \verb+edu+ +component as the most significant component. + +The key \verb+nameserver+ will be used in the lookup of the channel table to +find routing information for this domain. + +\item The \verb|cs.nott.ac.uk| entry will only match the exact name +\verb|cs.nott.ac.uk|. It will not match \verb|crg.cs.nott.ac.uk| or +\verb|admin.cs.nott.ac.uk|. + +The fully-qualified domain name is \verb+cs.nott.ac.uk+. + +The key \verb+cs.nott.ac.uk+ will be used to +access the routing information in the \file{channel} table. + +\item The \verb+computer-science.nott.ac.uk+ entry will only match the +exact name \verb+computer-science.nott.ac.uk+. The fully-qualified +domain name is \verb+cs.nott.ac.uk+. This string is also used to +access the routing information in the +\file{channel} table. + +\item The \verb+*.fr+ entry will match all domains with the most +significant component of \verb|fr| and at least one subdomain. +So it will match \verb+sorbonne.fr+ or \verb+nice.fr+ but it will not +match \verb+fr+ by itself. + +The fully-qualified domain name is constructed with the \verb+fr+ +component as the most significant component. + +No pointer to the routing information is specified. +So when parsing addresses of the form \verb+nice.fr+, PP will match this +entry which indicates the correct domain ordering. +However with no routing information for this form of the address, PP +will convert the address to X.400 as described in RFC 1148 and then +attempt to find routing information from the X.400 equivalent of the +\file{domain} table -- the \file{or} table. + +There is a similar mechanism in the \file{or} table. +Using these two mechanisms in tandem, you can keep pointers to X.400 routing +information in the \file{or} table and pointers to RFC-822 routing +information in the \file{domain} table. + +As a side effect, because the top level domain \verb|fr| has been matched, +the default route will not be considered as a possibility. + +\item The \verb+*.co.uk+ entry has two qualified entries. + +The first entry will only match the exact domain \verb+co.uk+ and +nothing else. + +The second entry will match all other domains with \verb+co.uk+ as the +two most significant components i.e \verb+xtel.co.uk+, +\verb+bnr.co.uk+ etc. + +The fully qualified domain name in both cases is constructed with the +\verb+co.uk+ as the two most significant components. +In the first case, there are no subdomain components to add so the +domain name is \verb+co.uk+. + +The pointer to the routing information differs for the two cases. +In the first case it is \verb+co.uk+. +In the second it is \verb+server.co.uk+. +This enables you to route differently depending on the number of +subdomain components. + +\item The \verb+*+ entry is an example use of the \verb+default +domain+. +It will match with anything that does not match any other rule. +The fully qualified domain name will be the same as on input. +The pointer to the routing information will be \verb+nameserver+. + +In the extreme case where you wish every domain to be routed via +domain name server technology, this can be the only entry in the +domain table. + +\[\begin{tabular}{l p{0.7\textwidth}} +Note: & The default route should be used with care. It is tempting to +use this as a catch all. This makes routing less efficient as every +domain that uses this will be sent to one host, effectively passing +the buck. It also means that users making small typo's in the top +level domain may have their mail routed a large distance before the +mistake is found. \\ + & \\ +Note: & It is usually sensible to put the relevant entries for the +local domains in the \file{domain} table, especially +{\verb|loc_dom_site|} and {\verb|loc_dom_mta|}. If not local addresses +will not be recognised as such. \\ +\end{tabular}\] + +\end{itemize} + +\section{The O/R Address Table}\index{tables, X.400 O/R}\label{sect:ortables} + +The \file{or} table provides routing and normalisation for X.400 +address in the same way the \file{domain} table does for RFC~822 addresses. +Lines are encoded in the form: + +\begin{quote}\small\begin{verbatim} + ":" ... +\end{verbatim}\end{quote} + +In the \verb|| field, the characters ``:'' and ``.'' must be +preceded by a ``$\backslash$'' character. + +The \verb|| and \verb|| fields on the RHS are separated +by white space, and so any space +characters in those fields must similarly be preceded by either +``$\backslash$'' or else the value should be encapsulated in double quotes. + +The \file{or}\index{or} table is used to evaluate O/R addresses. The +\verb++ is encoded as dmn-orname as specified in RFC~1148 +i.e. a sequence of \verb+$+ pairs separated by full +stops. + +The algorithm for O/R address analysis should be considered as +a ``tree-walking'' algorithm. +The O/R address components are sorted, and +components are looked up: first level 1; then level 2 + level 1 and so +on. So repeated lookups are carried out, using this table. +The first failed lookup breaks the loop with the last ``routable'' +match (\verb|mta| or \verb|local| matches) being chosen as the result +of the analysis. +If there is no ``routable'' match, the analysis has failed and the O/R +address is invalid. + +There is a wildcard facility that may be used when +constructing the LHS, \verb++. +To use the wildcard facility, set the \verb++ to the wildcard +symbol \verb+*+. +For example, consider the case where you wish to route all unknown +\verb+ADMD+s under one country to one mta. +This can be achieved by the following entry. +\begin{quote}\small\begin{verbatim} +ADMD$*.C$GB:mta admd.gb +\end{verbatim}\end{quote} +Given the address \verb+/S=pac/O=XTel/PRMD=X-Tel Services/ADMD= +/C=GB/+, the lookup of the O/R table will proceed as this +\begin{itemize} +\item lookup \verb+C$GB+, assume it succeeds +\item lookup \verb+ADMD$ .C$GB+, this fails +\item lookup \verb+ADMD$*.C$GB+, this matches the example entry +\item continue looking up \verb+PRMD$X-Tel Services$ADMD$*.C$GB+ +and so on till lookup fails. When the lookup fails, the last +successful mta or local entry is used for the appropriate routing. +\end{itemize} + +There are four possible instances of the \verb|| field, similar +in functionality and appearance to their counterparts in the +\file{domain} table. +\begin{describe} + +\item[\verb+valid+:] +This means that this part of the tree is OK. As lookup stops as soon +as an entry is not found, it is necessary to mark entries which have +no routing information as valid to allow lower entries to be found. + +\item [\verb+mta +:] +This identifies the MTA \verb|| as being associated with this +vertex of the tree. This \verb|| is a key into the PP \file{channel} +table. The search should \verb|not| stop at this point, as further tree +searching may determine a more optimal mta. + +\item [\verb+synonym +:] +This identifies a synonym, and indicates that all O/R components matched +so far should be replaced with those identified on the RHS, and the +search should now resume from the root. +The characters ``$\backslash$'' and ``.'' in the \verb|| +and/or \verb|| parts of the dmn-orname construction must always +be preceded by a ``$\backslash$''. + +For historical reasons, this encoding has a second equivalent form: +\verb+alias +. + +\item [\protect{\verb+local []+}:] +This identifies a local O/R Address. The remainder of the O/R address +should be used to determine a local mailbox. If the +\verb|subdom-name| is empty the normal \file{alias} and \file{user} tables are +consulted. If the \verb|subdom-name| is present, then as with the +similar feature in the \file{domain} table, this feature is used when one MTA +is supporting multiple local organisations, each with their own user +and alias tables. This is described in Section~\ref{sect:multihub}. + +\end{describe} + +Figure~\ref{example:or} gives an example which shows the validity of +some Country, ADMD, and PRMD values, and indicates which MTAs will +deal with which PRMDs. The MTA value given here is internal to the PP +lookup system, providing a key with which to reference the +channel table. + +\tagrind[hbtp]{or}{Example of Or Table}{example:or} + +\section {The Channel Table}\index{channel}\index{tables, channel} + +\pgm{Submit} uses the \file{channel} table to discover the +possible channels, and in some cases relaying MTAs, that may be used +to send a message on towards a remote host. +This remote host is the one identified by the \verb|mta| entries in +either the \file{or} table or the \file{domain} table. + +See Section~\ref{tablebuild:channel} on +page~\pageref{tablebuild:channel} for a method of building this table. +The format of an entry has the form: + +\begin{quote}\begin{verbatim} + ":" [ ] "("")" + ["," [ ] "("")" ...] +\end{verbatim}\end{quote} + +\begin{describe} +\item[\verb+key+:] is the index +name derived from the mta entry in the \file{domain} or \file{or} +tables -- the remote host. + +\item[\verb+mtaname+/\verb+channel+:] the \verb+mtaname+ derived from +this lookup will be used as a key in the appropriate outbound +\verb+channel+'s table -- the relaying MTA. If there is no +\verb|mtaname| present, then +the remote host is reached directly through that channel. This sort of +action is appropriate if the channel uses external information (such +as the DNS) to look up the domain. +\end{describe} + +Figure~\ref{example:channel} illustrates an extract of this table. + +There may be a number of possible channels for a given remote host. +Everything else being equal, the order of channels in the table is the +preferred method of delivery. +The authorisation process will select one of the possible channels and +this is the one used. + +\tagrind[hbtp]{chantbl}{Example of Channel Table}{example:channel} + + +\section{Supporting Multiple Organizations on One MTA} \label{sect:multihub} + +PP contains several features that enable a site to behave as multiple +mail hubs and/or as a central mail gateway between the external world +and the internal subdomains. The features in question are: +\begin{itemize} +\item the \verb+local+ key in the \file{domain} and/or \file{or} +tables, +\item the \verb+external+ qualifier in the \file{alias} tables, +\item and the \verb+-internal+ and \verb+-external+ flags to the +header normalisation filters, \pgm{p2norm} and \pgm{rfc822norm}. +\end{itemize} + +To explain how these features may be used, this section introduces +three possible configurations. Each one slightly more complex than its +predecessor. These examples consider the situation of two domains, +the main site name, \verb+xtel.co.uk+, and a subdomain under that +site, \verb+admin.xtel.co.uk+. + +\begin{enumerate} + +\item {\tt PP acting as two different, independent mail hubs.} + +This is the situation where one PP system is acting as two distinct +domains. + +The main domain \verb+xtel.co.uk+ has the information relating to its +local users in the tables named +\file{users} and \file{aliases}, +and the subdomain \verb+admin.xtel.co.uk+ has the information relating +to its local users in the tables \file{admin-users} and +\file{admin-aliases}. +There is no intersection between the \verb+xtel.co.uk+ name space and +the \verb+admin.xtel.co.uk+ name space so these tables can be +independently maintained. + +PP has to be informed that \verb+admin.xtel.co.uk+ is a local domain. +This is done via the relevant entry in the \file{domain} table and/or +the \file{or} table. +e.g. +\begin{quote}\small\begin{verbatim} +admin.xtel.co.uk:local=admin +OU$admin.O$XTel.PRMD$X-Tel Services.ADMD$ .C$GB:local admin +\end{verbatim}\end{quote} + +\item {\tt PP acting as one name space divided over two +adminstration domains.} + +This is the situation where PP is acting as one complete name space +composed of two separate adminstration domains, i.e. all users have +mail addresses of the form \verb+user@xtel.co.uk+. + +As above the information about local users is divided into two +separate sets of tables, \file{users} and \file{aliases}, and +\file{admin-users} and \file{admin-aliases}. +As above PP is informed that \verb+admin.xtel.co.uk+ is a local +domain. +But as these two domains are to be combined into one name space -- +\verb+xtel.co.uk+, there has to be an intersection between the two +sets of tables and in particular between the \file{aliases} tables. + +The intersection only applies to addresses in the +\verb+admin.xtel.co.uk+ adminstration domain. +The delivery information for these users is stored in the +\file{admin-users} table. +On delivery, PP has to be able to access this table. +Therefore it has to map from the address \verb+user@xtel.co.uk+ to +\verb+user@admin.xtel.co.uk+. +This is done via an entry in the \file{aliases} table of the form: +\begin{quote}\small\begin{verbatim} +user:alias user@admin.xtel.co.uk 822 +\end{verbatim}\end{quote} +The entry is an \verb+alias+ because the mapping is only required when +delivering a message to \verb+user+. +So for messages sent by \verb+user@xtel.co.uk+, the sender remains +\verb+user@xtel.co.uk+ and not \verb+user@admin.xtel.co.uk+. +The same is true for all occurances of \verb+user@xtel.co.uk+ in +any headers they will be left as is. +This also holds for x400 addresses and headers. + +To ensure that the name space is maintained, one has also to ensure +that the address \verb+user@admin.xtel.co.uk+ is mapped to +\verb+user@xtel.co.uk+ for senders and in headers. +This is so, because the user agents on the subdomain may stamp mail +with their subdomain's name i.e. \verb+admin.xtel.co.uk+ +To acheive this mapping, there should be an entry in the +\file{admin-aliases} table of the form: +\begin{quote}\small\begin{verbatim} +user:synonym user@xtel.co.uk 822 external +\end{verbatim}\end{quote} +The \verb+external+ qualifier prevents this \verb+synonym+ being +unwound if the responsibility for the address we are parsing is set +(i.e we are trying to delivery to that address, it is for internal +consumption). Unless the flags described below are used, the +\verb+synonym+ is always unwound for addresses in headers. + +WARNING: with the two entries in the two different \file{aliases} +tables, there is a possiblility of circular aliases. +The use of the \verb+external+ qualifier should stop most circles, but +it is adviseable to use the \verb+ckadr+ tool to check some example +addresses before going on-line with such a configuration. + +\item {\tt PP acting as a gateway between the external world and the +internal domains.} + +The previous configuration suffices for a gateway between the outside +world and the internal domains. However it may swamp the gateway +machine with internal messages. All users are represented in headers +as \verb+user@xtel.co.uk+ irrespective of which subdomain they are +under. So any replies to messages will be directed to +\verb+user@xtel.co.uk+ which is the gateway. It would be better if +internal recipients of the message saw the internal addresses. Hence +could bypass the gateway and send directly to the relevant domain. + +This is an issue which doesn't have any relevance for the parsing of +envelope addresses. It only effects the headers presented to the user +(both x400 headers and RFC 822 headers). As such, one has to set up +the PP tailor file and routing information so that messages going to +internal recipients have their headers reformatted differently than +messages going to external recipients. + +To obtain the different reformatting, one should tailor the +\verb+-internal+ and/or the \verb+-external+ flags for the +\pgm{p2norm} and \pgm{rfc822norm} filters. +By default, the header normalisation filters unwind all +\verb+synonym+'s including those marked with the \verb+external+ +qualifier. The presence of the \verb+-internal+ flag stops the +filters unwinding the \verb+synonym+'s marked \verb+external+. Thus +leaving \verb+user@admin.xtel.co.uk+ in headers. + +\end{enumerate} + +\section{RFC 1148 Mapping Tables} + +These mappings are used to convert between X.400 addressing +and RFC~822 addressing. The mappings involved are not algorithmic, +making necessary the use of such tables. +RFC~1148 describes in detail their function. +See Appendix~\ref{app:tables} for how to obtains copies of the +globally maintained tables in PP format. + +\subsection{The O/R to RFC~822 Table} + +The table \file{or2rfc}, exemplified in Figure~\ref{example:or2rfc}, +is for mapping OR names into RFC~822 addresses. The \verb++ is +encoded as domain-syntax (see RFC~987 and RFC~1026) and +\verb+value+ as dmn-orname. The longest possible match is sought. + +\tagrind[hbtp]{or2rfc}{Example of or2rfc Table}{example:or2rfc} + +\subsection{The RFC~822 to O/R table} +Performing exactly the reverse operation is +\file{rfc2or}\index{rfc2or}, which has the \verb++ encoded as +dmn-orname and the \verb++ as domain-syntax. An example of the +format is given in Figure~\ref{example:rfc2or}. + +\tagrind[hbtp]{rfc2or}{Example of rfc2or Table}{example:rfc2or} + +\subsection{The Known RFC~1148 Gateway Table} + +The \file{rfc1148gate} table has the same syntax as the \file{rfc2or} +table. Its entries represent gateways between X.400 and RFC~822 (via +RFC~1148). This table is used in the cases where RFC~822 messages are +relayed across an X.400 link. In such cases mapping to X.400 addresses +may not always make sense as there will effectively be routing +information encapsulated in the address. Normally this would cause the +message to fail. However, if it is known that the destination is an +RFC~1148 gateway, then the mapping can proceed in the expectation that +the other end can unwrap the message. + +An example RFC~1148 gateway file is shown in +Figure~\ref{examp:rfc1148g}. + +\tagrind[hbpt]{rfc1148g}{Example of RFC~1148 Gateway Table}{examp:rfc1148g} + +\section{PP Authorisation}\label{sect:auth} + +Authorisation is applied after address parsing, normalisation and +validation, to +establish whether the message is permitted to be transferred on a per +recipient basis. Address lookup may establish several possible +outbound channels for each recipient; authorisation selects one of +these after applying tests based on entries in the three authorisation +tables \file{auth.channel}, \file{auth.mta}, and \file{auth.user}. + +Access policy for channel pairs ( inbound + outbound ) determines how +the rights for the four entities: sender, recipient, sending MTA, and +destination MTA, are to be interpreted. ( ``Rights'' means one of the +four values in/out/both/none and a fifth value ``unset'' to indicate +that no table entry is present.) + +The intention is that one of these four may be shown to be authorising +the message (i.e., willing to pay for it). + +It should be noted that authorisation is not applied to delivery report +messages. + +\subsection{Access Policy} +The access policy is one of the following: +\begin{describe} +\item[\verb|none|:] +Message may not be transferred. + +\item[\verb|free|:] +No constraints on the four entities. + +\item[\verb|block| ( i.e., ``blockable'' ):] +- at least one of the four entities must enable the +message by specifying ``in'' or ``both'' for the inbound channel and ``out'' +or ``both'' for the outbound channel. If none of the four enable it, +the message may not be transferred. Therefore the +default is to not let messages through. +If a message fails in this mode, it effectively means that the message was +not authorised. + +\item[\verb|negative|:] +Any one of the four entities may stop transfer by disabling the +message. This implies the default state is to let everything through, +and special cases are stopped by explicit configuration. +If a message fails in this mode, it effectively means that the message +was prohibited. + +\end{describe} + +When determining rights for a proposed transfer the following +algorithm is followed: +\begin{itemize} +\item Determine the inbound and outbound channels and look up +this pair in the \file{auth.channel}\index{auth.channel} file. + +If there is no entry in this file, take the default from the tailoring +variable as the access policy for the channel. + +\item If the access policy is free or none, then the message is +allowed through or rejected respectively. + +\item If the access policy is negative, check the MTA and user +tables, \file{auth.mta}, and \file{auth.user} to see if this route is +explicitly disabled. + +\item If the access policy is block, check the user and MTA tables +to see if the route is explicitly enabled. +\end{itemize} + +\subsection{Table Formats} +There are three tables associated with authorisation, plus the tailor +variables. + +\subsubsection{Channel Authorisation} +The first of these tables is the \file{auth.channel} table. +This contains the overall policies for channel to channel relaying. +As the key, the table has the syntax: + +\begin{quote}\small\begin{verbatim} + "->" +\end{verbatim}\end{quote} + +If no value is found for the above, then as a fallback the values +\begin{quote}\small\begin{verbatim} + "->" "*" +"*" "->" +"*" "->" "*" +\end{verbatim}\end{quote} +are checked in that order. + +The values that the table can have are as follows: + +\begin{describe} +\item[\verb||:] Any of the above mentioned policies +(\verb|free|, \verb|block| etc.). + +\item[\verb|warnsender=|:] +Send a warning message to the sender if the authorisation fails, with +text taken from the given file (relative to the \file{wrndfldir}). + +\item[\verb|warnrecipient=|:] Send a warning message to the +recipient with text taken from the given file if the authorisation fails.. + +\item[\verb|sizelimit=|:] Enforce the given size +limit on messages. No messages larger than this size will be relayed. +This is obeyed regardless of the overall policy of the channel. (I.e., +A channel may be marked as free with a sizelimit, and the sizelimit +will still be enforced.) + +\item[\verb|test|:] This setting modifies the checking procedure to +always allow the message through. However, all the checking is carried +out and the result is logged. This is useful to test out the results +of a setting for a while before fully applying them. If either +\verb|warnsender| or \verb|warnrecipient| is set, the warning message +will be sent if the message would have normally failed the +authorisation checks. +\end{describe} + +If warning messages are to be sent, the contents of the message are +subject to macro expansion. The macros of the form \verb|$(key)| are +replaced with given values, as shown in Table~\ref{tab:warnexp}. + +\tagtable{warnexp}{Warning Message Macro Expansions}{tab:warnexp} + + +An example of the \file{auth.channel} table format might look like the +following: +\begin{quote}\small\begin{verbatim} +822-local->pss:free +822-local->local:block +822-local->slocal:free +822-local->smtp:free, warnsender=smtpwarnsender, test +822-local->janet:block, sizelimit=4000 +x400in84->x400out84:none +x400in84->local:free,sizelimit=10000 +822-local->x400out84:block,warnsender=restricted, test +smtp->smtp:block, test +\end{verbatim}\end{quote} + +\subsubsection{MTA authorisation} + +The next table is the MTA policy table in file \file{auth.mta}. This +governs the policy for a given MTA if the channel policy is not \verb|free| +or \verb|none|. The keys used in this table are the source MTA and +the destination MTA. Each of these are looked up separately to +determine policies. + +The allowed values for this field are any of the following in a +comma-separated list: +\begin{describe} +\item[\verb|=|:] +This specifies for given channels what directions are allowed for this +MTA. The possible directions are: + \begin{describe} + \item[\verb|in|:] Allow inbound traffic for this channel. + \item[\verb|out|:] Allow outbound traffic for this channel. + \item[\verb|both|:] Allow both inbound and outbound + traffic for this channel. + + \item[\verb|none|:] Allow no access for this channel. + \end{describe} + +\item[\verb|default=|:] +This specifies the default directions that traffic can flow in the +absence of a particular channel being specified. + +\item[\verb|requires=|:] +This MTA requires that the sender/recipient address being authorised +matches the given pattern. This is a standard regular expression as +specified in \man regex (3). + +\item[\verb|excludes=|:] +The MTA requires that the user being authorised does not match the +given pattern. + +\item[\verb|bodypart-excludes=|:] +This specifies a list of bodyparts that the MTA will not accept. +These bodyparts are taken from the list of standard bodyparts as +described in Section~\ref{tai:bodypart} on page~\pageref{tai:bodypart}. + +\item[\verb|sizelimit=|:] +The MTA will not relay messages larger than the given sizelimit. +\end{describe} + +An example of this table might look like the following: +\begin{quote}\small\begin{verbatim} +vs2.cs.ucl.ac.uk:default=both, smtp=out, x400out84=out, + 822-local=in, excludes="A.DaCruz.*" +localhost:default=in, x400in84=out, smtp=both, + 822-local=none, sizelimit=654321 +\end{verbatim}\end{quote} +(Lines are folded for readability.) + +\subsubsection{User Authorisation} + +The user table is where both the recipient and originator are +looked up to determine access rights. The key is either the full +normalized name of the user, or if local, just the local part of the +name. The values may contain any of the following: +\begin{describe} +\item[\verb|=|:] +This specifies, much as for the MTA, what directions are allowed for +this user. + +\item[\verb|default=|:] +This gives the default directions allowed for this user. + +\item[\verb|bodypart-excludes=|:] +A list of bodyparts that are not allowed to be sent to the user. + +\item[\verb|sizelimit=|:] +Disallow messages larger than this sizelimit. + +\end{describe} + +An example of the user authorisation table is: +\begin{quote}\small\begin{verbatim} +j.taylor@cs.ucl.ac.uk:default=both +/I=J/S=Taylor/OU=cs/O=ucl/PRMD=uk.ac/ADMD=gold 400/C=gb/:\ + bodypart-excludes=g3fax|dmd, sizelimit=100000, 822-local=both +a.dacruz@cs.ucl.ac.uk:default=both +s.kille@cs.ucl.ac.uk:default=both +p.cowen@computer-science.nottingham.ac.uk:default=both, \ + 822-local=in, x400out84=none +j.onions@computer-science.nottingham.ac.uk:default=both +\end{verbatim}\end{quote} + +\section{Authentication}\label{sect:authen} + +Components of PP must do appropriate checking that they are being +invoked correctly. Note that authentication is complementary to +authorisation. It is also a prerequisite. + +\subsection {Submit Authentication} + +\pgm{Submit} needs to verify the source of an inbound message. For messages from +an inbound channel (protocol server) accessing the MTA Abstract Service, this +means verification of the UID of the channel (typically to be ``root'' or +``pp''). For the MTS Abstract Service, the identity of the P1 originator must +be verified. These two verifications use the same mechanism. There are two +cases: + +\begin {enumerate} +\item Submission from a local process using pipes. In this case, the UID of +the invoking process is available, and can be the basis for authentication. + +\item For remote submission, the UID is not available, and so a password +based mechanism is used. This may also be used locally. +\end {enumerate} + +A password and the corresponding name are carried in the initial protocol +handshake. This may be overridden for later messages. + +Each (inbound) channel has an ``auth-table'' variable, which +identifies a table which is used in the manner described below. The +authentication table has three columns. These have the following meaning: + +\begin {enumerate} +\item String-encoded address, in the preferred format of the channel: +\begin {itemize} +\item X.400 O/R Address. +\item RFC~822 address. +\end {itemize} + +\item List of valid UIDs. + +\item Password (as in /etc/passwd). +\end {enumerate} + +Example files: + +\begin{quote}\small\begin {verbatim} +# +# Start of dummy 822 file +# +S.Kille@cs.ucl.ac.uk:steve|aiohpefcn + +# +# Dummy X.400 file +# +/i=s/s=kille/ou=cs/o=ucl/prmd=uk.ac/admd= /c=gb/:steve,pp +/i=j/s=onions/o=nott/prmd=uk.ac/admd=gold 400/c=gb/:jonions +\end{verbatim}\end{quote} + + +\subsection{QMGR Authentication} + +Management tools like the \pgm{MTAconsole} can connect to the +\pgm{qmgr} in two distinct +modes. These are +\begin{describe} +\item[\verb|no authentication|:] In this mode, no authentication is +done for the user. + +\item[\verb|weak authentication|:] In this mode a name and password +are passed across in the bind, so there is some limited authentication +of the initiator. +\end{describe} + +When an incoming call is received by the qmgr, authentication +information is checked in the \file{auth.qmgr}\index{auth.qmgr} table. +The format of this table is: +\begin{quote}\small\begin{verbatim} + ":" "passwd=" "," "rights=" +\end{verbatim}\end{quote} + +These parameters are interpreted in the following way: +\begin{describe} +\item[\verb|name|:] This is the name given in the bind parameters. If +the connection was bound with no authentication, the name \verb|anon| +is used for the lookup. If the name is not found in the table, then if +the user bound with authentication, the request is refused. If the +user bound without authentication, and the name \verb|anon| is not +present in the table, then limited access is allowed. + +\item[\verb|passwd|:] This value takes an encrypted passwd, which can +be generated with the utility \pgm{mkpasswd}\index{mkpasswd}. The +password passed in the bind information is encrypted and compared +against this value if present. If no \verb|passwd| field is present, +then a passwd is not required. + +\item[\verb|rights|:] This value is used to indicate the rights that +the initiator will be allowed. It may be one of the following values: +\[\begin{tabular}{|l | p{0.6\textwidth} |} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt none & The association is refused. \\ + \tt limited & The initiator is allowed to examine the queue + but not to change any parameters. \\ + \tt full & The initiator is allowed to examine the queue and + modify queue paramters \\ +\hline +\end{tabular}\] + +If it is missing, then limited access is assumed. +\end{describe} + +For example: +\begin{quote}\small\begin{verbatim} +anon:rights=none +admin:passwd=YNKJHgaawczz,rights=limited +pp:passwd=YNKcyeOsT6Fqc,rights=full +\end{verbatim}\end{quote} + +In this case the following is true: + +\begin{describe} +\item[\verb|anon|:] Unauthenticated users are not allowed any access +to the QMGR. + +\item[\verb|admin|:] The user admin with the correct password is +allowed to view the queue. + +\item[\verb|pp|:] The user pp, with the correct password, is allowed +full access to control the queue manager. +\end{describe} + +If no table is specified, limited access is allowed for any +connection. + +\section {The 822 Local Table}\index{tables, local} +\label{sect:local} + +The \file{ch.local}\index{ch.local} table is an example of a table +accessed by different channels; both \pgm{822-local} and \pgm{slocal} +channels use it in order to find out where and how to delivery mail to +registered users. +The LHS is the registered users mail address. +The format is of the RHS is of the form ``key=value.'' +The following table of key/value pairs +are allowed: +\begin{describe} +\item[uid] +The numeric user id to deliver the message as. +\item[gid] The numeric group id to deliver the message as. +\item[username] A username found in the password file. If this +entry is set, it sets defaults for uid,gid,shell,home and directory. +\item[directory] The directory to change to before starting delivery. +This implies CWD for any files which use relative path names. +If it is not set it defaults to home. +\item[mailbox] The name of the mailbox if default delivery is being +done. +\item[shell] The user's shell and the one which is exec'd to run +pipes etc. +\item[home] The user's home directory. +\item[mailformat] The default format to deliver mail in; this can be +either \verb|pp| for MMDF/PP style mailboxes or \verb|unix| for +sendmail compatible style (the default is \verb|pp|). +\item[restricted] this is set to true if the user is restricted. In +restricted mode the user cannot run arbitrary programs on delivery and +cannot change the PATH environment variable. +\item[mailfilter] The mailfilter file to use. This defaults to the +name of the mailfilter global tailor variable in the users home +directory. A value of \verb|none| disables this feature. +\item[sysmailfilter] The system default mailfilter file. This defaults +to the global tailor entry. A keyword of \verb|none| disables this facility. +\item[searchpath] The directory to look for binaries that the user can +run in restricted mode. +\item[opts] other options; not currently used. +%\hline +\end{describe} +If the +\verb|resticted| mode is in force, then the +\file{.mailfilter} file processing is reduced in functionality as +follows: +\begin{itemize} +\item The user is not allowed to set the variable PATH to search +other directories for programs. (Actually this variable can be set, it +is just ignored.) +\item The processes executed by the \verb|pipe| command must be in +the directory named in \verb|searchpath| (defaults to +\verb|USRBINDIR|\index{USRBINDIR} defined in the \file{Make.defs} file). +\item The processes executed by the \verb|pipe| command must be +executable by the system call \man exec(2). (E.g. redirection and +shell syntax will not be obeyed). +\end{itemize} + +For an entry in this table to be valid, it must either contain at +least a UNIX login id, or have a userid/groupid/directory to deliver to. + +For example: + +\begin{quote}\small\begin{verbatim} +Alina.DaCruz:username=alina home=/cs/users/vs1/alina +John.Taylor:username=jtaylor +Postie.Pat:username=pp +bug-filter:uid=32767 gid=1001 mailbox=/usr/spool/mail/bugs mailformat=unix +\end{verbatim}\end{quote} + +\pgm{Note}: for compatability with earlier releases the following format is +allowed: +\begin{quote}\begin{verbatim} +name ":" [ []] +\end{verbatim}\end{quote} + +\section {The X.400 (1984/1988) Outbound Table} +\index{tables, X.400 84}\index{tables, X.400 88}\label{tab:X.400(84)out} + +This table is used by the outbound X.400 channels, allowing them to map the +host name to the information needed for addressing of and connecting +to the remote MTA\index{ch.x400out84}. The key in this table is the +value representing the MTA derived from the ``mtaname'' field of the +\file{channel} table. The value is a set of \verb+key=value+ fields +separated by white space and/or commas. + +\begin{quote}\small\begin{verbatim} +mta key:rmta=xx,rpass=xx,rpsap='"591"/Janet=000005110000' +\end{verbatim}\end{quote} + +The \verb+mta key+ is the key from the address lookup. This is the +remote host to which the outgoing connection it to be made. +The following keys are recognised in the value field. +The format of these keys are common to both the outbound and inbound +X.400 tables and as such are described here and not under the X.400 +inbound table section. + +\begin{describe} +\item[\verb+lmta+:] The name of the local mtaname to pass in the +RTS connect parameters. + +\item[\verb+lpass+:] The passwd of the local site to pass in the +RTS connect parameters. + +\item[\verb+rmta+:] The name of the remote MTA to pass in the RTS +connect parameters. If this is not set, then no authentication will be +specified in the RTS connect. + +\item[\verb+rpass+:] The name of the remote password to pass in the +RTS connect parameters. There is no default for this and it should +not be set if the \verb+rmta+ is set. + +\item[\verb+rpsap+:] The remote presentation address. This is +specified in the string encoded format. Note that session selectors +and presentation selectors should always be absent in the 1984 RTS. +This is the only mandatory key on the RHS of the X.400 outbound table. + +\item[\verb+lpsap+:] The local presentation address. This is only +necessary if you need to claim to originate from a specific selector +or network address. Normally this parameter is not specified. + +\item[\verb+mode+:] The mode of RTS connection. This is either +\verb+mon+ for monologue (the default) or \verb+twa+ for two way +alternate. This only governs the mode passed initially, it does not +imply that the channel will work in TWA mode. + +\item[\verb+type+:] The type of RTS connection. This is one of the +following: + +\[\begin{tabular}{|l | p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt 1984 & Use the 1984 protocol mode (default). \\ + \tt 1988-X410 & Use the 1988 X.410 mode protocol, \\ + \tt 1988-normal & Use the 1988 normal mode protocol. \\ + \tt 1988 & Use the 1988 normal mode protocol (same as previous). \\ +\hline +\end{tabular}\] + +Obviously, this information is dependent on the capabilities of the +channel (a 1984-based channel will not be able to use the 1988 +protocol). + +\item[\verb+trynext+:] A key to another entry in the table. If a +connection using the current information fails, the outbound channel +will look up this key and +try making a connection using that data. + +\item[\verb+tracing+:] The style of tracing information to use. It may +take one of the following values: + +\[\begin{tabular}{|l | p{0.5\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt admd & Remove all but the first tracing component. \\ + \tt nointernal & Remove all internal tracing components. \\ + \tt local-internal & Keep only internal trace related to the + current PRMD. \\ + \tt all & keep all tracing information\\ +\hline +\end{tabular}\] +The default value is \verb|all|. + +The \verb|admd| mode should only be used when talking to a +particularly restrictive ADMD. Again, it depends on the capabilities +of the channel how closely this information can be followed. + +\item[\verb+rname+:] The ``real'' name of the remote MTA. This is +an entry +that is suitable for lookup in the domain table. It is not used for +the outbound channel. + +\item[\verb|fix-orig|:] This applies an on-the-fly change to the +originator address. The syntax is +\begin{quote}\small\begin{verbatim} +"fix-orig=" "->" +\end{verbatim}\end{quote} +and might be applied as +\begin{quote}\small\begin{verbatim} +fix-orig="/ADMD= /C=GB/->/ADMD=Gold 400/C=GB/ +\end{verbatim}\end{quote} +to change the ADMD from space, to \verb|Gold 400| in the originator +for outgoing messages to specific hosts. + +This key is only used by the outbound table. + +\item[\verb+other+:] Other information. This is a string and is +interpreted by the channel to allow other types of operation to be +specified. It is not currently used by the X.400 outbound channels. + +It is used by the X.400 inbound channels. +If \verb+other+ is set to \verb+sloppy+, the inbound channel will not +check against any \verb+rpass+ specified in the inbound table. + +\end{describe} + +If an entry with a key \verb|default|\index{default} exists in the +table, then this may be used to set default setting for all entries. +The value \verb|default| is looked up first and values filled in from +that setting, then the real entry is looked up and those values +override the default entry. + +An example outbound table is shown in Figure~\ref{example:x400out} +(lines are folded for clarity). + +\tagrind[hbtp]{x400out-examp}{Example of X.400 Outbound Channel Table}{example:x400out} + +\section {The X.400 (1984/1988) Inbound Table}\label{tab:X.400(84)in} + +This table\index{ch.x400in84}\index{ch.x400in88} is used by the inbound +X.400 channels, +and allows the channels to obtain the MTA name and other information +from the OSI calling address. The syntax is the same as the X.400 +outbound table, only the key is different. + +The key here is the information given in the session connection of the +remote calling host; the values are as indicated for the outbound +table. It is encoded in the string encoding for presentation +addresses using no macro substitution. Therefore, the keys look pretty +horrible. It is usual to maintain these tables with keys in macro form +and run them through the utility \pgm{nsapexpand} to expand the macros. + +The matching of incoming information with an entry in this table provides the +major security checking. Again an entry \verb|default| in the table +may be used to default many of the fields. + +An example inbound table is shown in Figure~\ref{example:x400in} +(again lines are +folded for clarity). + +\tagrind[hbtp]{x400in-examp}{Example of X.400 inbound Channel table}{example:x400in} + +\section {The List Table}\index{table, list}\label{sect:list} + +The \file{ch.list} table is used by the \pgm{list} channel to +expand local distribution lists. +Entries in this table have the format: + +\begin{quote}\begin{verbatim} + ":" [ "|" ...] "," + file= | "|" ... "," + description +\end{verbatim}\end{quote} + +\begin{describe} + +\item[\verb+listname+:] +The name of the distribution list, e.g., \verb+listname+. +Note that in order for the list to form +a valid local address, the local part of the name, \verb+listname+ in +the above examples, must have an entry in the local \file{users} +table, specifying that messages addressed to the list should be +delivered via the list channel. + +\item[\verb+moderator+:]\index{moderator} + The UNIX ids/login names of the moderators of the list. This element +of the table entry is purely for the use of the distribution list +management tool, \pgm{mlist} (see Volume~III (The PP Manual: +User's Guide)). Anyone with one of the specified uids +may use \pgm{mlist} to modify the contents of the list. + +\item[\verb+file+:] +The file containing the members of the list. If \verb++ is +not a fully qualified pathname, the required file will be assumed to +be under the \file{tbldir} directory structure. The format of such +files is one member's address per line. +Note that the file must exist for \pgm{mlist} to be able to be used on +the corresponding list (i.e. \pgm{mlist} is unable to create the files +only modify them). +Any lines in this file starting with the character \verb+#+ are ignored. + +\item[\verb+mail address+:] An address of a member of the list. +Note that because they are specified in the list table itself, +\pgm{mlist} cannot be used to modify such members. + +\item[\verb+description+:] A short description of the purpose of the list. +This description is output by \pgm{mlist} when requested. +\end{describe} + +Note that in order to form a valid entry in the list table, each entry +must be on one line and must contain two and only two commas. + +Comment line in tables start with a \verb+#+. +The list table extends this mechanism further. +Comment lines that are printed by \pgm{mlist} start with \verb+#Comment:+. +This allows the list table to have two levels of comments, +one for the editor of the list table and one for the user of \pgm{mlist}. + +\tagrind[hbtp]{lists-examp}{Example of List Table}{example:lists} + +If you have a large sendmail alias file to convert, you may find the utility +\man make-lists(8) of use. +\man make-lists(8) is found in the \file{Tools} directory. This utility +attempts to +convert lists of names into a format suitable for use in the list channel +of PP. Note: it does {\em not} convert all alias table entries, only lists. + +\section {The Shell Table}\index{table, shell}\label{sect:shell} + +The \file{ch.shell} table is referenced by the \pgm{shell} channel +when converting from the recipient address to the commands to execute +in its place. Entries in this table have the format: + +\begin{quote}\begin{verbatim} +
":" "," [['|']] + "," +\end{verbatim}\end{quote} + +\begin{describe} + +\item[\verb+address+:] specifies the recipient address, e.g., +\verb+shellprog+. +Note that in order for this to form a valid local address, the local +part, \verb+shellprog+ in the examples, must have an entry in the +local \file{users} table, specifying that messages sent to the address +should be delivered via the \pgm{shell} channel. + +\item[\verb+user id+:] specifies the user to run as when executing the +commands. This id is resolved using +\file{/etc/passwd}\index{/etc/passwd}. Alternatively it may be +specified as \verb|/| to run as an arbitrary user and group. + +\item[\verb+timeout period+:] +specifies how long, in seconds, the commands should be allowed to run +before the \pgm{shell} channel kills them off. If the timeout period +is not specified, the commands are allowed to run for the default +period of time, five minutes. If the period is zero then the +\pgm{shell} channel will not enforce a time limit for the commands. + +\item[\verb+qualifier+:] +qualifies the behaviour of the shell channel. +This qualifier is optional appended to the timeout period with a +\verb+|+ seperating the two values. +If the qualifier is set to the string \verb+solo+ then the shell +channel will restart(fork) the command line for each bodypart. + +\item[\verb+command line+:] +specifies the command line to execute. If the program name is not a +fully qualified pathname, the program is assumed to be under the +directory specified by \file{chandir}. Arguments of the form +\verb+$(key)+ will be expanded as described in +Table~\ref{tab:shellexp}. + +\end{describe} + +\tagtable{shellexp}{Shell Channel Expansion Macros}{tab:shellexp} + +When running, the \pgm{shell} channel pipes all the message body parts, in +order, to the program's standard input. +The \pgm{shell} channel understands an exit code of 0 as success and +otherwise as failure. + +An example of a \pgm{shell} table is shown in Figure~\ref{example:shell}. + +\tagrind[hbtp]{shell-examp}{Example of Shell Table}{example:shell} + +\subsection{Statistical Logging} + +Each line in the statistics log (``stat'') either logs the status of +inbound messages, or delivery reports that are generated, or notes a +message that is delivered. Amongst the parameters logged are: +\begin{itemize} +\item A success indicator ( e.g., ``ok'' or ``DR'' ). +\item Unique message id. +\item A P1 message ID. +\item Inbound channel$\rightarrow$outbound channel. +\item Sender. +\item Sending MTA. +\item Recipient. +\item Destination MTA. +\item Message size. +\item A diagnostic message. +\end{itemize} + +Fields are space-delimited and double quoted where necessary. + +Duplicate recipients are eliminated (second and subsequent) if there +is an exact match on the 822 or X.400 address (as appropriate), \pgm{not} the +original entry. + +Channel binding is performed after all other tests have been passed, and +takes into account any body parts actually received but not specified in the +message header. + +Unsuccessful recipients are flagged to generate nondelivery reports. + +The tool \pgm{statp}, found under the \file{Tools} directory, takes +the statistics log and converts it to something suitable for +processing via \verb+awk+ or other such processing tools. +There are several example awk scripts under the source directory +\file{Tools/statgen}. diff --git a/doc/manual/volume1/tables.tex.aux b/doc/manual/volume1/tables.tex.aux new file mode 100644 index 0000000..a700fde --- /dev/null +++ b/doc/manual/volume1/tables.tex.aux @@ -0,0 +1,20 @@ +\relax +\global\@namedef{cp@tables.tex}{ +\setcounter{page}{33} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{3} +\setcounter{subsection}{4} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{4} +\setcounter{table}{1} +} diff --git a/doc/manual/volume1/tableshellexp.tex b/doc/manual/volume1/tableshellexp.tex new file mode 100644 index 0000000..de8f46e --- /dev/null +++ b/doc/manual/volume1/tableshellexp.tex @@ -0,0 +1,29 @@ +\[\begin{tabular} {|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Key} & + \multicolumn{1}{|c|}{\bf Expansion} \\ +\hline + \tt sender & + the address of the sender of the message (original format) \\ + \tt 822sender & + the address of the sender (rfc822 format) \\ + \tt 400sender & + the address of the sender (x400 format) \\ + \tt recip & + the address of the recipient of the message (original format) \\ + \tt 822recip & + the address of the recipient (rfc822 format) \\ + \tt 400recip & + the address of the recipient (x400 format) \\ + \tt qid & + the queue id of the message (e.g., msg.a000000) \\ + \tt ua-id & + the user agent id of the message \\ + \tt p1-id & + the P1 id of the message \\ + \tt userid & The username or ID of the delivery process\\ + \tt groupid & The group name or ID of the delivery process \\ + \tt size & The size in bytes of the message \\ + \tt channelname & The name of the delivery channel \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tablewarn.tex b/doc/manual/volume1/tablewarn.tex new file mode 100644 index 0000000..6a4b941 --- /dev/null +++ b/doc/manual/volume1/tablewarn.tex @@ -0,0 +1,32 @@ +\[\begin{tabular} {|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Key} & + \multicolumn{1}{|c|}{\bf Expansion} \\ +\hline + \tt sender & + the address of the sender of the message (original format) \\ + \tt 822sender & + the address of the sender (rfc822 format) \\ + \tt 400sender & + the address of the sender (x400 format) \\ + \tt recips & + the address of the recipient of the message (original format) \\ + \tt 822recips & + the address of the recipient (rfc822 format) \\ + \tt 400recips & + the address of the recipient (x400 format) \\ + \tt qid & + the queue id of the message (e.g., msg.a000000) \\ + \tt ua-id & + the user agent id of the message \\ + \tt p1-id & + the P1 id of the message \\ + \tt locmta & + the local mta (\verb|loc_dom_mta|) \\ + \tt locsite & + the local site (\verb|loc_doc_site|) \\ + \tt hours-left & + the number of hours left until the message will be +returned. \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tablewarnexp.tex b/doc/manual/volume1/tablewarnexp.tex new file mode 100644 index 0000000..c155cd3 --- /dev/null +++ b/doc/manual/volume1/tablewarnexp.tex @@ -0,0 +1,30 @@ +\[\begin{tabular} {|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Key} & + \multicolumn{1}{|c|}{\bf Expansion} \\ +\hline + \tt sender & + the address of the sender of the message (original format) \\ + \tt 822sender & + the address of the sender (rfc822 format) \\ + \tt 400sender & + the address of the sender (x400 format) \\ + \tt recip & + the address of the recipient of the message (original format) \\ + \tt 822recip & + the address of the recipient (rfc822 format) \\ + \tt 400recip & + the address of the recipient (x400 format) \\ + \tt ua-id & + the user agent id of the message \\ + \tt p1-id & + the P1 id of the message \\ + \tt locsite & + the local site name \\ + \tt locmta & + the local mta name \\ + \tt reason & The reason for authorisation failure\\ + \tt direction & if the message is destined for the sender or +the recipient \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume1/tablex400info1.tex b/doc/manual/volume1/tablex400info1.tex new file mode 100644 index 0000000..2833c0f --- /dev/null +++ b/doc/manual/volume1/tablex400info1.tex @@ -0,0 +1,12 @@ +\[\begin {tabular}{l l} +\tt Technical Contact:& Peter Yee\\ +\tt Telephone:& not known\\ +\tt O/R Address:& C=US; ADMD=TELEMAIL; PRMD=ARC; O=NASA; S=yee;\\ +\tt MTA Name:& titan.arc.nasa.gov\\ +\tt MTA Password:& " " (i.e a one character space)\\ +\tt Transport Selector:& 591 (ascii)\\ +\tt TCP IP Address:& "128.102.128.5"\\ +\tt X.25 DTE Address:& not known\\ +\tt X.25 Protocol ID:& not known\\ +\tt ManagementDomains:& C=US;ADMD=TELEMAIL; PRMD=ARC;\\ +\end{tabular}\] diff --git a/doc/manual/volume1/tablex400info2.tex b/doc/manual/volume1/tablex400info2.tex new file mode 100644 index 0000000..c475979 --- /dev/null +++ b/doc/manual/volume1/tablex400info2.tex @@ -0,0 +1,15 @@ +\[\begin {tabular}{l l} +\tt Technical Contact:& John Andrews\\ +\tt Telephone:& 01-387-7050 ext 3691\\ +\tt O/R Address:& C=GB; ADMD=GOLD 400; PRMD=UK.AC;\\ +\tt& O=UCL; OU=UCL; S=Postmaster;\\ +\tt MTA Name:& UK.AC.UCL.CS\\ +\tt MTA Password:& " " (i.e a one character space)\\ +\tt Transport Selector:& 591 (ascii)\\ +\tt TCP IP Address:& 128.16.5.31\\ +\tt X.25 DTE Address:& 23421920030080\\ +\tt X.25 Protocol ID:& not needed\\ +\tt ManagementDomains:& C=GB; ADMD=GOLD 400; PRMD=UK.AC\\ +\tt& C=GB; ADMD=BTMHS; PRMD=UK.AC\\ +\tt& C=GB; ADMD= ; PRMD=UK.AC\\ +\end{tabular}\] diff --git a/doc/manual/volume1/tailor.tai b/doc/manual/volume1/tailor.tai new file mode 100644 index 0000000..6805f0e --- /dev/null +++ b/doc/manual/volume1/tailor.tai @@ -0,0 +1,425 @@ +############################################################ +# +# Tailor file for PP +# +# This version for sites with local smtp +# +############################################################ + +############################################################ +# +# The following variables will need tailoring +# +############################################################ +# +# The loc_dom_mta is the host that the MTA will reside on and execute from +# It is a fully qualified domain name and represent the physical machine +# Examples might be +# cheetah.nyser.net +# violet.berkeley.edu +# john.cs.nott.ac.uk +# +loc_dom_mta lancaster.xtel.co.uk +# +# The Sitename is what the rest of the world sees you as. This is typically +# a domain shorter than the full domain name. It is the name used to represent +# your site or group as a whole. This name normally hides the individual +# machine names +# Examples might be +# berkeley.edu +# nyser.net +# cs.nott.ac.uk +# +loc_dom_site xtel.co.uk +# +# The postmaster should include the local site name +# e.g. postmaster@berkeley.edu or postmaster@cs.nott.ac.uk +# +postmaster postmaster@xtel.co.uk +# +# The pplogin should be the username of the owner of pp. +# +pplogin pp +# +# The qmgrhost should be the same as the name found in isoentities file. +# This can be the same as loc_dom_mta name +# +pptsapd_addr LOCAL-ETHER=lancaster+20001 +qmgrhost lancaster +# +# The local or name should be the name of your site in X.400 terms. +# This is attribute value based, and starts with organisational units and +# works up to country. If you are unsure, leave it with just a country +# component, e.g. "/C=GB/" +# +loc_or "/o=xtel/prmd=X-Tel Services/admd= /c=GB/" +############################################################ +# +# That is the end of the things you must tailor - the rest are +# probably ok - but you should check. +# +############################################################ + +delim1 "\1\1\1\1\12" +delim2 "\1\1\1\1\12" +#returntime 36 +#queuestruct 100 +dap_user "c=GB@o=X-Tel Services Ltd@cn=lancaster@cn=pp qmgr" + + +authchannel free +authloglevel high +wrndfldir warnings +#submit_addr lancaster:pp-submit + +# Body types + +headertype 822 822-jnt 822-us p2 822-uk p22 ipn g3fax ps +bodypart ia5 dmd odif g3fax ipm voice iso6937 ia5-dk ps ms +bodypart oid.0.9.2342.60200172.99.1.4 + + +# **-- Mapping tables --** +# +# All of these table MUST have the names given here +tbl aliases show="Aliases: mapping -> local id", + flags=dbm +tbl users show="Users: mapping local id -> disposition", + flags=dbm +tbl x400-developers-aliases show="Aliases: mapping -> local id", + flags=linear +tbl x400-developers-users show="Users: mapping local id -> disposition", + flags=linear +tbl domain show="Mapping domain key ->full domain/MTA", + flags=dbm +tbl or show="Mapping O/R Address -> MTA",flags=dbm +tbl channel show="Binding MTA -> Channels",flags=dbm +tbl or2rfc show="RFC 987: X.400 -> RFC 822",flags=dbm +tbl rfc2or show="RFC 987: RFC 822 -> X.400",flags=dbm +tbl rfc1148gate show="Gateways that perform RFC 1148 conversions", + flags=dbm +tbl auth.channel show="Authorisation: channel policy",flags=linear +tbl auth.mta show="Authorisation: mta based",flags=linear +tbl auth.user show="Authorisation: user based",flags=linear +tbl auth.qmgr show="Authorisation: qmgr control",flags=dbm +# **-- Channel tables --** +# +# Needed by individual channels, not submit +tbl local file="ch.local", + show="local id -> user id + home directory", + flags=dbm + +tbl x400in84 file="ch.x400in84", + show="MTA -> connect info",flags=linear +tbl x400out84 file="ch.x400out84", + show="X.400(84) connect info -> MTA + other info", + flags=linear +tbl x400in88 file="ch.x400in88", + show="MTA -> connect info",flags=linear +tbl x400out88 file="ch.x400out88", + show="X.400(88) connect info -> MTA + other info", + flags=linear +tbl shell file="ch.shell", + show="info for shell chan" + flags=dbm +tbl list file="ch.list", + show="Lists: distribution lists", + flags=dbm +tbl uucp file="ch.uucp" + show="UUCP: rfc822 -> uucp", + flags=dbm +tbl fax file="ch.fax", + show="FAX: mappings and info", + flags=linear +tbl mslocal file="ch.mslocal", + show="Message Store:local id -> user id,home directory", + flags=linear + +chan 822-local prog=local, + show="Local Delivery channel",type=both, + sort="user time",adr=822,adr-order=usapref, + hdrin=822,hdrout=822-us, + bptin=ia5,bptout=ia5, + content-out=822,outtable=local,access=mts,drchan=dr2rfc + +chan bugs-local prog=local, + show="Local Delivery channel for Bug Reports",type=both, + sort="user time",adr=822,adr-order=usapref, + hdrin=822,hdrout=822-us, + bptin=ia5,bptout=ia5, + content-out=822,outtable=local,access=mts,drchan=dr2rfc + +chan xua show="XUA Submission Channel",type=in, + access=mts,adr-order=ukpref, + adr=x400, access=mts, + +chan x400in84 prog=x400in84,show="X400 inbound",type=in, + content-in=p2,adr=x400, + adr-order=ukpref,intable=x400in84 + +chan x400in88 prog=x400in88,show="X400 inbound (1988)",type=in, + content-in=p22,adr=x400, + adr-order=ukpref,intable=x400in88 + +chan x400out84 prog=x400out84,show="X400 outbound",type=out, + adr=x400,adr-order=ukpref, + content-out=p2, + hdrout=p2, + bptout="ia5,g3fax,odif", + outtable=x400out84 + +chan x400out88 prog=x400out88,show="X400 outbound",type=out, + adr=x400,adr-order=ukpref, + content-out=p22, + hdrout=p22, + bptout="ia5,g3fax,voice,odif,iso6937,oid.0.9.2342.60200172.99.1.4", + outtable=x400out88 + +chan mslocal prog=mslocal,show="MS local delivery",type=out, + hdrout="p22,p2,ipn", + bptout="ia5,g3fax,voice,iso6937",outtable=mslocal, + sort="user time",access=mts + +chan mslocal-beta prog=mslocalbeta,show="MS local delivery",type=out, + hdrout="p22,p2,ipn", + bptout="ia5,g3fax,voice,iso6937,oid.0.9.2342.60200172.99.1.4",outtable=mslocal, + sort="user time",access=mts + +chan smtp prog=smtp,show="with SMTP (PP)",type=both, + adr=822,adr-order=usapref,drchan=dr2rfc, + bptout=ia5,hdrout=822-us,content-out=822, + +chan pac-janet prog="greyout -P",show="via JANET with NIFTP (PP)", + type=in, adr=822,adr-order=ukpref, + hdrin=822-us, + outinfo=janet + +chan gb-janet prog="greyout -P",show="via JANET with NIFTP (PP)", + type=both, adr=822,adr-order=ukpref, + hdrout=822-jnt, + bptout=ia5,drchan=dr2rfc, + content-out=822,outinfo=janet +# mta=much.cs.nott.ac.uk, + +chan gb-pss prog=smtp,key=ipss, + show="via PSS with NIFTP (PP)",type=both, + adr=822,adr-order=ukpref,drchan=dr2rfc, + bptout=ia5,hdrout=822-jnt, + content-out=822,mta=much.cs.nott.ac.uk + +chan fax prog=G3Fax, show="Fax channel",type=both, + content-in=p22, hdrout=g3fax, bptout=g3fax, + drchan=dr2rfc,outtable=fax, sort="user time", +# outinfo="in=/dev/ttyb,out=/dev/faxout,confirm,debug,master=gal@xtel.co.uk" + outinfo="in=/dev/ttyb,out=/dev/faxout,confirm,softcar,debug" + ininfo="in=/dev/faxin,softcar,confirm,debug,master=gal@xtel.co.uk" + +chan faxyuch prog=G3Fax, show="Fax channel",type=both, + content-in=p22, + bptout="g3fax,ia5", drchan=dr2rfc, outtable=fax, + outinfo="in=/dev/ttyb,out=/dev/ttyb,master=faxmaster" + +chan dirlist prog=dirlist,show="Directory List channel",type=both, + drchan=dr2rfc,adr=x400,adr-order=usapref, + sort="user time", outinfo="dn=C=GB@O=X-Tel Services Ltd@CN=lancaster" + +chan list prog=list,show="List channel",type=both, + adr-order=usapref,outinfo="linked", + outtable=list,drchan=dr2rfc,sort="user time" + +chan uucp prog=uucp-out,key="uucp-out,rmail", + show="UUCP channel",type=both, + adr=822,adr-order=ukpref,outtable=uucp + outinfo="uux=/tmp/uux,host=nott-cs",drchan=dr2rfc + +chan dr2rfc prog=dr2rfc,show="Dr2rfc channel",type=both, + adr=822,adr-order=ukpref, + bptin=ia5,hdrin=822, + outinfo="return=all order=uk", + content-out=822 + +chan shell prog=shell,type=out,access=mts + show="Shell channel", + outtable=shell,sort="user time", + bptout="ia5,ps",hdrout=822-uk + +# QMGR special channels (load/manage/clean) + +chan qmgr-load prog=qmgr-load,show="Loading the QMGR", + type=qmgrload,outinfo="5"; + +chan msg-clean prog=msg-clean,show="Removing finished message" + type=delete + +chan trash prog=trash,show="Removing trash" + type=debris,outinfo=5h + +chan timeout prog=timeout,show="Timeout messages" + type=timeout + +chan warning prog=warnings,show="Send warning messages", + type=warn +chan splitter prog=splitter,type=split, + show="Divide message into single" +recipient messages +# **-- shaper channels --** + +# Flatteners + +chan p2flatten prog=p2flatten,show="Structured message -> P2", + type=shaper,content-out=p2 + +chan 822flatten prog=rfc934,type=shaper,content-out=822 + +chan p22flatten prog=p2flatten,show="Structured Message -> P22", + type=shaper,content-out=p22 + +# Unflatteners + +chan p2explode prog=p2explode,type=shaper,content-in=p2 + +chan p22explode prog=p2explode,type=shaper,content-in=p22 + + +# Header Filters +chan 822tofax prog=fcontrol,type=shaper, + hdrin=822-us,hdrout=g3fax, + outinfo="hdr2fax -from $(400sender) -to $(400recip) -subject $(ua-id) -table $(outtable) -outmta $(outmta)",outtable=fax, + cost=20,solo-proc=yes +chan 822touk prog=fcontrol,type=shaper, + hdrin=822, + hdrout=822-uk, + outinfo="rfc822norm -jnt -bigend" +chan 822tojnt prog=fcontrol,type=shaper, + hdrin=822,hdrout=822-jnt, + outinfo="rfc822norm -jnt -bigend -jntsender $(822SENDER)" +chan 822tous prog=fcontrol,type=shaper,hdrin=822, + hdrout=822-us, + outinfo="rfc822norm -822 -littleend" +chan 822top2 prog=RFCtoP2,type=shaper,hdrin=822-us,conv=1148 + hdrout=p2,cost=10, + show="RFC1148 RFC 822 -> P2" +chan 822top22 prog=RFCtoP2,type=shaper,hdrin=822-us,conv=1148 + hdrout=p22,cost=10, + show="RFC1148 RFC 822 -> P22" +chan p2to822 prog=P2toRFC,type=shaper,hdrout=822,conv=1148, + hdrin="ipn,p2",cost=10, + show="RFC1148 P2 -> RFC 822" +chan p22to822 prog=P2toRFC,type=shaper,hdrout=822,conv=1148 + hdrin="ipn,p22",cost=10, + show="RFC1148 P22 -> RFC 822" +chan p22top2 prog=fcontrol,type=shaper,hdrout=p2,hdrin=p22, + show="P22 to P2 downgrade", + conv=conv,cost=10,outinfo="p2norm -downgrade" +#identity map +chan p2top22 prog=fcontrol,type=shaper,hdrout=p22,hdrin=p2, + show="P2 to P22 upgrade",cost=1, + outinfo="/bin/cat" + +# Body part filters + +chan ia5-dk2ia5 prog=fcontrol,type=shaper,bptin=ia5-dk, + bptout=ia5,show="Danish ia5 to ia5", + conv=loss,outinfo="charset DK 38 UK 29" + +chan iso6937totxt prog=fcontrol,type=shaper,bptin=iso6937, + bptout=ia5,conv=loss,cost=15, + outinfo="asn -inchar iso_6937-2-add -outchar irv -inasn motis-86-6937 -outasn ia5", + show="ISO6937 -> IA5" + +chan g3faxtotxt prog=fcontrol,type=shaper,bptin=g3fax, + bptout=ia5,outinfo="removebp G3Fax", + show="Fax -> Text mapper",cost=100,conv=loss +chan txttofax prog=fcontrol,type=shaper,bptin=ia5, + bptout=g3fax, + outinfo="ia52fax -table $(outtable)",outtable=fax, + show="ia5 -> g3fax mapper" + +chan faxtops prog=fcontrol,type=shaper,bptin=g3fax, + bptout=ps,outinfo="fax2ps",show="fax -> postscript" + +chan mstops prog=fcontrol,type=shaper,bptin=ms, + bptout=ps,outinfo="/usr/local/bin/psroff -ms -t", + show="ms macros -> postscript" + +chan mstoia5 prog=fcontrol,type=shaper,bptin=ms, + bptout=ia5,outinfo="/bin/cat", + show="MS->Text mapper",cost=100,conv=loss + +chan xxtotxt prog=fcontrol,type=shaper,bptin=oid.0.9.2342.60200172.99.1.4, + bptout=ia5,outinfo="removebp oid.0.9.2342.60200172.99.1.4" + show="XXX -> Text mapper",cost=100,conv=loss + +chan voicetotxt prog=fcontrol,type=shaper,bptin=voice, + bptout=ia5,outinfo="removebp Voice" + show="Voice -> Text mapper",cost=100,conv=loss + +# **-- Logging for the rest of the prog --** +# +authlog level=notice, size=400 +operlog level=notice, size=400 +normlog level=notice, size=400, sflags=zero + +822flatten normlog file=filter +p2flatten normlog file=filter +822touk normlog file=filter +822tous normlog file=filter +dr2rfc normlog file=filter +fcontrol normlog file=filter +odif2txt normlog file=filter +p2explode normlog file=filter +rfc822norm normlog file=filter +trash normlog file=filter + +822top2 normlog file=rfc987 +p2to822 normlog file=rfc987 + +list normlog file=lists + +qmgr normlog file=qmgr +qmgr-load normlog file=qmgr + +smtp normlog file=smtp +smtpsrvr normlog file=smtp + +greyout normlog file=greyout +gb-janet normlog file=greyin +submit normlog file=submit dflags=close + +local normlog file=local +msg-clean normlog file=msg-clean + +x400in84 normlog file=x400in84,level=pdus +x400in84 isodelog rtsaplevel file=rts,level=all +x400in84 isodelog ssaplevel file=ssap,level=all +x400out84 normlog file=x400out84 + +x400in88 normlog file=x400in88 level=pdus,level=trace +x400out88 normlog file=x400out88 #level=all + +p7server normlog file=p7server level=all + +xfax normlog file=fax #level=debug +xfaxd normlog file=fax #level=debug +G3Fax normlog file=fax +hdr2fax normlog file=fax +ia52fax normlog file=fax + +#x400out88 isodelog rtsaplevel file=rts-out level=all +#x400out88 isodelog acsaplevel file=acsap-out level=all +#x400out88 isodelog psap2level file=psap2-out level=all +#x400out88 isodelog ssaplevel file=ssap-out level=all + + +#x400in88 isodelog rtsaplevel file=proto-in level=all +#x400in88 isodelog acsaplevel file=proto-in level=all +#x400in88 isodelog psap2level file=proto-in level=all + +pptsapd normlog file=pptsapd, dlevel=notice +dirlist normlog file=dirlist +mslocal normlog file=mslocal +xprobe normlog file=probe level=trace,level=pdus level=all +p7server isode ns_enable off +xua isode ns_enable off +libmsattr isode ns_enable off +#xckadr normlog level=all file=ckadr diff --git a/doc/manual/volume1/tailor.tex b/doc/manual/volume1/tailor.tex new file mode 100644 index 0000000..25f3806 --- /dev/null +++ b/doc/manual/volume1/tailor.tex @@ -0,0 +1,426 @@ +\File{tailor.tai},{12:13},{Dec 13 1991} +\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# Tailor file for PP}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# This version for sites with local smtp}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{}} +\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The following variables will need tailoring }} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The loc\_dom\_mta is the host that the MTA will reside on and execute from}} +\CE{}\L{\LB{\C{}\# It is a fully qualified domain name and represent the physical machine}} +\CE{}\L{\LB{\C{}\#}\Tab{8}{Examples might be}} +\CE{}\L{\LB{\C{}\#}\Tab{16}{cheetah.nyser.net}} +\CE{}\L{\LB{\C{}\# }\Tab{16}{violet.berkeley.edu}} +\CE{}\L{\LB{\C{}\#}\Tab{16}{john.cs.nott.ac.uk}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{loc\_dom\_mta}\Tab{16}{lancaster.xtel.co.uk}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The Sitename is what the rest of the world sees you as. This is typically}} +\CE{}\L{\LB{\C{}\# a domain shorter than the full domain name. It is the name used to represent}} +\CE{}\L{\LB{\C{}\# your site or group as a whole. This name normally hides the individual }} +\CE{}\L{\LB{\C{}\# machine names}} +\CE{}\L{\LB{\C{}\#}\Tab{8}{Examples might be}} +\CE{}\L{\LB{\C{}\#}\Tab{16}{berkeley.edu}} +\CE{}\L{\LB{\C{}\#}\Tab{16}{nyser.net}} +\CE{}\L{\LB{\C{}\#}\Tab{16}{cs.nott.ac.uk}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{loc\_dom\_site}\Tab{16}{xtel.co.uk}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The postmaster should include the local site name}} +\CE{}\L{\LB{\C{}\# e.g. postmaster@berkeley.edu or postmaster@cs.nott.ac.uk}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{postmaster}\Tab{16}{postmaster@xtel.co.uk}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The pplogin should be the username of the owner of pp.}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{pplogin}\Tab{16}{pp}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The qmgrhost should be the same as the name found in isoentities file.}} +\CE{}\L{\LB{\C{}\# This can be the same as loc\_dom\_mta name}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{pptsapd\_addr}\Tab{16}{LOCAL\-ETHER=lancaster+20001}} +\L{\LB{qmgrhost}\Tab{16}{lancaster}} +\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# The local or name should be the name of your site in X.400 terms.}} +\CE{}\L{\LB{\C{}\# This is attribute value based, and starts with organisational units and}} +\CE{}\L{\LB{\C{}\# works up to country. If you are unsure, leave it with just a country}} +\CE{}\L{\LB{\C{}\# component, e.g. \"\/C=GB\/\"}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{loc\_or}\Tab{16}{\S{}\"\/o=xtel\/prmd=X\-Tel Services\/admd= \/c=GB\/\"\SE{}}} +\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# That is the end of the things you must tailor \- the rest are}} +\CE{}\L{\LB{\C{}\# probably ok \- but you should check.}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#}} +\CE{}\L{\LB{}} +\L{\LB{delim1}\Tab{16}{\S{}\"\!1\!1\!1\!1\!12\"\SE{}}} +\L{\LB{delim2}\Tab{16}{\S{}\"\!1\!1\!1\!1\!12\"\SE{}}} +\L{\LB{\C{}\#returntime 36}} +\CE{}\L{\LB{\C{}\#queuestruct}\Tab{16}{100}} +\CE{}\L{\LB{dap\_user}\Tab{16}{\S{}\"c=GB@o=X\-Tel Services Ltd@cn=lancaster@cn=pp qmgr\"\SE{}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{authchannel}\Tab{16}{free}} +\L{\LB{authloglevel}\Tab{16}{high}} +\L{\LB{wrndfldir}\Tab{16}{warnings}} +\L{\LB{\C{}\#submit\_addr}\Tab{16}{lancaster:pp\-submit}} +\CE{}\L{\LB{}} +\L{\LB{\C{}\# Body types}} +\CE{}\L{\LB{}} +\L{\LB{headertype}\Tab{16}{822 822\-jnt 822\-us p2 822\-uk p22 ipn g3fax ps}} +\L{\LB{bodypart}\Tab{16}{ia5 dmd odif g3fax ipm voice iso6937 ia5\-dk ps ms}} +\L{\LB{bodypart}\Tab{16}{oid.0.9.2342.60200172.99.1.4}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{\C{}\# **\-\- Mapping tables \-\-**}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# All of these table MUST have the names given here}} +\CE{}\L{\LB{tbl}\Tab{8}{aliases}\Tab{24}{show=\S{}\"Aliases: mapping \-\> local id\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{users}\Tab{24}{show=\S{}\"Users: mapping local id \-\> disposition\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{x400\-developers\-aliases}\Tab{32}{show=\S{}\"Aliases: mapping \-\> local id\"\SE{},}} +\L{\LB{}\Tab{24}{flags=linear}} +\L{\LB{tbl}\Tab{8}{x400\-developers\-users}\Tab{32}{show=\S{}\"Users: mapping local id \-\> disposition\"\SE{},}} +\L{\LB{}\Tab{24}{flags=linear}} +\L{\LB{tbl}\Tab{8}{domain}\Tab{24}{show=\S{}\"Mapping domain key \-\>full domain\/MTA\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{or}\Tab{24}{show=\S{}\"Mapping O\/R Address \-\> MTA\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{channel}\Tab{24}{show=\S{}\"Binding MTA \-\> Channels\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{or2rfc}\Tab{24}{show=\S{}\"RFC 987: X.400 \-\> RFC 822\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{rfc2or}\Tab{24}{show=\S{}\"RFC 987: RFC 822 \-\> X.400\"\SE{},flags=dbm}} +\L{\LB{tbl}\Tab{8}{rfc1148gate}\Tab{24}{show=\S{}\"Gateways that perform RFC 1148 conversions\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{auth.channel}\Tab{24}{show=\S{}\"Authorisation: channel policy\"\SE{},flags=linear}} +\L{\LB{tbl}\Tab{8}{auth.mta}\Tab{24}{show=\S{}\"Authorisation: mta based\"\SE{},flags=linear}} +\L{\LB{tbl}\Tab{8}{auth.user}\Tab{24}{show=\S{}\"Authorisation: user based\"\SE{},flags=linear}} +\L{\LB{tbl}\Tab{8}{auth.qmgr}\Tab{24}{show=\S{}\"Authorisation: qmgr control\"\SE{},flags=dbm}} +\L{\LB{\C{}\# **\-\- Channel tables \-\-**}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{\C{}\# Needed by individual channels, not submit}} +\CE{}\L{\LB{tbl}\Tab{8}{local}\Tab{24}{file=\S{}\"ch.local\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"local id \-\> user id + home directory\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{}} +\L{\LB{tbl}\Tab{8}{x400in84}\Tab{24}{file=\S{}\"ch.x400in84\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"MTA \-\> connect info\"\SE{},flags=linear}} +\L{\LB{tbl}\Tab{8}{x400out84}\Tab{24}{file=\S{}\"ch.x400out84\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"X.400(84) connect info \-\> MTA + other info\"\SE{},}} +\L{\LB{}\Tab{24}{flags=linear}} +\L{\LB{tbl}\Tab{8}{x400in88}\Tab{24}{file=\S{}\"ch.x400in88\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"MTA \-\> connect info\"\SE{},flags=linear}} +\L{\LB{tbl}\Tab{8}{x400out88}\Tab{24}{file=\S{}\"ch.x400out88\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"X.400(88) connect info \-\> MTA + other info\"\SE{},}} +\L{\LB{}\Tab{24}{flags=linear}} +\L{\LB{tbl}\Tab{8}{shell}\Tab{24}{file=\S{}\"ch.shell\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"info for shell chan\"\SE{}}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{list}\Tab{24}{file=\S{}\"ch.list\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"Lists: distribution lists\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl}\Tab{8}{uucp}\Tab{24}{file=\S{}\"ch.uucp\"\SE{}}} +\L{\LB{}\Tab{24}{show=\S{}\"UUCP: rfc822 \-\> uucp\"\SE{},}} +\L{\LB{}\Tab{24}{flags=dbm}} +\L{\LB{tbl fax}\Tab{24}{file=\S{}\"ch.fax\"\SE{},}} +\L{\LB{ show=\S{}\"FAX: mappings and info\"\SE{},}} +\L{\LB{ flags=linear}} +\L{\LB{tbl}\Tab{8}{mslocal}\Tab{24}{file=\S{}\"ch.mslocal\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"Message Store:local id \-\> user id,home directory\"\SE{},}} +\L{\LB{}\Tab{24}{flags=linear}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{822\-local}\Tab{24}{ prog=local,}} +\L{\LB{}\Tab{8}{show=\S{}\"Local Delivery channel\"\SE{},type=both,}} +\L{\LB{}\Tab{8}{sort=\S{}\"user time\"\SE{},adr=822,adr\-order=usapref,}} +\L{\LB{}\Tab{8}{hdrin=822,hdrout=822\-us,}} +\L{\LB{}\Tab{8}{bptin=ia5,bptout=ia5,}} +\L{\LB{}\Tab{8}{content\-out=822,outtable=local,access=mts,drchan=dr2rfc}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{bugs\-local}\Tab{24}{ prog=local,}} +\L{\LB{}\Tab{8}{show=\S{}\"Local Delivery channel for Bug Reports\"\SE{},type=both,}} +\L{\LB{}\Tab{8}{sort=\S{}\"user time\"\SE{},adr=822,adr\-order=usapref,}} +\L{\LB{}\Tab{8}{hdrin=822,hdrout=822\-us,}} +\L{\LB{}\Tab{8}{bptin=ia5,bptout=ia5,}} +\L{\LB{}\Tab{8}{content\-out=822,outtable=local,access=mts,drchan=dr2rfc}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{xua}\Tab{24}{show=\S{}\"XUA Submission Channel\"\SE{},type=in,}} +\L{\LB{}\Tab{24}{access=mts,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{adr=x400, access=mts,}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{x400in84}\Tab{24}{prog=x400in84,show=\S{}\"X400 inbound\"\SE{},type=in,}} +\L{\LB{}\Tab{24}{content\-in=p2,adr=x400,}} +\L{\LB{}\Tab{24}{adr\-order=ukpref,intable=x400in84}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{x400in88}\Tab{24}{prog=x400in88,show=\S{}\"X400 inbound (1988)\"\SE{},type=in,}} +\L{\LB{}\Tab{24}{content\-in=p22,adr=x400,}} +\L{\LB{}\Tab{24}{adr\-order=ukpref,intable=x400in88}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{x400out84}\Tab{24}{prog=x400out84,show=\S{}\"X400 outbound\"\SE{},type=out,}} +\L{\LB{}\Tab{24}{adr=x400,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{content\-out=p2,}} +\L{\LB{}\Tab{24}{hdrout=p2,}} +\L{\LB{}\Tab{24}{bptout=\S{}\"ia5,g3fax,odif\"\SE{},}} +\L{\LB{}\Tab{24}{outtable=x400out84}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{x400out88}\Tab{24}{prog=x400out88,show=\S{}\"X400 outbound\"\SE{},type=out,}} +\L{\LB{}\Tab{24}{adr=x400,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{content\-out=p22,}} +\L{\LB{}\Tab{24}{hdrout=p22,}} +\L{\LB{}\Tab{24}{bptout=\S{}\"ia5,g3fax,voice,odif,iso6937,oid.0.9.2342.60200172.99.1.4\"\SE{},}} +\L{\LB{}\Tab{24}{outtable=x400out88}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{mslocal}\Tab{24}{prog=mslocal,show=\S{}\"MS local delivery\"\SE{},type=out,}} +\L{\LB{}\Tab{24}{hdrout=\S{}\"p22,p2,ipn\"\SE{},}} +\L{\LB{}\Tab{24}{bptout=\S{}\"ia5,g3fax,voice,iso6937\"\SE{},outtable=mslocal,}} +\L{\LB{}\Tab{24}{sort=\S{}\"user time\"\SE{},access=mts}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{mslocal\-beta}\Tab{24}{prog=mslocalbeta,show=\S{}\"MS local delivery\"\SE{},type=out,}} +\L{\LB{}\Tab{24}{hdrout=\S{}\"p22,p2,ipn\"\SE{},}} +\L{\LB{}\Tab{24}{bptout=\S{}\"ia5,g3fax,voice,iso6937,oid.0.9.2342.60200172.99.1.4\"\SE{},outtable=mslocal,}} +\L{\LB{}\Tab{24}{sort=\S{}\"user time\"\SE{},access=mts}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{smtp}\Tab{24}{prog=smtp,show=\S{}\"with SMTP (PP)\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{adr=822,adr\-order=usapref,drchan=dr2rfc,}} +\L{\LB{}\Tab{24}{bptout=ia5,hdrout=822\-us,content\-out=822,}} +\L{\LB{}} +\L{\LB{chan pac\-janet}\Tab{24}{prog=\S{}\"greyout \-P\"\SE{},show=\S{}\"via JANET with NIFTP (PP)\"\SE{},}} +\L{\LB{}\Tab{24}{type=in, adr=822,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{hdrin=822\-us,}} +\L{\LB{}\Tab{24}{outinfo=janet}} +\L{\LB{}} +\L{\LB{chan gb\-janet prog=\S{}\"greyout \-P\"\SE{},show=\S{}\"via JANET with NIFTP (PP)\"\SE{},}} +\L{\LB{}\Tab{24}{type=both, adr=822,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{hdrout=822\-jnt,}} +\L{\LB{}\Tab{24}{bptout=ia5,drchan=dr2rfc,}} +\L{\LB{}\Tab{24}{content\-out=822,outinfo=janet}} +\L{\LB{\C{}\#}\Tab{24}{mta=much.cs.nott.ac.uk,}} +\CE{}\L{\LB{}} +\L{\LB{chan}\Tab{8}{gb\-pss}\Tab{24}{prog=smtp,key=ipss,}} +\L{\LB{}\Tab{24}{show=\S{}\"via PSS with NIFTP (PP)\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{adr=822,adr\-order=ukpref,drchan=dr2rfc,}} +\L{\LB{}\Tab{24}{bptout=ia5,hdrout=822\-jnt,}} +\L{\LB{}\Tab{24}{content\-out=822,mta=much.cs.nott.ac.uk}} +\L{\LB{}} +\L{\LB{chan fax prog=G3Fax, show=\S{}\"Fax channel\"\SE{},type=both,}} +\L{\LB{ content\-in=p22, hdrout=g3fax, bptout=g3fax, }} +\L{\LB{}\Tab{24}{drchan=dr2rfc,outtable=fax, sort=\S{}\"user time\"\SE{},}} +\L{\LB{\C{}\# outinfo=\"in=\/dev\/ttyb,out=\/dev\/faxout,confirm,debug,master=gal@xtel.co.uk\"}} +\CE{}\L{\LB{ outinfo=\S{}\"in=\/dev\/ttyb,out=\/dev\/faxout,confirm,softcar,debug\"\SE{}}} +\L{\LB{}\Tab{24}{ininfo=\S{}\"in=\/dev\/faxin,softcar,confirm,debug,master=gal@xtel.co.uk\"\SE{}}} +\L{\LB{}} +\L{\LB{chan faxyuch prog=G3Fax, show=\S{}\"Fax channel\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{content\-in=p22,}} +\L{\LB{ bptout=\S{}\"g3fax,ia5\"\SE{}, drchan=dr2rfc, outtable=fax,}} +\L{\LB{ outinfo=\S{}\"in=\/dev\/ttyb,out=\/dev\/ttyb,master=faxmaster\"\SE{}}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{dirlist}\Tab{24}{prog=dirlist,show=\S{}\"Directory List channel\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{drchan=dr2rfc,adr=x400,adr\-order=usapref,}} +\L{\LB{}\Tab{24}{sort=\S{}\"user time\"\SE{}, outinfo=\S{}\"dn=C=GB@O=X\-Tel Services Ltd@CN=lancaster\"\SE{}}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{list}\Tab{24}{prog=list,show=\S{}\"List channel\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{adr\-order=usapref,outinfo=\S{}\"linked\"\SE{},}} +\L{\LB{}\Tab{24}{outtable=list,drchan=dr2rfc,sort=\S{}\"user time\"\SE{}}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{uucp}\Tab{24}{prog=uucp\-out,key=\S{}\"uucp\-out,rmail\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"UUCP channel\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{adr=822,adr\-order=ukpref,outtable=uucp}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"uux=\/tmp\/uux,host=nott\-cs\"\SE{},drchan=dr2rfc}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{dr2rfc}\Tab{24}{prog=dr2rfc,show=\S{}\"Dr2rfc channel\"\SE{},type=both,}} +\L{\LB{}\Tab{24}{adr=822,adr\-order=ukpref,}} +\L{\LB{}\Tab{24}{bptin=ia5,hdrin=822,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"return=all order=uk\"\SE{},}} +\L{\LB{}\Tab{24}{content\-out=822}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{shell}\Tab{24}{prog=shell,type=out,access=mts}} +\L{\LB{}\Tab{24}{show=\S{}\"Shell channel\"\SE{},}} +\L{\LB{}\Tab{24}{outtable=shell,sort=\S{}\"user time\"\SE{},}} +\L{\LB{}\Tab{24}{bptout=\S{}\"ia5,ps\"\SE{},hdrout=822\-uk}} +\L{\LB{}} +\L{\LB{\C{}\# QMGR special channels (load\/manage\/clean)}} +\CE{}\L{\LB{}} +\L{\LB{chan}\Tab{8}{qmgr\-load}\Tab{24}{prog=qmgr\-load,show=\S{}\"Loading the QMGR\"\SE{},}} +\L{\LB{}\Tab{24}{type=qmgrload,outinfo=\S{}\"5\"\SE{};}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{msg\-clean}\Tab{24}{prog=msg\-clean,show=\S{}\"Removing finished message\"\SE{}}} +\L{\LB{}\Tab{24}{type=delete}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{trash}\Tab{24}{prog=trash,show=\S{}\"Removing trash\"\SE{}}} +\L{\LB{}\Tab{24}{type=debris,outinfo=5h}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{timeout}\Tab{24}{prog=timeout,show=\S{}\"Timeout messages\"\SE{}}} +\L{\LB{}\Tab{24}{type=timeout}} +\L{\LB{}} +\L{\LB{chan warning}\Tab{24}{prog=warnings,show=\S{}\"Send warning messages\"\SE{},}} +\L{\LB{}\Tab{24}{type=warn}} +\L{\LB{chan splitter}\Tab{24}{prog=splitter,type=split,}} +\L{\LB{}\Tab{24}{show=\S{}\"Divide message into single\"\SE{}}} +\L{\LB{recipient messages}} +\L{\LB{\C{}\# **\-\- shaper channels \-\-**}} +\CE{}\L{\LB{}} +\L{\LB{\C{}\# Flatteners}} +\CE{}\L{\LB{}} +\L{\LB{chan}\Tab{8}{p2flatten}\Tab{24}{prog=p2flatten,show=\S{}\"Structured message \-\> P2\"\SE{},}} +\L{\LB{}\Tab{24}{type=shaper,content\-out=p2}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{822flatten}\Tab{24}{prog=rfc934,type=shaper,content\-out=822}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{p22flatten}\Tab{24}{prog=p2flatten,show=\S{}\"Structured Message \-\> P22\"\SE{},}} +\L{\LB{}\Tab{24}{type=shaper,content\-out=p22}} +\L{\LB{}} +\L{\LB{\C{}\# Unflatteners}} +\CE{}\L{\LB{}} +\L{\LB{chan}\Tab{8}{p2explode}\Tab{24}{prog=p2explode,type=shaper,content\-in=p2}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{p22explode}\Tab{24}{prog=p2explode,type=shaper,content\-in=p22}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{\C{}\# Header Filters}} +\CE{}\L{\LB{chan 822tofax prog=fcontrol,type=shaper,}} +\L{\LB{ hdrin=822\-us,hdrout=g3fax,}} +\L{\LB{ outinfo=\S{}\"hdr2fax \-from \$(400sender) \-to \$(400recip) \-subject \$(ua\-id) \-table \$(outtable) \-outmta \$(outmta)\"\SE{},outtable=fax,}} +\L{\LB{ cost=20,solo\-proc=yes}} +\L{\LB{chan}\Tab{8}{822touk}\Tab{24}{prog=fcontrol,type=shaper,}} +\L{\LB{}\Tab{24}{hdrin=822,}} +\L{\LB{}\Tab{24}{hdrout=822\-uk,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"rfc822norm \-jnt \-bigend\"\SE{}}} +\L{\LB{chan}\Tab{8}{822tojnt}\Tab{24}{prog=fcontrol,type=shaper,}} +\L{\LB{}\Tab{24}{hdrin=822,hdrout=822\-jnt,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"rfc822norm \-jnt \-bigend \-jntsender \$(822SENDER)\"\SE{}}} +\L{\LB{chan}\Tab{8}{822tous}\Tab{24}{prog=fcontrol,type=shaper,hdrin=822,}} +\L{\LB{}\Tab{24}{hdrout=822\-us,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"rfc822norm \-822 \-littleend\"\SE{}}} +\L{\LB{chan}\Tab{8}{822top2}\Tab{24}{prog=RFCtoP2,type=shaper,hdrin=822\-us,conv=1148}} +\L{\LB{}\Tab{24}{hdrout=p2,cost=10,}} +\L{\LB{}\Tab{24}{show=\S{}\"RFC1148 RFC 822 \-\> P2\"\SE{}}} +\L{\LB{chan}\Tab{8}{822top22}\Tab{24}{prog=RFCtoP2,type=shaper,hdrin=822\-us,conv=1148}} +\L{\LB{}\Tab{24}{hdrout=p22,cost=10,}} +\L{\LB{}\Tab{24}{show=\S{}\"RFC1148 RFC 822 \-\> P22\"\SE{}}} +\L{\LB{chan}\Tab{8}{p2to822}\Tab{24}{prog=P2toRFC,type=shaper,hdrout=822,conv=1148,}} +\L{\LB{}\Tab{24}{hdrin=\S{}\"ipn,p2\"\SE{},cost=10,}} +\L{\LB{}\Tab{24}{show=\S{}\"RFC1148 P2 \-\> RFC 822\"\SE{}}} +\L{\LB{chan}\Tab{8}{p22to822}\Tab{24}{prog=P2toRFC,type=shaper,hdrout=822,conv=1148}} +\L{\LB{}\Tab{24}{hdrin=\S{}\"ipn,p22\"\SE{},cost=10,}} +\L{\LB{}\Tab{24}{show=\S{}\"RFC1148 P22 \-\> RFC 822\"\SE{}}} +\L{\LB{chan}\Tab{8}{p22top2}\Tab{24}{prog=fcontrol,type=shaper,hdrout=p2,hdrin=p22,}} +\L{\LB{}\Tab{24}{show=\S{}\"P22 to P2 downgrade\"\SE{},}} +\L{\LB{}\Tab{24}{conv=conv,cost=10,outinfo=\S{}\"p2norm \-downgrade\"\SE{}}} +\L{\LB{\C{}\#identity map}} +\CE{}\L{\LB{chan}\Tab{8}{p2top22}\Tab{24}{prog=fcontrol,type=shaper,hdrout=p22,hdrin=p2,}} +\L{\LB{}\Tab{24}{show=\S{}\"P2 to P22 upgrade\"\SE{},cost=1,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"\/bin\/cat\"\SE{}}} +\L{\LB{}} +\L{\LB{\C{}\# Body part filters}} +\CE{}\L{\LB{}} +\L{\LB{chan ia5\-dk2ia5}\Tab{24}{prog=fcontrol,type=shaper,bptin=ia5\-dk,}} +\L{\LB{}\Tab{24}{bptout=ia5,show=\S{}\"Danish ia5 to ia5\"\SE{},}} +\L{\LB{}\Tab{24}{conv=loss,outinfo=\S{}\"charset DK 38 UK 29\"\SE{}}} +\L{\LB{}\Tab{24}{}} +\L{\LB{chan iso6937totxt}\Tab{24}{prog=fcontrol,type=shaper,bptin=iso6937,}} +\L{\LB{}\Tab{24}{bptout=ia5,conv=loss,cost=15,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"asn \-inchar iso\_6937\-2\-add \-outchar irv \-inasn motis\-86\-6937 \-outasn ia5\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"ISO6937 \-\> IA5\"\SE{}}} +\L{\LB{}} +\L{\LB{chan}\Tab{8}{g3faxtotxt}\Tab{24}{prog=fcontrol,type=shaper,bptin=g3fax,}} +\L{\LB{}\Tab{24}{bptout=ia5,outinfo=\S{}\"removebp G3Fax\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"Fax \-\> Text mapper\"\SE{},cost=100,conv=loss}} +\L{\LB{chan txttofax prog=fcontrol,type=shaper,bptin=ia5,}} +\L{\LB{ bptout=g3fax,}} +\L{\LB{}\Tab{24}{outinfo=\S{}\"ia52fax \-table \$(outtable)\"\SE{},outtable=fax,}} +\L{\LB{ show=\S{}\"ia5 \-\> g3fax mapper\"\SE{}}} +\L{\LB{}} +\L{\LB{chan faxtops}\Tab{24}{prog=fcontrol,type=shaper,bptin=g3fax,}} +\L{\LB{}\Tab{24}{bptout=ps,outinfo=\S{}\"fax2ps\"\SE{},show=\S{}\"fax \-\> postscript\"\SE{}}} +\L{\LB{}} +\L{\LB{chan mstops}\Tab{24}{prog=fcontrol,type=shaper,bptin=ms,}} +\L{\LB{}\Tab{24}{bptout=ps,outinfo=\S{}\"\/usr\/local\/bin\/psroff \-ms \-t\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"ms macros \-\> postscript\"\SE{}}} +\L{\LB{}} +\L{\LB{chan mstoia5}\Tab{24}{prog=fcontrol,type=shaper,bptin=ms,}} +\L{\LB{}\Tab{24}{bptout=ia5,outinfo=\S{}\"\/bin\/cat\"\SE{},}} +\L{\LB{}\Tab{24}{show=\S{}\"MS\-\>Text mapper\"\SE{},cost=100,conv=loss}} +\L{\LB{}} +\L{\LB{chan xxtotxt}\Tab{16}{prog=fcontrol,type=shaper,bptin=oid.0.9.2342.60200172.99.1.4,}} +\L{\LB{}\Tab{24}{bptout=ia5,outinfo=\S{}\"removebp oid.0.9.2342.60200172.99.1.4\"\SE{}}} +\L{\LB{}\Tab{24}{show=\S{}\"XXX \-\> Text mapper\"\SE{},cost=100,conv=loss}} +\L{\LB{}} +\L{\LB{chan voicetotxt}\Tab{24}{prog=fcontrol,type=shaper,bptin=voice,}} +\L{\LB{}\Tab{24}{bptout=ia5,outinfo=\S{}\"removebp Voice\"\SE{}}} +\L{\LB{}\Tab{24}{show=\S{}\"Voice \-\> Text mapper\"\SE{},cost=100,conv=loss}} +\L{\LB{}} +\L{\LB{\C{}\# **\-\- Logging for the rest of the prog \-\-**}} +\CE{}\L{\LB{\C{}\#}} +\CE{}\L{\LB{authlog level=notice, size=400}} +\L{\LB{operlog level=notice, size=400}} +\L{\LB{normlog level=notice, size=400, sflags=zero}} +\L{\LB{}} +\L{\LB{822flatten}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{p2flatten}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{822touk}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{822tous}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{dr2rfc}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{fcontrol}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{odif2txt}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{p2explode}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{rfc822norm}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{trash}\Tab{16}{normlog}\Tab{24}{ file=filter}} +\L{\LB{}} +\L{\LB{822top2}\Tab{16}{normlog}\Tab{24}{ file=rfc987}} +\L{\LB{p2to822}\Tab{16}{normlog}\Tab{24}{ file=rfc987}} +\L{\LB{}} +\L{\LB{list}\Tab{16}{normlog}\Tab{24}{ file=lists}} +\L{\LB{}} +\L{\LB{qmgr}\Tab{16}{normlog}\Tab{24}{ file=qmgr}} +\L{\LB{qmgr\-load}\Tab{16}{normlog}\Tab{24}{ file=qmgr}} +\L{\LB{}} +\L{\LB{smtp}\Tab{16}{normlog}\Tab{24}{ file=smtp}} +\L{\LB{smtpsrvr}\Tab{16}{normlog}\Tab{24}{ file=smtp}} +\L{\LB{}} +\L{\LB{greyout}\Tab{16}{normlog}\Tab{24}{ file=greyout}} +\L{\LB{gb\-janet}\Tab{16}{normlog file=greyin}} +\L{\LB{submit}\Tab{16}{normlog}\Tab{24}{ file=submit dflags=close}} +\L{\LB{}} +\L{\LB{local}\Tab{16}{normlog}\Tab{24}{ file=local}} +\L{\LB{msg\-clean}\Tab{16}{normlog}\Tab{24}{ file=msg\-clean}} +\L{\LB{}} +\L{\LB{x400in84}\Tab{16}{normlog}\Tab{24}{ file=x400in84,level=pdus}} +\L{\LB{x400in84}\Tab{16}{isodelog rtsaplevel file=rts,level=all}} +\L{\LB{x400in84}\Tab{16}{isodelog ssaplevel file=ssap,level=all}} +\L{\LB{x400out84}\Tab{16}{normlog}\Tab{24}{ file=x400out84}} +\L{\LB{}} +\L{\LB{x400in88}\Tab{16}{normlog}\Tab{24}{ file=x400in88 level=pdus,level=trace}} +\L{\LB{x400out88}\Tab{16}{normlog}\Tab{24}{ file=x400out88 \C{}\#level=all}} +\CE{}\L{\LB{}} +\L{\LB{p7server}\Tab{16}{normlog}\Tab{24}{ file=p7server level=all}} +\L{\LB{}} +\L{\LB{xfax}\Tab{16}{normlog}\Tab{24}{ file=fax \C{}\#level=debug}} +\CE{}\L{\LB{xfaxd}\Tab{16}{normlog}\Tab{24}{ file=fax \C{}\#level=debug}} +\CE{}\L{\LB{G3Fax}\Tab{16}{normlog}\Tab{24}{ file=fax}} +\L{\LB{hdr2fax}\Tab{16}{normlog}\Tab{24}{ file=fax}} +\L{\LB{ia52fax}\Tab{16}{normlog}\Tab{24}{ file=fax}} +\L{\LB{}} +\L{\LB{\C{}\#x400out88 isodelog}\Tab{24}{rtsaplevel file=rts\-out}\Tab{48}{level=all}} +\CE{}\L{\LB{\C{}\#x400out88 isodelog}\Tab{24}{acsaplevel file=acsap\-out}\Tab{56}{level=all}} +\CE{}\L{\LB{\C{}\#x400out88 isodelog}\Tab{24}{psap2level file=psap2\-out}\Tab{56}{level=all}} +\CE{}\L{\LB{\C{}\#x400out88 isodelog}\Tab{24}{ssaplevel file=ssap\-out}\Tab{48}{level=all}} +\CE{}\L{\LB{}} +\L{\LB{}} +\L{\LB{\C{}\#x400in88 isodelog}\Tab{24}{rtsaplevel file=proto\-in}\Tab{56}{level=all}} +\CE{}\L{\LB{\C{}\#x400in88 isodelog}\Tab{24}{acsaplevel file=proto\-in}\Tab{56}{level=all}} +\CE{}\L{\LB{\C{}\#x400in88 isodelog}\Tab{24}{psap2level file=proto\-in}\Tab{56}{level=all}} +\CE{}\L{\LB{}} +\L{\LB{pptsapd}\Tab{16}{normlog}\Tab{24}{ file=pptsapd,}\Tab{48}{dlevel=notice}} +\L{\LB{dirlist}\Tab{16}{normlog}\Tab{24}{file=dirlist}\Tab{40}{}} +\L{\LB{mslocal}\Tab{16}{normlog file=mslocal}} +\L{\LB{xprobe}\Tab{16}{normlog file=probe level=trace,level=pdus level=all}} +\L{\LB{p7server}\Tab{16}{isode ns\_enable off}} +\L{\LB{xua}\Tab{16}{isode ns\_enable off}} +\L{\LB{libmsattr}\Tab{24}{isode ns\_enable off}} +\L{\LB{\C{}\#xckadr normlog level=all file=ckadr}} diff --git a/doc/manual/volume1/users.tex b/doc/manual/volume1/users.tex new file mode 100644 index 0000000..c59cb29 --- /dev/null +++ b/doc/manual/volume1/users.tex @@ -0,0 +1,12 @@ +\small\begin{verbatim} + +##################### extract of `users' table #################### +# +Alina.DaCruz:822-local vs2.cs.ucl.ac.uk +Steve.Kille:822-local pyr1.cs.ucl.ac.uk +John.Taylor:822-local vs2.cs.ucl.ac.uk, slocal vs2.cs.ucl.ac.uk +Postie.Pat:822-local vs2.cs.ucl.ac.uk +x400-users:list +info-server:shell +# +\end{verbatim} diff --git a/doc/manual/volume1/version.sh b/doc/manual/volume1/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/manual/volume1/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/manual/volume1/volume1.aux b/doc/manual/volume1/volume1.aux new file mode 100644 index 0000000..1ce749f --- /dev/null +++ b/doc/manual/volume1/volume1.aux @@ -0,0 +1,24 @@ +\relax +\@input{preface.aux} +\@input{general.aux} +\@input{install.aux} +\@input{configure.aux} +\@input{tables.aux} +\@input{x400links.aux} +\@input{addon.aux} +\@input{management.aux} +\@input{appendix.aux} +\@input{x400tables.aux} +\@input{mu.aux} +\@input{qmgrproto.aux} +\bibdata{bcustom,pp} +\bibcite{BIND}{Dun} +\bibcite{IFIP.PP}{Kil88} +\bibcite{String.Addresses}{Kil89a} +\bibcite{RFC1148}{Kil89b} +\bibcite{RFC934}{{Mar}85} +\bibcite{TSAP.on.TCP}{RC87} +\bibcite{MH6.5}{Ros86} +\bibcite{POP}{Ros88} +\bibcite{ISODE}{Ros89} +\bibstyle{alpha} diff --git a/doc/manual/volume1/volume1.bbl b/doc/manual/volume1/volume1.bbl new file mode 100644 index 0000000..6471b82 --- /dev/null +++ b/doc/manual/volume1/volume1.bbl @@ -0,0 +1,57 @@ +\begin{thebibliography}{{Mar}85} + +\bibitem[Dun]{BIND} +Kevin~J. Dunlap. +\newblock {\em {Name Server Operations Guide for BIND}}. +\newblock University of California, Berkeley. +\newblock {BSD 4.3 Release}. + +\bibitem[Kil88]{IFIP.PP} +S.E. Kille. +\newblock {PP} - a message transfer agent. +\newblock In {\em IFIP WG 6.5 Conference on Message Handling Systems and + Distributed Applications}, pages 115--118. North Holland Publishing, October + 1988. + +\bibitem[Kil89a]{String.Addresses} +Stephen~E. Kille. +\newblock {A string encoding of Presentation Address}. +\newblock Research Note RN/89/14, Department of Computer Science, University + College London, February 1989. + +\bibitem[Kil89b]{RFC1148} +Stephen~E. Kille. +\newblock {Mapping between X.400(1988)/ISO10021 and RFC822}. +\newblock Request for Comments 1148, DDN Network Information Center, SRI + International, July 1989. + +\bibitem[{Mar}85]{RFC934} +{Marshall T. Rose and Einar A. Stefferud}. +\newblock {Proposed Standard for Message Encapsulation}. +\newblock Request for Comments 934, DDN Network Information Center, SRI + International, January 1985. + +\bibitem[RC87]{TSAP.on.TCP} +Marshall~T. Rose and Dwight~E. Cass. +\newblock {ISO Transport Services on top of the TCP}. +\newblock Request for Comments 1006, DDN Network Information Center, SRI + International, May 1987. + +\bibitem[Ros86]{MH6.5} +Marshall~T. Rose. +\newblock {\em {Changes to the Rand MH Message Handling System: MH \#6.5 for + 4.3BSD UNIX}}, May 1986. +\newblock MH documentation set. + +\bibitem[Ros88]{POP} +Marshall~T. Rose. +\newblock {Post Office Protocol~---~Version 3}. +\newblock Request for Comments 1081, DDN Network Information Center, SRI + International, December 1988. + +\bibitem[Ros89]{ISODE} +Marshall~T. Rose. +\newblock {\em {The ISO Development Environment: User's Manual}}. +\newblock The Wollongong Group, 5.0 edition, March 1989. + +\end{thebibliography} diff --git a/doc/manual/volume1/volume1.idx b/doc/manual/volume1/volume1.idx new file mode 100644 index 0000000..4661c7d --- /dev/null +++ b/doc/manual/volume1/volume1.idx @@ -0,0 +1,824 @@ +\indexentry{doc}{viii} +\indexentry{dbm}{2} +\indexentry{X25 access}{2} +\indexentry{ASN.1}{2} +\indexentry{libdsap.a}{2} +\indexentry{/bin/mail}{3} +\indexentry{sendmail{}}{3} +\indexentry{sendmail}{4} +\indexentry{rsh{}}{4} +\indexentry{pp-gen{}}{5} +\indexentry{Make.defs}{5} +\indexentry{config.h}{5} +\indexentry{make}{5} +\indexentry{CMDDIR}{5} +\indexentry{CHANDIR}{5} +\indexentry{FORMDIR}{5} +\indexentry{filtercontrol}{5} +\indexentry{TOOLDIR}{5} +\indexentry{C}{7} +\indexentry{C}{7} +\indexentry{C}{7} +\indexentry{pepy}{7} +\indexentry{posy}{7} +\indexentry{rosy}{7} +\indexentry{pepsy}{7} +\indexentry{lint {}}{7} +\indexentry{chown{}}{7} +\indexentry{chmod{}}{7} +\indexentry{LOGDIR}{8} +\indexentry{TAILOR}{8} +\indexentry{libpp.a}{8} +\indexentry{QUEDIR}{8} +\indexentry{TBLDIR}{8} +\indexentry{LIBSYS}{8} +\indexentry{dbm {}}{8} +\indexentry{LIBRESOLV}{8} +\indexentry{USRBINDIR}{8} +\indexentry{OPTIONALCHANS}{8} +\indexentry{OPTIONALFILTERS}{9} +\indexentry{FAXDRIVERS}{9} +\indexentry{FAXPAGESIZE}{9} +\indexentry{MANDIR}{9} +\indexentry{MANOPTS}{9} +\indexentry{CC}{10} +\indexentry{C}{10} +\indexentry{C}{10} +\indexentry{gcc}{10} +\indexentry{dbm}{10} +\indexentry{cc}{10} +\indexentry{OLDCC}{10} +\indexentry{C}{10} +\indexentry{gcc}{10} +\indexentry{cc}{10} +\indexentry{CCOPTIONS}{10} +\indexentry{C}{10} +\indexentry{LIBCCOPTIONS}{10} +\indexentry{C}{10} +\indexentry{LDOPTIONS}{10} +\indexentry{ROSY}{10} +\indexentry{POSY}{10} +\indexentry{PEPY}{10} +\indexentry{PEPSY}{10} +\indexentry{pepy}{10} +\indexentry{posy}{10} +\indexentry{rosy}{10} +\indexentry{pepsy}{10} +\indexentry{X11}{10} +\indexentry{true}{10} +\indexentry{LIBX}{10} +\indexentry{APPDEFAULTS}{10} +\indexentry{LIBPHOTO}{10} +\indexentry{xalert}{10} +\indexentry{NOPHOTOS}{10} +\indexentry{config.h}{10} +\indexentry{LINT}{10} +\indexentry{lint {}}{10} +\indexentry{LINTFLAGS}{10} +\indexentry{PGMPROT}{10} +\indexentry{PPUSER}{10} +\indexentry{ROOTUSER}{11} +\indexentry{CHOWN}{11} +\indexentry{chown {}}{11} +\indexentry{CHMOD}{11} +\indexentry{chmod {}}{11} +\indexentry{BACKUP}{11} +\indexentry{cp {}}{11} +\indexentry{echo {}}{11} +\indexentry{INSTALL}{11} +\indexentry{cp {}}{11} +\indexentry{install {}}{11} +\indexentry{h/config.h}{11} +\indexentry{DBM}{11} +\indexentry{NDBM}{11} +\indexentry{ndbm {}}{11} +\indexentry{dbm {}}{11} +\indexentry{ndbm {}}{11} +\indexentry{dbm {}}{11} +\indexentry{NAMESERVER}{11} +\indexentry{HAS\_FSYNC}{11} +\indexentry{fsync {}}{11} +\indexentry{UKORDER}{11} +\indexentry{VAT}{11} +\indexentry{CHANDIR}{11} +\indexentry{qmgr}{12} +\indexentry{qmgr}{12} +\indexentry{quedir}{12} +\indexentry{qmgrload}{12} +\indexentry{qmgr}{12} +\indexentry{qmgr}{12} +\indexentry{qmgr}{12} +\indexentry{qmgrload}{12} +\indexentry{qmgr}{12} +\indexentry{quedir}{12} +\indexentry{msg-clean}{12} +\indexentry{qmgr}{12} +\indexentry{trash}{12} +\indexentry{quedir}{12} +\indexentry{qmgr}{12} +\indexentry{timeout}{12} +\indexentry{dr2rfc}{12} +\indexentry{warning}{12} +\indexentry{splitter}{12} +\indexentry{submit}{12} +\indexentry{splitter}{12} +\indexentry{822-local}{12} +\indexentry{slocal}{12} +\indexentry{users}{12} +\indexentry{slocal}{12} +\indexentry{smtp}{13} +\indexentry{p2explode}{13} +\indexentry{p2flatten}{13} +\indexentry{p2explode}{13} +\indexentry{P2toRFC}{13} +\indexentry{RFCtoP2}{13} +\indexentry{rfc934}{13} +\indexentry{list}{14} +\indexentry{list}{14} +\indexentry{dirlist}{14} +\indexentry{shell}{14} +\indexentry{shell}{14} +\indexentry{splitter}{14} +\indexentry{fcontrol}{14} +\indexentry{FORMDIR}{14} +\indexentry{examples}{14} +\indexentry{README}{14} +\indexentry{smtp}{15} +\indexentry{822-local}{15} +\indexentry{list}{15} +\indexentry{/bin/mail}{15} +\indexentry{sendmail{}}{15} +\indexentry{cron{}}{15} +\indexentry{ckconfig {}}{15} +\indexentry{ckconfig}{15} +\indexentry{tailor}{16} +\indexentry{tailor}{16} +\indexentry{tailor}{16} +\indexentry{Make.defs}{16} +\indexentry{tailor}{16} +\indexentry{Make.defs}{16} +\indexentry{tailor}{16} +\indexentry{tailor}{16} +\indexentry{ckconfig {}}{16} +\indexentry{ckconfig}{16} +\indexentry{tailor}{16} +\indexentry{ckconfig}{16} +\indexentry{tailoring, variables}{17} +\indexentry{tailor}{17} +\indexentry{tailoring, simple}{17} +\indexentry{tailor}{17} +\indexentry{loc\_dom\_mta}{17} +\indexentry{loc\_dom\_site}{17} +\indexentry{domain}{17} +\indexentry{loc\_or}{17} +\indexentry{or}{17} +\indexentry{Note}{17} +\indexentry{qmgrhost}{17} +\indexentry{hostname {}}{17} +\indexentry{isoentities}{17} +\indexentry{submit}{17} +\indexentry{Submit}{17} +\indexentry{qmgr-pa.cache}{17} +\indexentry{isoentities}{17} +\indexentry{postmaster}{17} +\indexentry{bodypart}{18} +\indexentry{headertype}{18} +\indexentry{pptsapd\_addr}{18} +\indexentry{pptsapd}{18} +\indexentry{qmgr}{18} +\indexentry{pptsapd}{18} +\indexentry{pptsapd}{18} +\indexentry{cmddir}{18} +\indexentry{tbldir}{18} +\indexentry{dbmbuild}{18} +\indexentry{linear}{18} +\indexentry{quedir}{18} +\indexentry{logdir}{18} +\indexentry{chandir}{18} +\indexentry{chans}{18} +\indexentry{cmddir}{18} +\indexentry{cmddir}{18} +\indexentry{formdir}{18} +\indexentry{fcontrol}{18} +\indexentry{format}{18} +\indexentry{cmddir}{18} +\indexentry{cmddir}{18} +\indexentry{dbm}{19} +\indexentry{tbldir}{19} +\indexentry{ppdbm}{19} +\indexentry{pplogin}{19} +\indexentry{pp}{19} +\indexentry{/etc/passwd}{19} +\indexentry{isode}{19} +\indexentry{isotailor {}}{19} +\indexentry{authchannel}{19} +\indexentry{channel-auth}{19} +\indexentry{channel-auth}{19} +\indexentry{auth.channel}{19} +\indexentry{authloglevel}{19} +\indexentry{wrndfldir}{19} +\indexentry{tbldir}{19} +\indexentry{warninterval}{19} +\indexentry{nwarnings}{19} +\indexentry{returntime}{19} +\indexentry{lockstyle}{20} +\indexentry{flock {}}{20} +\indexentry{fcntl {}}{20} +\indexentry{lockf {}}{20} +\indexentry{flock {}}{20} +\indexentry{lockdir}{20} +\indexentry{/tmp}{20} +\indexentry{maxloops}{20} +\indexentry{maxhops}{20} +\indexentry{x400mta}{20} +\indexentry{submit\_addr}{20} +\indexentry{submit}{20} +\indexentry{inetd{}}{20} +\indexentry{submit}{20} +\indexentry{dap\_user}{20} +\indexentry{dap\_passwd}{21} +\indexentry{queuestruct}{21} +\indexentry{fsync {}}{21} +\indexentry{adminstration\_assigned\_alternate\_recipient}{21} +\indexentry{tailoring, logs}{21} +\indexentry{tailor}{21} +\indexentry{submit}{21} +\indexentry{log, file}{21} +\indexentry{logdir}{22} +\indexentry{log, level}{22} +\indexentry{log, dlevel}{22} +\indexentry{log, sflags}{22} +\indexentry{log, dflags}{22} +\indexentry{log, size}{22} +\indexentry{normlog}{22} +\indexentry{operlog}{23} +\indexentry{authlog}{23} +\indexentry{isodelog}{23} +\indexentry{submit}{24} +\indexentry{submit}{24} +\indexentry{submit}{24} +\indexentry{submit}{24} +\indexentry{submit}{24} +\indexentry{tailoring, tables}{24} +\indexentry{submit}{24} +\indexentry{tailor}{24} +\indexentry{tbldir}{24} +\indexentry{table, name}{24} +\indexentry{table, file}{24} +\indexentry{table, show}{24} +\indexentry{table, flags}{24} +\indexentry{table, dbm}{24} +\indexentry{table, linear}{24} +\indexentry{tbldir}{24} +\indexentry{table, override}{24} +\indexentry{tailoring, channels}{24} +\indexentry{channel tailor}{25} +\indexentry{channel, name}{25} +\indexentry{channel, prog}{25} +\indexentry{channel, key}{25} +\indexentry{channel, show}{25} +\indexentry{channel, type}{25} +\indexentry{channel, drchan}{26} +\indexentry{dr2rfc}{26} +\indexentry{channel, content-in}{26} +\indexentry{channel, content-out}{26} +\indexentry{channel, cost}{26} +\indexentry{rfc822norm}{26} +\indexentry{P2toRFC}{26} +\indexentry{removebp}{26} +\indexentry{p2flatten}{26} +\indexentry{channel, sort}{27} +\indexentry{channel, outinfo}{27} +\indexentry{channel, ininfo}{27} +\indexentry{fcontrol}{27} +\indexentry{fcontrol}{27} +\indexentry{channel, inadr}{27} +\indexentry{channel, outadr}{27} +\indexentry{channel, addr}{27} +\indexentry{channel, insubadr}{27} +\indexentry{channel, outsubadr}{27} +\indexentry{submit}{28} +\indexentry{submit}{28} +\indexentry{channel, subadr}{28} +\indexentry{channel, adr-order}{28} +\indexentry{submit}{28} +\indexentry{channel, bptin}{28} +\indexentry{channel, bpout}{28} +\indexentry{channel, outtable}{28} +\indexentry{channel, table}{28} +\indexentry{channel, intable}{28} +\indexentry{channel, mtatable}{28} +\indexentry{channel, mta}{28} +\indexentry{channel, access}{29} +\indexentry{channel, domain-norm}{29} +\indexentry{channel, maxproc}{29} +\indexentry{channel, auth-table}{29} +\indexentry{channel, conv}{29} +\indexentry{channel, probe}{29} +\indexentry{channel, trace}{30} +\indexentry{submit}{30} +\indexentry{channel, solo-proc}{30} +\indexentry{submit}{30} +\indexentry{hdr2fax}{30} +\indexentry{channel, bad-sender-policy}{30} +\indexentry{channel, check}{30} +\indexentry{isoentities}{32} +\indexentry{submit}{32} +\indexentry{MTAconsole}{32} +\indexentry{/etc/isoservices}{32} +\indexentry{iaed{}}{32} +\indexentry{tailor}{33} +\indexentry{mtatable}{33} +\indexentry{domain}{33} +\indexentry{greyin}{33} +\indexentry{channel}{34} +\indexentry{submit}{34} +\indexentry{submit}{34} +\indexentry{pipe{}}{34} +\indexentry{inetd}{34} +\indexentry{tailor}{34} +\indexentry{inetd.conf}{34} +\indexentry{qmgr}{34} +\indexentry{smtp}{34} +\indexentry{inetd {}}{34} +\indexentry{smtpd}{34} +\indexentry{inetd}{34} +\indexentry{/etc/inetd.conf}{34} +\indexentry{inetd.conf {}}{34} +\indexentry{pp.start}{35} +\indexentry{smtpd}{35} +\indexentry{smtpd}{35} +\indexentry{sloppy}{35} +\indexentry{x400in84}{35} +\indexentry{isoservices}{35} +\indexentry{channel, uucp}{36} +\indexentry{channel, decnet}{36} +\indexentry{decnet}{36} +\indexentry{inetd}{36} +\indexentry{dniserver.reg}{36} +\indexentry{dniserver}{36} +\indexentry{decnet}{36} +\indexentry{smtp}{37} +\indexentry{filter control}{37} +\indexentry{fcontrol}{37} +\indexentry{fcontrol}{37} +\indexentry{tailor}{37} +\indexentry{fcontrol}{37} +\indexentry{formdir}{37} +\indexentry{tailor}{37} +\indexentry{fcontrol}{37} +\indexentry{fcontrol}{39} +\indexentry{rfc822norm}{39} +\indexentry{rfc822norm}{39} +\indexentry{fcontrol}{39} +\indexentry{tailor}{39} +\indexentry{fcontrol}{40} +\indexentry{rfc822norm}{40} +\indexentry{fcontrol}{40} +\indexentry{rfc822norm}{40} +\indexentry{822touk}{40} +\indexentry{822tous}{40} +\indexentry{domain}{41} +\indexentry{alias}{41} +\indexentry{alias}{41} +\indexentry{p2norm}{41} +\indexentry{p2norm}{41} +\indexentry{or}{41} +\indexentry{aliases}{42} +\indexentry{p2norm}{42} +\indexentry{p2norm}{42} +\indexentry{p2norm}{42} +\indexentry{aliases}{42} +\indexentry{aliases}{42} +\indexentry{formdir}{42} +\indexentry{tailor}{42} +\indexentry{list}{42} +\indexentry{aliases}{43} +\indexentry{rfc1148}{43} +\indexentry{P2toRFC}{43} +\indexentry{RFCtoP2}{43} +\indexentry{P2toRFC}{44} +\indexentry{P2toRFC}{44} +\indexentry{P2toRFC}{44} +\indexentry{RFCtoP2}{44} +\indexentry{rfc934}{44} +\indexentry{rfc934}{44} +\indexentry{rfc934}{44} +\indexentry{rfc934}{44} +\indexentry{Lib/pp/static.c}{44} +\indexentry{p2flatten}{44} +\indexentry{p2flatten}{44} +\indexentry{p2flatten}{44} +\indexentry{p2flatten}{45} +\indexentry{p2explode}{45} +\indexentry{p2explode}{45} +\indexentry{qmgrload}{45} +\indexentry{qmgrload}{45} +\indexentry{tailor}{45} +\indexentry{msg-clean}{45} +\indexentry{msg-clean}{45} +\indexentry{debris}{45} +\indexentry{debris}{45} +\indexentry{tailor}{45} +\indexentry{debris}{45} +\indexentry{splitter}{46} +\indexentry{splitter}{46} +\indexentry{submit}{46} +\indexentry{timeout}{46} +\indexentry{timeout}{46} +\indexentry{warning}{46} +\indexentry{warning}{46} +\indexentry{warning}{46} +\indexentry{warndir}{46} +\indexentry{dr2rfc}{46} +\indexentry{dr2rfc}{46} +\indexentry{dr2rfc}{46} +\indexentry{dr2rfc}{46} +\indexentry{dr2rfc}{46} +\indexentry{dr2rfc}{46} +\indexentry{submit}{46} +\indexentry{dr2rfc}{48} +\indexentry{qmgr}{48} +\indexentry{pptsapd}{48} +\indexentry{pptsapd}{48} +\indexentry{aliases}{50} +\indexentry{users}{50} +\indexentry{domain}{50} +\indexentry{channel}{50} +\indexentry{or}{50} +\indexentry{submit}{50} +\indexentry{domain}{50} +\indexentry{or}{50} +\indexentry{users}{50} +\indexentry{aliases}{50} +\indexentry{channel}{50} +\indexentry{or2rfc}{50} +\indexentry{rfc2or}{50} +\indexentry{rfc1148gate}{50} +\indexentry{or}{50} +\indexentry{domain}{50} +\indexentry{channel}{50} +\indexentry{aliases}{50} +\indexentry{aliases}{51} +\indexentry{aliases}{51} +\indexentry{users}{51} +\indexentry{or2rfc}{51} +\indexentry{rfc2or}{51} +\indexentry{rfc1148gate}{51} +\indexentry{submit}{51} +\indexentry{ckadr}{51} +\indexentry{tables, alias}{51} +\indexentry{aliases}{51} +\indexentry{aliases}{52} +\indexentry{aliases}{53} +\indexentry{user}{53} +\indexentry{aliases}{53} +\indexentry{table, users}{53} +\indexentry{users}{53} +\indexentry{822-local}{53} +\indexentry{slocal}{53} +\indexentry{shell}{54} +\indexentry{table, domain}{54} +\indexentry{domain}{54} +\indexentry{submit}{54} +\indexentry{domain}{54} +\indexentry{channel}{55} +\indexentry{aliases}{55} +\indexentry{users}{55} +\indexentry{domain}{56} +\indexentry{domain}{56} +\indexentry{domain}{56} +\indexentry{domain}{56} +\indexentry{domain}{56} +\indexentry{domain}{56} +\indexentry{channel}{57} +\indexentry{or}{57} +\indexentry{channel}{58} +\indexentry{channel}{58} +\indexentry{domain}{58} +\indexentry{or}{58} +\indexentry{or}{58} +\indexentry{or}{58} +\indexentry{domain}{58} +\indexentry{domain}{59} +\indexentry{tables, X.400 O/R}{59} +\indexentry{or}{59} +\indexentry{domain}{59} +\indexentry{or}{59} +\indexentry{or}{59} +\indexentry{domain}{60} +\indexentry{channel}{60} +\indexentry{alias}{60} +\indexentry{user}{60} +\indexentry{domain}{60} +\indexentry{channel}{60} +\indexentry{tables, channel}{60} +\indexentry{Submit}{60} +\indexentry{channel}{60} +\indexentry{or}{60} +\indexentry{domain}{60} +\indexentry{domain}{62} +\indexentry{or}{62} +\indexentry{domain}{63} +\indexentry{or}{63} +\indexentry{alias}{63} +\indexentry{p2norm}{63} +\indexentry{rfc822norm}{63} +\indexentry{users}{63} +\indexentry{aliases}{63} +\indexentry{admin-users}{63} +\indexentry{admin-aliases}{63} +\indexentry{domain}{63} +\indexentry{or}{63} +\indexentry{users}{63} +\indexentry{aliases}{63} +\indexentry{admin-users}{63} +\indexentry{admin-aliases}{63} +\indexentry{aliases}{63} +\indexentry{admin-users}{64} +\indexentry{aliases}{64} +\indexentry{admin-aliases}{64} +\indexentry{aliases}{64} +\indexentry{p2norm}{65} +\indexentry{rfc822norm}{65} +\indexentry{or2rfc}{65} +\indexentry{rfc2or}{65} +\indexentry{rfc2or}{65} +\indexentry{rfc1148gate}{66} +\indexentry{rfc2or}{66} +\indexentry{auth.channel}{66} +\indexentry{auth.mta}{66} +\indexentry{auth.user}{66} +\indexentry{auth.channel}{67} +\indexentry{auth.channel}{67} +\indexentry{auth.mta}{67} +\indexentry{auth.user}{67} +\indexentry{auth.channel}{68} +\indexentry{wrndfldir}{68} +\indexentry{auth.channel}{68} +\indexentry{auth.mta}{69} +\indexentry{regex {}}{69} +\indexentry{Submit}{71} +\indexentry{MTAconsole}{71} +\indexentry{qmgr}{71} +\indexentry{auth.qmgr}{72} +\indexentry{auth.qmgr}{72} +\indexentry{mkpasswd}{72} +\indexentry{mkpasswd}{72} +\indexentry{tables, local}{73} +\indexentry{ch.local}{73} +\indexentry{ch.local}{73} +\indexentry{822-local}{73} +\indexentry{slocal}{73} +\indexentry{.mailfilter}{73} +\indexentry{USRBINDIR}{73} +\indexentry{Make.defs}{73} +\indexentry{exec{}}{74} +\indexentry{Note}{74} +\indexentry{tables, X.400 84}{74} +\indexentry{tables, X.400 88}{74} +\indexentry{ch.x400out84}{74} +\indexentry{channel}{74} +\indexentry{default}{76} +\indexentry{ch.x400in84}{76} +\indexentry{ch.x400in88}{76} +\indexentry{nsapexpand}{76} +\indexentry{table, list}{77} +\indexentry{ch.list}{77} +\indexentry{list}{77} +\indexentry{users}{77} +\indexentry{moderator}{77} +\indexentry{mlist}{77} +\indexentry{mlist}{77} +\indexentry{tbldir}{77} +\indexentry{mlist}{77} +\indexentry{mlist}{77} +\indexentry{mlist}{77} +\indexentry{mlist}{78} +\indexentry{mlist}{78} +\indexentry{mlist}{78} +\indexentry{make-lists{}}{78} +\indexentry{make-lists{}}{78} +\indexentry{Tools}{78} +\indexentry{table, shell}{78} +\indexentry{ch.shell}{78} +\indexentry{shell}{78} +\indexentry{users}{78} +\indexentry{shell}{78} +\indexentry{/etc/passwd}{78} +\indexentry{/etc/passwd}{78} +\indexentry{shell}{78} +\indexentry{shell}{79} +\indexentry{chandir}{79} +\indexentry{shell}{79} +\indexentry{shell}{79} +\indexentry{shell}{79} +\indexentry{not}{80} +\indexentry{statp}{80} +\indexentry{Tools}{80} +\indexentry{Tools/statgen}{80} +\indexentry{or}{81} +\indexentry{rfc2or}{83} +\indexentry{or2rfc}{83} +\indexentry{rfc1148}{83} +\indexentry{ts\_communities}{86} +\indexentry{rfc2or}{87} +\indexentry{or2rfc}{87} +\indexentry{or}{87} +\indexentry{tailor}{87} +\indexentry{tailor}{89} +\indexentry{tailor}{89} +\indexentry{tailor}{89} +\indexentry{tailor}{90} +\indexentry{tailor}{92} +\indexentry{x400out84}{93} +\indexentry{tailor}{93} +\indexentry{fax}{95} +\indexentry{channel}{96} +\indexentry{users}{96} +\indexentry{hdr2fax}{96} +\indexentry{hdr2fax}{96} +\indexentry{hdr2fax}{96} +\indexentry{hdr2fax}{96} +\indexentry{ia52fax}{96} +\indexentry{hdr2fax}{96} +\indexentry{hdr2fax}{97} +\indexentry{hdr2fax}{97} +\indexentry{hdr2fax}{97} +\indexentry{hdr2fax}{97} +\indexentry{hdr2fax}{97} +\indexentry{hdr2fax}{98} +\indexentry{ia52fax}{98} +\indexentry{Make.defs}{98} +\indexentry{hdr2fax}{98} +\indexentry{hdr2fax}{98} +\indexentry{fcontrol}{98} +\indexentry{fcontrol}{99} +\indexentry{hdr2fax}{99} +\indexentry{hdr2fax}{99} +\indexentry{hdr2fax}{99} +\indexentry{hdr2fax}{99} +\indexentry{ia52fax}{99} +\indexentry{ia52fax}{99} +\indexentry{fcontrol}{99} +\indexentry{ia52fax}{100} +\indexentry{asn}{102} +\indexentry{fcontrol}{102} +\indexentry{formdir}{102} +\indexentry{asn}{102} +\indexentry{fcontrol}{103} +\indexentry{fcontrol}{103} +\indexentry{asn}{103} +\indexentry{asn}{103} +\indexentry{submit}{104} +\indexentry{qmgrload}{104} +\indexentry{msg-clean}{105} +\indexentry{timout}{105} +\indexentry{warning}{105} +\indexentry{tailor}{106} +\indexentry{msg-clean}{106} +\indexentry{qmgr-load}{106} +\indexentry{tailor}{115} +\indexentry{tailor}{115} +\indexentry{LINEconsole}{116} +\indexentry{LINEconsole}{116} +\indexentry{LINEconsole}{117} +\indexentry{regex {}}{117} +\indexentry{lconsole}{118} +\indexentry{lconsole}{119} +\indexentry{lconsole}{119} +\indexentry{ckchan}{121} +\indexentry{ckchan}{121} +\indexentry{ckchan}{121} +\indexentry{ckchan}{121} +\indexentry{ckconfig}{122} +\indexentry{tailor}{122} +\indexentry{chndfldir}{122} +\indexentry{tailor}{122} +\indexentry{tbldir}{122} +\indexentry{ckconfig}{122} +\indexentry{ckconfig}{122} +\indexentry{ckconfig}{122} +\indexentry{ckconfig}{122} +\indexentry{ckconfig}{122} +\indexentry{ckadr}{122} +\indexentry{ckadr}{122} +\indexentry{ckadr}{122} +\indexentry{ckadr}{123} +\indexentry{ckadr}{123} +\indexentry{ckadr}{123} +\indexentry{ckadr}{123} +\indexentry{ckadr}{123} +\indexentry{ckadr}{123} +\indexentry{only}{123} +\indexentry{only}{123} +\indexentry{ckadr}{123} +\indexentry{probe}{124} +\indexentry{tailor}{124} +\indexentry{tailor}{124} +\indexentry{tailor}{124} +\indexentry{probe}{124} +\indexentry{probe}{124} +\indexentry{submit}{125} +\indexentry{submit}{125} +\indexentry{submit}{125} +\indexentry{tailor}{125} +\indexentry{ckconfig}{125} +\indexentry{ckadr}{125} +\indexentry{dbmbuild}{125} +\indexentry{submit}{125} +\indexentry{console}{126} +\indexentry{pptsapd}{126} +\indexentry{ckconfig}{126} +\indexentry{tailor}{126} +\indexentry{pptsapd}{126} +\indexentry{ntail}{126} +\indexentry{tools}{126} +\indexentry{tail {}}{126} +\indexentry{aliases}{126} +\indexentry{users}{126} +\indexentry{local channel}{126} +\indexentry{list channel}{126} +\indexentry{authorisation}{126} +\indexentry{or}{126} +\indexentry{channel}{127} +\indexentry{domain}{127} +\indexentry{channel}{127} +\indexentry{domain}{127} +\indexentry{channel}{127} +\indexentry{domain}{127} +\indexentry{abbrev}{127} +\indexentry{c-nrs}{127} +\indexentry{pp.dmn}{127} +\indexentry{abbrev}{127} +\indexentry{abbrev}{128} +\indexentry{abbrev}{128} +\indexentry{pp.chan}{129} +\indexentry{c-nrs}{129} +\indexentry{tjoin}{129} +\indexentry{Tjoin}{129} +\indexentry{channel}{129} +\indexentry{tjoin}{130} +\indexentry{alias}{130} +\indexentry{users}{130} +\indexentry{dbmbuild}{130} +\indexentry{tailoring, filters}{131} +\indexentry{tailor}{131} +\indexentry{tailor}{131} +\indexentry{submit}{131} +\indexentry{fcontrol}{131} +\indexentry{uuencode}{131} +\indexentry{submit}{131} +\indexentry{submit}{131} +\indexentry{submit}{132} +\indexentry{822top2}{132} +\indexentry{rc.local}{132} +\indexentry{rc.local}{132} +\indexentry{pp.start}{132} +\indexentry{pptsapd}{132} +\indexentry{smtpsrvr}{132} +\indexentry{inetd}{132} +\indexentry{tsapd}{133} +\indexentry{isode-gen {}}{133} +\indexentry{kill}{133} +\indexentry{pp.start}{133} +\indexentry{dbmbuild}{133} +\indexentry{pp.night}{133} +\indexentry{dbmbuild}{133} +\indexentry{oper}{133} +\indexentry{stat}{133} +\indexentry{oper}{133} +\indexentry{stat}{133} +\indexentry{tools}{133} +\indexentry{statp}{133} +\indexentry{stat}{133} +\indexentry{awk {}}{133} +\indexentry{quedir}{134} +\indexentry{quedir}{134} +\indexentry{addr}{134} +\indexentry{base}{134} +\indexentry{filter.number}{134} +\indexentry{report.number}{134} +\indexentry{addr}{134} +\indexentry{pp-tables/}{147} +\indexentry{pp-tables/}{148} +\indexentry{mu}{149} +\indexentry{submit}{149} +\indexentry{mu.defaults}{149} +\indexentry{mu.defaults}{149} +\indexentry{submit}{149} +\indexentry{mu.defaults}{149} +\indexentry{argh.c}{150} +\indexentry{submit}{150} +\indexentry{submit}{150} +\indexentry{submit}{150} +\indexentry{submit}{150} +\indexentry{submit}{150} +\indexentry{submit}{150} +\indexentry{submit}{151} +\indexentry{submit}{151} +\indexentry{submit}{151} +\indexentry{submit}{151} +\indexentry{submit}{151} +\indexentry{submit}{153} +\indexentry{\LaTeX {}}{166} diff --git a/doc/manual/volume1/volume1.ind b/doc/manual/volume1/volume1.ind new file mode 100644 index 0000000..d5d8563 --- /dev/null +++ b/doc/manual/volume1/volume1.ind @@ -0,0 +1,381 @@ +\begin{theindex}\makeatletter +\raggedright +\def\newindex#1{{\huge\hspace{-.5in}\parbox[t]{.5in}{\makebox[.35in][c]{\uppercase{#1}}}\vspace{-1.5ex}}} +\item 822-local, 12, 15, 53, 66 +\item 822top2, 132 +\item 822touk, 40 +\item 822tous, 40 +\indexspace +\newindex{a} +\item abbrev, 127, 128 +\item addr, 134 +\item admin-aliases, 63 +\item adminstration\_assigned\_alternate\_recipient, 21 +\item admin-users, 63 +\item alias, 41, 60, 62, 130 +\item aliases, 42, 43, 50, 51, 52, 55, 63, 64, 126 +\item APPDEFAULTS, 10 +\item argh.c, 150 +\item asn, 101, 102, 103 +\item ASN.1, 2 +\item authchannel, 19 +\item auth.channel, 74, 75 +\item authlog, 23 +\item authloglevel, 19 +\item auth.mta, 74, 75, 77 +\item authorisation, 126 +\item auth.qmgr, 79 +\item auth.user, 74, 75 +\item awk, 133 +\indexspace +\newindex{b} +\item BACKUP, 11 +\item base, 134 +\item /bin/mail, 3, 15 +\item bodypart, 18 +\indexspace +\newindex{c} +\item C, 7, 9, 10 +\item CC, 9 +\item cc, 10 +\item CCOPTIONS, 10 +\item CHANDIR, 5, 11 +\item chandir, 18, 72 +\item channel, 34, 50, 55, 57, 58, 60, 67, 96, 127, 129 +\subitem access, 29 +\subitem addr, 27 +\subitem adr-order, 28 +\subitem auth-table, 29 +\subitem bad-sender-policy, 30 +\subitem bpout, 28 +\subitem bptin, 28 +\subitem check, 30 +\subitem content-in, 26 +\subitem content-out, 26 +\subitem conv, 29 +\subitem cost, 26 +\subitem decnet, 36 +\subitem domain-norm, 29 +\subitem drchan, 26 +\subitem inadr, 27 +\subitem ininfo, 27 +\subitem insubadr, 27 +\subitem intable, 28 +\subitem key, 25 +\subitem maxproc, 29 +\subitem mta, 28 +\subitem mtatable, 28 +\subitem name, 25 +\subitem outadr, 27 +\subitem outinfo, 27 +\subitem outsubadr, 27 +\subitem outtable, 28 +\subitem probe, 29 +\subitem prog, 25 +\subitem show, 25 +\subitem solo-proc, 30 +\subitem sort, 27 +\subitem subadr, 28 +\subitem table, 28 +\subitem trace, 30 +\subitem type, 25 +\subitem uucp, 36 +\item channel tailor, 25 +\item channel-auth, 19 +\item chans, 18 +\item ch.list, 70 +\item ch.local, 66 +\item chmod, 7 +\item CHMOD, 11 +\item chndfldir, 122 +\item chown, 7, 10 +\item ch.shell, 71 +\item ch.x400in84, 69 +\item ch.x400in88, 69 +\item ch.x400out84, 67 +\item ckadr, 51, 122, 123, 125 +\item ckchan, 121 +\item ckconfig, 15, 16, 122, 125, 126 +\item CMDDIR, 5 +\item cmddir, 18 +\item c-nrs, 127, 129 +\item config.h, 5, 10 +\item console, 126 +\item cp, 11 +\item cron, 15 +\indexspace +\newindex{d} +\item dap\_passwd, 21 +\item dap\_user, 20 +\item dbm, 2, 8, 9, 11, 19 +\item dbmbuild, 18, 125, 130, 133 +\item debris, 45 +\item decnet, 36 +\item default, 69 +\item dirlist, 14 +\item dniserver, 36 +\item dniserver.reg, 36 +\item doc, viii +\item domain, 17, 33, 41, 50, 54, 56, 58, 59, 60, 62, 63, 127 +\item dr2rfc, 12, 26, 46 +\indexspace +\newindex{e} +\item echo, 11 +\item /etc/inetd.conf, 34 +\item /etc/isoservices, 32 +\item /etc/passwd, 19, 72 +\item examples, 14 +\item exec, 67 +\indexspace +\newindex{f} +\item fax, 95 +\item FAXDRIVERS, 9 +\item fcntl, 20 +\item fcontrol, 14, 18, 27, 37, 39, 40, 98, 99, 101, 102, 131 +\item filter control, 37 +\item filtercontrol, 5 +\item filter.number, 134 +\item flock, 20 +\item format, 18 +\item FORMDIR, 5, 14 +\item formdir, 18, 37, 42, 101 +\item fsync, 11, 21 +\indexspace +\newindex{g} +\item gcc, 9, 10 +\item greyin, 33 +\indexspace +\newindex{h} +\item HAS\_FSYNC, 11 +\item h/config.h, 11 +\item hdr2fax, 30, 96, 97, 98, 99 +\item headertype, 18 +\item hostname, 17 +\indexspace +\newindex{i} +\item ia52fax, 96, 98, 99 +\item iaed, 32 +\item inetd, 20, 34, 36, 132 +\item inetd.conf, 34 +\item install, 11 +\item isode, 19 +\item isode-gen, 133 +\item isodelog, 23 +\item isoentities, 17, 32 +\item isoservices, 35 +\item isotailor, 19 +\indexspace +\newindex{k} +\item kill, 133 +\indexspace +\newindex{l} +\item \LaTeX {}, 166 +\item lconsole, 118, 119 +\item LDOPTIONS, 10 +\item LIBCCOPTIONS, 10 +\item libdsap.a, 2 +\item LIBPHOTO, 10 +\item libpp.a, 8 +\item Lib/pp/static.c, 44 +\item LIBRESOLV, 8 +\item LIBSYS, 8 +\item LIBX, 10 +\item linear, 18 +\item LINEconsole, 116, 117 +\item lint, 7 +\item LINT, 10 +\item LINTFLAGS, 10 +\item list, 13, 15, 42, 70 +\item list channel, 126 +\item local channel, 126 +\item loc\_dom\_mta, 17 +\item loc\_dom\_site, 17 +\item lockdir, 20 +\item lockf, 20 +\item lockstyle, 20 +\item loc\_or, 17 +\item log, dflags, 22 +\subitem dlevel, 22 +\subitem file, 21 +\subitem level, 22 +\subitem sflags, 22 +\subitem size, 22 +\item LOGDIR, 8 +\item logdir, 18, 22 +\indexspace +\newindex{m} +\item .mailfilter, 67 +\item make, 5 +\item Make.defs, 5, 16, 67 +\item make-lists, 71 +\item MANDIR, 9 +\item MANOPTS, 9 +\item maxhops, 20 +\item maxloops, 20 +\item mkpasswd, 79 +\item mlist, 70, 71 +\item moderator, 70 +\item msg-clean, 12, 45, 105, 106 +\item MTAconsole, 32, 79 +\item mtatable, 33 +\item mu, 149 +\item mu.defaults, 149 +\indexspace +\newindex{n} +\item NAMESERVER, 11 +\item NDBM, 11 +\item NOPHOTOS, 10 +\item normlog, 22 +\item not, 79 +\item Note, 17, 67 +\item nsapexpand, 70 +\item ntail, 126 +\item nwarnings, 19 +\indexspace +\newindex{o} +\item OLDCC, 10 +\item only, 123 +\item oper, 133 +\item operlog, 23 +\item OPTIONALCHANS, 8 +\item OPTIONALFILTERS, 9 +\item or, 17, 41, 50, 57, 58, 59, 60, 62, 63, 81, 87, 126 +\item or2rfc, 50, 51, 64, 83, 87 +\indexspace +\newindex{p} +\item p2explode, 13, 45 +\item p2flatten, 13, 26, 44 +\item p2norm, 41, 42, 62, 64 +\item P2toRFC, 13, 26, 43, 44 +\item pepsy, 7 +\item PEPSY, 10 +\item pepy, 7, 10 +\item PGMPROT, 10 +\item pipe, 34 +\item postmaster, 17 +\item posy, 7 +\item POSY, 10 +\item pp, 19 +\item pp.chan, 129 +\item ppdbm, 19 +\item pp.dmn, 127 +\item pp-gen, 5 +\item pplogin, 19 +\item pp.night, 133 +\item pp.start, 35, 132, 133 +\item pp-tables/, 147, 148 +\item pptsapd, 18, 48, 126, 132 +\item pptsapd\_addr, 18 +\item PPUSER, 10 +\item probe, 124 +\indexspace +\newindex{q} +\item qmgr, 11, 12, 18, 34, 48, 79 +\item qmgrhost, 17 +\item qmgrload, 12, 45, 104 +\item qmgr-load, 106 +\item qmgr-pa.cache, 17 +\item QUEDIR, 8 +\item quedir, 12, 18, 134 +\item queuestruct, 21 +\indexspace +\newindex{r} +\item rc.local, 132 +\item README, 14 +\item regex, 77, 117 +\item removebp, 26 +\item report.number, 134 +\item returntime, 19 +\item rfc1148, 43, 83 +\item rfc1148gate, 50, 51, 66 +\item rfc2or, 50, 51, 65, 66, 83, 87 +\item rfc822norm, 26, 39, 40, 62, 64 +\item rfc934, 13, 44 +\item RFCtoP2, 13, 43, 44 +\item ROOTUSER, 10 +\item rosy, 7, 10 +\item rsh, 4 +\indexspace +\newindex{s} +\item sendmail, 3, 4, 15 +\item shell, 14, 53, 71, 72 +\item slocal, 12, 53, 66 +\item sloppy, 35 +\item smtp, 13, 15, 34, 37 +\item smtpd, 34, 35 +\item smtpsrvr, 132 +\item splitter, 12, 14, 46 +\item stat, 133 +\item statp, 133 +\item submit, 12 +\item Submit, 17 +\item submit, 20, 21, 24, 28, 30, 32, 34, 46, 50, 51, 54 +\item Submit, 60, 73 +\item submit, 104, 125, 131, 132, 149, 150, 151, 153 +\item submit\_addr, 20 +\indexspace +\newindex{t} +\item table, dbm, 24 +\subitem domain, 54 +\subitem file, 24 +\subitem flags, 24 +\subitem linear, 24 +\subitem list, 70 +\subitem name, 24 +\subitem override, 24 +\subitem shell, 71 +\subitem show, 24 +\subitem users, 53 +\item tables, alias, 51 +\subitem channel, 60 +\subitem local, 66 +\subitem X.400 84, 67 +\subitem X.400 88, 67 +\subitem X.400 O/R, 59 +\item tail, 126 +\item TAILOR, 8 +\item tailor, 16, 17, 21, 24, 33, 34, 37, 39, 42, 45, 68, 87, 89, 90, 92, 93, 106, 115, 122, 124, 125, 126, 131 +\item tailoring, channels, 24 +\subitem filters, 131 +\subitem logs, 21 +\subitem simple, 17 +\subitem tables, 24 +\subitem variables, 17 +\item TBLDIR, 8 +\item tbldir, 18, 19, 24, 71, 122 +\item timeout, 12, 46 +\item timout, 105 +\item tjoin, 129, 130 +\item /tmp, 20 +\item TOOLDIR, 5 +\item Tools, 71 +\item tools, 126, 133 +\item trash, 12 +\item true, 10 +\item tsapd, 133 +\item ts\_communities, 86 +\indexspace +\newindex{u} +\item UKORDER, 11 +\item user, 53, 60 +\item users, 12, 50, 51, 53, 55, 63, 70, 72, 96, 126, 130 +\item USRBINDIR, 8, 67 +\item uuencode, 131 +\indexspace +\newindex{v} +\item VAT, 11 +\indexspace +\newindex{w} +\item warndir, 46 +\item warning, 12, 46, 105 +\item warninterval, 19 +\item wrndfldir, 19, 75 +\indexspace +\newindex{x} +\item X11, 10 +\item X25 access, 2 +\item x400in84, 35 +\item x400mta, 20 +\item x400out84, 93 +\item xalert, 10 +\end{theindex} diff --git a/doc/manual/volume1/volume1.lof b/doc/manual/volume1/volume1.lof new file mode 100644 index 0000000..6c4e3ea --- /dev/null +++ b/doc/manual/volume1/volume1.lof @@ -0,0 +1,47 @@ +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} +\contentsline {figure}{\numberline {3.1}{\ignorespaces Example of Log Tailoring}}{23} +\contentsline {figure}{\numberline {3.2}{\ignorespaces Example of Table Tailoring}}{25} +\contentsline {figure}{\numberline {3.3}{\ignorespaces Example of Channel Tailor Entry}}{31} +\contentsline {figure}{\numberline {3.4}{\ignorespaces Example of Filter Control Tailoring}}{38} +\contentsline {figure}{\numberline {3.5}{\ignorespaces Simple Shell Script Filter}}{38} +\addvspace {10pt} +\contentsline {figure}{\numberline {4.1}{\ignorespaces Example of Alias Table}}{52} +\contentsline {figure}{\numberline {4.2}{\ignorespaces Example of Users Table}}{54} +\contentsline {figure}{\numberline {4.3}{\ignorespaces Example of Domain Table}}{57} +\contentsline {figure}{\numberline {4.4}{\ignorespaces Example of Or Table}}{61} +\contentsline {figure}{\numberline {4.5}{\ignorespaces Example of Channel Table}}{62} +\contentsline {figure}{\numberline {4.6}{\ignorespaces Example of or2rfc Table}}{65} +\contentsline {figure}{\numberline {4.7}{\ignorespaces Example of rfc2or Table}}{66} +\contentsline {figure}{\numberline {4.8}{\ignorespaces Example of RFC\penalty \@M \ 1148 Gateway Table}}{66} +\contentsline {figure}{\numberline {4.9}{\ignorespaces Example of X.400 Outbound Channel Table}}{76} +\contentsline {figure}{\numberline {4.10}{\ignorespaces Example of X.400 inbound Channel table}}{77} +\contentsline {figure}{\numberline {4.11}{\ignorespaces Example of List Table}}{78} +\contentsline {figure}{\numberline {4.12}{\ignorespaces Example of Shell Table}}{80} +\addvspace {10pt} +\contentsline {figure}{\numberline {5.1}{\ignorespaces Example of an O/R Table to Edit}}{84} +\contentsline {figure}{\numberline {5.2}{\ignorespaces O/R Table after Editing}}{85} +\contentsline {figure}{\numberline {5.3}{\ignorespaces Example of X.400 Outbound Table}}{88} +\contentsline {figure}{\numberline {5.4}{\ignorespaces Example of Channel Table}}{88} +\contentsline {figure}{\numberline {5.5}{\ignorespaces Example of X.400 Inbound Table}}{91} +\contentsline {figure}{\numberline {5.6}{\ignorespaces Example of X.400 Incoming Logs}}{92} +\addvspace {10pt} +\contentsline {figure}{\numberline {6.1}{\ignorespaces Example of Fax Table}}{97} +\contentsline {figure}{\numberline {6.2}{\ignorespaces Example Tailoring of Fax Channels}}{99} +\contentsline {figure}{\numberline {6.3}{\ignorespaces Examples of the asn filter}}{103} +\addvspace {10pt} +\contentsline {figure}{\numberline {7.1}{\ignorespaces Extract From the Console's Tailoring}}{116} +\contentsline {figure}{\numberline {7.2}{\ignorespaces Example of Address File}}{135} +\contentsline {figure}{\numberline {7.3}{\ignorespaces Example Delivery Report Format}}{135} +\addvspace {10pt} +\contentsline {figure}{\numberline {A.1}{\ignorespaces An Example Tailor File}}{143} +\addvspace {10pt} +\contentsline {figure}{\numberline {B.1}{\ignorespaces An Example Start Script}}{144} +\addvspace {10pt} +\contentsline {figure}{\numberline {C.1}{\ignorespaces An Example Nightly Script}}{146} +\addvspace {10pt} +\addvspace {10pt} +\contentsline {figure}{\numberline {E.1}{\ignorespaces io\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em} Interface}}{153} +\addvspace {10pt} +\contentsline {figure}{\numberline {F.1}{\ignorespaces QMGR ROS}}{163} diff --git a/doc/manual/volume1/volume1.lot b/doc/manual/volume1/volume1.lot new file mode 100644 index 0000000..3ff6991 --- /dev/null +++ b/doc/manual/volume1/volume1.lot @@ -0,0 +1,24 @@ +\addvspace {10pt} +\addvspace {10pt} +\contentsline {table}{\numberline {2.1}{\ignorespaces Make Variables That Should Be Set}}{6} +\contentsline {table}{\numberline {2.2}{\ignorespaces Make Variables That Can Be Defaulted}}{7} +\addvspace {10pt} +\contentsline {table}{\numberline {3.1}{\ignorespaces Filter Control Expansion Macros}}{39} +\contentsline {table}{\numberline {3.2}{\ignorespaces Warning expansion macros}}{47} +\addvspace {10pt} +\contentsline {table}{\numberline {4.1}{\ignorespaces Warning Message Macro Expansions}}{69} +\contentsline {table}{\numberline {4.2}{\ignorespaces Shell Channel Expansion Macros}}{79} +\addvspace {10pt} +\contentsline {table}{\numberline {5.1}{\ignorespaces Example of X.400 Information for NASA}}{82} +\contentsline {table}{\numberline {5.2}{\ignorespaces Example of X.400 Information for UCL}}{82} +\addvspace {10pt} +\addvspace {10pt} +\contentsline {table}{\numberline {7.1}{\ignorespaces MTA Console Accelerators}}{114} +\contentsline {table}{\numberline {7.2}{\ignorespaces Tailor File Entries to Console Keys.}}{115} +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} +\contentsline {table}{\numberline {E.1}{\ignorespaces Summary of MU flags}}{152} +\addvspace {10pt} diff --git a/doc/manual/volume1/volume1.major b/doc/manual/volume1/volume1.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/manual/volume1/volume1.major @@ -0,0 +1 @@ +1 diff --git a/doc/manual/volume1/volume1.minor b/doc/manual/volume1/volume1.minor new file mode 100644 index 0000000..3d9988a --- /dev/null +++ b/doc/manual/volume1/volume1.minor @@ -0,0 +1 @@ +335 diff --git a/doc/manual/volume1/volume1.tex b/doc/manual/volume1/volume1.tex new file mode 100644 index 0000000..6a2498e --- /dev/null +++ b/doc/manual/volume1/volume1.tex @@ -0,0 +1,98 @@ +% run this through LaTeX + +% SEK - this is a PP document, designed to be easy to convert to +% an ISODE Manual Section if we want to + +\input lcustom + + +\documentstyle[11pt,sfwmac,tgrind,twoside,a4]{report} + +\newcount\volnum +\volnum=1 +\makeatletter +\def\preface{\chapter*{Preface\@mkboth{PREFACE}{PREFACE}}} +\makeatother + +\makeindex + +\input{dist-params} + +\pagenumbering{roman} + +\begin{document} + +\newcommand{\PP}{{\em PP}} +\newcommand{\SP}{\vspace{.25in}} + +% \readauxfiles + +\title{{\Huge\bf PP} \\ + \vskip 1.5em + \LARGE\sl Volume 1: Installation and Operation} +\author{ +Julian Onions \\ +X-Tel Services Ltd \and +Peter Cowen \\ +X-Tel Services Ltd \and +Alina da Cruz \\ +Department of Computer Science \\ +University College London \and +Steve Kille \\ +Department of Computer Science \\ +University College London +} +\date{\ifdraft \versiondate/\\ \tt Draft Version \versiontag/ + \else \today\\ + (Version \ppversion/)\fi} + +\maketitle +\newpage + +\thispagestyle{empty} +\setcounter{page}{0} +\mbox{} +\newpage + +\tableofcontents + +\listoftables + +\listoffigures + +\include{preface} + +\newpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi +\pagenumbering{arabic} + + +\include{general} +\include{install} +\include{configure} +\include{tables} +\include{x400links} +\include{addon} +\include{management} +\appendix +\include{appendix} +\include{x400tables} +\include{mu} +\include{qmgrproto} +\bibliography{bcustom,pp} +\bibliographystyle{alpha} + +\input volume1.ind + +\clearpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi + +%\typeout{you can usually ignore the message about Label(s) may have changed} + +\end{document} diff --git a/doc/manual/volume1/volume1.toc b/doc/manual/volume1/volume1.toc new file mode 100644 index 0000000..02623fa --- /dev/null +++ b/doc/manual/volume1/volume1.toc @@ -0,0 +1,184 @@ +\contentsline {chapter}{\numberline {1}General Considerations}{1} +\contentsline {section}{\numberline {1.1}Overview}{1} +\contentsline {section}{\numberline {1.2}General Requirements}{1} +\contentsline {subsection}{\numberline {1.2.1}Systems}{1} +\contentsline {subsection}{\numberline {1.2.2}Disk space}{2} +\contentsline {subsection}{\numberline {1.2.3}Communications Requirements}{2} +\contentsline {subsection}{\numberline {1.2.4}X Window System}{2} +\contentsline {subsection}{\numberline {1.2.5}QUIPU}{2} +\contentsline {section}{\numberline {1.3}Specific Channel Requirements}{3} +\contentsline {section}{\numberline {1.4}User Agents}{3} +\contentsline {section}{\numberline {1.5}Compatibility with Older MTAs}{3} +\contentsline {subsection}{\numberline {1.5.1}MMDF}{3} +\contentsline {subsection}{\numberline {1.5.2}Sendmail}{4} +\contentsline {section}{\numberline {1.6}MTA Layout}{4} +\contentsline {section}{\numberline {1.7}Performance}{4} +\contentsline {chapter}{\numberline {2}Installing PP}{5} +\contentsline {section}{\numberline {2.1}Compile Time Configuration}{5} +\contentsline {subsection}{\numberline {2.1.1}Make.defs}{5} +\contentsline {subsection}{\numberline {2.1.2}h/config.h}{11} +\contentsline {section}{\numberline {2.2}Overview of Channels}{11} +\contentsline {subsection}{\numberline {2.2.1}Mandatory Channels}{12} +\contentsline {subsection}{\numberline {2.2.2}Optional Channels}{12} +\contentsline {section}{\numberline {2.3}Example Configurations}{14} +\contentsline {subsubsection}{Local SMTP}{15} +\contentsline {subsubsection}{SMTP mail}{15} +\contentsline {subsubsection}{Janet mail}{15} +\contentsline {section}{\numberline {2.4}Configuration of User Agents}{15} +\contentsline {section}{\numberline {2.5}Checking the Configuration of Your System}{15} +\contentsline {chapter}{\numberline {3}Configuring PP}{16} +\contentsline {section}{\numberline {3.1}The General Syntax of Tailor File Entries}{16} +\contentsline {section}{\numberline {3.2}Variable Tailor File Entries}{17} +\contentsline {subsection}{\numberline {3.2.1}Mandatory Tailoring Variables}{17} +\contentsline {subsection}{\numberline {3.2.2}Optional Tailoring Variables}{18} +\contentsline {section}{\numberline {3.3}Logging Tailor File Entries.}{21} +\contentsline {subsection}{\numberline {3.3.1}Diverting Logging Streams}{23} +\contentsline {section}{\numberline {3.4}Table Tailor File Entries}{24} +\contentsline {section}{\numberline {3.5}Channel Tailor File Entries}{24} +\contentsline {section}{\numberline {3.6}ISODE Runtime Tailoring}{32} +\contentsline {subsection}{\numberline {3.6.1}Queue Manager Tailoring}{32} +\contentsline {subsection}{\numberline {3.6.2}X.400 Tailoring}{32} +\contentsline {section}{\numberline {3.7}Channel Pairing}{33} +\contentsline {section}{\numberline {3.8}Tailoring of Common Channels}{34} +\contentsline {subsection}{\numberline {3.8.1}Submit}{34} +\contentsline {subsection}{\numberline {3.8.2}Protocol Channels}{34} +\contentsline {subsubsection}{SMTP channel}{34} +\contentsline {subsubsection}{X.400 inbound channel}{35} +\contentsline {subsubsection}{UUCP Channel}{36} +\contentsline {subsubsection}{{\psf DECnet} MAIL11 channel}{36} +\contentsline {subsection}{\numberline {3.8.3}Filter Control and Common Filters}{37} +\contentsline {subsubsection}{RFC\penalty \@M \ 822 Filter}{39} +\contentsline {subsubsection}{P2norm Filter}{41} +\contentsline {subsubsection}{Body Part Deleting Filters}{42} +\contentsline {subsubsection}{ODIF filters}{42} +\contentsline {subsection}{\numberline {3.8.4}The List Channel}{42} +\contentsline {subsection}{\numberline {3.8.5}The RFC 1148 Channels}{43} +\contentsline {subsection}{\numberline {3.8.6}Shaping Channels}{44} +\contentsline {subsubsection}{RFC 934 Channel}{44} +\contentsline {subsubsection}{P2flatten Channel}{44} +\contentsline {subsubsection}{P2explode Channel}{45} +\contentsline {subsection}{\numberline {3.8.7}Miscellaneous Channels}{45} +\contentsline {subsubsection}{Qmgrload Channel}{45} +\contentsline {subsubsection}{Msg-Clean Channel}{45} +\contentsline {subsubsection}{Debris Channel}{45} +\contentsline {subsubsection}{Splitter Channel}{46} +\contentsline {subsubsection}{Timeout Channel}{46} +\contentsline {subsubsection}{Warning Channel}{46} +\contentsline {subsubsection}{Dr2rfc Channel}{46} +\contentsline {section}{\numberline {3.9}How Channels Work}{48} +\contentsline {chapter}{\numberline {4}PP Tables}{50} +\contentsline {section}{\numberline {4.1}Basic Operation of the Tables}{50} +\contentsline {section}{\numberline {4.2}The General Syntax of Table Entries.}{51} +\contentsline {section}{\numberline {4.3}The Aliases Table}{51} +\contentsline {section}{\numberline {4.4}The Users Table}{53} +\contentsline {section}{\numberline {4.5}The Domain Table}{54} +\contentsline {section}{\numberline {4.6}The O/R Address Table}{59} +\contentsline {section}{\numberline {4.7}The Channel Table}{60} +\contentsline {section}{\numberline {4.8}Supporting Multiple Organizations on One MTA}{63} +\contentsline {section}{\numberline {4.9}RFC 1148 Mapping Tables}{65} +\contentsline {subsection}{\numberline {4.9.1}The O/R to RFC\penalty \@M \ 822 Table}{65} +\contentsline {subsection}{\numberline {4.9.2}The RFC\penalty \@M \ 822 to O/R table}{65} +\contentsline {subsection}{\numberline {4.9.3}The Known RFC\penalty \@M \ 1148 Gateway Table}{66} +\contentsline {section}{\numberline {4.10}PP Authorisation}{66} +\contentsline {subsection}{\numberline {4.10.1}Access Policy}{67} +\contentsline {subsection}{\numberline {4.10.2}Table Formats}{67} +\contentsline {subsubsection}{Channel Authorisation}{68} +\contentsline {subsubsection}{MTA authorisation}{69} +\contentsline {subsubsection}{User Authorisation}{70} +\contentsline {section}{\numberline {4.11}Authentication}{70} +\contentsline {subsection}{\numberline {4.11.1}Submit Authentication}{71} +\contentsline {subsection}{\numberline {4.11.2}QMGR Authentication}{71} +\contentsline {section}{\numberline {4.12}The 822 Local Table}{73} +\contentsline {section}{\numberline {4.13}The X.400 (1984/1988) Outbound Table}{74} +\contentsline {section}{\numberline {4.14}The X.400 (1984/1988) Inbound Table}{76} +\contentsline {section}{\numberline {4.15}The List Table}{77} +\contentsline {section}{\numberline {4.16}The Shell Table}{78} +\contentsline {subsection}{\numberline {4.16.1}Statistical Logging}{79} +\contentsline {chapter}{\numberline {5}Setting Up X.400 Links}{81} +\contentsline {section}{\numberline {5.1}Remote Site Information}{81} +\contentsline {subsection}{\numberline {5.1.1}Conventions}{83} +\contentsline {section}{\numberline {5.2}Setting Up the Routing Tables}{83} +\contentsline {subsection}{\numberline {5.2.1}Routing and Mapping tables}{83} +\contentsline {subsection}{\numberline {5.2.2}Editing the O/R Table}{83} +\contentsline {subsubsection}{X.400 Outbound Procedures}{86} +\contentsline {subsection}{\numberline {5.2.3}Editing the X.400 Outbound Table}{86} +\contentsline {subsection}{\numberline {5.2.4}Channel Table Usage}{87} +\contentsline {subsection}{\numberline {5.2.5}Edit the Channel Table}{87} +\contentsline {subsection}{\numberline {5.2.6}X.400 Inbound Procedures}{89} +\contentsline {subsection}{\numberline {5.2.7}Editing the X.400 Inbound Table}{89} +\contentsline {subsection}{\numberline {5.2.8}Testing Outbound Connections}{92} +\contentsline {subsection}{\numberline {5.2.9}How to make a test X.400 connection to a remote site}{92} +\contentsline {subsection}{\numberline {5.2.10}A Common X.400 Incoming Connection Problem}{93} +\contentsline {chapter}{\numberline {6}Additional Capabilities}{95} +\contentsline {section}{\numberline {6.1}G3Fax capability in PP}{95} +\contentsline {subsection}{\numberline {6.1.1}Fax Addressing}{95} +\contentsline {subsection}{\numberline {6.1.2}The Fax Table}{96} +\contentsline {subsection}{\numberline {6.1.3}Fax Conversion}{98} +\contentsline {subsubsection}{The \unhbox \voidb@x \hbox {\pit hdr2fax} Filter}{98} +\contentsline {subsubsection}{The \unhbox \voidb@x \hbox {\pit ia52fax} Filter}{99} +\contentsline {subsection}{\numberline {6.1.4}The Fax Transmission and Reception Channels}{100} +\contentsline {subsubsection}{The Panasonic Systemfax 250 Driver}{100} +\contentsline {subsubsection}{The Outbound Transmission Channel}{100} +\contentsline {subsubsection}{The Inbound Reception Daemon}{101} +\contentsline {subsubsection}{The Fujitsu dexNet200 Driver}{102} +\contentsline {section}{\numberline {6.2}ASN.1 Filter}{102} +\contentsline {subsection}{\numberline {6.2.1}Runtime Options}{102} +\contentsline {subsection}{\numberline {6.2.2}Tailoring}{103} +\contentsline {subsubsection}{Tailoring Examples}{103} +\contentsline {chapter}{\numberline {7}Managing PP}{104} +\contentsline {section}{\numberline {7.1}QMGR}{104} +\contentsline {subsection}{\numberline {7.1.1}Message Submission}{104} +\contentsline {subsection}{\numberline {7.1.2}Queue Reading}{104} +\contentsline {subsection}{\numberline {7.1.3}Active Channel}{104} +\contentsline {subsection}{\numberline {7.1.4}Passive Channel}{105} +\contentsline {subsection}{\numberline {7.1.5}Cleanups, Timeouts, Warnings and Debris}{105} +\contentsline {subsection}{\numberline {7.1.6}QMGR Management and Tailoring}{105} +\contentsline {section}{\numberline {7.2}MTA Console}{107} +\contentsline {subsection}{\numberline {7.2.1}The MTA Console's Display}{107} +\contentsline {subsubsection}{The Monitor Mode}{108} +\contentsline {subsubsection}{The Control Mode}{108} +\contentsline {subsection}{\numberline {7.2.2}Configuring The MTA Console}{108} +\contentsline {subsubsection}{Totals Configuration.}{108} +\contentsline {subsubsection}{Colour Configuration.}{109} +\contentsline {subsubsection}{Static Connection Configuration.}{109} +\contentsline {subsubsection}{Confirmation Configuration.}{109} +\contentsline {subsubsection}{Heuristic Configuration}{109} +\contentsline {subsubsection}{Configuration of Timeouts and Retries.}{110} +\contentsline {subsection}{\numberline {7.2.3}The Effect of the Mouse Buttons and Keys}{111} +\contentsline {subsection}{\numberline {7.2.4}Badness}{114} +\contentsline {subsubsection}{Tailoring of Upperbounds}{114} +\contentsline {section}{\numberline {7.3}LINEconsole}{116} +\contentsline {subsection}{\numberline {7.3.1}LINEconsole Commands}{117} +\contentsline {section}{\numberline {7.4}Lconsole}{118} +\contentsline {section}{\numberline {7.5}Checkup Procedures}{121} +\contentsline {subsection}{\numberline {7.5.1}ckchan}{121} +\contentsline {subsection}{\numberline {7.5.2}ckconfig}{122} +\contentsline {subsection}{\numberline {7.5.3}Checking of Addresses}{122} +\contentsline {subsubsection}{Ckadr}{122} +\contentsline {subsubsection}{Probes}{124} +\contentsline {section}{\numberline {7.6}Dealing with Errors}{125} +\contentsline {section}{\numberline {7.7}Managing Tables}{126} +\contentsline {subsubsection}{RFC 1148 Mapping Tables}{126} +\contentsline {subsubsection}{Domain and Channel Tables}{127} +\contentsline {subsubsection}{Generation of the domain table}{127} +\contentsline {subsubsection}{Generation of the Channel Table}{129} +\contentsline {section}{\numberline {7.8}Adding New Users and MTAs}{130} +\contentsline {section}{\numberline {7.9}Adding Filters, Shapers + EITs}{131} +\contentsline {subsection}{\numberline {7.9.1}Adding A New Encoded Information Type}{131} +\contentsline {subsection}{\numberline {7.9.2}Adding a New Content Type}{131} +\contentsline {section}{\numberline {7.10}The Day--to--Day Running of PP}{132} +\contentsline {subsection}{\numberline {7.10.1}How to Start Up the PP System}{132} +\contentsline {subsection}{\numberline {7.10.2}What to Run Each Night}{133} +\contentsline {subsection}{\numberline {7.10.3}Saving Logs}{133} +\contentsline {section}{\numberline {7.11}Examining the PP Queue}{134} +\contentsline {subsection}{\numberline {7.11.1}Delivery Reports}{134} +\contentsline {subsection}{\numberline {7.11.2}Receipt Notifications}{134} +\contentsline {chapter}{\numberline {A}Example of the Tailor File}{136} +\contentsline {chapter}{\numberline {B}Example of the PP Start Script}{144} +\contentsline {chapter}{\numberline {C}Example of the PP Script Run Nightly}{145} +\contentsline {chapter}{\numberline {D}Obtaining X.400 Tables}{147} +\contentsline {chapter}{\numberline {E}Testing PP --- the MTS User Interface}{149} +\contentsline {section}{\numberline {E.1}Overview}{149} +\contentsline {section}{\numberline {E.2}User Input}{151} +\contentsline {section}{\numberline {E.3}MU Internals}{152} +\contentsline {chapter}{\numberline {F}QMGR Protocol}{154} diff --git a/doc/manual/volume1/volume1.vrsn b/doc/manual/volume1/volume1.vrsn new file mode 100644 index 0000000..7def622 --- /dev/null +++ b/doc/manual/volume1/volume1.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.335}% + \gdef\versiondate/{Mon Dec 16 14:13:30 GMT 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/manual/volume1/x400in-examp.tex b/doc/manual/volume1/x400in-examp.tex new file mode 100644 index 0000000..145dd8c --- /dev/null +++ b/doc/manual/volume1/x400in-examp.tex @@ -0,0 +1,11 @@ +{\small +\begin{verbatim} +default:lmta="us",lpass="bar" +"3459"/Int-X25(80)=208006030203:rname="france-kwai", + rmta="kwai.inria.fr" +"425"/Int-X25(80)=26245622190113:rname="germany-ibm", + rmta="foo",rpass="foo" +Janet=000021000018:rname="pp-nottingham",rmta="cs.nott.ac.uk" +Janet=000005111680:rname="pp-vs2",rmta="cs.ucl.ac.uk" +\end{verbatim} +} diff --git a/doc/manual/volume1/x400in-examp2.tex b/doc/manual/volume1/x400in-examp2.tex new file mode 100644 index 0000000..028f08b --- /dev/null +++ b/doc/manual/volume1/x400in-examp2.tex @@ -0,0 +1,27 @@ +\begin{quote}\small\begin{verbatim} +#-*********************** +# +# +# -*** UCL's default local entry ***- +# -*** this is different for every PP site ***- +# +# (Folded for readabilty) +# +default:lpsap='"591"/Internet=bells', + lmta="UK.AC.UCL.CS",lpass=" " +# +# -*** NASA ***- +# +"591"/Internet=titan.arc.nasa.gov:rname="us-nasa", + rmta="titan.arc.nasa.gov",rpass=" " +"591"/Internet=128.102.128.5:rname="us-nasa", + rmta="titan.arc.nasa.gov",rpass=" " +# +# -*** UCL ***- +# +"591"/X121+23421920030080:rname="ucl", + rmta="UK.AC.UCL.CS",rpass=" " +# +# +#-*********************** +\end{verbatim}\end{quote} diff --git a/doc/manual/volume1/x400links.aux b/doc/manual/volume1/x400links.aux new file mode 100644 index 0000000..2068091 --- /dev/null +++ b/doc/manual/volume1/x400links.aux @@ -0,0 +1,55 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {5}Setting Up X.400 Links}{81}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {5.1}Remote Site Information}{81}} +\newlabel{lab.remoteinfo}{{5.1}{81}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {5.1}{\ignorespaces Example of X.400 Information for NASA}}{82}} +\newlabel{remoteinfo.example1}{{5.1}{82}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {5.2}{\ignorespaces Example of X.400 Information for UCL}}{82}} +\newlabel{remoteinfo.example2}{{5.2}{82}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.1.1}Conventions}{83}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {5.2}Setting Up the Routing Tables}{83}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.1}Routing and Mapping tables}{83}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.2}Editing the O/R Table}{83}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.1}{\ignorespaces Example of an O/R Table to Edit}}{84}} +\newlabel{lab.or.tbl1}{{5.1}{84}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.2}{\ignorespaces O/R Table after Editing}}{85}} +\newlabel{lab.or.tbl2}{{5.2}{85}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{X.400 Outbound Procedures}{86}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.3}Editing the X.400 Outbound Table}{86}} +\citation{String.Addresses} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.4}Channel Table Usage}{87}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.5}Edit the Channel Table}{87}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.3}{\ignorespaces Example of X.400 Outbound Table}}{88}} +\newlabel{lab.x400out.tbl}{{5.3}{88}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.4}{\ignorespaces Example of Channel Table}}{88}} +\newlabel{lab.channel.tbl}{{5.4}{88}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.6}X.400 Inbound Procedures}{89}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.7}Editing the X.400 Inbound Table}{89}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.5}{\ignorespaces Example of X.400 Inbound Table}}{91}} +\newlabel{lab.x400in.tbl}{{5.5}{91}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.8}Testing Outbound Connections}{92}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {5.6}{\ignorespaces Example of X.400 Incoming Logs}}{92}} +\newlabel{examp:log}{{5.6}{92}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.9}How to make a test X.400 connection to a remote site}{92}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {5.2.10}A Common X.400 Incoming Connection Problem}{93}} +\global\@namedef{cp@x400links}{ +\setcounter{page}{95} +\setcounter{equation}{0} +\setcounter{enumi}{3} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{5} +\setcounter{section}{2} +\setcounter{subsection}{10} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{6} +\setcounter{table}{2} +} diff --git a/doc/manual/volume1/x400links.tex b/doc/manual/volume1/x400links.tex new file mode 100644 index 0000000..b2f49b2 --- /dev/null +++ b/doc/manual/volume1/x400links.tex @@ -0,0 +1,481 @@ +\chapter {Setting Up X.400 Links} + +This chapter shows how to go about setting up X.400 interconnection +with other sites. + +Information on X.400 routing and connection establishment is entirely +table driven. As yet there is no standardised support by the message +directory service. This section describes how to set up the \file{or} +routing tables, and the other tables needed for bilaterally agreed +linkage. + +To set up an X.400 connection, information about the remote site +needs to be obtained and an entry needs to be inserted in the PP tables. + +\section {Remote Site Information} + +Obtain the information below prior to setting up an X.400 link. + +\label {lab.remoteinfo} +\begin {tabular}{l l p{0.5\textwidth}} +\tt& Technical Contact:& The person you contact if things go wrong.\\ +\tt& Telephone:& Telephone number of the technical contact.\\ +\tt*& O/R Address:& Address of a contact person.\\ +\tt*& MTA Name:& Name by which the remote site identifies itself.\\ +\tt*& MTA Password:& Password by which the remote site identifies itself.\\ +\tt*& Transport Selector:& A port identifier at the transport level.\\ +\tt& Network Address:& The X.25 DTE and/or IP address of the remote site.\\ +\tt*& X.25 Protocol ID:& A port identifier at the X.25 level.\\ +\tt*& ManagementDomains:& Any management domain/s (MD) that + the remote site provides a connection to.\\ +\end{tabular} + +Any information prefixed with an ``*'' may be optional. + +Examples of the format are shown in Tables~\ref{remoteinfo.example1} +and~\ref{remoteinfo.example2}. + +\tagtable[hbpt]{x400info1}{Example of X.400 Information for +NASA}{remoteinfo.example1} + +\tagtable[hbpt]{x400info2}{Example of X.400 Information for UCL}{remoteinfo.example2} + + +\subsection{Conventions} +These are some of the conventions that PP uses for X.400 links. These +need not be followed strictly but make a good starting point. + +\begin{itemize} +\item ISODE uses a transport selector. This should be ASCII-encoded +and should be all numeric (to conform to X.400(84)). The value ``591'' +is often used. + +\item The MTA name is usually an appropriate domain. In the UK this +is in NRS (i.e., big endian domain) order. + +\item The MTA password is usually a single space. +\end{itemize} + +\section {Setting Up the Routing Tables} + +The following steps need to be taken to set up the X.400 routing +tables. + +\subsection{Routing and Mapping tables} +First, a number of mapping tables need to be installed. If +you do not have a copy of them, you will need to get one. Copies should be +obtained from University College London (see Appendix~\ref{app:tables} +for details). + +\begin{describe} +\item[\verb|or|:] The O/R Table (See Figure~\ref{lab.or.tbl1} below and +Section~\ref{sect:ortables}). +\item[\verb|rfc2or|:] The RFC~822 to O/R Table (See +Figure~\ref{example:rfc2or}) . +\item[\verb|or2rfc|:] The O/R to RFC~822 Table (See +Figure~\ref{example:or2rfc}). +\item[\verb|rfc1148gate|:] The RFC~1148 known gateways file. +\end{describe} + +The \file{rfc2or}, \file{or2rfc} and \file{rfc1148} are the RFC~1148 +tables which should be placed in the Table directory. + +\subsection{Editing the O/R Table} + +Replace the \verb|_DEFAULT_MTA_| occurrences with appropriate remote +site names. These are the names by which the sites are internally +identifiable within PP. The choice of name is up to the PP +administrator, and is used for identification purposes only. + +Local information should be prepended to this table, and will override +later entries. + +When observing the example O/R tables in Figures~\ref{lab.or.tbl1} +and \ref{lab.or.tbl2} please note that: + +\begin{itemize} +\item The O/R skeleton table in Figure~\ref{lab.or.tbl1} on +page~\pageref{lab.or.tbl1} is a truncated example of the {\em +retrieved} UCL O/R master table. + +\item The O/R skeleton table in Figure~\ref{lab.or.tbl2} on +page~\pageref{lab.or.tbl2}, is a truncated example of an {\em edited} +UCL O/R master table. +\end{itemize} + +\tagrind[hbtp]{exampleortbl}{Example of an O/R Table to Edit}{lab.or.tbl1} + +\tagrind[hbtp]{exampleortbl2}{O/R Table after Editing}{lab.or.tbl2} + +\subsubsection{X.400 Outbound Procedures} + +A brief description of how the X.400 outbound table is used within PP follows: + +\begin{itemize} +\item PP connects to a remote site using the address specified in the +\verb|rpsap| field. These address are tried in the order definined in +the \verb|ts_communities|\index{ts\_communities} ISODE variable. +If all addresses fail, and the entry in the x.400 outbound table +contains a \verb|trynext| entry, that site will be tried too. + +\item When the connection is requested, PP gives its local MTA name +and password as identification. + +\item The remote site {\em either} accepts connection and returns +its own MTA name and password {\em or} it rejects the connection and +gives as its reason ``validation failure''. + +\item If the remote site rejects the connection, PP terminates +the X.400 connection. + +\item If the remote site has accepted the connection, PP +matches the returned MTA name and password against the values held for +the remote site, in the X.400 outbound table (i.e the \verb|rmta| and +\verb|rpass| fields). + +\item If the remote site's MTA name and password match, then +connection has been set up, and PP starts to transmit a message; +otherwise PP terminates the X.400 connection. +\end{itemize} + +\subsection{Editing the X.400 Outbound Table} + +Insert a default entry in the X.400 outbound table if it does not +exist, where the key has the value ``default'' with the following +fields set. These are the default values by which the the local PP +identifies itself to a remote site when an outgoing X.400 connection +is made. Refer to the X.400 outbound table in +Figure~\ref{lab.x400out.tbl} when doing this. +\begin{describe} +\item[\verb|lmta|:] Local MTA name. +\item[\verb|lpass|:] Local password. +\item[\verb|lpsap|:] Local network address (same format as \verb|rpsap|). +\end{describe} + +When the O/R table was previously edited, the remote site names that +were chosen by the PP administrator should have been carefully +recorded. These are the names that are now used to ``key'' into the +X.400 outbound table. In addition to this, the information below is +also required (refer to Figure~\ref{lab.remoteinfo}). +\begin{itemize} +\item MTA name and password (both optional). +\item Network address (mandatory) +\item Transport selector (optional) +\item Protocol ID or PID (optional). +\end{itemize} + +Insert an entry in the X.400 outbound table, +where the remote site information maps into the following fields. +Refer to the X.400 outbound table example in Figure~\ref{lab.x400out.tbl} +when doing this. + +\begin{itemize} +\item remote site name - \verb|key|. +\item MTA name - \verb|rmta|. +\item Password - \verb|rpass|. +\item Network address, TSAP and PID - \verb|rpsap|. +\end{itemize} + +\subsection*{NOTE} + +\begin{itemize} + +\item All keys in the X.400 outbound table must be unique. + +\item If the \verb|rmta| and \verb|rpass| are not specified, this +means that the remote site is using {\em either} some other method +of validation {\em or} no validation at all. + +\item The \verb|rpsap| field has a number of different types of formats, +some of which may be seen in Figure~\ref{lab.x400out.tbl}. +The formats are described in \cite{String.Addresses}. + +\end{itemize} + +The X.400 outbound table below gives the NASA and UCL entries using +the remote site information specified in Figures~\ref{remoteinfo.example1} +and~\ref{remoteinfo.example2}. Some possible \verb|rpsap| formats are also +shown. + +\tagrind[hbpt]{chx400out}{Example of X.400 Outbound Table}{lab.x400out.tbl} + +\subsection{Channel Table Usage} +The section describes briefly the actions that are taken to validate +an X.400 address. + +\begin{enumerate} +\item Parse an address in X.400 style using the \file{rfc2or} and +\file{or2rfc} tables if necessary to convert from RFC~822 format. + +\item Use the \file{or} table to try and locate a remote site +name, through which the address may be relayed + +\item If a remote site name is associated with the address, then +look at the channel table to locate the cheapest route by which that +remote site may be reached. +\end{enumerate} + + +\subsection{Edit the Channel Table} + +The channel table below gives the NASA and UCL entries using the +remote site information specified in the tables in +Figure~\ref{remoteinfo.example1}. + +\begin{itemize} +\item Note that the key to this table has the same value as that in +the X.400 outbound table in Figure~\ref{lab.x400out.tbl}. + +\item Also, note that the name specified in the rounded brackets is the +name of the X.400 outbound channel, and possesses the same value as +that specified in the \file{tailor} file. +\end{itemize} + +\tagrind[hbtp]{chanx400examp}{Example of Channel Table}{lab.channel.tbl} + +\subsection{X.400 Inbound Procedures} + +A brief description of how the X.400 inbound table is used within PP. + +\begin{itemize} +\item A remote site requests a connection with the local PP system, +and within the request its remote network address, MTA name and +password are specified. + +\item The local PP uses the remote network address as a key into +the X.400 inbound table. + +\item If the key is invalid, then the local PP sends a rejection +back to the remote site, giving ``validation failure'' as the reason. + +\item If the key is valid, then the remote site's MTA name +and password are checked against its {\em rmta} and {\em rpass} +values specified within the X.400 inbound table. + +\item If the values match, then the local PP accepts the request +by returning its MTA name and password, and begins to get ready +for remote message transmission. + +\item If the values do not match, then the local PP sends a rejection +back to the remote site, giving ``validation failure'' as the reason. +\end{itemize} + +{\bf NOTE:} 2 additional fields may be set to facilitate +X.400 inbound connection testing. + +\begin{describe} + +\item[\verb|ininfo=sloppy|:] If this is set in the \file{tailor} file, +allows the acceptance of all incoming connections. All validation +checks are bypassed. + +\item[\verb|other=sloppy|:] set in the X.400 inbound table +against a particular remote site entry bypasses the +validation checks for that site's remote MTA name and password. +\end{describe} + +\subsection{Editing the X.400 Inbound Table} + +Before editing this table the PP administrator needs to: +\begin {itemize} +\item Decide whether or not to be selective over the acceptance +of remote site connections. If {\em all} remote site connections are +to be accepted, then in the \file{tailor} file the X.400 inbound +channel is tailored with \verb|ininfo=sloppy|, and {\em no} entries +need to be registered in this table. If entries are registered, +they will be bypassed. + +\item Decide whether or not remote site MTA name and password +validation checks are to be done. This decision should only +be taken if \verb|ininfo=sloppy| is not set in the \file{tailor} file +for the X.400 inbound channel. If no MTA name and password +validation checks are to be carried out, then for that remote entry +in the X.400 inbound table, set \verb|other=sloppy|. +\end {itemize} + +Please note when taking these decisions: +\begin{itemize} +\item If \verb|ininfo=sloppy| is set within the \file{tailor} file for the +X.400 inbound channel, the network address of a remote site +is still used as a key into the X.400 inbound table to obtain its +remote site name (\verb|rname|). +If the key is invalid, then the remote site name is set to its +network address. +This will cause problems, if delivery notifications are requested +by such a site, as the local PP would be unable to use +the remote site name to key into the X.400 outbound table. +Therefore \verb|ininfo=sloppy| should be set for testing purposes only. + +\item That for each remote site an X.400 inbound and outbound entry +should exist. +Otherwise if \verb|ininfo=sloppy| is set, +and a remote site's network address keys successfully into the +X.400 inbound table, unless there +is a corresponding entry in the X.400 outbound table, no mail +will be able to be sent to that site. +\end{itemize} + +When the X.400 outbound table was previously edited, the following +remote site information should have been obtained: + +\begin{itemize} +\item remote site name (chosen by the PP administrator). +\item MTA name and password (both optional). +\item Network address (mandatory). +\item Transport selector (optional) . +\end{itemize} + +As the X.400 inbound table is very similar to the X.400 outbound +table the same information is again required, +only this time, instead of making a connection to a remote site, +the concern is centered on a remote site requesting a local connection. + +The fields in the X.400 inbound table (see +Figure~\ref{lab.x400in.tbl}) are very similar to the ones in the X.400 +outbound table (see Figure~\ref{lab.x400out.tbl}), and should be set +accordingly, except for two main differences: + +\begin {describe} +\item[\verb|rpsap|:] acts as the table entry key. +\item[\verb|rname|:] is an extra parameter which specifies the remote site name. +This should have the same value as the remote site \verb|key| in the +X.400 outbound table. +\end{describe} + +The X.400 inbound table below gives the NASA and UCL entries using the +remote site information specified in Figure~\ref{remoteinfo.example1}. + +\tagrind[hbtp]{x400in-examp2}{Example of X.400 Inbound Table}{lab.x400in.tbl} + +In Figure~\ref{lab.x400in.tbl} above, it can be seen that: + +\begin{itemize} +\item The PID field is {\em never} used in the \verb|rpsap| key. + +\item If a remote site has a number of network addresses, +all may be specified in the \verb|rpsap| of the remote site's X.400 +outbound entry (see Figure~\ref{lab.x400out.tbl}) but there +will need to be a number of inbound +\verb|rpsap| entries for each network address belonging to that remote site. +Though all other details (\verb|rname|, \verb|rmta|, \verb|rpass|) +would be the same. +\end {itemize} + + +\subsection {Testing Outbound Connections} + +\begin{itemize} +\item Go to the PP log directory. +\item Look at the X.400 incoming log. The log should look like those +in Figure~\ref{examp:log}. +\end{itemize} + +\tagrind[hbpt]{logx400-examp}{Example of X.400 Incoming Logs}{examp:log} + +From this log, the following remote site information may be obtained, +which can then be inserted as two entries in the X.400 inbound and +outbound tables. + +\begin{itemize} +\item The TSAP: None for the first entry and ``PHL'' for the second. + +\item The Network Address: 5052334300018 for the first entry and +302049600717 for the second. + +\item The MTA Name: ``manta.cng.dit.csiro.au'' for the first entry and +``foo'' for the second. + +\item The password - `` '' for the first and ``foobar'' for the second. +\end{itemize} + +However, note that: + +\begin{itemize} + +\item A remote site does not have to be specified in the X.400 inbound table +for a connection to be successful. If in the \file{tailor} file the +X.400 Inbound Channel is tailored with \verb|ininfo=sloppy|, then all +remote connections are accepted. + +\item If on the other hand MTA name and password validation is to +be ignored, then for that remote entry in the X.400 inbound table, +\verb|other=sloppy| is added. +\end{itemize} + +\subsection {How to make a test X.400 connection to a remote site} + +\begin{itemize} +\item Go to the table directory. +\item Put the remote site information in the appropriate tables. +\item Use the channel in ``ping'' mode to +make an RTS connection to the remote site. This is done by running the +channel binary as follows: +\begin{quote}\small\begin{verbatim} +x400out88 ping -m mta -c channel +\end{verbatim}\end{quote} +Similarly for \pgm{x400out84}. + +\item Check the PP logs. The failure/success will be recorded there. + +\item The following failure reasons may be given: + +\begin{itemize} +\item ``Validation failure'': The remote site has either got +an erroneous PP entry in their tables, or they haven't recorded +your entry at all. + +\item ``Unacceptable dialogue mode'': Either the remote site does not +support monologue or the RTS ASN.1 encoding is bust. + +\item ``Connect request refused on this network connection'': + remote site is either down or its network listener is not running. + +\item ``Busy'': remote site is busy, try again later. + +\item ``Protocol Error'': protocol problems. + +\item ``Remote system problem'': remote site's process has terminated +abruptly. + +\item ``Timer expired'': remote system's process is looping. +\end{itemize} + +\item If the ``ping'' was successful, then +try transmitting a proper message, using the `mail' +program. If during transmission a protocol error is received then this +needs to be resolved. +To analyse this problem, it may be necessary to obtain the required +X.400 information by turning up the rts, session, +and transport logging in the PP \file{tailor} file. This can be done +by adding the following 3 entries: + +\begin{description} +\item isodelog rtsaplevel file=rts level=pdus +\item isodelog ssaplevel file=session level=pdus +\item isodelog tsaplevel file=transport level=pdus +\end{description} +\end{itemize} + +\subsection{A Common X.400 Incoming Connection Problem} + +Sometimes a remote site attempts to do an RTS recovery, due to some +transmission failure. PP at the moment, does not support recovery, and +so a ``cannotRecover'' reason is given. This sometimes does not +terminate the connection due to a bug in the remote site's software, +and so it keeps on trying, which leads to much network activity. + +The X.400 Incoming logs will look something like: + +\begin{quote}\small\begin{verbatim} + 2/ 8 8:30:31 x400in 01392 (#52 ) + Starting x400in (via X400(84) inbound) + 2/ 8 8:30:33 x400in 01392 (#52 ) + RtBInit, [Congestion at RtSAP] + rejecting attempted recovery +\end{verbatim}\end{quote} + + +To get the network address of the remote site attempting the recovery, +look at the ISODE tsapd.log, and then match the network address +against the X.400 inbound table keys. + diff --git a/doc/manual/volume1/x400out-examp.tex b/doc/manual/volume1/x400out-examp.tex new file mode 100644 index 0000000..02a0816 --- /dev/null +++ b/doc/manual/volume1/x400out-examp.tex @@ -0,0 +1,12 @@ +{\small +\begin{verbatim} +default:lmta="us",lpass=" ", +germany-nixdorf:rmta="nme",rpsap='Int-X25(80)=26245300042203' +france-derieux:rmta="persona",rpsap='Int-X25(80)=208075200131' +france-reunir:rmta="sunir.reunir.fr", + rpsap='Int-X25(80)=20803500034996' +pp-nottingham:rmta="pp.cs.nott.ac.uk", + rpsap='"591"/Janet=000021000018+PID+03010100' +vs2.cs.ucl.ac.uk:rmta="vs2.cs.ucl.ac.uk", + rpsap='"591"/Internet=vs2.cs.ucl.ac.uk' +\end{verbatim} } diff --git a/doc/manual/volume1/x400tables.aux b/doc/manual/volume1/x400tables.aux new file mode 100644 index 0000000..4376635 --- /dev/null +++ b/doc/manual/volume1/x400tables.aux @@ -0,0 +1,24 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {D}Obtaining X.400 Tables}{147}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\newlabel{app:tables}{{D}{147}} +\global\@namedef{cp@x400tables}{ +\setcounter{page}{149} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{4} +\setcounter{section}{0} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume1/x400tables.tex b/doc/manual/volume1/x400tables.tex new file mode 100644 index 0000000..a69c5b4 --- /dev/null +++ b/doc/manual/volume1/x400tables.tex @@ -0,0 +1,88 @@ +\chapter{Obtaining X.400 Tables}\label{app:tables} + +The following tables are necessary for correct X.400 operation. These +tables should be obtained from UCL. The tables are: +\begin{describe} +\item[\verb|or|:] The O/R Table. +\item[\verb|rfc2or|:] The RFC~822 to O/R mapping table +\item[\verb|or2rfc|:] The O/R to RFC~822 mapping table. +\item[\verb|rfc1148gate|:] The RFC~1148 known gateways file. +\end{describe} + +These tables can be fetched in a number of ways. + +\begin{describe} +\item[FTP:] If you have access to Internet FTP then use anonymous FTP +to cs.ucl.ac.uk [128.16.5.31] to retrieve the files from the directory +\file{pp-tables/}. For example: + +\begin{quote}\small\begin{verbatim} +% ftp cs.ucl.ac.uk +Connected to bells.cs.ucl.ac.uk. +220 bells.cs.ucl.ac.uk FTP server (SunOS 4.0) ready. +Name (cs.ucl.ac.uk:pp): anonymous +331 Guest login ok, send ident as password. +Password: +230 Guest login ok, access restrictions apply. +ftp> get pp-tables/or or +... +ftp> get pp-tables/or2rfc or2rfc +... +ftp> close +% +\end{verbatim}\end{quote} + +\item[FTAM:] If you have access to FTAM on Janet, PSS or the Internet, +you may obtain the tables from UCL using one of the following: +\begin{itemize} +\item Janet DTE 00000511160013 with TSEL 259 (ascii-encoded) +\item PSS DTE 23421920030013 with TSEL 259 (ascii-encoded) +\item Internet address cs.ucl.ac.uk ([128.16.5.31]) port 102 with TSEL +259 (ascii-encoded) +\end{itemize} +Use the ``anon'' user-identity and retrieve the files in the +\file{pp-tables/} directory. For example: +\begin{quote}\small\begin{verbatim} +% ftam ucl +user (ucl:pp): anon +ucl... connected +ANONymous user permitted, access restrictions apply +ucl> get pp-tables/or /tmp/or +ftam: unstructured text file transfer +ftam: 5792 bytes received in 5.88 seconds (0.96 Kbytes/s) +... +ucl> close +% +\end{verbatim}\end{quote} + +\item[NIFTP:] If you run NIFTP over the public X.25 or over Janet, and +are registered in the NRS at salford, you can use NIFTP with username +``guest'' and your name as password, to access UK.AC.UCL.CS to +retrieve the files found under \verb||. For example: +\begin{quote}\small\begin{verbatim} +% cpf 'or'@uk.ac.ucl.cs or +% +\end{verbatim}\end{quote} + +\item[MAIL:] The files may be obtained by mail by sending a suitable +query to the address \verb|info-server@cs.ucl.ac.uk|. This query +should consist of a message body with the lines: +\begin{quote}\small\begin{verbatim} +Request: pp-tables +Topic: or +Topic: rfc2or +Topic: or2rfc +Topic: rfc1148gate +\end{verbatim}\end{quote} +E.g.: +\begin{quote}\small\begin{verbatim} +% mail info-sver@cs.ucl.ac.uk < $@; \ + then exit 0; else rm $@; exit 1; fi' + +.c.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.h.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if $(TGRIND) -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.ry.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.bnf.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lbnf $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.make.tex:; sh -c 'if $(TGRIND) -f -lsrc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if $(WEAVE) $<; then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; $(DVIIMP) $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if $(DVI2PS) $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +######################################################################### +# End of extension rules +######################################################################### + +INPUTS = \ + bcustom.bib grindefs networking.bib sfwmac.sty \ + captcont.sty grindefs.sty pp.bib tgrind.sty \ + dist-params.tex lcustom.tex sfwdoc.bib trademark.tex \ + a4.sty + +############################################################# +# Here it is... +############################################################# + +all: volume2.dvi + +inst-all:; + +install: inst-all clean + +lint:; + +clean:; rm -f volume2.imp volume2.ps volume2.dvi volume2.log \ + volume2.blg _* \#* $(INPUTS) + +grind: volume2.dvi + true + $(DVISP) $(DFLAGS) volume2 + +imp: volume2.imp + +ps: volume2.ps + +true:; + + +############################################################# +# volume2 +############################################################# + +# customization files, et. al., not included below +volume2.dvi: volume2.vrsn + +volume2.vrsn: volume2.tex \ + $(INPUTS) \ + preface.tex \ + general.tex \ + tablelog.tex \ + submission.tex \ + adrstruct.tex qstruct.tex prmstruct.tex rpbstruct.tex \ + tablerpcodes.tex io.tex tablecrit.tex \ + tableexplicit.tex rchan.tex eit.tex \ + channels.tex \ + qmgrif.tex tablediag.tex tablereason.tex \ + outbound.tex delv-rep.tex \ + delivery.tex volume2.ind \ + version.sh + @version.sh volume2 + +$(INPUTS): + ln -s ../texinputs/$@ . + +############################################################# +# miscellany +############################################################# + +biblio:; bibtex volume2 + +preview: volume2.dvi \ + true + xdvi volume2.dvi + +index:; idx2ind -l volume2 diff --git a/doc/manual/volume2/adrstruct.h b/doc/manual/volume2/adrstruct.h new file mode 100644 index 0000000..ca24de9 --- /dev/null +++ b/doc/manual/volume2/adrstruct.h @@ -0,0 +1,126 @@ +typedef struct ad_redirection { + struct ad_redirection *rd_next; + char *rd_addr; /* O/R Name */ + char *rd_dn; /* Distinguished Name */ + UTC rd_time; + int rd_reason; +} Redirection; + +typedef struct adr_struct { + int ad_no; /* recipient number */ + /* PP's key to this adr */ + + /* Next 3 parms may be modfiied */ + /* in Q. Fixed text encoding */ + int ad_status; /* recipient status */ + int ad_rcnt; /* reformatters done count */ + + /* -- MTS Service Parms */ + + char *ad_value; /* address-original */ + char *ad_dn; /* Directory Distinguished Name */ + /* QUIPU string encoding */ + + int ad_usrreq; /* user-report-request bit */ + int ad_explicitconversion; /* explicit conversion */ + int ad_type; /* address-type */ + + char *ad_orig_req_alt; /* originator requested alternate */ + /* recipient - std encoded */ + char ad_orig_req_alt_crit; + +#define AD_RDM_MAX 4 + int ad_req_del[AD_RDM_MAX]; /* requested delivery method */ + char ad_req_del_crit; + + char ad_phys_forward; /* boolean - is physical */ + /* forwarding allowed */ + char ad_phys_forward_crit; + + char ad_phys_fw_ad_req; + char ad_phys_fw_ad_crit; + /* boolean - request for phys */ + /* foward address */ + + int ad_phys_modes; + char ad_phys_modes_crit; + + int ad_reg_mail_type; + char ad_reg_mail_type_crit; + char *ad_recip_number_for_advice; + char ad_recip_number_for_advice_crit; + + OID ad_phys_rendition_attribs; + char ad_phys_rendition_attribs_crit; + + int ad_pd_report_request; + char ad_pd_report_request_crit; + Redirection *ad_redirection_history; + char ad_redirection_history_crit; + + struct qbuf *ad_message_token; + char ad_message_token_crit; + + struct qbuf *ad_content_integrity; + char ad_content_integrity_crit; + + int ad_proof_delivery; + char ad_proof_delivery_crit; + /* boolean. Is proof of delivery */ + /* requested */ + + /* -- MTA Service Params (calculated for MTS AS) */ + + int ad_extension; /* extension-id */ + int ad_resp; /* responsibility bit */ + int ad_mtarreq; /* mta-report-request bit */ + int ad_subtype; /* address-subtype */ + + + X400_Extension *ad_per_recip_ext_list; + /* bucket for new and private */ + /* odds and sods */ + + /* -- parameters calculated by PP -- */ + /* -- Note: the outbound mta is held in ad_outchan -- */ + + char *ad_r400adr; /* x400-addr */ + char *ad_r822adr; /* rfc-addr */ + + /* -- should only be set for inbound x400 channels -- */ + char *ad_r400orig; /* original form of x400 address */ + + /* -- next two should only be set for -- */ + /* -- unroutable originator addresses -- */ + char *ad_r400DR; /* x400 address for DRs */ + char *ad_r822DR; /* 822 address for DRs */ + + char *ad_content; /* outgoing content type */ + + LIST_RCHAN *ad_fmtchan; /* reformatting channels */ + LIST_RCHAN *ad_outchan; /* outbound channel structure */ + LIST_BPT *ad_eit; /* outgoing eit's */ + + + /* -- from here onwards extra PP specific info -- */ + /* -- Diagnostics for any address parsing failures -- */ + + int ad_parse_stat; /* address parsing err status */ + char *ad_parse_message; /* address parsing err message */ + int ad_reason; /* DR reason failure */ + int ad_diagnostic; /* DR diagnostic code */ + char *ad_add_info; /* DR supplementary info */ + + Aparse *aparse; /* parsing bucket */ + + /* -- Address Control File offsets for fixed length variables -- */ + + off_t ad_no_offset; /* offset param for recip number */ + off_t ad_stat_offset; /* offset param for recip status */ + off_t ad_rcnt_offset; /* offset param for reformat next */ + + + struct adr_struct *ad_next; +} ADDR; + +#define NULLADDR ((ADDR *)0) diff --git a/doc/manual/volume2/adrstruct.tex b/doc/manual/volume2/adrstruct.tex new file mode 100644 index 0000000..55d87db --- /dev/null +++ b/doc/manual/volume2/adrstruct.tex @@ -0,0 +1,127 @@ +\File{adrstruct.h},{10:25},{Nov 20 1991} +\L{\LB{typedef struct ad\_redirection \{}} +\L{\LB{}\Tab{8}{struct ad\_redirection *rd\_next;}} +\L{\LB{}\Tab{8}{char}\Tab{16}{*rd\_addr;}\Tab{32}{\C{}\/* O\/R Name *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{16}{*rd\_dn;}\Tab{32}{\C{}\/* Distinguished Name *\/\CE{}}} +\L{\LB{}\Tab{8}{UTC}\Tab{16}{rd\_time;}} +\L{\LB{}\Tab{8}{int}\Tab{16}{rd\_reason;}} +\L{\LB{\} Redirection;}} +\L{\LB{}} +\L{\LB{typedef struct}\Tab{16}{adr\_struct \{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_no;}\Tab{40}{\C{}\/* recipient number *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* PP\'s key to this adr *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{40}{\C{}\/* Next 3 parms may be modfiied *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* in Q. Fixed text encoding *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_status;}\Tab{40}{\C{}\/* recipient status *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_rcnt;}\Tab{40}{\C{}\/* reformatters done count *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- MTS Service Parms *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_value;}\Tab{40}{\C{}\/* address\-original *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_dn;}\Tab{40}{\C{}\/* Directory Distinguished Name *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* QUIPU string encoding *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_usrreq;}\Tab{40}{\C{}\/* user\-report\-request bit *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_explicitconversion;}\Tab{48}{\C{}\/* explicit conversion *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_type;}\Tab{40}{\C{}\/* address\-type *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_orig\_req\_alt; \C{}\/* originator requested alternate *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* recipient \- std encoded *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_orig\_req\_alt\_crit;}} +\L{\LB{}} +\L{\LB{\#define AD\_RDM\_MAX}\Tab{24}{4}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_req\_del[AD\_RDM\_MAX];}\Tab{48}{\C{}\/* requested delivery method *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_req\_del\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_forward; \C{}\/* boolean \- is physical }\Tab{72}{*\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* forwarding allowed *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_forward\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_fw\_ad\_req;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_fw\_ad\_crit;}} +\L{\LB{}\Tab{40}{\C{}\/* boolean \- request for phys *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* foward address *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_phys\_modes;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_modes\_crit;}} +\L{\LB{}\Tab{40}{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_reg\_mail\_type;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_reg\_mail\_type\_crit;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_recip\_number\_for\_advice;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_recip\_number\_for\_advice\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{OID}\Tab{24}{ad\_phys\_rendition\_attribs;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_phys\_rendition\_attribs\_crit;}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_pd\_report\_request;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_pd\_report\_request\_crit;}} +\L{\LB{}\Tab{8}{Redirection}\Tab{24}{*ad\_redirection\_history;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_redirection\_history\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*ad\_message\_token;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_message\_token\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*ad\_content\_integrity;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_content\_integrity\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int }\Tab{24}{ad\_proof\_delivery;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{ad\_proof\_delivery\_crit;}} +\L{\LB{}\Tab{32}{\C{}\/* boolean. Is proof of delivery *\/\CE{}}} +\L{\LB{}\Tab{32}{\C{}\/* requested *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- MTA Service Params (calculated for MTS AS) *\/\CE{}}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_extension;}\Tab{40}{\C{}\/* extension\-id *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_resp;}\Tab{40}{\C{}\/* responsibility bit *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_mtarreq;}\Tab{40}{\C{}\/* mta\-report\-request bit *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_subtype;}\Tab{40}{\C{}\/* address\-subtype *\/\CE{}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{}\Tab{8}{X400\_Extension}\Tab{24}{*ad\_per\_recip\_ext\_list;}} +\L{\LB{}\Tab{40}{\C{}\/* bucket for new and private *\/\CE{}}} +\L{\LB{}\Tab{40}{\C{}\/* odds and sods *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- parameters calculated by PP \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- Note: the outbound mta is held in ad\_outchan \-\- *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_r400adr;}\Tab{40}{\C{}\/* x400\-addr *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_r822adr;}\Tab{40}{\C{}\/* rfc\-addr *\/\CE{}}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- should only be set for inbound x400 channels \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_r400orig;}\Tab{40}{\C{}\/* original form of x400 address *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- next two should only be set for \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- unroutable originator addresses \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_r400DR;}\Tab{40}{\C{}\/* x400 address for DRs *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_r822DR;}\Tab{40}{\C{}\/* 822 address for DRs *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_content;}\Tab{40}{\C{}\/* outgoing content type *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{LIST\_RCHAN}\Tab{24}{*ad\_fmtchan;}\Tab{40}{\C{}\/* reformatting channels *\/\CE{}}} +\L{\LB{}\Tab{8}{LIST\_RCHAN}\Tab{24}{*ad\_outchan;}\Tab{40}{\C{}\/* outbound channel structure *\/\CE{}}} +\L{\LB{}\Tab{8}{LIST\_BPT}\Tab{24}{*ad\_eit;}\Tab{40}{\C{}\/* outgoing eit\'s *\/\CE{}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- from here onwards extra PP specific info \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- Diagnostics for any address parsing failures \-\- *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_parse\_stat;}\Tab{40}{\C{}\/* address parsing err status *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_parse\_message; \C{}\/* address parsing err message *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_reason;}\Tab{40}{\C{}\/* DR reason failure *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{ad\_diagnostic;}\Tab{40}{\C{}\/* DR diagnostic code *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ad\_add\_info;}\Tab{40}{\C{}\/* DR supplementary info *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{Aparse}\Tab{24}{*aparse;}\Tab{40}{\C{}\/* parsing bucket *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- Address Control File offsets for fixed length variables \-\- *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{off\_t}\Tab{24}{ad\_no\_offset;}\Tab{40}{\C{}\/* offset param for recip number *\/\CE{}}} +\L{\LB{}\Tab{8}{off\_t}\Tab{24}{ad\_stat\_offset; \C{}\/* offset param for recip status *\/\CE{}}} +\L{\LB{}\Tab{8}{off\_t}\Tab{24}{ad\_rcnt\_offset; \C{}\/* offset param for reformat next *\/\CE{}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct adr\_struct *ad\_next;}} +\L{\LB{\} ADDR;}} +\L{\LB{}} +\L{\LB{\#define NULLADDR ((ADDR *)0)}} diff --git a/doc/manual/volume2/channels.aux b/doc/manual/volume2/channels.aux new file mode 100644 index 0000000..8c8e12e --- /dev/null +++ b/doc/manual/volume2/channels.aux @@ -0,0 +1,51 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {3}Channels}{31}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.1}Overview}{31}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.2}The Queue Interface}{31}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.1}Major Structures}{31}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.1}{\ignorespaces Channel / Queue Manager Interface Structures}}{32}} +\newlabel{struct:qmgrif}{{3.1}{32}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.2}Basic Access}{33}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Queue Manager Interaction}{33}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Address File Routines}{36}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Message files}{37}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.3}Delivery Notifications}{38}} +\newlabel{set:dr}{{3.2.3}{38}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {3.1}{\ignorespaces Reason Codes}}{39}} +\newlabel{tab:reason}{{3.1}{39}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.4}Successful Delivery}{39}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.5}Verification and Trust}{40}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.3}Example Usage}{41}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.1}Outbound Channels}{41}} +\newlabel{example:outbound}{{3.2}{41}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.2}{\ignorespaces Example Outbound Channel}}{43}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.2}Address Parsing}{43}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.3}Local Pickup}{44}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.4}TWA Channel}{44}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3.5}Delivery Reports}{45}} +\newlabel{examp:dr}{{3.3}{45}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {3.3}{\ignorespaces Example Delivery Report Generation}}{45}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.4}Formatters and Converters}{45}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.4.1}Simple Converters}{45}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.4.2}Complex Filters}{45}} +\global\@namedef{cp@channels}{ +\setcounter{page}{47} +\setcounter{equation}{0} +\setcounter{enumi}{4} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{1} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{4} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{3} +\setcounter{table}{1} +} diff --git a/doc/manual/volume2/channels.tex b/doc/manual/volume2/channels.tex new file mode 100644 index 0000000..96985ca --- /dev/null +++ b/doc/manual/volume2/channels.tex @@ -0,0 +1,732 @@ +% -*- LaTeX -*- +\chapter {Channels} + +\section {Overview} + +This chapter describes the interface which provides the message +delivery aspects of the message transfer abstract service and MTA +abstract service. The major component of this is a set of routines +for accessing the PP queue. As these routines are usually used in the +context of a channel process, their usage is illustrated in various +types of channel. There are also additional functions to facilitate +reformatting/conversion. + +The following types of channel are supported: + +\begin{itemize} +\item Protocol outbound channel (MTA AS delivery). + +\item Local delivery channel (MT AS delivery). + +\item Local pickup channel (MT AS delivery). + +\item Remote TWA channel (MTA AS delivery). + +\item Reformatters. +\end{itemize} + +\section {The Queue Interface} + +\subsection {Major Structures} + +The major structures in use for reading the queue are the following:- +\begin{itemize} +\item The parameter structure described in Figure~\ref{prm:struct} on +page~\pageref{prm:struct}. + +\item The queue structure described in Figure~\ref{q:struct} on +page~\pageref{q:struct}. + +\item The address structure described in Figure~\ref{adr:struct} on +page~\pageref{adr:struct}. + +\end{itemize} + +There is also a separate set of routines and structures for +interacting with the queue manager. This interface makes use of the +structures defined in +Figure~\ref{struct:qmgrif}.\index{type\_Qmgr\_DeliveryStatus} +\index{type\_Qmgr\_Channel}\index{type\_Qmgr\_ProcMsg}\index{type\_Qmgr\_QID} +\index{type\_Qmgr\_RecipientId} +\tagrind[hbtp]{qmgrif}{Channel / Queue Manager Interface Structures} +{struct:qmgrif} + +These structures are derived from the queue manager ROS specification +given in Appendix~F of Volume~1. + +\subsection {Basic Access} + +The basic access provided to the queue is through a set of library +calls. There are several classes of routines which can be divided up +into queue manager interaction, address file processing routines and +message body routines. Most of the operations described here are only +useful for outbound channels. + +\subsubsection{Queue Manager Interaction} + +The queue manager interaction is normally handled by a single +procedure, +\linebreak +\verb|channel_control|, which manages the session with the +QMGR and calls the appropriate routines on receipt of ROS operations. + +\begin{quote}\index{channel\_control}\begin{verbatim} +int channel_control (argc, argv, initfnx, + procfnx, endfnx) +int argc; +char **argv; +IFP initfnx; +struct type_Qmgr_DeliveryStatus *(*procfnx)(); +IFP endfnx; +\end{verbatim}\end{quote} + +The arguments are as follows: +\begin{describe} +\item[\verb|argc|/\verb|argv|:] The argument count and vector, normally +copied from the \verb|main| procedure. These are used to recapture the +state of the association as outbound channels are normally run under +the \man pptsapd (8) daemon. + +\item[\verb|initfnx|:] An initialisation function. This is called to +initialise the channel and inform it of its name. + +\item[\verb|procfnx|:] A function called for each QMGR process +message operation. + +\item[\verb|endfnx|:] A function called when the session with the QMGR +is terminated. The constant \verb|NULLIFP| may be used if this function +is not required. +\end{describe} +The \verb|channel_control| function invokes its own error handlers +and does not normally return. + + +The two functions \verb|initfnx| and \verb|procfnx| shown above are the key to the channels +operation. The initialisation function should be defined in the +following way: +\begin{quote}\begin{verbatim} +int initfnx (arg) +struct type_Qmgr_Channel *arg; +\end{verbatim}\end{quote} + +The function should then decide whether the given channel argument is +sensible for this channel and return one of the constants \verb|OK| or +\verb|NOTOK|. This function is normally only called once by the QMGR, +but in cases where the same program can run as a number of channels it +may be called subsequently to reinitialise the channel to a different +mode of operation. + +The process function is the one that does the real work of the +channel. It should be defined like this: +\begin{quote}\begin{verbatim} +struct type_Qmgr_DeliveryStatus *processmessage (arg) +struct type_Qmgr_ProcMsg *arg; +\end{verbatim}\end{quote} +The function should then attempt to process the given message for the +given recipients. This usually involves first reading the address +control file given as part of the structure passed. + +When the processing of the message has finished, the function should +return a pointer to a list of recipient numbers together with a status +field. This structure is the \verb|type_Qmgr_DeliveryStatus| +structure. This specifies for each recipient whether the operation was +a success or failure. The status values are: +\begin{describe} +\item[\verb|int\_Qmgr\_status\_success|:]\index{status\_success} +The operation was successful, the next processing stage can be +considered. + +\item[\verb|int\_Qmgr\_status\_negativeDR|:]\index{status\_negativeDR} +The message has failed, and a delivery report {\em must} be written. + +\item[\verb|int\_Qmgr\_status\_positiveDR|:] +\index{status\_positiveDR} +The message has succeeded, and a confirmation is required. This {\em +must} be written out. + +\item[\verb|int\_Qmgr\_status\_successSharedDR|:] +\index{status\_successSharedDR} +The message has suceeded and a delivery report is to be sent. However, +the delivery report will be sent as the result of processing another +recipient. + +\item[\verb|int\_Qmgr\_status\_failureSharedDR|:] +\index{status\_failureSharedDR} +The message has failed, and a delivery report should be sent for +this recipient, but this will be sent as the result of another +recipients actions. + +\item[\verb|int\_Qmgr\_status\_messageFailure|:] +\index{status\_messageFailure} +The message has temporarily failed; other messages on the same channel +may succeed and this message may succeed later at a second attempt. + +\item[\verb|int\_Qmgr\_status\_mtaFailure|:] +\index{status\_mtaFailure} +The remote MTA is not responding: the attempt should be retried at a +later time. Further messages on this channel to this MTA should not be +considered at this attempt. + +\item[\verb|int\_Qmgr\_status\_mtaAndMessageFailure|:] +\index{status\_mtaAndMessageFailure} +This is an indication that there was a failure whilst transferring the +message to the MTA. This channel should be attempted again in the near +future. +\end{describe} + +To aid in setting these values, a set of support routines is provided +in the library. These routines all update the global variable +\verb|deliverystate| which is suitable as a return value for the +process function. Note, however, that the value of +\verb|int_Qmgr_status_permanentFailure| is ``sticky''; this value may +be set, but once set cannot be overwritten by these routines. This is +because normally when an address is marked with this status, a +delivery report is written out and the message is updated accordingly +(see Section~\ref{set:dr} for routines to write out delivery reports). +To set the status then to something else would confuse the queue +manager. The routines are as follows: + +\begin{quote}\index{delivery\_init}\begin{verbatim} +struct type_Qmgr_DeliveryStatus *delivery_init (users) +struct type_Qmgr_UserList *users; +\end{verbatim}\end{quote} + +This routine initialises the structure. It does by allocating an +element for each of the users passed in the argument. The single +parameter is the list of users passed over by the QMGR. + +\begin{quote}\index{delivery\_set}\begin{verbatim} +struct type_Qmgr_DeliveryStatus + *delivery_setstate (rno, val, reason) +int rno, val; +char *reason; +\end{verbatim}\end{quote} + +This routine sets the value of the given recipient number to the +indicated value in the global structure (with the above proviso). It +also includes a string indicating the reason for failure, if failure +occurred. This string is passed back to the QMGR for display by +the MTAconsole. It should be set to the constant \verb|NULLCP| +if the recipient was handled successfully or no diagnostic reason is available. + +\begin{quote}\index{delivery\_setall}\begin{verbatim} +struct type_Qmgr_DeliveryStatus + *delivery_setallstate (val, reason) +int val; +char *reason; +\end{verbatim}\end{quote} + +This routine sets all users' status to the given value. This is useful +when a connection cannot be established, for instance, and all recipients +must be put in the same state (again, the above proviso about delivery +reports holds). The reason field is the same as above. + +Occasionally it may occur that a permanent failure is received but it +is not possible to write a delivery report (e.g., a full disk). In this +case the address file should not be updated and the DR status should +be set to message failure (the next retry should also give a DR and +then hopefully a report can be written). To aid in resetting these +variables the following procedure is useful. + +\begin{quote}\index{delivery\_resetDRs}\begin{verbatim} +struct type_Qmgr_DeliveryStatus + *delivery_resetDRs (val) +int val; +\end{verbatim}\end{quote} + +The argument is the state to set the DR values to (nearly always +\linebreak +\verb|int_Qmgr_Status_messageFailure|). + + +The termination function, if used, should be defined as follows. +\begin{quote}\begin{verbatim} +int endfuction () +\end{verbatim}\end{quote} + +This routine is used to close down anything required before exiting +the program. The calling routine will execute this function before sending +the final disconnect to the QMGR and exiting. + + +\subsubsection{Address File Routines} + +The address file reading is usually the first operation a channel does +on receiving the instruction to process a message. This is usually +achieved by first building up the name of the message file to be read +in from the queue id, and then invoking the procedure \verb|rd_msg|. +\begin{quote}\index{rd\_msg}\begin{verbatim} +int rd_msg (msg, prm, qp, ad_sndr, ad_recip, ad_count) +char *msg; +struct prm *prm; +Q_struct *qp; +ADDR **ad_sndr, + **ad_recip; +int *ad_count; +\end{verbatim}\end{quote} +The parameters are: +\begin{describe} +\item[\verb|msg|:] The address control file. + +\item[\verb|prm|:] The message parameters. + +\item[\verb|qp|:] The message queue structure. + +\item[\verb|ad\_sndr|:] the originator of the message. + +\item[\verb|ad\_recip|:] The list of recipients of the message. + +\item[\verb|ad\_count|:] A count of the number of recipient addresses. +\end{describe} + +The routine returns a status to indicate success or failure. As part +of its operation it locks the address file to prevent simultaneous +access by other channels. + +When the message has been processed, the lock {\em must} be released +by calling the function \verb|rd_end|. +\begin{quote}\index{rd\_end}\begin{verbatim} +int rd_end (); +\end{verbatim}\end{quote} + +If the messages status changes in some manner, the address file must +be updated. This is achieved by one of the following functions. +\begin{quote}\index{wr\_ad\_status}\index{wr\_ad\_rcntno}\begin{verbatim} +int wr_ad_status (ap, type} +ADDR *ap; +int type; + +int wr_ad_rcntno (ap, rcnt) +ADDR *ap; +int rcnt; +\end{verbatim}\end{quote} + +The \verb|wr_ad_status| routine is used to update the status of the address. +This can take one of the following values. +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_STAT\_PEND& The address is pending\\ + \tt AD\_STAT\_DONE& The address has been finished with\\ +\hline +\end{tabular}\] + + +The \verb|wr_ad_rcntno| is used to update the reformatter count variable. + +\subsubsection{Message files} + +There are a number of routines to allow a channel to iterate through +the set of message files to deliver. First in this set is a function +to allow location of the relevant directory. This function maps a +given queue id as given by the QMGR into a directory basename with the +message files in relating to a given address. It is +used as follows: +\begin{quote}\index{qid2dir}\begin{verbatim} +int qid2dir (qid, ap, exists, cpp) +char *qid; +ADDR *ap; +int exists; +char **cpp; +\end{verbatim}\end{quote} +The arguments to this are +\begin{describe} +\item[\verb|qid|:] A character string containing the queue identifier. + +\item[\verb|ap|:] The address that is being processed. + +\item[\verb|exists|:] A flag, this should be \verb|TRUE| if the directory +should exist, and \verb|FALSE| if it doesn't matter. + +\item[\verb|cpp|:] A character pointer that is assigned the +resulting directory name. +\end{describe} + +The function will return \verb|OK| on successful completion and +\verb|NOTOK| on failure. + +The next operation is typically to visit each of the message files in +turn. This is handled by the following routines. + +\begin{quote}\index{msg\_rinit}\begin{verbatim} +int msg_rinit (dir) +char *dir; +\end{verbatim}\end{quote} + +The argument here is: +\begin{describe} +\item[\verb|dir|:] The directory base of the message (usually +obtained from a call to \verb|qid2dir|). +\end{describe} + +This function returns the usual \verb|OK|/\verb|NOTOK| status. + +Following this, the function \verb|msg_rfile| is called repeatedly +until it returns \verb|RP_DONE| to obtain each of the files composing +the message. +\begin{quote}\index{msg\_rfile}\begin{verbatim} +int msg_rfile (buf) +char *buf; +\end{verbatim}\end{quote} +The argument is: +\begin{describe} +\item[\verb|buf|:] A pointer to a character buffer (of size +\verb|FILNSIZE|) which is filled in with the file name if the call succeeds.. +\end{describe} + +Finally, when all files have been processed, or if the operation is to +be aborted, the function \verb|msg_rend| is called: +\begin{quote}\index{msg\_rend}\begin{verbatim} +int msg_rend () +\end{verbatim}\end{quote} + +\subsection {Delivery Notifications}\label{set:dr} + +Delivery reports should be written out by a channel when it is clear +that the message cannot be delivered or if the message has been +delivered and confirmation is requested. The routine +\verb|set_1dr| is then used to set the appropriate status in the +address structure: + +\begin{quote}\index{set\_1dr}\begin{verbatim} +int set_1dr (qp, ad_no, msg, reason, diag, str) +Q_struct *qp; +int ad_no; +char *msg; +int reason; +int diag; +char *str; +\end{verbatim}\end{quote} + +The arguments to this function are as follows: +\begin{describe} +\item[\verb|qp|:] A pointer to a queue structure representing +the message. The queue structure should have the address components +filled in (this is normally the case). + +\item[\verb|ad\_no|:] The address number that this report is for. + +\item[\verb|msg|:] The queue name of the message being processed. + +\item[\verb|reason|:] A reason code for the message failure. This +should be chosen from one of those in Table~\ref{tab:reason} on +page~\pageref{tab:reason}. + +\item[\verb|diag|:] A diagnostic code for the message failure. +This is supplementary information to the reason code. It should be one +of those values given in the file \file{dr.h}. There are a large +number of these available. + +\item[\verb|str|:] A character string which records the reason +for the failure. This should be something that describes the failure. +This field should always be filled in with something appropriate. + +\end{describe} + +\tagtable{reason}{Reason Codes}{tab:reason} + +When calling this function the routine should return to the QMGR one +of the following variables: +\[\begin{tabular}{|l | p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Qmgr code} & + \multicolumn{1}{|c|}{\bf When Applicable} \\ +\hline + \tt positiveDR & For the first recipeint with a + positive delivery report \\ + \tt successSharedDR& For subsequent recipients with + positive delivery reports\\ + \tt negativeDR & For the first recipient with a + negative delivery report \\ + \tt failureSharedDR& For subsequent recipients with + negative delivery reports \\ +\hline +\end{tabular}\] + +Once the recipients have been marked with \verb|set_1dr|, the last +step necessary is to write out the actual delivery report by calling +\verb|wr_q2dr|. This is defined as follows: + +\begin{quote}\index{wr\_q2dr}\begin{verbatim} +int wr_q2dr (qp, msgid) +Q_struct *qp; +char *msgid; +\end{verbatim}\end{quote} + +The arguments to this function are: +\begin{describe} +\item[\verb|qp|:] A pointer to the queue structure representing +the message with the address components filled in. + +\item[\verb|msgid|:] The queue id for this message. +\end{describe} + +This function will then write out the reports and update the queue +entries with their new status. + +\subsection{Successful Delivery} + +A successful delivery is recorded in the stat log. This is done +by the routine \verb|wr_q2dr| if a positive delivery report is +required. Alterntively, if no report is required, the delivery is +noted with the function \verb|wr_stat| which is called as follows. + +\begin{quote}\index{wr\_stat}\begin{verbatim} +int wr_stat (ap, qp, msg, size) +ADDR *ap; +Q_struct *qp; +char *msg; +int size; +\end{verbatim}\end{quote} +The parameters to this are: +\begin{itemize} +\item[\verb|ap|:] The address that has been successfully delivered. +\item[\verb|qp|:] The queue structure for this message. +\item[\verb|msg|:] The queue name for this message. +\item[\verb|size|:] The size in bytes of the message delivered. This +may be different from the size in the queue file. +\end{itemize} + +When a message has been delivered successfully, it is necessary to +check several things. These are: +\begin{enumerate} +\item If a positive delivery report was requested, one should be +composed with \verb|set_1dr| and \verb|wr_q2dr|. +\item Otherwise, the status should be updated to \verb|AD_DONE| +with a call to +\linebreak +\verb|wr_ad_status|. +\item The QMGR return status should be updated to either +\linebreak +\verb|int_Qmgr_Status_success| or \verb|int_Qmgr_Status_positiveDR|. +\item If \verb|wr_q2dr| is not necessary (there was no request for +positive delivery reports). A call should be made to \verb|wr_stat| to +indicate in the statistics that successful delivery has been achieved. +\end{enumerate} + +\subsection {Verification and Trust} + +Channels are trusted processes, and as such should respect this trust. +As far as possible they should check that the data they are being +given is reasonable. This includes the following: +\begin{itemize} +\item That the channel name and type is reasonable for this channel. + +\item That the address requested to be processed exists and is ready +to be processed (e.g., it has passed through all reformatters). + +\item That the type of address is correct for this type of channel +(e.g., RFC~822 for smtp or X.400 for X.400 channels). + +\item That the message is not locked by another channel. + +\item That the channel is the same as the channel given in the +address structure. +\end{itemize} + +For common outbound channels and filters these checks are encapsulated +in the functions, \verb|chan_acheck|\index{chan\_acheck}, +\verb|lchan_acheck|\index{lchan\_acheck} and +\verb|chan_dcheck|\index{chan\_dcheck}. + +These calls are similar in function; one checks the address is okay +to process for filters and outbound channels; the second is for local +channels; and the last is for channels that can handle delivery reports. +They are called in the following way: + +\begin{quote}\small\begin{verbatim} +int chan_acheck (ap, mychan, first, mta) +ADDR *ap; +CHAN *mychan; +int first, +char **mta; +\end{verbatim}\end{quote} + +The arguments are as follows: +\begin{describe} +\item[\verb|ap|:] The address to be checked. +\item[\verb|mychan|:] The channel that is doing this checking. +\item[\verb|first|:] If this is the first address to be checked. This +is used to determine if the mta parameter can be changed. +\item[\verb|mta|:] The MTA this should connect to. If the constant +\verb|NULLVP| is used, the mta parameter will not be filled in or +checked. If the mta is the address of a pointer with \verb|NULL| +contents then it will be updated if required. If the mta is a pointer +to a string, then it is checked that the mta does not change unless +the \verb|first| flag is set. This ensures for channels that batch +messages to the same host, that all addresses in this message are +destined for the same MTA. +\end{describe} +It returns either the constant \verb|OK| or \verb|NOTOK|. If +\verb|NOTOK| then the \verb|deliverystate| is updated in a suitable way. +If \verb|OK| then the address should be processed, and the +\verb|deliverystate| updated accordingly. + +The function \verb|lchan_acheck| is almost equivalent, except in place +of the \verb|mta| parameter is a user. + +\begin{quote}\small\begin{verbatim} +int lchan_acheck (ap, mychan, first, user) +ADDR *ap; +CHAN *mychan; +int first, +char **user; +\end{verbatim}\end{quote} + +The last function is similar but suitable for channels that can handle +delivery reports (such as X.400). + +\begin{quote}\small\begin{verbatim} +int dchan_acheck (ap, asp, mychan, first, mta) +ADDR *ap, *asp; +CHAN *thechan; +int first; +char **mta; +\end{verbatim}\end{quote} + +The only difference for this call is that an address structure +referencing the originator must be passed in as the second parameter. + +\section {Example Usage} + +\subsection {Outbound Channels} + +Presented here is a skeleton of an outbound channel. This structure is +not required, but is a common way of achieving the results. + +\tagrindfile{outbound}{Example Outbound Channel}{example:outbound} + +\subsection{Address Parsing} + +Occasionally it is necessary for a channel to parse or manipulate an +address. Most channels can get away without needing this however. +Some of the basic parsing routines are given here. + +The basic interface to parsing is \verb|ad_parse|. This takes an +address and attempts to parse it according to the given type and +domain ordering. It is called as: + +\begin{quote}\index{ad\_parse}\begin{verbatim} +int ad_parse (ap, rp, order) +ADDR *ap; +RP_Buf *rp; +int order; +\end{verbatim}\end{quote} + +The parameters are: +\begin{describe} +\item[\verb|ap|:] The address structure with the address to be parsed +in the \verb|ad_value| structure member. The address type should be +set in \verb|ad_type|. +\item[\verb|rp|:] A reply structure which is updated with the results +of the parsing. +\item[\verb|order|:] The expected order of the domains. This is one of +the following: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt CH\_USA\_ONLY& US order domain only\\ + \tt CH\_USA\_PREF& US order prefered \\ + \tt CH\_UK\_ONLY& UK order domains only\\ + \tt CH\_UK\_PREF& UK order prefered \\ +\hline +\end{tabular}\] +This is usually input from the channel structure. +\end{describe} + +This routine returns an \verb|RP| code which can be checked with +\verb|rp_isgood| to see if the address was parsed. If it fails, a +suitable error will be written in the \verb|RP_Buf| structure. + +When delivering to local addresses it is often necessary to reduce a +global address down to a user of the system. The routine +\verb|ad_getlocal| can be of use here. This routine takes an address +and returns just the local part of it if any, else \verb|NULLCP|. It +is called as follows: + +\begin{quote}\index{ad\_getlocal}\begin{verbatim} +char *ad_getlocal (addr, type, resp) +char *addr; +int type; +int resp; +\end{verbatim}\end{quote} + +The arguments are: +\begin{describe} +\item[\verb|addr|:] A string-encoded form of the address; either an +RFC~822 address or an RFC~1148 encoded X.400 address. + +\item[\verb|type|:] The type of address, either \verb|AD_X400_type| or +\verb|AD_822_type|. + +\item[\verb|resp|:] If the address is a recipient, this value should +be \verb|1|, else \verb|0|. +\end{describe} + +\subsection {Local Pickup} + +This style of channel has not yet been written. + +\subsection {TWA Channel} + +%Show how this can be used as ``pull only'', and as full TWA in conjunction +%with submission. Need to have both QMGR and server initiated approach. +This style of channel has not yet been written. + +\subsection {Delivery Reports} + +A typical interface to the delivery report functions is shown in +Figure~\ref{examp:dr}. + +\tagrindfile{delv-rep}{Example Delivery Report Generation}{examp:dr} + +\section {Formatters and Converters} + + +Formatters and converters can run in two ways. Generally the simple +filters work on single files, the complex filters work on several +files at once. The majority of filters should be of the simple kind. + +\subsection{Simple Converters} + +The simple converters are programs that read from the standard input, +do some formatting, and write the result to the standard output. +This type of formatter is invoked by the filtercontrol program, +\verb|fcontrol|\index{fcontrol}. + +These simple filters should return a suitable exit status to confirm +that the conversion completed successfully. They follow the standard +\unix/ tradition of returning \verb|0| on success and anything else on +failure. + +These filters may be anything from simple shell/awk/sed scripts to +more complex {\em C} programs. + +\subsection{Complex Filters} + +More complex formatters are necessary if the formatting needs to +convert more than one file. This is the case for formatters that change +the directory structure, or combine several files into one. These +formatters require more work, but are similar to the channel programs +in their operation. The QMGR interface is in fact identical. +The only real difference is in the \verb|qid2dir|\index{qid2dir} +routine used to locate the directory. The starting directory is found +using the normal \verb|qid2dir| routine. The destination directory is +found using the same routine, but first incrementing the formatter +count in the address structure, and then calling the routine with the +flag set to \verb|FALSE|. The formatter should however place its +output in a temporary directory which will then be renamed to the +destination directory if the transformation is successful. This allows +for failure at any point in the reformatting. + +%Usually can just do filters --- describe + +%Notes on model for restructuring + +% \subsection{Example} + +% to be written. diff --git a/doc/manual/volume2/delivery.aux b/doc/manual/volume2/delivery.aux new file mode 100644 index 0000000..1bb9548 --- /dev/null +++ b/doc/manual/volume2/delivery.aux @@ -0,0 +1,25 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {4}Delivery Formats}{52}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.1}Overview}{52}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.2}RFC-822/MMDF format}{52}} +\global\@namedef{cp@delivery}{ +\setcounter{page}{53} +\setcounter{equation}{0} +\setcounter{enumi}{7} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{4} +\setcounter{section}{2} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume2/delivery.tex b/doc/manual/volume2/delivery.tex new file mode 100644 index 0000000..9d8b4d3 --- /dev/null +++ b/doc/manual/volume2/delivery.tex @@ -0,0 +1,16 @@ +\chapter {Delivery Formats} + +\section {Overview} + +In many cases, local delivery will proceed by delivery into a mailbox of +well defined format. These are defined here. Where appropriate, standard +library routines to facilitate manipulation of these formats are also given. + +\section {RFC~822/MMDF format} + +The standard RFC~822/MMDF mailbox format is a single file with +messages in separated by delimeters. The delimeter is tailorable so +may be any string - but normally it is a sequence of four control-A's +and a newline. There are two delimeters, which may be the same string +or may be different. This format is not expected to used much once +suitable user agents have been written. diff --git a/doc/manual/volume2/delv-rep.c b/doc/manual/volume2/delv-rep.c new file mode 100644 index 0000000..822e070 --- /dev/null +++ b/doc/manual/volume2/delv-rep.c @@ -0,0 +1,14 @@ +... + { + char buffer[BUFSIZ]; + + (void) sprintf (buffer, "Address %s failed for reason %s", + ap -> ad_r822adr, rstr); + + (void) delivery_set (ap -> ad_no, + int_Qmgr_status_permanentFailure); + set_dr (qp, ap -> ad_no, msg_name, + DRR_UNABLE_TO_TRANSFER, + DRD_UNRECOGNISED_OR, buffer); + } +... diff --git a/doc/manual/volume2/delv-rep.tex b/doc/manual/volume2/delv-rep.tex new file mode 100644 index 0000000..5d902bf --- /dev/null +++ b/doc/manual/volume2/delv-rep.tex @@ -0,0 +1,15 @@ +\File{delv\-rep.c},{09:19},{Mar 17 1989} +\L{\LB{...}} +\L{\LB{ \{}} +\L{\LB{}\Tab{8}{\K{char} buffer[BUFSIZ];}} +\L{\LB{}} +\L{\LB{}\Tab{8}{(\K{void}) sprintf (buffer, \S{}\"Address \%s failed for reason \%s\"\SE{},}} +\L{\LB{}\Tab{24}{ap \-\> ad\_r822adr, rstr);}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{(\K{void}) delivery\_set (ap \-\> ad\_no,}} +\L{\LB{}\Tab{24}{ int\_Qmgr\_status\_permanentFailure);}} +\L{\LB{}\Tab{8}{set\_dr (qp, ap \-\> ad\_no, msg\_name,}} +\L{\LB{}\Tab{16}{ DRR\_UNABLE\_TO\_TRANSFER,}} +\L{\LB{}\Tab{16}{ DRD\_UNRECOGNISED\_OR, buffer);}} +\L{\LB{ \}}} +\L{\LB{...}} diff --git a/doc/manual/volume2/eit.h b/doc/manual/volume2/eit.h new file mode 100644 index 0000000..f2dc2dc --- /dev/null +++ b/doc/manual/volume2/eit.h @@ -0,0 +1,4 @@ +typedef struct list_bpt { + char *li_name; + struct list_bpt *li_next; +} LIST_BPT; diff --git a/doc/manual/volume2/eit.tex b/doc/manual/volume2/eit.tex new file mode 100644 index 0000000..3c6f24e --- /dev/null +++ b/doc/manual/volume2/eit.tex @@ -0,0 +1,5 @@ +\File{eit.h},{10:37},{Aug 24 1990} +\L{\LB{typedef struct list\_bpt \{}} +\L{\LB{}\Tab{8}{char *li\_name;}} +\L{\LB{}\Tab{8}{struct list\_bpt *li\_next;}} +\L{\LB{\} LIST\_BPT;}} diff --git a/doc/manual/volume2/general.aux b/doc/manual/volume2/general.aux new file mode 100644 index 0000000..5fa8a54 --- /dev/null +++ b/doc/manual/volume2/general.aux @@ -0,0 +1,37 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}General}{1}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.1}Overview}{1}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.2}Initialisation}{1}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.3}Runtime Tailoring}{2}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.4}Logging}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.4.1}Logging Levels}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.4.2}Logging Structures}{2}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {1.1}{\ignorespaces Logging Levels}}{3}} +\newlabel{tab:logging}{{1.1}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.4.3}Logging Macros}{3}} +\newlabel{logging}{{1.4.3}{3}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1.5}Code Location}{5}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.5.1}Library Code}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.5.2}Core Programs}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {1.5.3}Other Directories}{7}} +\global\@namedef{cp@general}{ +\setcounter{page}{8} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{1} +\setcounter{section}{5} +\setcounter{subsection}{3} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{1} +} diff --git a/doc/manual/volume2/general.tex b/doc/manual/volume2/general.tex new file mode 100644 index 0000000..134d04e --- /dev/null +++ b/doc/manual/volume2/general.tex @@ -0,0 +1,361 @@ +\chapter {General} + +\section {Overview} + +There are certain approaches taken by PP processes. These are described +here to facilitate emulation by new processes. These are not strict +guidelines, but following existing practises will usually be easier +and make upgrading the software less painful. + +\section {Initialisation} + +All PP programs generally start by calling one or more initialisation +routines. This may vary depending on what the channel needs to know. +This initialisation does various things, amongst which are: +\begin{itemize} +\item Reading global parameters from the tailor file. +\item Initialising the logging packages. +\item Handling of signals. +\end{itemize} + +The normal method of initialising a process is to call the following +routine very early on (usually one of the first things): +\begin{quote}\index{sys\_init}\begin{verbatim} +sys_init (name) +char *name; +\end{verbatim}\end{quote} + +This routine does most of the initialisation required. The argument is +usually the value of \verb|argv[0]|, which is used in the logging +initialisation to record the name of this program. + +For some programs however, this sort of initialisation is not +appropriate. In this case another interface may be better. +\begin{quote}\index{pp\_initialise}\begin{verbatim} +int pp_initialise (name, flags) +char *name; +int flags; +\end{verbatim}\end{quote} +This routine will read in the tailor file, but will optionally not +configure certain aspects depending on the flags. The name is the same +as in \verb|sys_init|. The flags can be any of the following: +\[\begin{tabular}{|l|p{.6\textwidth}} +\hline + \multicolumn{1}{|c|}{\bf Flag}& + \multicolumn{1}{|c|}{\bf Effect} \\ +\hline + \tt TAI\_NONE & No special tailoring is done.\\ + \tt TAI\_LOGS & Reset all logs to use the PP log directory. \\ + \tt TAI\_SIGNALS & Set handlers for certain signals. \\ + \tt TAI\_ALL & All of the above. \\ +\hline +\end{tabular}\] +The flags may be combined by bitwise the bitwise or operator. + +\section {Runtime Tailoring} + +The runtime tailoring for PP is complex, as there are many parameters +that can affect the operation of the system. The main things tailored +are pathnames to locate commonly used programs; file names and +directories; or the more complex tailoring to define such things as +channels and tables. See Volume 1 for the full detail. + +To add new items to be tailored, it is necessary to add some code to +the parsing routines. For simple additions, it is necessary only to +modify the tables and the switch statement in the file +\file{pp/Lib/tai/tai\_sys.c}. More complex tailoring is best done by +creating a separate procedure, possible in a new file. Such additional +tailoring should not be undertaken lightly as it will make the new +version of PP incompatable with existing and new versions. + +\section {Logging} + +All logging works through a standard package. This package includes +features to limit the log files and to notify administrators of errors. +The logging has some structure too it and the following are the +general rules used when programming PP. + +\subsection {Logging Levels} + +The logging package takes a bit mask of values to log. This is +compared with the current setting of the logging level and then +certain values are logged. The levels available are shown in +Table~\ref{tab:logging}. The values \verb|LLOG_NONE| and +\verb|LLOG_ALL| are special: the first is no logging at all, the +latter sets all bits in the bitmask. + +\tagtable{log}{Logging Levels}{tab:logging} + +\subsection {Logging Structures} + +There are three log structures used in PP. The structures themselves +are defined in the include file \file{isode/logger.h}. These +structures are of type \mbox{\verb|LLog *|}\index{LLog} and are the +following: + +\index{log\_norm}\index{log\_stat}\index{log\_oper}% +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Structure}& + \multicolumn{1}{|c|}{\bf Usage}\\ +\hline + \tt log\_norm& Normal logging\\ + \tt log\_oper& Critical Operator message\\ + \tt log\_stat& Statistical and Authorisation \\ +\hline +\end{tabular}\] +These structures are rarely used explicitly. With few exceptions, the +logging macros described below use the \verb|log_norm| structure. + +\subsection {Logging Macros}\label{logging} +There are several macros defined to aid in the use of logging. The +definitions of these macros can be found in the include file +\file{ll\_log.h}. These macros may be used in the following way: +\begin{quote}\index{PP\_LOG}\begin{verbatim} +PP_LOG (level, (format, arg1, arg2 ...)) +int level; +char *str; +\end{verbatim}\end{quote} +This macro is used for most of the non-debugging logging. The +arguments to this call are as follows: +\begin{describe} +\item[\verb|level|:] One of the logging levels specified above. +However, as there are macros provided for fatal errors and debugging, +it is usually only the values of +\linebreak +\verb|LLOG_EXCEPTIONS| and +\verb|LLOG_PDUS| which are used as the argument here. The +\verb|LLOG_EXCEPTIONS| is used to log failures that are not critical. +The \verb|LLOG_PDUS| level is used to trace any protocol exchanges -- +using the +\verb|PP_PDUS| macro if suitable. + +\item[\verb|format|:] This is a printf-like format string which +together with any arguments {\em must} be enclosed in brackets as +shown. The +\verb|format| and any number of optional \verb|arg|s produce the +logging message. +\end{describe} + +The next macro is a more general macro which allows logging of system +error messages to be attached to the basic log message. + +\begin{quote}\index{PP\_SLOG}\begin{verbatim} +PP_SLOG (level, what, (format, arg1, arg2 ...)) +int level; +char *what; +char *format; +\end{verbatim}\end{quote} +This is similar to the \verb|PP_LOG| macro, but the extra argument if +not null ensures that operating system call failures are logged as +well. This macro should be used where it is suspected that a system +call has failed. +\begin{describe} +\item[\verb|level|:] The logging level. +\item[\verb|what|:] A string which if not the null pointer logs +the system error. +\item[\verb|format|:] A printf-like format string. +\end{describe} + +For more urgent cases of logging, the following macro is provided: + +\begin{quote}\index{PP\_OPER}\begin{verbatim} +PP_OPER (what, (format, arg1, arg2 ...)) +char *what, *format; +\end{verbatim}\end{quote} + +This macro is used for logging of extreme problems. It should only be +used for errors that require operator intervention. These errors +typically end up in a separate log as well as the normal log and are +always logged at the \verb|LLOG_FATAL| level. It is assumed that the +system administrator will look through this log frequently and will +immediately take action on anything found there. The arguments are: +\begin{describe} +\item[\verb|what|:] This is a string which is used to construct a +system error message. This should only be present if a system call is +suspected of failing. Otherwise the constant \verb|NULLCP| should be used. + +\item[\verb|format|:] This string is used as a printf like syntax +to produce the message together with optional arguments as in the case +of \verb|PP_LOG|. Again, this parameter and any arguments {\em must} +be enclosed in brackets as shown. +\end{describe} + +Another logging call is provided for statistical and authorisational +data: + +\begin{quote}\index{PP\_STAT}\begin{verbatim} +PP_STAT ((format, arg1, arg2 ...)) +char *format; +\end{verbatim}\end{quote} +This macro is used for logging statistical information. It should be +used where useful to record statistics like number of messages and +times, etc. Its arguments are printf like, and {\em must} be enclosed +in the double brackets as shown. + +\begin{quote}\index{PP\_NOTICE}\begin{verbatim} +PP_NOTICE ((format, arg1, arg2 ...)) +char *format +\end{verbatim}\end{quote} +This macro is used to record interesting events in protocol exchanges. +It should be used so that the basic flow of a program may be observed, +without undue amounts of log file space or extra machine load. Common +logging events should be: connecting to a host, terminating a +connection, and the transfer of a message. + +\begin{quote}\index{PP\_TRACE}\begin{verbatim} +PP_TRACE ((format, arg1, arg2 ...)) +char *format; +\end{verbatim}\end{quote} +This macro is used throughout the source code to trace the calling of +functions and the general flow of the programs and libraries. It logs +the information at the \verb|LLOG_TRACE| level, and this macro is +dependent on the value of the \verb|PP_DEBUG| define. If this is not +defined then the \verb|PP_TRACE| macros are not compiled in. +The arguments are identical to the \verb|PP_STAT| macro. + +\begin{quote}\index{PP\_DBG}\begin{verbatim} +PP_DBG ((format, arg1, arg2 ...)) +char *format; +\end{verbatim}\end{quote} +This macro is similar to the \verb|PP_TRACE| macro, except it logs at +the level of +\linebreak +\verb|LLOG_DEBUG| and will not expand to anything unless +\verb|PP_DEBUG| is defined and has a value greater than 1 (usually +\verb+PP_DEBUG_ALL+\index{PP\_DEBUG\_ALL}). This macro +should be used for very detailed tracing, or where large amounts of +logging are likely to be generated. + +\begin{quote}\index{PP\_PDU}\begin{verbatim} +PP_PDU ((fnx, pe, text, rw)) +IFP fnx; +PE pe; +char *text; +int rw; +\end{verbatim}\end{quote} +This macro is for logging of ASN.1\index{ASN.1} protocol data units (PDUs). +It is only compiled in if \verb|PP_DEBUG| is +\verb+PP_DEBUG_SOME+\index{PP\_DEBUG\_SOME} or greater. The arguments +are as follows: +\begin{describe} +\item[\verb|fnx|:] A function to print out the PDU. This should +be a function constructed by the printer option of pepy. + +\item[\verb|pe|:] The presentation element to print out. + +\item[\verb|str|:] An explanatory string, usually the name of +the PDU. + +\item[\verb|rw|:] A flag indicating the direction the PDU is +going. Set to \verb|PDU_WRITE| to indicate the pdu is being +written and \verb|PDU_READ| to show it is being read. +\end{describe} +Non ASN.1\index{ASN.1} protocol exchanges can be logged with the +\verb|PP_LOG| macro at the +\linebreak +\verb|LLOG_PDUS| level. + +If other logging calls not described here are needed, they can be +constructed from the more general \verb|SLOG|\index{SLOG} macro +described in the ISODE manual. Use of this feature is discouraged. + +\section {Code Location} + +The code to PP is arranged in a hierarchy of directories. This is a +brief tour around the structure. + +\subsection{Library Code} + +Much of the PP system is in the library code. This is found in +the directory \verb|Lib/|\index{Lib/} under the top directory of the PP +distribution. The library itself is split into several +subdirectories. These are as follows: + +\begin{describe} +\item[\verb|addr/|:]\index{addr/} The RFC~822 address parser +library. This +contains ways to manipulate and process RFC~822 addresses. + +\item[\verb|format/|:]\index{format/} This directory contains support routines for +formatting messages. + +\item[\verb|io/|:]\index{io/} This directory contains most of the routines +concerned with writing out and reading in structures. It is generally +used for reading in structures and writing them out. + +\item[\verb|or/|:]\index{or/} This directory has a set of routines for +manipulating O/R addresses. + +\item[\verb|parse/|:]\index{parse/} This directory contains the code to do the generic +parsing of addresses. It contains the general interface to X.400 and +RFC~822 addresses. + +\item[\verb|pp/|:]\index{pp/} This directory contains many of the basic PP +specific routines such as manipulation of structures, PP structures, and +the flattening and unflattening of these structures. + +\item[\verb|qmgr/|:]\index{qmgr/} This directory contains the code required to +interface with the QMGR process. + +\item[\verb|table/|:]\index{table/} This directory contains routines for accessing +the databases used by PP for routing, aliases and the like. + +\item[\verb|tai/|:]\index{tai/} This contains the routines responsible for +reading and parsing the \file{tailor} file. + +\item[\verb|util/|:]\index{util/} This directory contains some +generally useful common procedures. + +\item[\verb|x400/|:]\index{x400/} This directory contains +support routines for X.400 handling. +\end{describe} + +\subsection{Core Programs} + +The next major directory to be considered is the +\verb|Src/|\index{Src/} directory. This contains the core programs +required by PP. These are: +\begin{describe} +\item[\verb|MTAconsole/|:]\index{MTAconsole/} This is the source +code for the X-based MTA console program. It monitors the overall +running of PP. + +\item[\verb|LINEconsole/|:]\index{LINEconsole} The source for a line +based console program. + +\item[\verb|lconsole/|:]\index{lconsole} The source for an alternative +line based console. + +\item[\verb|submit/|:]\index{submit/} This is the source for the +submission process. All messages entering the queue go through this process. + +\item[\verb|qmgr/|:]\index{qmgr/} This is the source for the +QMGR process. + +\item[\verb|pptsapd/|:]\index{pptsapd/} This is the source for the pp +tsap daemon. This is the process that runs the channels invoked by the +queue manager. + +\end{describe} + +\subsection{Other Directories} +The are the following other directories which have some significance. + +\begin{describe} +\item[\verb|h/|:]\index{h/} Contains all the public header files used in +the PP system. + +\item[\verb|doc/|:]\index{doc/} Contains the documentation on PP. + +\item[\verb|man/|:]\index{man/} Contains manual pages on the PP programs. + +\item[\verb|Uip/|:]\index{Uip/} Contains some user interface programs for +submitting messages to PP. + +\item[\verb|Tools/|:]\index{Tools/} Contains several programs +useful for building up parts of the PP system or verifying it. + +\item[\verb|Chans/|:]\index{Chans/} The channel programs can all be +found under the directory \verb|Chans/|. +\end{describe} diff --git a/doc/manual/volume2/idx2ind b/doc/manual/volume2/idx2ind new file mode 100755 index 0000000..357a385 --- /dev/null +++ b/doc/manual/volume2/idx2ind @@ -0,0 +1,53 @@ +#! /bin/sh +: 'idx2ind - new LaTeX index converter - 11-Jul-88/JLR' + +L=%% +case x$1 in + x-l) L=""; shift ;; +esac + +for i +do + awk 'BEGIN {for (i = 97; i < 123; i++) # index letters "a" to "z" + printf "%c\n", i; exit}' |\ + cat - $i.idx |\ + sed \ + -e 's/ / /g'\ + -e 's/^\\indexentry{\(.*\)}{\([^}]*\)}$/\1 \2/'\ + -e 's/^\\verb\(.\)\(.*\)\1 \(.*\)$/\2 \3 \\verb\1\2\1/'\ + -e '/\\/!s/ *{}//'\ + -e '/,/{;s/^\(.*\) \(.*\)$/\1 \2 \1/;s/,/ /;}' |\ + sort -u -t" " +0fd -1 +1n |\ + awk -F" " ' +BEGIN {printf "\\begin{theindex}\\makeatletter\n" + printf "\\raggedright\n" + printf "\\def\\newindex#1{{\\huge\\hspace{-.5in}" + printf "\\parbox[t]{.5in}{\\makebox[.35in][c]{\\uppercase{#1}}}" + printf "\\vspace{-1.5ex}}}\n" + } +NF == 1 {x = $1; next} # NF=1: index letter + {n = $1} +NF == 3 {n = $3} # NF=3: special sort key +n == p {printf ", %s", $2; next} # another page number +p != "" {printf "\n"} # end of this item +x != "" {if (p != "") # index letter? + printf "\\indexspace\n" + printf "'$L'\\newindex{%s}\n", x + } + {x = s = ""; i = n; l = $2} # reset +/,/ {s = "sub" # sub-item + nf = split (i, a, ","); k = a[1]; i = a[2] + split (p, pk, ",") + if (pk[1] != k && pk[1] != k"{}") # should use substr... + {i = n; s =""} + else for (j = 3; j <= nf; j++) # add sub-sub-items + i = sprintf ("%s,%s", i, a[j]) + } + {printf "\\%sitem %s, %s", s, i, l} + {p = n} # save for next comparison +END {printf "\n\\end{theindex}\n" + }' > $i.ind + +done + +exit 0 diff --git a/doc/manual/volume2/io.c b/doc/manual/volume2/io.c new file mode 100644 index 0000000..c734b95 --- /dev/null +++ b/doc/manual/volume2/io.c @@ -0,0 +1,56 @@ +submit_message (orig, recips, fp) +ADDR *orig; +ADDR *recips; +FILE *fp; +{ + RP_Buf rps, *rp = &rps; + char buf[BUFSIZ]; + ADDR *ap; + + if (rp_isbad (io_init(rp))) + error (); + + if (rp_isbad (io_wprm (prm, rp))) + error (); + + if (rp_isbad (io_wrq (q, rp))) + error (); + + if (rp_isbad (io_wadr (orig, AD_ORIGINATOR, rp))) + error (); + + for (ap = ad_recipients; ap; ap = ap -> ad_next) + if (rp_isbad (io_wadr (ap, AD_RECIPIENT, rp))) + error (); + + if (rp_isbad (io_adend(rp))) + error (); + + if (rp_isbad (io_tinit(rp))) + error (); + + if (rp_isbad (io_tpart ("hdr.822", FALSE, rp))) + error (); + + while (fgets( buf, sizeof buf, fp)) + if (rp_isbad (io_tdata (buf, strlen (buf)))) + error (); + + if (rp_isbad (io_tdend(rp))) + error (); + + if (rp_isbad (io_tpart ("1.ia5", FALSE, rp))) + error (); + + while (fgets (buf, sizeof buf, stdin)) + if (rp_isbad (io_tdata (buf, strlen (buf)))) + error (); + + if (rp_isbad (io_tdend (rp))) + error (); + + if (rp_isbad (io_tend (rp))) + error (); + + io_end(OK); +} diff --git a/doc/manual/volume2/io.tex b/doc/manual/volume2/io.tex new file mode 100644 index 0000000..72f63fd --- /dev/null +++ b/doc/manual/volume2/io.tex @@ -0,0 +1,57 @@ +\File{io.c},{10:17},{Sep 17 1990} +\L{\LB{\Proc{submit\_message}submit\_message (orig, recips, fp)}} +\L{\LB{ADDR}\Tab{8}{*orig;}} +\L{\LB{ADDR}\Tab{8}{*recips;}} +\L{\LB{FILE}\Tab{8}{*fp;}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{RP\_Buf}\Tab{16}{rps, *rp = \&rps;}} +\L{\LB{}\Tab{8}{char}\Tab{16}{buf[BUFSIZ];}} +\L{\LB{}\Tab{8}{ADDR}\Tab{16}{*ap;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_init(rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_wprm (prm, rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_wrq (q, rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_wadr (orig, AD\_ORIGINATOR, rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{for (ap = ad\_recipients; ap; ap = ap \-\> ad\_next)}} +\L{\LB{}\Tab{16}{if (rp\_isbad (io\_wadr (ap, AD\_RECIPIENT, rp)))}} +\L{\LB{}\Tab{24}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_adend(rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tinit(rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tpart (\S{}\"hdr.822\"\SE{}, FALSE, rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{while (fgets( buf, sizeof buf, fp))}} +\L{\LB{}\Tab{16}{if (rp\_isbad (io\_tdata (buf, strlen (buf))))}} +\L{\LB{}\Tab{24}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tdend(rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tpart (\S{}\"1.ia5\"\SE{}, FALSE, rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{while (fgets (buf, sizeof buf, stdin))}} +\L{\LB{}\Tab{16}{if (rp\_isbad (io\_tdata (buf, strlen (buf))))}} +\L{\LB{}\Tab{24}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tdend (rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (io\_tend (rp)))}} +\L{\LB{}\Tab{16}{error ();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{ io\_end(OK);}} +\L{\LB{\}}} diff --git a/doc/manual/volume2/make b/doc/manual/volume2/make new file mode 100755 index 0000000..be14df3 --- /dev/null +++ b/doc/manual/volume2/make @@ -0,0 +1,11 @@ +#! /bin/sh + +if [ -f ../../../Make.defs ] +then + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../../../Make.defs -f Makefile ${1+"$@"} +else + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../Make.defs -f Makefile ${1+"$@"} +fi + diff --git a/doc/manual/volume2/outbound.c b/doc/manual/volume2/outbound.c new file mode 100644 index 0000000..1d1d0a5 --- /dev/null +++ b/doc/manual/volume2/outbound.c @@ -0,0 +1,111 @@ +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); /* init the channel - and find out who we are */ + + dirinit(); /* get to the right directory */ +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc, argv, chaninit, process, endproc); + else +#endif + channel_control (argc, argv, chaninit, process, endproc); + exit (0); +} + +static int chaninit (arg) +struct type_Qmgr_Channel *arg; +{ + char *p = qb2str (arg); + + if ((mychan = ch_nm2struct (p)) == (CHAN *)0) + err_abrt (RP_PARM, "Channel '%s' not known", p); + exam_init (mychan); + free (p); + return OK; +} + +static int endproc () +{ + if (cur_host) + exam_close (OK); +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + struct type_Qmgr_UserList *up; + Q_struct Qstruct, *qp = &Qstruct; + int retval; + ADDR *ap, + *ad_sendr = NULLADDR, + *ad_recip = NULLADDR, + *alp, + *ad_list = NULLADDR; + int ad_count; + + if (this_msg) free (this_msg); + + this_msg = qb2str (arg -> qid); + + PP_TRACE (("process msg %s", this_msg)); + + bzero ((char *)&prm, sizeof prm); + bzero ((char *)qp, sizeof *qp); + + (void) delivery_init (arg -> users); + + retval = rd_msg (this_msg, &prm, qp, &ad_sendr, &ad_recip, &ad_count); + + if (rp_isbad (retval)) { + PP_LOG (LLOG_EXCEPTIONS, ("rd_msg err: %s", this_msg)); + return delivery_setall (int_Qmgr_status_messageFailure); + } + + sender = ad_sendr -> ad_r822adr; + + + for (ap = ad_recip; ap; ap = ap -> ad_next) { + for (up = arg ->users; up; up = up -> next) { + if (up -> RecipientId -> parm != ap -> ad_no) + continue; + + if (chan_acheck (ap, mychan, + ad_list == NULL, &cur_mta) == NOTOK) + continue; + } + if (up == NULL) + continue; + + if (ad_list == NULLADDR) + ad_list = alp = (ADDR *) calloc (1, sizeof *alp); + else { + alp -> ad_next = (ADDR *) calloc (1, sizeof *alp); + alp = alp -> ad_next; + } + *alp = *ap; + alp -> ad_next = NULLADDR; + } + + if (ad_list == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list")); + rd_end (); + return deliverystate; + } + + deliver (ad_list, qp); /* do what is required */ + + rd_end(); + + return deliverystate; +} + + +static void dirinit() /* Change into pp queue space */ +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, "Unable to change directory to '%s'", + quedfldir); +} diff --git a/doc/manual/volume2/outbound.tex b/doc/manual/volume2/outbound.tex new file mode 100644 index 0000000..23b75aa --- /dev/null +++ b/doc/manual/volume2/outbound.tex @@ -0,0 +1,112 @@ +\File{outbound.c},{11:14},{Aug 24 1990} +\L{\LB{\Proc{main}main (argc, argv)}} +\L{\LB{int argc;}} +\L{\LB{char **argv;}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{sys\_init (argv[0]); \C{}\/* init the channel \- and find out who we are *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{dirinit(); \C{}\/* get to the right directory *\/\CE{}}} +\L{\LB{\#ifdef PP\_DEBUG}} +\L{\LB{}\Tab{8}{if (argc \> 1 \&\& strcmp (argv[1], \S{}\"debug\"\SE{}) == 0)}} +\L{\LB{}\Tab{16}{debug\_channel\_control (argc, argv, chaninit, process, endproc);}} +\L{\LB{}\Tab{8}{else}} +\L{\LB{\#endif}} +\L{\LB{}\Tab{16}{channel\_control (argc, argv, chaninit, process, endproc);}} +\L{\LB{}\Tab{8}{exit (0);}} +\L{\LB{\}}} +\L{\LB{}} +\L{\LB{static int chaninit (arg)}} +\L{\LB{struct type\_Qmgr\_Channel *arg;}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{char *p = qb2str (arg);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if ((mychan = ch\_nm2struct (p)) == (CHAN *)0)}} +\L{\LB{}\Tab{16}{err\_abrt (RP\_PARM, \S{}\"Channel \'\%s\' not known\"\SE{}, p);}} +\L{\LB{}\Tab{8}{exam\_init (mychan);}} +\L{\LB{}\Tab{8}{free (p);}} +\L{\LB{}\Tab{8}{return OK;}} +\L{\LB{\}}} +\L{\LB{}} +\L{\LB{static int endproc ()}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{if (cur\_host)}} +\L{\LB{}\Tab{16}{exam\_close (OK);}} +\L{\LB{\}}} +\L{\LB{}} +\L{\LB{static struct type\_Qmgr\_DeliveryStatus *process (arg)}} +\L{\LB{struct type\_Qmgr\_ProcMsg *arg;}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{struct prm\_vars prm;}} +\L{\LB{}\Tab{8}{struct type\_Qmgr\_UserList *up;}} +\L{\LB{}\Tab{8}{Q\_struct Qstruct, *qp = \&Qstruct;}} +\L{\LB{}\Tab{8}{int retval;}} +\L{\LB{}\Tab{8}{ADDR *ap,}} +\L{\LB{}\Tab{16}{*ad\_sendr = NULLADDR,}} +\L{\LB{}\Tab{16}{*ad\_recip = NULLADDR,}} +\L{\LB{}\Tab{16}{*alp,}} +\L{\LB{}\Tab{16}{*ad\_list = NULLADDR;}} +\L{\LB{}\Tab{8}{int ad\_count;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (this\_msg) free (this\_msg);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{this\_msg = qb2str (arg \-\> qid);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{PP\_TRACE ((\S{}\"process msg \%s\"\SE{}, this\_msg));}} +\L{\LB{}} +\L{\LB{}\Tab{8}{bzero ((char *)\&prm, sizeof prm);}} +\L{\LB{}\Tab{8}{bzero ((char *)qp, sizeof *qp);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{(void) delivery\_init (arg \-\> users);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{retval = rd\_msg (this\_msg, \&prm, qp, \&ad\_sendr, \&ad\_recip, \&ad\_count);}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (rp\_isbad (retval)) \{}} +\L{\LB{}\Tab{16}{PP\_LOG (LLOG\_EXCEPTIONS, (\S{}\"rd\_msg err: \%s\"\SE{}, this\_msg));}} +\L{\LB{}\Tab{16}{return delivery\_setall (int\_Qmgr\_status\_messageFailure);}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{sender = ad\_sendr \-\> ad\_r822adr;}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{}\Tab{8}{for (ap = ad\_recip; ap; ap = ap \-\> ad\_next) \{}} +\L{\LB{}\Tab{16}{for (up = arg \-\>users; up; up = up \-\> next) \{}} +\L{\LB{}\Tab{24}{if (up \-\> RecipientId \-\> parm != ap \-\> ad\_no)}} +\L{\LB{}\Tab{32}{continue;}} +\L{\LB{}} +\L{\LB{}\Tab{24}{if (chan\_acheck (ap, mychan,}} +\L{\LB{}\Tab{40}{ ad\_list == NULL, \&cur\_mta) == NOTOK)}} +\L{\LB{}\Tab{32}{continue;}} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}\Tab{16}{if (up == NULL)}} +\L{\LB{}\Tab{24}{continue;}} +\L{\LB{}} +\L{\LB{}\Tab{16}{if (ad\_list == NULLADDR)}} +\L{\LB{}\Tab{24}{ad\_list = alp = (ADDR *) calloc (1, sizeof *alp);}} +\L{\LB{}\Tab{16}{else \{}} +\L{\LB{}\Tab{24}{alp \-\> ad\_next = (ADDR *) calloc (1, sizeof *alp);}} +\L{\LB{}\Tab{24}{alp = alp \-\> ad\_next;}} +\L{\LB{}\Tab{16}{\}}} +\L{\LB{}\Tab{16}{*alp = *ap;}} +\L{\LB{}\Tab{16}{alp \-\> ad\_next = NULLADDR;}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{if (ad\_list == NULLADDR) \{}} +\L{\LB{}\Tab{16}{PP\_LOG (LLOG\_EXCEPTIONS, (\S{}\"No recipients in user list\"\SE{}));}} +\L{\LB{}\Tab{16}{rd\_end ();}} +\L{\LB{}\Tab{16}{return deliverystate;}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{deliver (ad\_list, qp); \C{}\/* do what is required *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{rd\_end();}} +\L{\LB{}} +\L{\LB{}\Tab{8}{return deliverystate;}} +\L{\LB{\}}} +\L{\LB{}} +\L{\LB{}} +\L{\LB{static void dirinit() \C{}\/* Change into pp queue space *\/\CE{}}} +\L{\LB{\{}} +\L{\LB{}\Tab{8}{if (chdir (quedfldir) \< 0)}} +\L{\LB{}\Tab{16}{err\_abrt (RP\_LIO, \S{}\"Unable to change directory to \'\%s\'\"\SE{},}} +\L{\LB{}\Tab{48}{quedfldir);}} +\L{\LB{\}}} diff --git a/doc/manual/volume2/preface.aux b/doc/manual/volume2/preface.aux new file mode 100644 index 0000000..6d85420 --- /dev/null +++ b/doc/manual/volume2/preface.aux @@ -0,0 +1,20 @@ +\relax +\global\@namedef{cp@preface}{ +\setcounter{page}{6} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{0} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume2/preface.tex b/doc/manual/volume2/preface.tex new file mode 100644 index 0000000..2671f0f --- /dev/null +++ b/doc/manual/volume2/preface.tex @@ -0,0 +1,13 @@ +% -*- Latex -*- + +\preface + +This volume describes the PP programming interface. This covers: + +\begin{itemize} +\item Submission of messages such as might be used by a user agent. +\item Submission of messages as by a protocol channel. +\item Writing channel programs. +\end{itemize} +It also explains the major data structures used in PP and the +conventions such as logging and initialisation. diff --git a/doc/manual/volume2/prmstruct.h b/doc/manual/volume2/prmstruct.h new file mode 100644 index 0000000..762fdc5 --- /dev/null +++ b/doc/manual/volume2/prmstruct.h @@ -0,0 +1,7 @@ +struct prm_vars { + char *prm_logfile; + int prm_loglevel; + int prm_opts; + char *prm_passwd; +}; + diff --git a/doc/manual/volume2/prmstruct.tex b/doc/manual/volume2/prmstruct.tex new file mode 100644 index 0000000..2a29e04 --- /dev/null +++ b/doc/manual/volume2/prmstruct.tex @@ -0,0 +1,8 @@ +\File{prmstruct.h},{10:35},{Jul 16 1990} +\L{\LB{struct prm\_vars \{}} +\L{\LB{}\Tab{8}{char *prm\_logfile;}} +\L{\LB{}\Tab{8}{int prm\_loglevel;}} +\L{\LB{}\Tab{8}{int prm\_opts;}} +\L{\LB{}\Tab{8}{char}\Tab{16}{*prm\_passwd;}} +\L{\LB{\};}} +\L{\LB{}} diff --git a/doc/manual/volume2/qmgrif.h b/doc/manual/volume2/qmgrif.h new file mode 100644 index 0000000..9cf2c6e --- /dev/null +++ b/doc/manual/volume2/qmgrif.h @@ -0,0 +1,29 @@ +struct type_Qmgr_ProcMsg { + struct type_Qmgr_QID *qid; + + struct type_Qmgr_UserList *users; + + struct type_Qmgr_Channel *channel; +}; + +struct type_Qmgr_DeliveryStatus { + struct type_Qmgr_IndividualDeliveryStatus *IndividualDeliveryStatus; + + struct type_Qmgr_DeliveryStatus *next; +}; + +struct type_Qmgr_IndividualDeliveryStatus { + struct type_Qmgr_RecipientId *recipient; + + integer status; +#define int_Qmgr_status_success 0 +#define int_Qmgr_status_successSharedDR 1 +#define int_Qmgr_status_failureSharedDR 2 +#define int_Qmgr_status_negativeDR 3 +#define int_Qmgr_status_positiveDR 4 +#define int_Qmgr_status_messageFailure 5 +#define int_Qmgr_status_mtaFailure 6 +#define int_Qmgr_status_mtaAndMessageFailure 7 + + struct qbuf *info; +}; diff --git a/doc/manual/volume2/qmgrif.tex b/doc/manual/volume2/qmgrif.tex new file mode 100644 index 0000000..feac6ec --- /dev/null +++ b/doc/manual/volume2/qmgrif.tex @@ -0,0 +1,30 @@ +\File{qmgrif.h},{13:13},{Mar 25 1991} +\L{\LB{struct type\_Qmgr\_ProcMsg \{}} +\L{\LB{ struct type\_Qmgr\_QID *qid;}} +\L{\LB{}} +\L{\LB{ struct type\_Qmgr\_UserList *users;}} +\L{\LB{}} +\L{\LB{ struct type\_Qmgr\_Channel *channel;}} +\L{\LB{\};}} +\L{\LB{}} +\L{\LB{struct type\_Qmgr\_DeliveryStatus \{}} +\L{\LB{ struct type\_Qmgr\_IndividualDeliveryStatus *IndividualDeliveryStatus;}} +\L{\LB{}} +\L{\LB{ struct type\_Qmgr\_DeliveryStatus *next;}} +\L{\LB{\};}} +\L{\LB{}} +\L{\LB{struct type\_Qmgr\_IndividualDeliveryStatus \{}} +\L{\LB{ struct type\_Qmgr\_RecipientId *recipient;}} +\L{\LB{}} +\L{\LB{ integer status;}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_success}\Tab{32}{0}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_successSharedDR}\Tab{40}{1}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_failureSharedDR}\Tab{40}{2}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_negativeDR}\Tab{40}{3}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_positiveDR}\Tab{40}{4}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_messageFailure}\Tab{40}{5}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_mtaFailure}\Tab{40}{6}} +\L{\LB{\#define}\Tab{8}{int\_Qmgr\_status\_mtaAndMessageFailure}\Tab{48}{7}} +\L{\LB{}} +\L{\LB{ struct}\Tab{16}{qbuf}\Tab{24}{*info;}} +\L{\LB{\};}} diff --git a/doc/manual/volume2/qstruct.h b/doc/manual/volume2/qstruct.h new file mode 100644 index 0000000..c79d0d5 --- /dev/null +++ b/doc/manual/volume2/qstruct.h @@ -0,0 +1,90 @@ +typedef struct Qstruct { + + int msgtype; /* Type of message */ +#define MT_UMPDU 1 +#define MT_DMPDU 2 +#define MT_PMPDU 3 + +/* -- MTS Parameters */ + + long msgsize; /* Size of message */ + UTC defertime; /* Deffered time */ + UTC latest_time; + char latest_time_crit; + + char nwarns; /* Number of warning msgs to send */ + int warninterval; /* Interval between warning msgs */ + int retinterval; /* Interval after which return mail */ + char *cont_type; /* Content type of message */ + EncodedIT orig_encodedinfo; /* Original Encoded Info Types */ + int priority; /* Priority of message */ +#define PRIO_NORMAL 0 +#define PRIO_NONURGENT 1 +#define PRIO_URGENT 2 + + char disclose_recips; + char implicit_conversion_prohibited; + char alternate_recip_allowed; + char content_return_request; + + char recip_reassign_prohibited; + char recip_reassign_crit; + + char dl_expansion_prohibited; + char dl_expansion_crit; + + char conversion_with_loss_prohibited; + char conversion_with_loss_crit; + + char *ua_id; /* UA content id */ + char *pp_content_correlator; + /* PP preferred string form */ + struct qbuf *general_content_correlator; + char content_correlator_crit; + /* ASN.1 uninterpreted */ + + FullName *originator_return_address; + char originator_return_address_crit; + + int forwarding_request; + char forwarding_request_crit; + + struct qbuf *originator_certificate; + char originator_certificate_crit; + + struct qbuf *algorithm_identifier; + char algorithm_identifier_crit; + /* content confidentiality */ + + struct qbuf *message_origin_auth_check; + /* also for Probe */ + char message_origin_auth_check_crit; + + struct qbuf *security_label; + char security_label_crit; + + int proof_of_submission_request; /* boolean */ + char proof_of_submission_crit; + + X400_Extension *per_message_extensions; + + ADDR *Oaddress; /* Orig addr - linked list */ + ADDR *Raddress; /* Recip addrs - linked list */ + +/* -- MTA AS Parameters */ + LIST_RCHAN *inbound; /* Inbound MTA/Channel */ + MPDUid msgid; /* Message ID */ + Trace *trace; /* Trace info */ + DLHistory *dl_expansion_history; + char dl_expansion_history_crit; + +/* -- PP calculated parameters */ + EncodedIT encodedinfo; /* Encoded information types */ + UTC queuetime; /* Time that message was enqueued */ + UTC departime; /* Time that message left the queue */ + int n_bodyparts; + int n_forwarded; + + /* -- Queue Control File offsets for fixed length variables -- */ + off_t nwarns_offset; /* offset param for nwarns */ +} Q_struct; diff --git a/doc/manual/volume2/qstruct.tex b/doc/manual/volume2/qstruct.tex new file mode 100644 index 0000000..dd56f1c --- /dev/null +++ b/doc/manual/volume2/qstruct.tex @@ -0,0 +1,91 @@ +\File{qstruct.h},{10:22},{Nov 20 1991} +\L{\LB{typedef struct Qstruct \{}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{msgtype;}\Tab{40}{\C{}\/* Type of message *\/\CE{}}} +\L{\LB{\#define MT\_UMPDU 1}} +\L{\LB{\#define MT\_DMPDU 2}} +\L{\LB{\#define MT\_PMPDU 3}} +\L{\LB{}} +\L{\LB{\C{}\/* \-\- MTS Parameters *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{long}\Tab{24}{msgsize;}\Tab{40}{\C{}\/* Size of message *\/\CE{}}} +\L{\LB{}\Tab{8}{UTC}\Tab{24}{defertime;}\Tab{40}{\C{}\/* Deffered time *\/\CE{}}} +\L{\LB{}\Tab{8}{UTC}\Tab{24}{latest\_time;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{latest\_time\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{nwarns;}\Tab{40}{\C{}\/* Number of warning msgs to send *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{warninterval;}\Tab{40}{\C{}\/* Interval between warning msgs *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{retinterval;}\Tab{40}{\C{}\/* Interval after which return mail *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*cont\_type;}\Tab{40}{\C{}\/* Content type of message *\/\CE{}}} +\L{\LB{}\Tab{8}{EncodedIT}\Tab{24}{orig\_encodedinfo; \C{}\/* Original Encoded Info Types *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{priority;}\Tab{40}{\C{}\/* Priority of message *\/\CE{}}} +\L{\LB{\#define PRIO\_NORMAL 0}} +\L{\LB{\#define PRIO\_NONURGENT 1}} +\L{\LB{\#define PRIO\_URGENT 2}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{disclose\_recips;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{implicit\_conversion\_prohibited;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{alternate\_recip\_allowed;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{content\_return\_request;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{recip\_reassign\_prohibited;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{recip\_reassign\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{dl\_expansion\_prohibited;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{dl\_expansion\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{conversion\_with\_loss\_prohibited;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{conversion\_with\_loss\_crit;}} +\L{\LB{}\Tab{8}{}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*ua\_id;}\Tab{40}{\C{}\/* UA content id *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{*pp\_content\_correlator; }} +\L{\LB{}\Tab{40}{\C{}\/* PP preferred string form *\/\CE{}}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*general\_content\_correlator;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{content\_correlator\_crit;}} +\L{\LB{}\Tab{40}{\C{}\/* ASN.1 uninterpreted *\/\CE{}}} +\L{\LB{}\Tab{40}{}} +\L{\LB{}\Tab{8}{FullName}\Tab{24}{*originator\_return\_address;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{originator\_return\_address\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{forwarding\_request;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{forwarding\_request\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*originator\_certificate;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{originator\_certificate\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*algorithm\_identifier;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{algorithm\_identifier\_crit;}} +\L{\LB{ }\Tab{24}{\C{}\/* content confidentiality *\/\CE{}}} +\L{\LB{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*message\_origin\_auth\_check; }} +\L{\LB{}\Tab{32}{\C{}\/* also for Probe *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{message\_origin\_auth\_check\_crit;}} +\L{\LB{}\Tab{32}{}} +\L{\LB{}\Tab{8}{struct qbuf}\Tab{24}{*security\_label;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{security\_label\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{int}\Tab{24}{proof\_of\_submission\_request;}\Tab{56}{\C{}\/* boolean *\/\CE{}}} +\L{\LB{}\Tab{8}{char}\Tab{24}{proof\_of\_submission\_crit;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{X400\_Extension}\Tab{24}{*per\_message\_extensions;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{ADDR}\Tab{24}{*Oaddress;}\Tab{40}{\C{}\/* Orig addr \- linked list *\/\CE{}}} +\L{\LB{}\Tab{8}{ADDR}\Tab{24}{*Raddress;}\Tab{40}{\C{}\/* Recip addrs \- linked list *\/\CE{}}} +\L{\LB{}} +\L{\LB{\C{}\/* \-\- MTA AS Parameters *\/\CE{}}} +\L{\LB{}\Tab{8}{LIST\_RCHAN}\Tab{24}{*inbound;}\Tab{40}{\C{}\/* Inbound MTA\/Channel *\/\CE{}}} +\L{\LB{}\Tab{8}{MPDUid}\Tab{24}{msgid;}\Tab{40}{\C{}\/* Message ID *\/\CE{}}} +\L{\LB{}\Tab{8}{Trace}\Tab{24}{*trace;}\Tab{40}{\C{}\/* Trace info *\/\CE{}}} +\L{\LB{}\Tab{8}{DLHistory}\Tab{24}{*dl\_expansion\_history;}} +\L{\LB{}\Tab{8}{char}\Tab{24}{dl\_expansion\_history\_crit;}} +\L{\LB{}} +\L{\LB{\C{}\/* \-\- PP calculated parameters *\/\CE{}}} +\L{\LB{}\Tab{8}{EncodedIT}\Tab{24}{encodedinfo;}\Tab{40}{\C{}\/* Encoded information types *\/\CE{}}} +\L{\LB{}\Tab{8}{UTC}\Tab{24}{queuetime;}\Tab{40}{\C{}\/* Time that message was enqueued *\/\CE{}}} +\L{\LB{}\Tab{8}{UTC}\Tab{24}{departime;}\Tab{40}{\C{}\/* Time that message left the queue *\/\CE{}}} +\L{\LB{}\Tab{8}{int}\Tab{24}{n\_bodyparts;}} +\L{\LB{}\Tab{8}{int}\Tab{24}{n\_forwarded;}} +\L{\LB{}} +\L{\LB{}\Tab{8}{\C{}\/* \-\- Queue Control File offsets for fixed length variables \-\- *\/\CE{}}} +\L{\LB{}\Tab{8}{off\_t}\Tab{24}{nwarns\_offset;}\Tab{40}{\C{}\/* offset param for nwarns *\/\CE{}}} +\L{\LB{\} Q\_struct;}} diff --git a/doc/manual/volume2/rchan.h b/doc/manual/volume2/rchan.h new file mode 100644 index 0000000..f60cb5d --- /dev/null +++ b/doc/manual/volume2/rchan.h @@ -0,0 +1,13 @@ +typedef struct list_rchan { + char *li_mta; /* the MTA */ + CHAN *li_chan; /* the channel its on */ + union { + AUTH *li_un_auth; /* auth stuff used in submit */ + char *li_un_dir; /* the directory associated */ + } list_rchan_un; + struct list_rchan *li_next; /* next in the chain */ +} LIST_RCHAN; +#define li_auth list_rchan_un.li_un_auth +#define li_dir list_rchan_un.li_un_dir + +#define NULLIST_RCHAN ((LIST_RCHAN *)0) diff --git a/doc/manual/volume2/rchan.tex b/doc/manual/volume2/rchan.tex new file mode 100644 index 0000000..0f3d91d --- /dev/null +++ b/doc/manual/volume2/rchan.tex @@ -0,0 +1,14 @@ +\File{rchan.h},{10:21},{Nov 20 1991} +\L{\LB{typedef struct list\_rchan \{}} +\L{\LB{}\Tab{8}{char *li\_mta; \C{}\/* the MTA *\/\CE{}}} +\L{\LB{}\Tab{8}{CHAN *li\_chan; \C{}\/* the channel its on *\/\CE{}}} +\L{\LB{}\Tab{8}{union \{}} +\L{\LB{}\Tab{16}{AUTH *li\_un\_auth; \C{}\/* auth stuff used in submit *\/\CE{}}} +\L{\LB{}\Tab{16}{char}\Tab{32}{*li\_un\_dir; \C{}\/* the directory associated *\/\CE{}}} +\L{\LB{}\Tab{8}{\} list\_rchan\_un;}} +\L{\LB{}\Tab{8}{struct list\_rchan *li\_next; \C{}\/* next in the chain *\/\CE{}}} +\L{\LB{\} LIST\_RCHAN;}} +\L{\LB{\#define li\_auth list\_rchan\_un.li\_un\_auth}} +\L{\LB{\#define li\_dir list\_rchan\_un.li\_un\_dir}} +\L{\LB{}} +\L{\LB{\#define NULLIST\_RCHAN ((LIST\_RCHAN *)0)}} diff --git a/doc/manual/volume2/rpbstruct.h b/doc/manual/volume2/rpbstruct.h new file mode 100644 index 0000000..401b753 --- /dev/null +++ b/doc/manual/volume2/rpbstruct.h @@ -0,0 +1,6 @@ +typedef struct rp_bufstruct /* for reading reply strings */ +{ + unsigned char rp_val; + char rp_line[256]; +} RP_Buf; + diff --git a/doc/manual/volume2/rpbstruct.tex b/doc/manual/volume2/rpbstruct.tex new file mode 100644 index 0000000..da48135 --- /dev/null +++ b/doc/manual/volume2/rpbstruct.tex @@ -0,0 +1,7 @@ +\File{rpbstruct.h},{19:39},{Nov 3 1988} +\L{\LB{\K{typedef} \K{struct} rp\_bufstruct \C{}\/* for reading reply strings *\/\CE{}}} +\L{\LB{\{}} +\L{\LB{ \K{unsigned} \K{char} rp\_val;}} +\L{\LB{ \K{char} rp\_line[256];}} +\L{\LB{\} RP\_Buf;}} +\L{\LB{}} diff --git a/doc/manual/volume2/submission.aux b/doc/manual/volume2/submission.aux new file mode 100644 index 0000000..2dc650f --- /dev/null +++ b/doc/manual/volume2/submission.aux @@ -0,0 +1,66 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {2}Message Submission}{8}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.1}Overview}{8}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.2}The io\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em} Interface}{8}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.1}Major Structures}{8}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Channel Lists}{9}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.1}{\ignorespaces Channel List Structure}}{9}} +\newlabel{rchan:struct}{{2.1}{9}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Encoded Information Types}{10}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.2}{\ignorespaces Encoded Information Type Structure}}{10}} +\newlabel{eit:struct}{{2.2}{10}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.3}{\ignorespaces Management Parameter Structure}}{11}} +\newlabel{prm:struct}{{2.3}{11}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Management Parameters}{11}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Per-Message Information}{12}} +\newlabel{q:struct}{{2.4}{12}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {2.1}{\ignorespaces Criticality Codes}}{14}} +\newlabel{tbl:crit}{{2.1}{14}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.4}{\ignorespaces Queue Structure}}{14}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{The Address structure}{17}} +\newlabel{adr:struct}{{2.5}{18}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.5}{\ignorespaces Address Structure}}{20}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {2.2}{\ignorespaces Table of Explicit Conversion Values}}{21}} +\newlabel{tbl:explicit}{{2.2}{21}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.2}Reply Value Structure}{22}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.6}{\ignorespaces Reply Structure}}{22}} +\newlabel{rpbuf:struct}{{2.6}{22}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.3}Procedure Calls}{23}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Initialisation}{23}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Message Management Parameters}{23}} +\@writefile{lot}{\string\contentsline\space {table}{\string\numberline\space {2.3}{\ignorespaces Return Codes}}{24}} +\newlabel{tab:rpcodes}{{2.3}{24}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Per-Message Parameters}{25}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Originator and Recipient Addresses}{25}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Body Part Submission}{25}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Termination}{26}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2.4}Example}{26}} +\newlabel{example:io}{{2.7}{26}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.7}{\ignorespaces Example Interaction with Submit}}{27}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.3}The RFC\penalty \@M \ 822 Interface}{28}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.1}Initialisation}{28}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.2}Addresses and Headers}{28}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.3}Text Submission}{29}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.4}Termination}{30}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.4}Debugging}{30}} +\global\@namedef{cp@submission}{ +\setcounter{page}{31} +\setcounter{equation}{0} +\setcounter{enumi}{7} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{2} +\setcounter{section}{4} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{7} +\setcounter{table}{3} +} diff --git a/doc/manual/volume2/submission.tex b/doc/manual/volume2/submission.tex new file mode 100644 index 0000000..427e797 --- /dev/null +++ b/doc/manual/volume2/submission.tex @@ -0,0 +1,1010 @@ +% -*- LaTeX -*- +\chapter {Message Submission} + +\section {Overview} + +This chapter describes the procedural interface for message +submission. This interface reflects the submission interface of both +the message transfer abstract service and the MTA abstract service. +It is therefore used for: + +\begin{itemize} +\item User interfaces submitting messages (message transfer abstract +service). + +\item Inbound channels submitting messages (MTA abstract service). +\end{itemize} + +It is a generalised interface, with aspects beyond X.400, but it is +broadly targeted for X.400 usage. The general function of the +interface is as follows: + +\begin{enumerate}\index{submit protocol} +\item Initialise submission. + +\item Initialise Message (per-message parameters). + +\item Handshake on addresses. + +\item Transfer one or more body parts. + +\item Final handshake to lock message into the queue or abort. + +\item Goto 2, until no more messages. + +\item Terminate submission. +\end{enumerate} + +\section {The io\_ Interface} + +The \verb|io_| interface is the full interface to PP. All routines +have the prefix \verb|io_| and all return some type of status +indicating success or failure. + +\subsection {Major Structures} + +The following are the key structures used in submission. These +structures should be filled in and passed over to \pgm{submit} by the +procedures defined below. + +\subsubsection{Channel Lists} + +A channel list is the structure used to keep channels and hosts. It is +defined in file \file{list\_rchan.h} and the structure is shown in +Figure~\ref{rchan:struct} + +\tagrind[hbtp]{rchan}{Channel List Structure}{rchan:struct} +\index{LIST\_RCHAN} + +The use of the structure members are: +\begin{describe} +\item[\verb|li\_mta|:] The MTA name as a character string. +\item[\verb|li\_chan|:] The associated channel structure. +\item[\verb|li\_auth|:] Authorisation parameters. This should not +normally be filled in. +\item[\verb|li\_dir|:] A directory reference. This should not normally +be used. +\item[\verb|li\_next|:] The next element in the list. +\end{describe} + +There are several routines to manipulate such structures. + + +A new list element can be created by using the routine +\verb|list_rchan_new|. This is defined as: +\begin{quote}\index{list\_rchan\_new}\begin{verbatim} +LIST_RCHAN *list_rchan_new (mta, chan) +char *mta; +char *chan; +\end{verbatim}\end{quote} +The parameters to this call are: +\begin{describe} +\item[\verb|mta|:] The name of the MTA. This parameter is copied intop +heap storage. +\item[\verb|chan|:] The name of a channel. This is converted to a +channel structure internally. +\end{describe} + +A new structure can be added onto the end of a list, or if the list is +empty can be set as the first element by a call to +\verb|list_rchan_add|. This is defined as: +\begin{quote}\index{list\_rchan\_add}\begin{verbatim} +void list_rchan_add (base, new) +LIST_RCHAN **base; +LIST_RCHAN *new; +\end{verbatim}\end{quote} + +The linked list structure can be freed by calling +\verb|list_rchan_free|, which is defined as: +\begin{quote}\index{list\_rchan\_free}\begin{verbatim} +void list_rchan_free (list) +LIST_RCHAN *list; +\end{verbatim}\end{quote} + +Two other useful routines are those to convert a string into a channel +structure. The first one is a simple string to structure routine: +\begin{quote}\index{ch\_nm2struct}\begin{verbatim} +CHAN *ch_nm2struct (name) +char *name; +\end{verbatim}\end{quote} +This converts from the given \verb|name| into a channel structure, or +returns \verb|NULLCHAN| if there is no match. + +For inbound channels when filling in the queue structure with inbound +parameters it is necessary first to allocate a channel list with one +of the above functions, but not to fill in the channel part of it. +This should be filled in with the routine: +\begin{quote}\index{ch\_mta2struct}\begin{verbatim} +CHAN *ch_mta2struct (name, mta) +char *name, *mta; +\end{verbatim}\end{quote} +This routine returns a channel structure based on a name and an MTA. +This allows the particular channel to be selected dependant upon the +MTA the message is received from. This allows the channel pairing to +take place. + +\subsubsection{Encoded Information Types} +Encoded information types are used in several places in PP. They are +kept internally as a linked list of strings which contain either the +name of the information type, or a string representation of an object +identifier. The structure is shown in Figure~\ref{eit:struct}. + +\tagrind[hbtp]{eit}{Encoded Information Type Structure}{eit:struct} + +There are some support routines to help construct these lists. +A new structure can be allocated with a value stored in help space by +using the function \verb|list_bpt_new|. This is defined as: +\begin{quote}\index{list\_bpt\_new}\begin{verbatim} +LIST_BPT *list_bpt_new (value) +char *value; +\end{verbatim}\end{quote} + +A linked list structure can be duplicated by using +\verb|list_bpt_dup|. This returns a separate duplicate list. It is +defined as: +\begin{quote}\index{list\_bpt\_dup}\begin{verbatim} +LIST_BPT *list_bpt_dup (list) +LIST_BPT *list; +\end{verbatim}\end{quote} + +A new element may be added to the end of a list, or become the first +member if the list is empty, by calling \verb|list_bpt_add|. This is +defined as: +\begin{quote}\index{list\_bpt\_add}\begin{verbatim} +void list_bpt_add (base, new) +LIST_BPT **base; +LIST_BPT *new; +\end{verbatim}\end{quote} + +A list may be searched for a particular type of element by using +\verb|list_bpt_find|. This returns either the first matching entry or +\verb|NULLIST_BPT| if no such element is found. +\begin{quote}\index{list\_bpt\_find}\begin{verbatim} +LIST_BPT *list_bpt_find (list, item) +LIST_BPT *list; +char *item; +\end{verbatim}\end{quote} + +Finally, a linked list may be deallocated up by calling the routine +\verb|list_bpt_free|: +\begin{quote}\index{list\_bpt\_free}\begin{verbatim} +void list_bpt_free (list) +LIST_BPT *list; +\end{verbatim}\end{quote} + + +\subsubsection{Management Parameters} + +The management parameters are defined in the file \file{prm.h} and the +structure is shown in Figure~\ref{prm:struct}. These values are set +before each message submission to change the general policies of +\pgm{submit}. + +There are two support routines for manipulating this structure. The +first, \verb|prm_init|, initialises the structure to its default +state. The second, \verb|prm_free|, frees off all allocated variables +within the structure. +\begin{quote}\small\index{prm\_init}\index{prm\_free}\begin{verbatim} +void prm_init (pp) +struct prm_vars *pp; + +void prm_free (pp) +struct prm_vars *pp; +\end{verbatim}\end{quote} + + +\tagrind{prmstruct}{Management Parameter Structure}{prm:struct} +\index{struct~prm\_vars} + +The use of each of the members of this structure are: +\begin{describe}\index{parameter structure}\index{prm} + +\item[\verb|prm\_logfile|:] A logfile to be used for this specific message. + +\item[\verb|prm\_loglevel|:] A logging level to be used for this message. +It should be one of the levels of logging specified in \file{ll\_log.h}. + +\item[\verb|prm\_opts|:] A set of options to control \pgm{submit}. +This should be one of the following: +\[\begin{tabular}{|l|p{0.6\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt PRM\_NONE& No options\\ + \tt PRM\_ACCEPTALL& + \pgm{submit} should accept bad recipient addresses + and generate error reports itself\\ + \tt PRM\_NOTRACE & + \pgm{submit} should not generate Received: or Via: + lines. \\ +\hline +\end{tabular}\] + +\item[\verb|prm\_passwd|:] A password to authenticate the local +user's submission (not used as yet). +\end{describe} + +\subsubsection{The Per-Message Information} + +The per-message information is defined in the file \file{q.h} and the +structure is shown in Figure~\ref{q:struct}. Only the fields which +should or may be filled in by interface programs are +described in detail. The rest are calculated by \pgm{submit} if +necessary. + +\tagrindfile{qstruct}{Queue Structure}{q:struct}\index{Q\_struct} + +The queue structure controls most of the per message parameters. There +are a number of utility routines to help manipulate these structures. + +The routine \verb|q_init| can be used initialise an empty structure. +The routine \verb|q_free| can be used to free off allocated fields +within the structure. +\begin{quote}\index{q\_init}\index{q\_free}\begin{verbatim} +int q_init (qp) +Q_struct *qp; + +int q_free (qp) +Q_struct *qp; +\end{verbatim}\end{quote} + +Typically an inbound channel will only fill in one or two parameters, +most can be safely defaulted unless required. It is important to set +the \verb|inbound| parameter and to fill in the list of encoded +information types and possible the content type. The rest are all +optional. + +The elements of the queue structure are now described. Some elements +have an associated flag with the name ending with \verb|crit|. This +refers to an element in the structure with a similar name. This +element indicates what the criticality constraints on the element +are. Values for the settings of these are shown in +Table~\ref{tbl:crit}. These values may be logically or'd together to +set several critical values. + +\tagtable{crit}{Criticality Codes}{tbl:crit} + +\begin{describe}\index{queue structure}\index{Q\_struct} + +\item[\verb|msgtype|:] The type of message being submitted. This +should be one of the following: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt MT\_UMPDU& Normal message\\ + \tt MT\_DMPDU& A delivery report\\ + \tt MT\_PMPDU& A Probe \\ +\hline +\end{tabular}\] +The \verb|q_init| routine defaults this value to \verb|MT_UMPDU|. + +\item[\verb|cont\_type|:] The content type of the message. This +should be one of the defined types; normally one of the following: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt "822"& An RFC~822 content\\ + \tt "p2"& A P2 1984 content\\ + \tt "p22" & A P2 1988 content \\ +\hline +\end{tabular}\] +As these values are common, they are available via the following +string variables. +\begin{quote}\small\begin{verbatim} +extern char *cont_822; +extern char *cont_p2; +extern char *cont_p22; +\end{verbatim}\end{quote} + +An empty content implies that the message will be submitted in +structured form (usually the default for RFC~822 messages). + +\item[\verb|encodedinfo|:] A list of encoded information types. +This should include all the encoded types that are in the message, and +should be a member of the list defined in the bodypart tailor +variable. +Although any encoded information type present in the bodypart list is +allowed, PP knows about some special cases. These are: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt "ia5"& An Ia5 (ascii) body part\\ + \tt "hdr.822"& An RFC~822 header\\ + \tt "hdr.p2" & A P2 1984 header \\ + \tt "hdr.p22" & A P2 1988 header \\ + \tt "hdr.ipn" & An IPN header \\ +\hline +\end{tabular}\] +These definitions are available in the external variables as follows: +\begin{quote}\small\begin{verbatim} +extern char *hdr_822_bp; +extern char *hdr_p2_bp; +extern char *hdr_p22_bp; +extern char *hdr_ipn_bp; +extern char *ia5_bp; +\end{verbatim}\end{quote} +\end{describe} + +The following variables can all be safely defaulted to those +initialised by \verb|q_init|, but can be varied as required. + +\begin{describe} + +\item[\verb|defertime|:] The time the message should wait for +before being delivered (for deferred delivery): optional. + +\item[\verb|latest\_time|:] The latest delivery time this message +should be delivered by. + +\item[\verb|nwarns|:] The number of warning messages to be sent if +the message is delayed. + +\item[\verb|warninterval|:] The interval of time between +successive warnings. + +\item[\verb|retinterval|:] The time to wait before returning the +message as undeliverable. + + +\item[\verb|priority|:] The priority associated with the +message. This takes one of the following values: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt PRIO\_NORMAL& The default\\ + \tt PRIO\_NONURGENT& A low priority message\\ + \tt PRIO\_URGENT& A high priority message\\ +\hline +\end{tabular}\] + +\item[\verb|disclose\_recips|:] A true/false flag indicating whether +recipients should be disclosed. + +\item[\verb|implicit\_conversion|:] A true/false flag indicating +if implicit conversion can be performed. + +\item[\verb|alternate\_recip\_allowed|:] A true/false flag indicating +if the message can be sent to an alternate recipient. + +\item[\verb|content\_return\_request|:] A true/false flag indicating +if the message content should be returned on delivery failure. + +\item[\verb|recip\_reassign\_prohibited|:] A flag indicating if the +recipient may reassign the message to a new recipient. + +\item[\verb|dl\_expansion\_prohibited|:] A flag indicating if the +message may not be expanded into a distribution list. + +\item[\verb|conversion\_with\_loss\_prohibited|:] A flag indicating if +conversion is allowed even if it loses information. + +\item[\verb|ua\_id|:] The user agent ID. This is a string that +identifies the message to a user agent. + +\item[\verb|pp\_content\_correlator|:] The internal version of the +content correlator. + +\item[\verb|general\_content\_correlator|:] The content correlator +of the message. + +\item[\verb|originator\_return\_address|:] The postal return +address of the originator. + +\item[\verb|forwarding\_request|:] An indication of whether +the physical forwarding address should be returned to the originator. + +\item[\verb|originator\_certificate|:] This element conveys the +certificate of the originator when secuure messaging is being used. + +\item[\verb|algorithm\_identifier|:] An indication of the +encryption algorithm used for message encryption. + +\item[\verb|message\_origin\_auth\_check|:] This element allows +MTAs and recipients to \linebreak[3] authenticate the message origin. + +\item[\verb|security\_label|:] A label indicating the security policy. + +\item[\verb|proof\_of\_submission|:] An indication of whether proof +of submission is \linebreak[3] required. + +\item[\verb|per\_message\_extensions|:] A holder for any additional +elements of the message. + +\item[\verb|Oaddress|:] Should be empty for submission. + +\item[\verb|Raddress|:] Should be empty for submission. + +\item[\verb|inbound|:] The inbound channel/mta pair +This is important as this controls authentication and authorisation. + +\item[\verb|msgid|:] The MTS identifier of this message (P1 level). + +\item[\verb|trace|:] The trace fields. + +\item[\verb|dl\_expansion\_history|:] A trace of the distribution +lists this message has been expanded by. + +\end{describe} + +\subsubsection{The Address structure}\index{addressing} + +The address structure contains all the information about each address. +The structure is defined in the file \file{adr.h}. The same structure +is used for both Recipient and Originator address. The structure is +shown in Figure~\ref{adr:struct}. There are a number of support +routines that help construct addresses. + +The routine \verb|adr_new| creates a new address structure with some +of the values filled in. This structure is the minimum necessary set +of values to submit a recipient. To create an Originator, the +responsibility bit \verb|ad_resp| should be set to false, and the +status (\verb|ad_stat|) should be set to \verb|AD_STAT_DONE|. +The routine is defined as: +\begin{quote}\small\index{adr\_new}\begin{verbatim} +ADDR *adr_new (str, type, rno) +char *str; +int type; +int rno; +\end{verbatim}\end{quote} +The arguments to this call are +\begin{describe} +\item[\verb|str|:] The address in string format, either RFC~822 or the +string form of the O/R name. +\item[\verb|type|:] This is the type of address; it should be one of +the values suitable for \verb|ad_type|. +\item[\verb|rno|:] The recipient number. Set this to 0 if you do not +care about this value. +\end{describe} + +The routine \verb|ad_init| will initialise an \verb|ADDR| structure to +its default values. It is defined as: +\begin{quote}\small\index{adr\_init}\begin{verbatim} +void adr_init (ap) +ADDR *ap; +\end{verbatim}\end{quote} + +The routine \verb|adr_add| adds an address onto the end of a linked +list of addresses, or allocates the first node if the list is empty. +\begin{quote}\small\index{adr\_add}\begin{verbatim} +void adr_add (base, new) +ADDR **base; +ADDR *new; +\end{verbatim}\end{quote} + +The routine \verb|adr_tfree| frees a list of addresses freeing of all +allocated elements and the structures themselves. +\begin{quote}\small\index{adr\_tfree}\begin{verbatim} +void adr_tfree (ap) +ADDR *ap; +\end{verbatim}\end{quote} + +The routine \verb|adr_free| frees off all the allocated elements +within a single address structure but does not free the structure +itself. +\begin{quote}\small\index{adr\_free}\begin{verbatim} +void adr_free (ap) +ADDR *ap; +\end{verbatim}\end{quote} + +\bigskip + +\tagrindfile{adrstruct}{Address Structure}{adr:struct} + +Only the non-internal fields are described here: +\begin{describe}\index{address structure}\index{ADDR} + +\item[\verb|ad\_extension|:] The extension identifier for this address. + +\item[\verb|ad\_status|:] The status of this address, one of: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_STAT\_PEND& for recipients awaiting delivery\\ + \tt AD\_STAT\_DONE& for recipients not to be delivered to\\ +\hline +\end{tabular}\] + +\item[\verb|ad\_dn|:] The distinguished name component of the address. + +\item[\verb|ad\_usrreq|:] This maps to the X.400 user request +bits. It has the one of the following values: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_USR\_NOREPORT& No delivery reports requested\\ + \tt AD\_USR\_BASIC& Delivery failutes should be reported\\ + \tt AD\_USR\_CONFIRM& Deliveries should be confirmed\\ + \tt AD\_USR\_NONE& Undefined value\\ +\hline +\end{tabular}\] + +\item[\verb|ad\_explicitconversion|:] Is explicit conversion +required. It should be one of the values defined in +Table~\ref{tbl:explicit}. + +\tagtable{explicit}{Table of Explicit Conversion Values}{tbl:explicit} + +\item[\verb|ad\_type|:] The address type. This is one of the following +values: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_X400\_TYPE& An X.400 format address\\ + \tt AD\_822\_TYPE& An RFC~822 format address\\ + \tt AD\_ANY\_TYPE& An address in any of the above formats\\ +\hline +\end{tabular}\] + +\item[\verb|ad\_orig\_req\_alt|:] The originator requested alternate +recipient, if supplied. + +\item[\verb|ad\_req\_del|:] The requested delivery method. This is +an array of delivery method alternatives. + +\item[\verb|ad\_phys\_forward|:] If physical forwarding is allowed. + +\item[\verb|ad\_phys\_fw\_ad\_req|:] A request to supply the +physical forwarding address of the recipient. + +\item[\verb|ad\_phys\_modes|:] Specifies the type of delivery required. + +\item[\verb|ad\_reg\_mail\_type|:] The type of registered mail in +use. + +\item[\verb|ad\_recip\_number\_for\_advice|:] The number for advice +to call for delivery. + +\item[\verb|ad\_phys\_rendition\_attribute|:] The physical rendition +attributes for the \linebreak[3] address when transfered to the postal service. + +\item[\verb|ad\_pd\_report\_request|:] An option to supply a physical +delivery report. + +\item[\verb|ad\_redirection\_history|:] The redirection history for +this address. + +\item[\verb|ad\_message\_token|:] A security parameter for message tokens. + +\item[\verb|ad\_content\_integrity|:] A content integrity check parameter. + +\item[\verb|ad\_proof\_delvery|:] Proof of delivery is requested. + +\item[\verb|ad\_resp |:] The responsibility bit. This should be +set to either \verb|TRUE| or \verb|FALSE|. + +\item[\verb|ad\_mtareq|:] This maps to the X.400 MTA +report request bits. It should be set to one of the following: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_MTA\_NONE& Undefined value\\ + \tt AD\_MTA\_BASIC& Generate Delivery failures\\ + \tt AD\_MTA\_CONFIRM& Generate Delivery confirmations\\ + \tt AD\_MTA\_AUDIT\_CONFIRM& Generate full trace confirmations\\ +\hline +\end{tabular}\] + +\item[\verb|ad\_subtype|:] The subtype of the address if +appropriate. This is only used for RFC~822 addresses at present. The +values are: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt AD\_NOSUBTYPE& No particular sub type\\ + \tt AD\_JNT& JANET style address\\ + \tt AD\_REAL733& RFC~733 style address\\ + \tt AD\_REAL822& RFC~822 style address\\ +\hline +\end{tabular}\] + +\item[\verb|ad\_pre\_recip\_ext\_list|:] A list of extension +attributes. + +\item[\verb|ad\_value|:] This is the address submitted. + +\item[\verb|ad\_next|:] The link to the next address if they are in a +linked list. +\end{describe} + +\subsection{Reply Value Structure} + +The reply value buffer structure is shown in +Figure~\ref{rpbuf:struct}. This is used in all handshakes with \pgm{submit} +to return a status and an explanatory string. + +\tagrind[hbp]{rpbstruct}{Reply Structure}{rpbuf:struct} + +The structure here is: + +\begin{describe}\index{Reply structure}\index{RP\_Buf} +\item[\verb|rp\_val|:] The value returned; this is one of those +defined in \file{retcode.h}. + +\item[\verb|rp\_line|:] An optional explanatory string. +\end{describe} + +\subsection {Procedure Calls} + +The submission interface is procedural and has a handshake at most of +the interaction points. This interaction is reasonably complex but +allows the submission to be flexible; this interface can be used to +validate address as well as to submit message. + +Most of these routines return a set of codes as defined in +\file{retcode.h} to indicate success or failure of the operation. The +codes indicate detailed status and are shown in +Table~\ref{tab:rpcodes}. Two macros are useful for determining the +general status of the reply. The behave as though they were defined as: +\begin{quote}\index{rp\_isgood}\index{rp\_isbad}\begin{verbatim} +int rp_isgood (code) +int code; + +int rp_isbad (code) +int code; +\end{verbatim}\end{quote} +where ``code'' is the return code. The macros return boolean values of +\verb|TRUE| if the code is generally good or bad respectively. + +\tagtable[hbtp]{rpcodes}{Return Codes}{tab:rpcodes} + +Along with other parameters, these routines usually take an +\verb|RP_Buf|\index{RP\_Buf} structure which is updated with the code +and an explanatory string if the routine fails in some way. + +\subsubsection{Initialisation} + +To initialise the submission system it is first necessary to call the +routine \verb|io_init|: +\begin{quote}\index{io\_init}\begin{verbatim} +int io_init (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +This call initialises the submission by either invoking \pgm{submit} +as a child process or by connecting to a \pgm{submit} daemon. It +returns a good or bad status, and fills in the \verb|rp| structure if +the response is bad. + +\subsubsection{Message Management Parameters} + +The first set of parameters to negotiate with \pgm{submit} are the +management parameters. These are defined in the structure in +Figure~\ref{prm:struct} on page~\pageref{prm:struct}. This structure +is passed over using the \verb|io_wprm| routine: +\begin{quote}\index{io\_wprm}\begin{verbatim} +int io_wprm (prm, rp) +struct prm_vars *prm; +RP_Buf *rp; +\end{verbatim}\end{quote} +The parameter structure is often only sparsely filled (or even empty), +as the default values assumed are usually correct for most common +submissions. + +\subsubsection{Per-Message Parameters} + +The next stage is the per-message parameters. This is achieved by +filling in a \verb|Q_struct|\index{Q\_struct} structure and passing it +to \pgm{submit}. +Once the structure is complete it can be written to \pgm{submit} using the +\verb|io_wrq| routine: +\begin{quote}\index{io\_wrq}\begin{verbatim} +io_wrq (qp, rp) +Q_struct *qp; +RP_Buf *rp; +\end{verbatim}\end{quote} + + +\subsubsection{Originator and Recipient Addresses} + +After the general parameters have been passed by the above routines, +the send is passed over in the standardised address structure. +The call to achieve this is the \verb|wr_adr| routine: +\begin{quote}\index{io\_wadr}\begin{verbatim} +int io_wadr (ap, type, rp) +ADDR *addr; +int type; +RP_Buf *rp; +\end{verbatim}\end{quote} +The type parameter is either \verb|AD_ORIGINATOR| or +\verb|AD_RECIPIENT|. First the originator address is passed over and +checked followed by the list of recipients. This is then followed by +each of the recipient addresses. In this way, each address is checked +and any failures can be pinpointed. + +When all the addresses have been submitted, the address list is +terminated with the call: +\begin{quote}\index{io\_adend}\begin{verbatim} +int io_adend (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +This concludes the preliminaries, and the body of the message can be +transferred. + +\subsubsection{Body Part Submission} + +The body parts presented are dependent on the type of message being +transferred. To initialise for body part submission, the following +function is called: +\begin{quote}\index{io\_tinit}\begin{verbatim} +io_tinit (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +This initialises for text submission. + +Following this call it is necessary to initialise for the first body +part. This is done by: +\begin{quote}\index{io\_tpart}\begin{verbatim} +int io_tpart (name, link, rp) +char *name; +int link; +RP_Buf *rp; +\end{verbatim}\end{quote} +The name is the name of this part, for an RFC~822 body part it is +usually something like \verb|hdr.822| and \verb|2.ia5| for the two +parts of the message. For X.400, it is more often just a single file +\verb|p2| or similar with the whole of the message in. The link +parameter is a Boolean value to indicate whether the name is actually +a secret link to another file in the queue to be linked with \man +link (2); this is only for use by special channels and normally will be +rejected by \pgm{submit}. If the link is false, then the data stream +is read for the body part contents. + +All Data is passed with the following routine: +\begin{quote}\index{io\_tdata}\begin{verbatim} +io_tdata (buffer, length) +char *buffer; +int length; +\end{verbatim}\end{quote} +The buffer is a pointer to an array of characters of length \verb|length|, +which are written into the file created by the \verb|io_tpart| call. + +Once the body part has been written, the +data stream is terminated by the call: +\begin{quote}\index{io\_tdend}\begin{verbatim} +io_tdend (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +which closes the stream and returns the status in rp. + +\subsubsection{Termination} + +Once all the body parts have been passed over the message is finally +submitted with the following call: +\begin{quote}\index{io\_tend}\begin{verbatim} +io_tend (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +This puts the message into the queue and allows it to be delivered. + + +Finally, the whole session with \pgm{submit} can be terminated using +the \verb|io_end| call. The termination can either be graceful, or a +program can, upon detecting an error, call an abort to the submission +process at any time with this function: +\begin{quote}\index{io\_end}\begin{verbatim} +int io_end (type) +int type; +\end{verbatim}\end{quote} +The \verb|type| parameter is set to one of the following: +\[\begin{tabular}{|l|l|} +\hline + \multicolumn{1}{|c|}{\bf Value}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt OK& The submission is successful\\ + \tt NOTOK& The submission should be aborted\\ +\hline +\end{tabular}\] + + +\subsection {Example} + +An example interaction with submit is shown in Figure~\ref{example:io}. + +\tagrindfile{io}{Example Interaction with Submit}{example:io} + +\section {The RFC~822 Interface} + +PP provides a full service interface, most of which is not needed by +RFC~822-based systems. A simplified interface is provided on top of +the \verb|io_| interface. This interface is characterised by procedure +calls with the prefix \verb|pps_| for PP simple interface. + +It assumes a large number of default parameters and does not allow for +much variation. It does provide an easy route for constructing +\pgm{/bin/mail}-like programs and can be used within programs to fire off +system generated messages. This interface runs as a state machine, +and the procedures must be called in the correct order to get the +correct results. + +All routines return the constant \verb|NOTOK| on failure and \verb|OK| +on success. The \verb|NOTOK| is unrecoverable, and the interface must +be started again from the beginning. All routines in addition take an +\verb|RP_Buf| pointer which is updated if the call fails. This may be +used to give better diagnostics. + +\subsection{Initialisation} + +To initialise this interface, a client program calls the +\verb|pps_init| routine. This attempts to initialise the association +with \pgm{submit}. +\begin{quote}\index{pps\_init}\small\begin{verbatim} +pps_init (subject, rp) +char *subject; +RP_Buf *rp; +\end{verbatim}\end{quote} +The parameters to this routine are: +\begin{describe} + +\item[\verb|subject|:] the subject line of the message, the constant +\verb|NULLCP| may be used if no subject line is required. + +\item[\verb|rp|:] An \verb|RP_Buf| structure pointer that is updated +if the call fails. +\end{describe} + +The errors produced by this call are usually the result of some deep +system problem, such as failing to connect with the \pgm{submit} process. + +\subsection{Addresses and Headers} + +To supply recipient addresses for the message, the routines +\verb|pps_adr|, \verb|pps_to| and \verb|pps_cc| are called. The +\verb|pps_adr| supplies a new address to the system for this message. +Use of the \verb|pps_to| and \verb|pps_cc| routines switches the +status of the address between that of primary recipient and secondary +recipient (i.e., the To and CC header lines). +\begin{quote}\index{pps\_adr}\index{pps\_to}\index{pps\_cc}\begin{verbatim} +pps_adr (address, rp) +char *address; +RP_Buf *rp; + +pps_to(rp) +RP_Buf *rp; + +pps_cc(rp) +RP_Buf *rp; +\end{verbatim}\end{quote} +The arguments are: +\begin{describe} +\item[\verb|address|:] The recipient address as a legal RFC~822 +format address. + +\item[\verb|rp|:] An \verb|RP_Buf| structure pointer that is updated +if the call fails. +\end{describe} +The possible errors from these calls usually arise from the failure to +call \verb|pps_init|. The \verb|pps_to| and \verb|pps_cc| calls are +entirely optional and may be interspersed with the \verb|pps_adr| +calls in any order. + +Finally, when the addresses have all been submitted, the address phase +is ended by calling \verb|pps_aend|. +\begin{quote}\index{pps\_aend}\begin{verbatim} +pps_aend (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} + +At this stage, other headers may optionally be added by the +\verb|pps_hdr| routine. This is normally not necessary as the header +fields \verb|To|, \verb|Cc|, \verb|From|, and \verb|Date| will +automatically be generated. +\begin{quote}\index{pps\_hdr}\begin{verbatim} +pps_hdr (name, contents, rp) +char *name, + *contents; +RP_Buf *rp; +\end{verbatim}\end{quote} + +If the message is only being submitted to one recipient, there is a +shorthand form which replaces the routines from \verb|pps_init| up to +and including the \verb|pps_tinit| call. This routine, \verb|pps_1adr|, +is occasionally useful for submitting error reports to the system +administrator or similar. +\begin{quote}\index{pps\_1adr}\begin{verbatim} +pps_1adr (subject, address, rp) +char *subject, + *address; +RP_Buf *rp; +\end{verbatim}\end{quote} +The parameters to this routine are: +\begin{describe} +\item[\verb|subject|:] The subject of the message. As above this can +be the constant \verb|NULLCP| for no subject. + +\item[\verb|address|:] The RFC~822 format recipient address +\end{describe} + +\subsection{Text Submission} + +To add the body of the message, the routine \verb|pps_tinit| is called +first to initialise for text. This terminates the header part of the +message and prepares for the text to be submitted. +\begin{quote}\index{pps\_tinit}\begin{verbatim} +pps_tinit (rp) +RP_Buf *rp; +\end{verbatim}\end{quote} + +The text is then submitted in two ways. The first method is as a +sequence of null terminated character strings using the \verb|pps_txt| +routine. The second method is by passing an open file descriptor to +the routine \verb|pps_file|. +\begin{quote}\index{pps\_txt}\index{pps\_file}\begin{verbatim} +pps_txt (string, rp) +char *string; +RP_Buf *rp; + +pps_file (fp, rp) +FILE *fp; +RP_Buf *rp; +\end{verbatim}\end{quote} +The parameters to these calls are: +\begin{describe} +\item[\verb|string|:] A null terminated string of characters. + +\item[\verb|file|:] A stdio file stream opened for reading. This is +read up to the end of file. +\end{describe} +These calls may be freely intermixed in any fashion. + +\subsection{Termination} + +To finally submit the message, it is necessary to call the routine +\verb|pps_end|. This terminates the interaction for this message and +resets the state. +\begin{quote}\index{pps\_end}\begin{verbatim} +pps_end (status, rp) +int status; +RP_Buf *rp; +\end{verbatim}\end{quote} +The status parameter is either \verb|OK| if the submission +is satisfactory and \verb|NOTOK| if the submission is to be +aborted. The \verb|NOTOK| version may be called at any point to +abort the submission and return to the \verb|pps_init| state. + +\section {Debugging}\index{debugging} + +Most of the debugging can be done through the logs. Typically turning +the logging levels to include trace and debug will give large amounts +of information and will slow the processes down considerably! The +system should not normally be run with full logging for these reasons. + +The use of the \verb|PP_TRACE|\index{PP\_TRACE} and +\verb|PP_DBG|\index{PP\_DBG} macros described in Section~\ref{logging} +on page~\pageref{logging} are very useful for inclusion in program +text. the \verb|PP_TRACE| should be used to indicate the flow of +control. Usually a \verb|PP_TRACE| call is included in each +significant procedure call and typically displays the procedure name +and any useful information about procedure arguments. + +The \verb|PP_DBG| macro is used anywhere that very detailed tracing +might be needed such as printing out individual variables or similar. +In particular, library routines usually use this macro to log tracing, +as this sort of logging is not required as often as the tracing in +programs. + +The \verb|PP_NOTICE|\index{PP\_NOTICE} call should be used when +interesting events happen to allow the progress of the program to be +monitored. + +The \verb|PP_PDUS|\index{PP\_PDUS} macro and the \verb|LLOG_PDUS| +logging level should be used to log any protocol exchanges that might +be of interest. diff --git a/doc/manual/volume2/tablecrit.tex b/doc/manual/volume2/tablecrit.tex new file mode 100644 index 0000000..c72e142 --- /dev/null +++ b/doc/manual/volume2/tablecrit.tex @@ -0,0 +1,11 @@ +\[\begin{tabular}{|l| l|} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt CRITICAL\_NONE& Not critical\\ + \tt CRITICAL\_SUBMISSION& Critical for submission\\ + \tt CRITICAL\_TRANSFER& Critical for Transfer\\ + \tt CRITICAL\_DELIVERY& Critical for Delivery\\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume2/tablediag.tex b/doc/manual/volume2/tablediag.tex new file mode 100644 index 0000000..e68280b --- /dev/null +++ b/doc/manual/volume2/tablediag.tex @@ -0,0 +1,33 @@ +\[\begin{tabular}{|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Diagnostic}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt DRD\_UNRECOGNISED\_OR & + The sender or recipient name is unknown\\ + \tt DRD\_AMBIGUOUS\_OR & + The sender or recipient name is ambiguous\\ + \tt DRD\_MTA\_CONGESTION & + Problems with the MTA (catch all!)\\ + \tt DRD\_LOOP\_DETECTED & + A loop has been detected in routing\\ + \tt DRD\_UA\_UNAVAILABLE & + The user agent is not available\\ + \tt DRD\_MAX\_TIME\_EXPIRED & + The message was not delivered before the specified +delivery time\\ + \tt DRD\_ENCINFOTYPES\_NOTSUPPORTED & + The encoded information types are not supported at the +destination\\ + \tt DRD\_CONTENT\_TOO\_LONG & + The message is too big to be delivered \\ + \tt DRD\_CONVERSION\_IMPRACTICAL & + The conversion required by this message is not sensible\\ + \tt DRD\_CONVERSION\_PROHIBITED & + The conversion required for delivery is prohibitied\\ + \tt DRD\_IMPLICITCONV\_NOTREGISTERED & + The implicit conversion required can't be performed\\ + \tt DRD\_INVALID\_PARAMETERS & + There is a problem with the message parameters\\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume2/tableexplicit.tex b/doc/manual/volume2/tableexplicit.tex new file mode 100644 index 0000000..a59e081 --- /dev/null +++ b/doc/manual/volume2/tableexplicit.tex @@ -0,0 +1,27 @@ +\[\begin{tabular}{|l|} +\hline + \multicolumn{1}{|c|}{\bf Value} \\ +\hline + \tt AD\_EXP\_NONE \\ + \tt AD\_EXP\_IA5\_TEXT\_TO\_TELETEX \\ + \tt AD\_EXP\_TELETEX\_TO\_TELEX \\ + \tt AD\_EXP\_TELEX\_TO\_IA5\_TEXT \\ + \tt AD\_EXP\_TELEX\_TO\_TELETEX \\ + \tt AD\_EXP\_TELEX\_TO\_G4\_CLASS\_1 \\ + + + \tt AD\_EXP\_TELEX\_TO\_VIDEOTEX \\ + \tt AD\_EXP\_IA5\_TEXT\_TO\_TELEX \\ + \tt AD\_EXP\_TELEX\_TO\_G3\_FACSIMILE \\ + \tt AD\_EXP\_IA5\_TEXT\_TO\_G3\_FACSIMILE \\ + \tt AD\_EXP\_IA5\_TEXT\_TO\_G4\_CLASS\_1 \\ + \tt AD\_EXP\_IA5\_TEXT\_TO\_VIDEOTEX \\ + \tt AD\_EXP\_TELETEX\_TO\_IA5\_TEXT \\ + \tt AD\_EXP\_TELETEX\_TO\_G3\_FACSIMILE \\ + \tt AD\_EXP\_TELETEX\_TO\_G4\_CLASS\_1 \\ + \tt AD\_EXP\_TELETEX\_TO\_VIDEOTEX \\ + \tt AD\_EXP\_VIDEOTEX\_TO\_TELEX \\ + \tt AD\_EXP\_VIDEOTEX\_TO\_IA5\_TEXT \\ + \tt AD\_EXP\_VIDEOTEX\_TO\_TELETEX \\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume2/tablelog.tex b/doc/manual/volume2/tablelog.tex new file mode 100644 index 0000000..b029e09 --- /dev/null +++ b/doc/manual/volume2/tablelog.tex @@ -0,0 +1,13 @@ +\normalsize +\[\begin{tabular}{r l} + +\tt LLOG\_NONE& Not logged \\ +\tt LLOG\_FATAL& Fatal errors \\ +\tt LLOG\_EXCEPTIONS& Exceptional events \\ +\tt LLOG\_NOTICE& General information \\ +\tt LLOG\_PDUS& Printing of Protocol Data Units\\ +\tt LLOG\_TRACE& Program Tracing \\ +\tt LLOG\_DEBUG& Full debugging\\ +\tt LLOG\_ALL& All Values \\ + +\end{tabular}\] diff --git a/doc/manual/volume2/tablemuflags.tex b/doc/manual/volume2/tablemuflags.tex new file mode 100644 index 0000000..b478131 --- /dev/null +++ b/doc/manual/volume2/tablemuflags.tex @@ -0,0 +1,20 @@ +\[\begin{tabular}{ll} +Flag & Purpose\\[1ex] + +default & override mu.defaults\\ +file & input from file(s)\\ +value & command line specification of value\\ +body & body part file name(s)\\ +tree & directory name(s) (not yet implemented)\\ +confirm & wait for y/n after \verb+$+ substitution\\ +nofix & ignore errors resulting from user input\\ +help & list flag table analysis\\ +-- & same as --help\\ +! & dummy next flag to terminate sequence ( future use )\\ +0 & debug (see above)\\ +1 & debug\\ +2 & debug\\ +3 & debug\\ +4 & debug\\ + +\end{tabular}\] diff --git a/doc/manual/volume2/tablereason.tex b/doc/manual/volume2/tablereason.tex new file mode 100644 index 0000000..41bad32 --- /dev/null +++ b/doc/manual/volume2/tablereason.tex @@ -0,0 +1,24 @@ +\[\begin{tabular}{|l|p{0.4\textwidth}|} +\hline + \multicolumn{1}{|c|}{\bf Reason}& + \multicolumn{1}{|c|}{\bf Meaning}\\ +\hline + \tt DRR\_NO\_REASON& + No reason is given for the failure (should not be used + normally)\\ + \tt DRR\_TRANSFER\_FAILURE& + Unable to transfer the message to the destination \\ + \tt DRR\_UNABLE\_TO\_TRANSFER& + There is a problem with the message that causes the failure\\ + \tt DRR\_CONVERSION\_NOT\_PERFORMED& + A conversion is required and cannot be done\\ + \tt DRR\_PHYS\_RENDITION\_NOT\_PERFORMED& + Can not print the message in the required format\\ + \tt DRR\_PHYS\_DELIVERY\_NOT\_PERFORMED& + Physical delivery of the message didn't work\\ + \tt DRR\_RESTRICTED\_DELIVERY& + The recipient subscribes to a restricted delivery service.\\ + \tt DRR\_DIRECTORY\_OP\_UNSUCCESSFUL& + A required directory operation failed\\ +\hline +\end{tabular}\] diff --git a/doc/manual/volume2/tablerpcodes.tex b/doc/manual/volume2/tablerpcodes.tex new file mode 100644 index 0000000..211ffdb --- /dev/null +++ b/doc/manual/volume2/tablerpcodes.tex @@ -0,0 +1,38 @@ +\[\begin{tabular}{r l} + \multicolumn{1}{c}{\bf Value}& + \multicolumn{1}{c}{\bf Meaning}\\ + \tt RP\_DONE & General purpose done value \\ + \tt RP\_OK & General purpose OK value \\ + \tt RP\_MOK & Message accepted \\ + \tt RP\_MAST & Master side \\ + \tt RP\_SLAV & Slave side\\ + \tt RP\_AOK & Address OK \\ + \tt RP\_HOK & Host OK \\ + \tt RP\_AGN & Temporary failure\\ + \tt RP\_TIME & Timeout\\ + \tt RP\_NOOP & No op\\ + \tt RP\_EOF & End of file\\ + \tt RP\_NET & Network failure\\ + \tt RP\_BHST & Bad host interaction\\ + \tt RP\_DHST & destination connection broke\\ + \tt RP\_NIO & Network I/O problem\\ + \tt RP\_NS & Temporary nameserver failure\\ + \tt RP\_FIO & File I/O problem\\ + \tt RP\_FCRT & File creation problem\\ + \tt RP\_FOPN & File opening problem\\ + \tt RP\_LIO & Local I/O problem\\ + \tt RP\_LOCK & Resource locked\\ + \tt RP\_MECH & Mechanism failed\\ + \tt RP\_NO & General purpose failure\\ + \tt RP\_BAD & General purpose failure\\ + \tt RP\_PROT & General protocol failure\\ + \tt RP\_RPLY & Bad reply code\\ + \tt RP\_NAUTH & Bad authorisation\\ + \tt RP\_NDEL & Couldn't deliver\\ + \tt RP\_HUH & Parse error\\ + \tt RP\_NCMD & No such command\\ + \tt RP\_PARM & Bad parameter\\ + \tt RP\_UCMD & Unknown command\\ + \tt RP\_PARSE & Address parse error\\ + \tt RP\_USER & Unknown user\\ +\end{tabular}\] diff --git a/doc/manual/volume2/version.sh b/doc/manual/volume2/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/manual/volume2/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/manual/volume2/volume2.aux b/doc/manual/volume2/volume2.aux new file mode 100644 index 0000000..cfaa5a6 --- /dev/null +++ b/doc/manual/volume2/volume2.aux @@ -0,0 +1,5 @@ +\relax +\@input{preface.aux} +\@input{general.aux} +\@input{submission.aux} +\@input{channels.aux} diff --git a/doc/manual/volume2/volume2.idx b/doc/manual/volume2/volume2.idx new file mode 100644 index 0000000..00a7187 --- /dev/null +++ b/doc/manual/volume2/volume2.idx @@ -0,0 +1,175 @@ +\indexentry{sys\_init}{1} +\indexentry{pp\_initialise}{1} +\indexentry{pp/Lib/tai/tai\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}sys.c}{2} +\indexentry{isode/logger.h}{2} +\indexentry{LLog}{2} +\indexentry{log\_norm}{2} +\indexentry{log\_stat}{2} +\indexentry{log\_oper}{2} +\indexentry{ll\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}log.h}{3} +\indexentry{PP\_LOG}{3} +\indexentry{PP\_SLOG}{4} +\indexentry{PP\_OPER}{4} +\indexentry{PP\_STAT}{4} +\indexentry{PP\_NOTICE}{4} +\indexentry{PP\_TRACE}{5} +\indexentry{PP\_DBG}{5} +\indexentry{PP\_DEBUG\_ALL}{5} +\indexentry{PP\_PDU}{5} +\indexentry{ASN.1}{5} +\indexentry{PP\_DEBUG\_SOME}{5} +\indexentry{ASN.1}{5} +\indexentry{SLOG}{5} +\indexentry{Lib/}{6} +\indexentry{addr/}{6} +\indexentry{format/}{6} +\indexentry{io/}{6} +\indexentry{or/}{6} +\indexentry{parse/}{6} +\indexentry{pp/}{6} +\indexentry{qmgr/}{6} +\indexentry{table/}{6} +\indexentry{tai/}{6} +\indexentry{tailor}{6} +\indexentry{util/}{6} +\indexentry{x400/}{6} +\indexentry{Src/}{6} +\indexentry{MTAconsole/}{6} +\indexentry{LINEconsole}{6} +\indexentry{lconsole}{6} +\indexentry{submit/}{7} +\indexentry{qmgr/}{7} +\indexentry{pptsapd/}{7} +\indexentry{h/}{7} +\indexentry{doc/}{7} +\indexentry{man/}{7} +\indexentry{Uip/}{7} +\indexentry{Tools/}{7} +\indexentry{Chans/}{7} +\indexentry{submit protocol}{8} +\indexentry{submit}{8} +\indexentry{list\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}rchan.h}{9} +\indexentry{LIST\_RCHAN}{9} +\indexentry{list\_rchan\_new}{9} +\indexentry{list\_rchan\_add}{10} +\indexentry{list\_rchan\_free}{10} +\indexentry{ch\_nm2struct}{10} +\indexentry{ch\_mta2struct}{10} +\indexentry{list\_bpt\_new}{10} +\indexentry{list\_bpt\_dup}{11} +\indexentry{list\_bpt\_add}{11} +\indexentry{list\_bpt\_find}{11} +\indexentry{list\_bpt\_free}{11} +\indexentry{prm.h}{11} +\indexentry{submit}{11} +\indexentry{prm\_init}{11} +\indexentry{prm\_free}{11} +\indexentry{struct~prm\_vars}{11} +\indexentry{parameter structure}{11} +\indexentry{prm}{11} +\indexentry{ll\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}log.h}{12} +\indexentry{submit}{12} +\indexentry{submit}{12} +\indexentry{submit}{12} +\indexentry{q.h}{12} +\indexentry{submit}{12} +\indexentry{Q\_struct}{14} +\indexentry{q\_init}{14} +\indexentry{q\_free}{14} +\indexentry{queue structure}{14} +\indexentry{Q\_struct}{14} +\indexentry{addressing}{17} +\indexentry{adr.h}{17} +\indexentry{adr\_new}{17} +\indexentry{adr\_init}{17} +\indexentry{adr\_add}{18} +\indexentry{adr\_tfree}{18} +\indexentry{adr\_free}{18} +\indexentry{address structure}{20} +\indexentry{ADDR}{20} +\indexentry{submit}{22} +\indexentry{Reply structure}{22} +\indexentry{RP\_Buf}{22} +\indexentry{retcode.h}{23} +\indexentry{retcode.h}{23} +\indexentry{rp\_isgood}{23} +\indexentry{rp\_isbad}{23} +\indexentry{RP\_Buf}{23} +\indexentry{io\_init}{23} +\indexentry{submit}{23} +\indexentry{submit}{23} +\indexentry{submit}{23} +\indexentry{io\_wprm}{23} +\indexentry{Q\_struct}{25} +\indexentry{submit}{25} +\indexentry{submit}{25} +\indexentry{io\_wrq}{25} +\indexentry{io\_wadr}{25} +\indexentry{io\_adend}{25} +\indexentry{io\_tinit}{25} +\indexentry{io\_tpart}{25} +\indexentry{link {}}{26} +\indexentry{submit}{26} +\indexentry{io\_tdata}{26} +\indexentry{io\_tdend}{26} +\indexentry{io\_tend}{26} +\indexentry{submit}{26} +\indexentry{io\_end}{26} +\indexentry{/bin/mail}{28} +\indexentry{submit}{28} +\indexentry{pps\_init}{28} +\indexentry{submit}{28} +\indexentry{pps\_adr}{28} +\indexentry{pps\_to}{28} +\indexentry{pps\_cc}{28} +\indexentry{pps\_aend}{29} +\indexentry{pps\_hdr}{29} +\indexentry{pps\_1adr}{29} +\indexentry{pps\_tinit}{29} +\indexentry{pps\_txt}{30} +\indexentry{pps\_file}{30} +\indexentry{pps\_end}{30} +\indexentry{debugging}{30} +\indexentry{PP\_TRACE}{30} +\indexentry{PP\_DBG}{30} +\indexentry{PP\_NOTICE}{30} +\indexentry{PP\_PDUS}{30} +\indexentry{type\_Qmgr\_DeliveryStatus}{31} +\indexentry{type\_Qmgr\_Channel}{31} +\indexentry{type\_Qmgr\_ProcMsg}{31} +\indexentry{type\_Qmgr\_QID}{31} +\indexentry{type\_Qmgr\_RecipientId}{31} +\indexentry{channel\_control}{33} +\indexentry{pptsapd {}}{33} +\indexentry{status\_success}{34} +\indexentry{status\_negativeDR}{34} +\indexentry{status\_positiveDR}{34} +\indexentry{status\_successSharedDR}{34} +\indexentry{status\_failureSharedDR}{34} +\indexentry{status\_messageFailure}{34} +\indexentry{status\_mtaFailure}{34} +\indexentry{status\_mtaAndMessageFailure}{34} +\indexentry{delivery\_init}{35} +\indexentry{delivery\_set}{35} +\indexentry{delivery\_setall}{35} +\indexentry{delivery\_resetDRs}{35} +\indexentry{rd\_msg}{36} +\indexentry{rd\_end}{36} +\indexentry{wr\_ad\_status}{36} +\indexentry{wr\_ad\_rcntno}{36} +\indexentry{qid2dir}{37} +\indexentry{msg\_rinit}{37} +\indexentry{msg\_rfile}{37} +\indexentry{msg\_rend}{37} +\indexentry{set\_1dr}{38} +\indexentry{dr.h}{38} +\indexentry{wr\_q2dr}{39} +\indexentry{wr\_stat}{39} +\indexentry{chan\_acheck}{40} +\indexentry{lchan\_acheck}{40} +\indexentry{chan\_dcheck}{40} +\indexentry{ad\_parse}{44} +\indexentry{ad\_getlocal}{44} +\indexentry{fcontrol}{45} +\indexentry{qid2dir}{45} +\indexentry{\LaTeX {}}{47} diff --git a/doc/manual/volume2/volume2.ind b/doc/manual/volume2/volume2.ind new file mode 100644 index 0000000..c11b3a2 --- /dev/null +++ b/doc/manual/volume2/volume2.ind @@ -0,0 +1,188 @@ +\begin{theindex}\makeatletter +\raggedright +\def\newindex#1{{\huge\hspace{-.5in}\parbox[t]{.5in}{\makebox[.35in][c]{\uppercase{#1}}}\vspace{-1.5ex}}} +\newindex{a} +\item addr/, 6 +\item ADDR, 20 +\item address structure, 20 +\item addressing, 17 +\item ad\_getlocal, 44 +\item ad\_parse, 44 +\item adr\_add, 18 +\item adr\_free, 18 +\item adr.h, 17 +\item adr\_init, 17 +\item adr\_new, 17 +\item adr\_tfree, 18 +\item ASN.1, 5 +\indexspace +\newindex{b} +\item /bin/mail, 28 +\indexspace +\newindex{c} +\item chan\_acheck, 40 +\item chan\_dcheck, 40 +\item channel\_control, 33 +\item Chans/, 7 +\item ch\_mta2struct, 10 +\item ch\_nm2struct, 10 +\indexspace +\newindex{d} +\item debugging, 30 +\item delivery\_init, 35 +\item delivery\_resetDRs, 35 +\item delivery\_set, 35 +\item delivery\_setall, 35 +\item doc/, 7 +\item dr.h, 38 +\indexspace +\newindex{f} +\item fcontrol, 45 +\item format/, 6 +\indexspace +\newindex{h} +\item h/, 7 +\indexspace +\newindex{i} +\item io/, 6 +\item io\_adend, 25 +\item io\_end, 26 +\item io\_init, 23 +\item io\_tdata, 26 +\item io\_tdend, 26 +\item io\_tend, 26 +\item io\_tinit, 25 +\item io\_tpart, 25 +\item io\_wadr, 25 +\item io\_wprm, 23 +\item io\_wrq, 25 +\item isode/logger.h, 2 +\indexspace +\newindex{l} +\item \LaTeX {}, 47 +\item lchan\_acheck, 40 +\item lconsole, 6 +\item Lib/, 6 +\item LINEconsole, 6 +\item link, 26 +\item list\_bpt\_add, 11 +\item list\_bpt\_dup, 11 +\item list\_bpt\_find, 11 +\item list\_bpt\_free, 11 +\item list\_bpt\_new, 10 +\item LIST\_RCHAN, 9 +\item list\_rchan\_add, 10 +\item list\_rchan\_free, 10 +\item list\_rchan\_new, 9 +\item list\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}rchan.h, 9 +\item LLog, 2 +\item ll\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}log.h, 3, 12 +\item log\_norm, 2 +\item log\_oper, 2 +\item log\_stat, 2 +\indexspace +\newindex{m} +\item man/, 7 +\item msg\_rend, 37 +\item msg\_rfile, 37 +\item msg\_rinit, 37 +\item MTAconsole/, 6 +\indexspace +\newindex{o} +\item or/, 6 +\indexspace +\newindex{p} +\item parameter structure, 11 +\item parse/, 6 +\item pp/, 6 +\item PP\_DBG, 5, 30 +\item PP\_DEBUG\_ALL, 5 +\item PP\_DEBUG\_SOME, 5 +\item pp\_initialise, 1 +\item pp/Lib/tai/tai\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}sys.c, 2 +\item PP\_LOG, 3 +\item PP\_NOTICE, 4, 30 +\item PP\_OPER, 4 +\item PP\_PDU, 5 +\item PP\_PDUS, 30 +\item pps\_1adr, 29 +\item pps\_adr, 28 +\item pps\_aend, 29 +\item pps\_cc, 28 +\item pps\_end, 30 +\item pps\_file, 30 +\item pps\_hdr, 29 +\item pps\_init, 28 +\item PP\_SLOG, 4 +\item PP\_STAT, 4 +\item pps\_tinit, 29 +\item pps\_to, 28 +\item pps\_txt, 30 +\item PP\_TRACE, 5, 30 +\item pptsapd/, 7 +\item pptsapd, 33 +\item prm, 11 +\item prm\_free, 11 +\item prm.h, 11 +\item prm\_init, 11 +\indexspace +\newindex{q} +\item q\_free, 14 +\item q.h, 12 +\item qid2dir, 37, 45 +\item q\_init, 14 +\item qmgr/, 6, 7 +\item Q\_struct, 14, 25 +\item queue structure, 14 +\indexspace +\newindex{r} +\item rd\_end, 36 +\item rd\_msg, 36 +\item Reply structure, 22 +\item retcode.h, 23 +\item RP\_Buf, 22, 23 +\item rp\_isbad, 23 +\item rp\_isgood, 23 +\indexspace +\newindex{s} +\item set\_1dr, 38 +\item SLOG, 5 +\item Src/, 6 +\item status\_failureSharedDR, 34 +\item status\_messageFailure, 34 +\item status\_mtaAndMessageFailure, 34 +\item status\_mtaFailure, 34 +\item status\_negativeDR, 34 +\item status\_positiveDR, 34 +\item status\_success, 34 +\item status\_successSharedDR, 34 +\item struct~prm\_vars, 11 +\item submit/, 7 +\item submit, 8, 11, 12, 22, 23, 25, 26, 28 +\item submit protocol, 8 +\item sys\_init, 1 +\indexspace +\newindex{t} +\item table/, 6 +\item tai/, 6 +\item tailor, 6 +\item Tools/, 7 +\item type\_Qmgr\_Channel, 31 +\item type\_Qmgr\_DeliveryStatus, 31 +\item type\_Qmgr\_ProcMsg, 31 +\item type\_Qmgr\_QID, 31 +\item type\_Qmgr\_RecipientId, 31 +\indexspace +\newindex{u} +\item Uip/, 7 +\item util/, 6 +\indexspace +\newindex{w} +\item wr\_ad\_rcntno, 36 +\item wr\_ad\_status, 36 +\item wr\_q2dr, 39 +\item wr\_stat, 39 +\indexspace +\newindex{x} +\item x400/, 6 +\end{theindex} diff --git a/doc/manual/volume2/volume2.lof b/doc/manual/volume2/volume2.lof new file mode 100644 index 0000000..8e55435 --- /dev/null +++ b/doc/manual/volume2/volume2.lof @@ -0,0 +1,13 @@ +\addvspace {10pt} +\addvspace {10pt} +\contentsline {figure}{\numberline {2.1}{\ignorespaces Channel List Structure}}{9} +\contentsline {figure}{\numberline {2.2}{\ignorespaces Encoded Information Type Structure}}{10} +\contentsline {figure}{\numberline {2.3}{\ignorespaces Management Parameter Structure}}{11} +\contentsline {figure}{\numberline {2.4}{\ignorespaces Queue Structure}}{14} +\contentsline {figure}{\numberline {2.5}{\ignorespaces Address Structure}}{20} +\contentsline {figure}{\numberline {2.6}{\ignorespaces Reply Structure}}{22} +\contentsline {figure}{\numberline {2.7}{\ignorespaces Example Interaction with Submit}}{27} +\addvspace {10pt} +\contentsline {figure}{\numberline {3.1}{\ignorespaces Channel / Queue Manager Interface Structures}}{32} +\contentsline {figure}{\numberline {3.2}{\ignorespaces Example Outbound Channel}}{43} +\contentsline {figure}{\numberline {3.3}{\ignorespaces Example Delivery Report Generation}}{45} diff --git a/doc/manual/volume2/volume2.lot b/doc/manual/volume2/volume2.lot new file mode 100644 index 0000000..41db14b --- /dev/null +++ b/doc/manual/volume2/volume2.lot @@ -0,0 +1,8 @@ +\addvspace {10pt} +\contentsline {table}{\numberline {1.1}{\ignorespaces Logging Levels}}{3} +\addvspace {10pt} +\contentsline {table}{\numberline {2.1}{\ignorespaces Criticality Codes}}{14} +\contentsline {table}{\numberline {2.2}{\ignorespaces Table of Explicit Conversion Values}}{21} +\contentsline {table}{\numberline {2.3}{\ignorespaces Return Codes}}{24} +\addvspace {10pt} +\contentsline {table}{\numberline {3.1}{\ignorespaces Reason Codes}}{39} diff --git a/doc/manual/volume2/volume2.major b/doc/manual/volume2/volume2.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/manual/volume2/volume2.major @@ -0,0 +1 @@ +1 diff --git a/doc/manual/volume2/volume2.minor b/doc/manual/volume2/volume2.minor new file mode 100644 index 0000000..fa8f08c --- /dev/null +++ b/doc/manual/volume2/volume2.minor @@ -0,0 +1 @@ +150 diff --git a/doc/manual/volume2/volume2.tex b/doc/manual/volume2/volume2.tex new file mode 100644 index 0000000..5f07034 --- /dev/null +++ b/doc/manual/volume2/volume2.tex @@ -0,0 +1,79 @@ +% -*- LaTeX -*- +% run this through LaTeX + +% SEK - this is a PP document, designed to be easy to convert to +% an ISODE Manual Section if we want to + +\input lcustom + +\documentstyle[11pt,sfwmac,tgrind,twoside,a4]{report} + +\makeatletter +\def\preface{\chapter*{Preface\@mkboth{PREFACE}{PREFACE}}} +\makeatother +\makeindex + +\input{dist-params} + +\newcount\volnum +\volnum=2 + +\pagenumbering{roman} + +\begin{document} + +\title{{\Huge\bf PP}\vskip 1.5em + \LARGE\sl Volume 2: Programmer's Guide} +\author{Julian Onions \\ X-Tel Services Ltd} + + +\date{\ifdraft \versiondate/\\ \tt Draft Version \versiontag/\else + \today\\ + (Version \ppversion/)\fi} + +\maketitle +\newpage + +\thispagestyle{empty} +\setcounter{page}{0} +\mbox{} +\newpage + +\tableofcontents + +\listoftables + +\listoffigures + +\include{preface} + +\newpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi +\pagenumbering{arabic} + +% \part {Introduction} +% \include{introduction} + +% \part {Programming PP} +\include{general} +\include{submission} +\include{channels} +%\include{delivery} + +% \bibliography{bcustom,sfwdoc,networking} +% \bibliographystyle{alpha} + +\input volume2.ind + +\clearpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi + +%\typeout{you can usually ignore the message about Label(s) may have changed} + +\end{document} diff --git a/doc/manual/volume2/volume2.toc b/doc/manual/volume2/volume2.toc new file mode 100644 index 0000000..de00e20 --- /dev/null +++ b/doc/manual/volume2/volume2.toc @@ -0,0 +1,56 @@ +\contentsline {chapter}{\numberline {1}General}{1} +\contentsline {section}{\numberline {1.1}Overview}{1} +\contentsline {section}{\numberline {1.2}Initialisation}{1} +\contentsline {section}{\numberline {1.3}Runtime Tailoring}{2} +\contentsline {section}{\numberline {1.4}Logging}{2} +\contentsline {subsection}{\numberline {1.4.1}Logging Levels}{2} +\contentsline {subsection}{\numberline {1.4.2}Logging Structures}{2} +\contentsline {subsection}{\numberline {1.4.3}Logging Macros}{3} +\contentsline {section}{\numberline {1.5}Code Location}{5} +\contentsline {subsection}{\numberline {1.5.1}Library Code}{6} +\contentsline {subsection}{\numberline {1.5.2}Core Programs}{6} +\contentsline {subsection}{\numberline {1.5.3}Other Directories}{7} +\contentsline {chapter}{\numberline {2}Message Submission}{8} +\contentsline {section}{\numberline {2.1}Overview}{8} +\contentsline {section}{\numberline {2.2}The io\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em} Interface}{8} +\contentsline {subsection}{\numberline {2.2.1}Major Structures}{8} +\contentsline {subsubsection}{Channel Lists}{9} +\contentsline {subsubsection}{Encoded Information Types}{10} +\contentsline {subsubsection}{Management Parameters}{11} +\contentsline {subsubsection}{The Per-Message Information}{12} +\contentsline {subsubsection}{The Address structure}{17} +\contentsline {subsection}{\numberline {2.2.2}Reply Value Structure}{22} +\contentsline {subsection}{\numberline {2.2.3}Procedure Calls}{23} +\contentsline {subsubsection}{Initialisation}{23} +\contentsline {subsubsection}{Message Management Parameters}{23} +\contentsline {subsubsection}{Per-Message Parameters}{25} +\contentsline {subsubsection}{Originator and Recipient Addresses}{25} +\contentsline {subsubsection}{Body Part Submission}{25} +\contentsline {subsubsection}{Termination}{26} +\contentsline {subsection}{\numberline {2.2.4}Example}{26} +\contentsline {section}{\numberline {2.3}The RFC\penalty \@M \ 822 Interface}{28} +\contentsline {subsection}{\numberline {2.3.1}Initialisation}{28} +\contentsline {subsection}{\numberline {2.3.2}Addresses and Headers}{28} +\contentsline {subsection}{\numberline {2.3.3}Text Submission}{29} +\contentsline {subsection}{\numberline {2.3.4}Termination}{30} +\contentsline {section}{\numberline {2.4}Debugging}{30} +\contentsline {chapter}{\numberline {3}Channels}{31} +\contentsline {section}{\numberline {3.1}Overview}{31} +\contentsline {section}{\numberline {3.2}The Queue Interface}{31} +\contentsline {subsection}{\numberline {3.2.1}Major Structures}{31} +\contentsline {subsection}{\numberline {3.2.2}Basic Access}{33} +\contentsline {subsubsection}{Queue Manager Interaction}{33} +\contentsline {subsubsection}{Address File Routines}{36} +\contentsline {subsubsection}{Message files}{37} +\contentsline {subsection}{\numberline {3.2.3}Delivery Notifications}{38} +\contentsline {subsection}{\numberline {3.2.4}Successful Delivery}{39} +\contentsline {subsection}{\numberline {3.2.5}Verification and Trust}{40} +\contentsline {section}{\numberline {3.3}Example Usage}{41} +\contentsline {subsection}{\numberline {3.3.1}Outbound Channels}{41} +\contentsline {subsection}{\numberline {3.3.2}Address Parsing}{43} +\contentsline {subsection}{\numberline {3.3.3}Local Pickup}{44} +\contentsline {subsection}{\numberline {3.3.4}TWA Channel}{44} +\contentsline {subsection}{\numberline {3.3.5}Delivery Reports}{45} +\contentsline {section}{\numberline {3.4}Formatters and Converters}{45} +\contentsline {subsection}{\numberline {3.4.1}Simple Converters}{45} +\contentsline {subsection}{\numberline {3.4.2}Complex Filters}{45} diff --git a/doc/manual/volume2/volume2.vrsn b/doc/manual/volume2/volume2.vrsn new file mode 100644 index 0000000..e8d8237 --- /dev/null +++ b/doc/manual/volume2/volume2.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.150}% + \gdef\versiondate/{Wed Dec 11 21:36:55 GMT 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/manual/volume2/xx.dvi b/doc/manual/volume2/xx.dvi new file mode 100644 index 0000000000000000000000000000000000000000..387d81e129eec1a02f8250f0c0744bce42af5f35 GIT binary patch literal 14656 zcmd^GX>4586@Ip7;sAjn0TBU27M21^CLY@ddvw{=id8fV-gy* zKRoG3kux*zF5h>~`Odk^d|X>|+tAO>n6Kbf_vh26b+N0anXZ#^ooUgzbEA=lrby$Q zdC}%*!`*nIh93K}*Fn6t)$VC(N^kpY!JfU_Y9HeNeYO7lw0E|mj47vmFyjj4)HjzZ z$D*qVv1Io^wBeCf)5sodzRO{T@7S4KOU=5pc)W%`e(YFN@#DLq8LwG?c_}lPrRwRS znsX;U9nEC6AOFTfXohdbYA<_#&7cxA3&)aHv|%I~LAw=OqwRegN2fEZPh;6W*1?H91q79GE%Va0seldSyUdBI4|E9gk>ggjO@Ik>|G}6d?mO5 zi^!Wf@;0-#mr#Zu`^8a!@<@Z1SUF>)Q3M4v>nThIj+TQFSKr`3Q$%;g6{==wQftb21&MK=0?s-{V6}KVk#;@ z717#iTHNRzmf35mNd)RW$tnaY0Di5+mLhQ5odmPUl5x#qF$d|F)abNq6@koy+c_nu zZg;_Ys8&}n+g5v-7ivs*y4^|5woz`Shm<$h{piAch>tWLrg}X(OS1Bi7Yr6CX_R$p zSAsjgW~M#m`?K#-l%5`?ZrLXpul~ODa$dbLt4ED7FZ}8|Rpc<`@XOzq(18jCbV%h} zp?b>wyT5Jni0Le(@7lMfRuO)I@1ndK5I!Myt5`}O%t8(Nyo2#Ys_rsBU!-{T4?Z&v zL8iSE|8&bpW1-X{G(y`T+Q?2Z7DtIi64$EgC@7VOJ{X5E%6+i>eMOj9PN4Q$JfJ31 zI`fog=TsrEa-ik!CGcW#66;5Z6M5>YC0j_|bX`CWCUY3|F#k=Z1b zr)Ii&RQZvM2NO`lZihu3qMBaBbWNP^@SUHPrlU;~8)3FL;hFcwA!zBAh3rgV zME1JkejGP2D?ktw8(qVeYdc=}xVOhGoaVxD5-&C2jKKl`PU!Oej_|u<<8c1}ZAud6 zY?hm|JP3p8xZQQSvD7nNBhD9kGCAS!;KFfCL`6VCRoeKO3FQ{+?e)FEas7>sxQPdt36GKXN zht+kZ_xba8wh)0tpYRB;cG|k5g2C;_Z{8v>6Xa$AxlEz4nL{yQIoQyhv8IY(7aWDo z&A+L?ObE%oOX!f;w34cWb$)(@h${}8MyL1r%%V@diL=J@sZ1$0U;;LjO59~THNKBS z9$N}YdEvKJYd#6FQ9x`p3E}`nH{Z_QY1JjIYAyinm6K_fjp4!e|@xC z3-tRxy27L=Q)gAs@0VV?RNP4l@jFQ;|0Gp>C+RUPHB;~uuYPPvG?QzbcoTp45qU`| zlbeT6MEfvre*#V^impIC&Tl6ze`+CaC#}C&+)m2uJoVONc$*Qd$t;!)E%-pSm>+|N zsG8xcsgz}^G3+cRnC(02+F{(E>K-2SJ3743f*0}S7TQ>*eX58z;o+OniOqcKA>Pq@7gYQ#0PyUoiG~WyD{REgk z(?Nuv0&hL89?9fpJpQb(2bf1S1LjLNFR_zAa~^5Y^=!!9K$N;y0yIBh^?SwLGfc~N zRLjBSMyC(r#9ar*Uf(pBZ(4p5$FkV&ExtwNTc#V#7huUS;a5-ZN@&OvAK#c%LB^mj zjy0@7n2B;DGYA$s_4^a5;}f>nu&5M#gRwYFZ~AKubGSd>nIyb)Y$72}Mgy~Q2+efS zI)UzOUrn0$<6sb8$t8%l%+ATX?@8l@&6HQhCQP3(b4&3ZIeReL@Pn@))Vu|2LL;lN z2P*mR)y-~I2irJ}W~85fk7XwL)Zw|fKIKo+StPT4^6pH~d!e7a9b{(&SQnR(&?B!h z`MFOo*rPjZVs?f0%itVj2EuFh__o$-s5&0aP2P=1=O_w1HCy|=DF)?e-NytI6ew{Y z59b*}dtW6dAEp5EHBK_wmxJJr3zKulg-OYjg-DX?Pa2=87JLMzJ1=l!?i)S4mq`}r z7VMuNA%6plWA$(RJ`~pTO z27D^iaX`+_4=kTFF({A{t9i5{v@LeMi}Uq3#Nt2;NP-9Sx=F^5P{Dw7DhVVT(odv5 z3TJTWbQCT6u4%Z|AIWsA_JErU%$NQ!gC+etk0wpGkZe;M4#V(fp zh+Vp-xBg;&O)q@M8C~Az4?GoI)63+FRWuu(`~P_F%_zO9BwFZtR|0MOOPumhanx7B!(Sg zI7vD#15nHbR8imw#Z0MAf;fOB=PyK*>tewLO~wonukbBSZlFu^z0e&a2rW(=LK-Sr zbYo(^?A5fgb-OdfFIOlDwulRi6laqlVz$e(OE5!F5h#!7+)=wBs}zN#m7RgU@3hvEl+&Q-FP>q+gbhWevt@#>2b;Qz`S(a(pVzcVP=6@Wj zgT+_1F7D`B-oCOk=wrZNkN6_>1goWzz$P>T6|t*Yegp7FmQ49;83M zG(o3gLWiNFW6|pTR620u6@mw$3v{)^G9B)YrtU8SRDU(}NzUvrG4eheTcc9=dEExu&+(tspRHN1;Di3jH&qKoUSt%oA0r7dqOWO!=J-IgvB5C-Hl zc&_DQe&OpROsLf6d7%RbTuP2BXA-3v86#shMpepkn559FLna*}&-$ zT-nf#-+?6Al(VGVqpqmG_H4NlMGB<#4E2Iq#5AY|d;GcbVYr%LtRxvVuJsI3R0jh@ z9uc9=C57VI?$;cl4Jd#BhT&8@(0B+?+8>*kdbHuv;zVZa(S|2dso8B>_iX3@{VTt* zQ}_N?A&`++#*5#xegrDnw`&E8C^-`;RDkOVtt7ypigSpp7N^{r6qT68AiF$=+l=HI zk_nMSGN)@6gnxf(*tBg8HkG|=MmDr(zsk)+)rmLp@{2pA{sqjTTquleCrnp|IZ^G3 z+7$bGRGITKT-SON!;T)1sG`1m*8=6dq($Y51Oz*RNb-ihVU$QP45d2cpt^V0Xa<2r zRAGK-<0J~@F^M`F$ytk9gBnwXb8dG84hy59sKsW4`P4$`q?z25=LYyUqM*I#oFEbR zV587L4Ifp`xPXQ$^ldx`!_DCWy&9U*W-! zzx0EEfX|wUs=R-eRA{v1p()6!-M3tt2hW`S31-Ny;U6SMm`*S00StkCoJeNp^kz$t zI(E#n`&MpKCSjA0{)r#2G(IV>hT97jNwycdSs_u_rr_u?lRM?JzX|4nCL0=x2h4+A za3Ams$AaU49lskelB&IyxX4#mTrAKMasA*vZU$I_`v?j)34r`08@?byP-CuTF<$2Q zHgk9=$O2|-je5Efo6t&If^l`&@UQ=`X%#|HgXcvKIk>^;|{DGC|8nZ zaN^GShGe2t!8O-Dn;k7jm;Zg?v{7?ykG zBYAS9Q4mp~rlVD!cl`UOm5jdRjtwaAX!%ExE`7&anwym?#t>9}M>wLH!ZuK)5nGV} zG^`=1h-eSi2DDE=i5?e#PuhKY+4x5em$Gri!8`E $@; \ + then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if $(LATEX) \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.pic.tex:; tpic $< + +.tai.tex:; sh -c 'if $(TGRIND) -f -d $(GRINDEFS) -ltai $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.c.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.h.tex:; sh -c 'if $(TGRIND) -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if $(TGRIND) -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.ry.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lpepy $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.bnf.tex:; sh -c 'if $(TGRIND) -d $(GRINDEFS) -f -lbnf $< \ + | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.make.tex:; sh -c 'if $(TGRIND) -f -lsrc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if $(WEAVE) $<; then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; $(DVIIMP) $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if $(DVI2PS) $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +######################################################################### +# End of extension rules +######################################################################### + +INPUTS = \ + bcustom.bib grindefs networking.bib sfwmac.sty \ + captcont.sty grindefs.sty pp.bib tgrind.sty \ + dist-params.tex lcustom.tex sfwdoc.bib trademark.tex \ + a4.sty + +############################################################# +# Here it is... +############################################################# + +all: volume3.dvi + +inst-all:; + +install: inst-all clean + +lint:; + +clean:; rm -f volume3.imp volume3.ps volume3.dvi volume3.log \ + volume3.blg _* \#* $(INPUTS) + +grind: volume3.dvi + true + $(DVISP) $(DFLAGS) volume3 + +imp: volume3.imp + +ps: volume3.ps + +true:; + + +############################################################# +# volume3 +############################################################# + +# customization files, et. al., not included below +volume3.dvi: volume3.vrsn + +volume3.vrsn: volume3.tex \ + $(INPUTS) \ + intro.tex \ + local.tex \ + local-examp.tex \ + local-bnf.tex \ + lists.tex \ + utility.tex \ + volume3.ind \ + version.sh + @version.sh volume3 + +$(INPUTS): + ln -s ../texinputs/$@ . + +############################################################# +# miscellany +############################################################# + +biblio:; bibtex volume3 + +preview: volume3.dvi \ + true + xdvi volume3.dvi + +index:; idx2ind -l volume3 diff --git a/doc/manual/volume3/idx2ind b/doc/manual/volume3/idx2ind new file mode 100755 index 0000000..357a385 --- /dev/null +++ b/doc/manual/volume3/idx2ind @@ -0,0 +1,53 @@ +#! /bin/sh +: 'idx2ind - new LaTeX index converter - 11-Jul-88/JLR' + +L=%% +case x$1 in + x-l) L=""; shift ;; +esac + +for i +do + awk 'BEGIN {for (i = 97; i < 123; i++) # index letters "a" to "z" + printf "%c\n", i; exit}' |\ + cat - $i.idx |\ + sed \ + -e 's/ / /g'\ + -e 's/^\\indexentry{\(.*\)}{\([^}]*\)}$/\1 \2/'\ + -e 's/^\\verb\(.\)\(.*\)\1 \(.*\)$/\2 \3 \\verb\1\2\1/'\ + -e '/\\/!s/ *{}//'\ + -e '/,/{;s/^\(.*\) \(.*\)$/\1 \2 \1/;s/,/ /;}' |\ + sort -u -t" " +0fd -1 +1n |\ + awk -F" " ' +BEGIN {printf "\\begin{theindex}\\makeatletter\n" + printf "\\raggedright\n" + printf "\\def\\newindex#1{{\\huge\\hspace{-.5in}" + printf "\\parbox[t]{.5in}{\\makebox[.35in][c]{\\uppercase{#1}}}" + printf "\\vspace{-1.5ex}}}\n" + } +NF == 1 {x = $1; next} # NF=1: index letter + {n = $1} +NF == 3 {n = $3} # NF=3: special sort key +n == p {printf ", %s", $2; next} # another page number +p != "" {printf "\n"} # end of this item +x != "" {if (p != "") # index letter? + printf "\\indexspace\n" + printf "'$L'\\newindex{%s}\n", x + } + {x = s = ""; i = n; l = $2} # reset +/,/ {s = "sub" # sub-item + nf = split (i, a, ","); k = a[1]; i = a[2] + split (p, pk, ",") + if (pk[1] != k && pk[1] != k"{}") # should use substr... + {i = n; s =""} + else for (j = 3; j <= nf; j++) # add sub-sub-items + i = sprintf ("%s,%s", i, a[j]) + } + {printf "\\%sitem %s, %s", s, i, l} + {p = n} # save for next comparison +END {printf "\n\\end{theindex}\n" + }' > $i.ind + +done + +exit 0 diff --git a/doc/manual/volume3/intro.aux b/doc/manual/volume3/intro.aux new file mode 100644 index 0000000..3babbb4 --- /dev/null +++ b/doc/manual/volume3/intro.aux @@ -0,0 +1,23 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {1}Introduction}{1}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\global\@namedef{cp@intro}{ +\setcounter{page}{3} +\setcounter{equation}{0} +\setcounter{enumi}{0} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{1} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{1} +\setcounter{section}{0} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume3/intro.tex b/doc/manual/volume3/intro.tex new file mode 100644 index 0000000..5c6e0ee --- /dev/null +++ b/doc/manual/volume3/intro.tex @@ -0,0 +1,60 @@ +% -*- LaTeX -*- + +\chapter{Introduction} + +This manual is concerned with the user-visible tools associated with +PP. Other tools which are management oriented or system related are +described in other volumes. + +Most of the work of a message transfer system is not visible to the +user, who typically interacts with some intermediary (user agent or +UA). As such this manual is a collection of the tools and interfaces +that are directly visible to the user. Conceptually, they may be +considered as a part of the UA, which for convenience and performance +are implemented as a part of the MTA. + +The main components of this volume consider the following: + +\begin{describe} +\item[\verb|local delivery|:] Local delivery is one of the more +obviously noticeable parts of PP to the user. This is where the +message leaves the transfer system and enters the user's domain. As +such, this interface is tailorable to a considerable degree. PP does +not restrict the user to a given delivery program, but can be +configured on both a per recipient and a per message-type basis. This +is conceptually a user agent function, but it is often more efficient +to do this operation at the user agent/MTA boundary. + +\item[\verb|distribution lists|:] Maintenance and use of +distribution lists is another area where the end user is directly +involved. This verges on administration, but is administration that +can be delegated to given users for each list. The areas discussed +here are the administration of distribution lists and the information +associated with such lists. + +\item[\verb|user oriented management|:] There are certain +administrative functions that it is useful to make available to end +users. These include checking the progress of individual messages and +checking the validity of addresses and usernames. + +\end{describe} + +Much of the information presented here is often available in the +online \unix/ manuals but usually in a much less verbose format. +These are listed here: +\begin{describe} +\item[\man chkmf (1)] Check the \file{.mailfilter} syntax. +\item[\man ckmail (1)] Check status of your mail. +\item[\man flagmail (1)] Notify a server program of new mail. +\item[\man mail (1)] A very dumb mail submission program. +\item[\man malias (1)] Show what mailing lists expand to. +\item[\man mlist (1)] Distribution list maintenance program. +\item[\man ttyalert (1)] Alert of new mail on the terminal. +\item[\man xalert (1)] Alert of new mail in an X window. +\item[\man resend (1)] Resubmit a message to more recipients. +\item[\man strip\_addr (1)] Remove comments and extraneous parts from an +RFC~822 \linebreak[3]address. + +\item[\man mailfilter(5)] Brief description of the + \file{.mailfilter} syntax. +\end{describe} diff --git a/doc/manual/volume3/lists.aux b/doc/manual/volume3/lists.aux new file mode 100644 index 0000000..b003841 --- /dev/null +++ b/doc/manual/volume3/lists.aux @@ -0,0 +1,40 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {3}Distribution List Maintenance}{17}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.1}File based Distribution Lists}{17}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1.1}What you can and cannot do with \unhbox \voidb@x \hbox {\string\pit\space mlist}}{17}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1.2}How \unhbox \voidb@x \hbox {\string\pit\space mlist} can run}{18}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1.3}\unhbox \voidb@x \hbox {\string\pit\space malias}.}{19}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3.2}X.500 Directory based distribution lists}{19}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.1}The Basics}{19}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.2}The DIT Entries for the list}{20}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.3}ORNames}{21}} +\newlabel{DL:ORName}{{3.2.3}{21}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.4}The DL tool}{22}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.5}Creating a List}{23}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Creating}{23}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Upgrading}{23}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.6}Managing a List}{23}} +\newlabel{DL:1list}{{3.2.6}{23}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.7}Maintaining a List}{24}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2.8}Printing a List}{25}} +\global\@namedef{cp@lists}{ +\setcounter{page}{26} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{3} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{3} +\setcounter{section}{2} +\setcounter{subsection}{8} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume3/lists.tex b/doc/manual/volume3/lists.tex new file mode 100644 index 0000000..c3760e0 --- /dev/null +++ b/doc/manual/volume3/lists.tex @@ -0,0 +1,544 @@ +% -*- LaTeX -*- + +\chapter {Distribution List Maintenance} + +\section{File based Distribution Lists} + +PP provides an interactive tool for maintaining distribution lists, +\pgm{mlist}. +This tool allows you, the user, to view, modify and generally manage +the members of a given list. +What you are allowed to do to a list depends on the access rights +set on that list. + +The access rights for a list are set when the one of the managers of that list +first uses \pgm{mlist} to manage the list. +There are four modes of access rights: +\begin{description} +\item [free:] Anyone can add or remove members of the list. +\item [public:] Anyone can add themselves to or remove themselves from the list. +\item [private:] Only managers of the list can add or remove members; +\item [secret:] Only managers of the list can view or alter the members +of a list. +\end{description} +If you are a manager of a list, the access rights are bypassed and you +are given {\em free} access to the list. + + +\subsection {What you can and cannot do with \pgm{mlist}} + +For all modes of access except {\em free}, the maintenance of the +list is done via a series of questions. +For example: +\begin{quote}\small\begin{verbatim} +You (pac) are not in this list +Do you wish to be added ? [y/n] +\end{verbatim}\end{quote} + +With {\em free} access, the maintenance is done via a menu of options. +\begin{description} + +\item [add:] A list of possible mail addresses is expected with this +option (either following the add command or on the next line). +\pgm{mlist} checks that each address is a valid mail address and +that the normalised address does not already exist in the list. +Addresses that pass both these tests are added to the list. + +\item [remove:] A regular expression is expected with this option. +Any address that matches this expression is a candidate +for removal from the list. +\pgm{mlist} asks the user whether each candidate should be removed. + +\item [find:] As with the {\em remove} option, a regular +expression is expected. +Any address that matches the expressions is printed out. + +\item [verify:] This option goes through the list +checking that each member is a valid mail address. +\end{description} + +As well as these maintenance options, there are a few inspection +options +\begin{description} + +\item [print:] This option prints out all the information concerning +the list. +This information consists of all the members of the list, the list +moderator's mail address, and the user ids of the moderators of the list. + +\item [list:] This option displays all the lists known to the local PP system. +Each list also has a short description of its purpose. + +\item [help:] This option displays all the options that are available +to you. + +\end{description} + +If the list you require does not exist, there is one further +option, {\tt create}. +This option prompts you for all the details of the list you require +and posts them to the postmaster. +If the postmaster decides to grant you this list, he or she will then +do the appropriate administration to create the list. +Once the postmaster has done this, you can use \pgm{mlist} to +manipulate the list. + +If you have done this and the list you requested now appears in the +output of the \verb+list+ option but \pgm{mlist} still thinks it does +not know +about that list, then it is possible that the postmaster overlooked +creating an empty file to contain the list when he or she was adding +the list to PP's tables. + +\subsection {How \pgm{mlist} can run} + +\pgm{mlist} takes each list specified on the command line in turn, and +enables you to modify it. +If no lists are specified on the command line, \pgm{mlist} enters a loop. +Within this loop, you choose the lists you wish to modify. +When you have finished modifying the required lists, you can choose to +{\tt quit} the loop and exit \pgm{mlist}. + +\pgm{mlist} can take several command line arguments: +\begin{description} + +\item [-user 'username'] This specifies the username one wants to be +known as when altering lists. Only privileged users can use this flag. + +\item [-uid 'userid'] This specifies the user Id one wants to be known +as when altering lists. Only privileged users can use this flag. + +\item [-order 'domain order'] This specifies the preferred domain +ordering to use when parsing addresses. This can be specified as: +\begin{description} +\item [usa] usa domain ordering ONLY. +\item [uk] uk domain ordering ONLY. +\item [usapref] usa domain ordering preferred. +\item [ukpref] uk domain ordering preferred. +\end{description} +The default is usa domain ordering only. +\end{description} + +\subsection {\pgm{malias}.} + +The \pgm{malias} tool is a passive version of \pgm{mlist}. +Using the \pgm{malias} tool, you can only view the members of specified lists. +You are unable to modify, in any way, the contents of a list. + +\section{X.500 Directory based distribution lists} + +\newcommand{\option}[1]{``\verb|#1|''} + +Directory lists use the OSI directory to store the list of recipients. +This has the advantage that the list can be easily viewed using any +Directory User Agent (DUA), making the management task easier. +Some knowledge of the QUIPU Directory service is assumed. + + +\subsection {The Basics} + +The manager of the system must set up a directory list in the user +table for PP to be able to expand them. Once this is done, the +maintenance of the list can be delegated to anyone with the +appropriate permissions. To set up a local directory based list +called \verb+raboof+, an entry in the \file{users} table is needed. +This should look something like + +\begin{quote}\index{dirlist}\begin{verbatim} +raboof:dirlist lancaster.xtel.co.uk +\end{verbatim}\end{quote} + +Each mail list needs a manager. Typically this is the mail list name +with \verb+-request+ appended, \verb+raboof-request+ in this case. +So the PP \file{aliases} table may contain something like: + +\begin{quote}\begin{verbatim} +raboof-request:alias c.robbins +\end{verbatim}\end{quote} + +When mail for \verb+raboof+ comes in, the directory list channel is run +The first action is to convert the \verb+raboof+ name into a Directory Name. +First the ISODE \file{isoaliases} in the \file{ETCDIR} is consulted. If +there is an entry of the form + +\begin{quote}\begin{verbatim} +raboof "c=GB@o=Site@cn=The Raboof List" +\end{verbatim}\end{quote} + +Then the given directory name is used. If no such entry is found, then a +one level directory {\em search} operation is used. The base of the +search is defined by the \verb+local_DIT+ variable in the +\file{dsaptailor} file in the \file{ETCDIR} directory. +The search looks for entries belonging to the objectclass +\verb|ppDistributionList| +with a \verb+commonName+ attribute of \verb+raboof+. +\footnote{\verb+raboof+ does not have to be the RDN of the entry, just an +attribute. However you should ensure that the above search will only +match one entry. If in doubt use an alias.} + +Finally, the entry is read and the mail is delivered to the indicated +recipients. + +\subsection{The DIT Entries for the list} + +The main entry, as described above must belong to the object class +\verb+ppDistributionList+. This has the following mandatory +attributes: + +\begin{description} +\item[\verb+mhsDLMembers+:] + The ORName of members of the list. Section~\ref{DL:ORName} + discusses the format of ORNames in detail. + +\item[\verb+owner+:] + The DN of the owner of the list. Typically, this will be a + role entry for the \verb+-request+ of the list. The object + class \verb+ppRole+ is useful for this as it allows you to + specify an \verb+mhsORAddress+ for the role. A typical entry + might be: + \begin{quote}\footnotesize\begin{verbatim} +cn= The Raboof List Manager +cn= raboof-request +roleOccupant= c=GB@o=X-Tel Services Ltd@cn=Colin Robbins +mhsORAddresses= /S=Raboof-request/O=XTEL/PRMD=X-Tel Services/ADMD= /C=GB/ + \end{verbatim} \end{quote} + +\item[\verb+cn+:] + The name of the list. + +\item[\verb+mhsDLSubmitPermissions+:] + This defines who can send to the list. + The default is a special token \option{ALL} which permits + anybody to send mail to the list. However it is + possible to restrict the use of the list. The syntax is: + \begin{quote}\begin{verbatim} + ::= | | \ + | + ::= 'GROUP #' + \end{verbatim} +A member of the X.500 group \verb+DN+ can send to the list. + \begin{verbatim} + ::= 'INDIVIDUAL #' + \end{verbatim} +The individual defined by \verb+ORName+ may send to the list. + \begin{verbatim} + ::= 'MEMBER #' + \end{verbatim} +A Member of the named list may send. +This only works if the named list is also directory based. + \begin{verbatim} + ::= 'PATTERN #' + \end{verbatim} +Anybody whose ORName Matches the $<$ORName$>$ pattern can send. +E.g., if $<$ORName$>$ was ``c=GB'', then only people in ``GB'' could send +to the list. + \end{quote} +\item[\verb+mhsORAddresses+:] + The mail address of the list, in this case + \begin{quote}\small\begin{verbatim} +/S=raboof/O=XTEL/PRMD=X-Tel Ltd/ADMD= /C=GB/ + \end{verbatim}\end{quote} +\end{description} + +The optional attributes are listed below. + +\begin{description} +\item[\verb+dl-policy+:] + The list delivery policy. + It is generally best to leave this to the default + value of: further list expansion allowed; use the original + parameter for the conversion prohibited header; + use low priority. + + To change the default the syntax is + \begin{quote}\begin{verbatim} + ::= $ $ + ::= 'TRUE' | 'FALSE' + \end{verbatim} +If \verb+TRUE+ sub lists are also expanded. + \begin{verbatim} + ::= 'ORIGINAL' | 'TRUE' | 'FALSE' + \end{verbatim} +Is message content conversion allowed. +\verb+ORIGINAL+ implies use the parameter from the original message. + \begin{verbatim} + ::= 'ORIGINAL' | 'HIGH' | 'LOW' | 'NORMAL' + \end{verbatim} +The priority to use when delivering the message. +\verb+ORIGINAL+ implies use the parameter from the original message. + \end{quote} +\item[\verb+description+:] + A textual description of the list. +\end{description} +The following attributes may be present but are not used by the +directory list channel. +\begin{description} +\item[\verb+o+:] + The associated organisation (if any) +\item[\verb+ou+:] + The associated organisationalUnit (if any). +\item[\verb+seeAlso+:] + A reference to another directory entry. +\item[\verb+mhsDeliverableContentTypes+:] + Acceptable content types. +\item[\verb+mhsdeliverableEits+:] + Acceptable encoded information types. +\item[\verb+mhsPreferredDeliveryMethods+:] + A list of preferred delivery methods. +\end{description} + +\subsection{ORNames}\label{DL:ORName} + +The most important part of directory lists is the originator-recipient +name (ORName) of members of the list. +An ORName consists of an optional directory name (DN), a dollar +(\option{\$}) separator and an originator-recipient address (ORAddress). + +ORAddresses can be specified as text encoded X.400 addresses +\begin{quote}\begin{verbatim} +/S=Robbins/O=XTEL/PRMD=X-Tel Services/ADMD= /C=GB/ +\end{verbatim}\end{quote} +or as rfc822 mail addresses +\begin{quote}\begin{verbatim} +C.Robbins@xtel.co.uk +\end{verbatim}\end{quote} +In the later case, this will be converted into a X.400 style address. +This conversion is useful as a short cut in giving all users with a +\verb+rfc822mailbox+ attribute in the +directory a \verb+mhsORAddress+ attribute. + +To specify an ORName as an ORAddress only (with no DN component) you +need to precede the ORAddress with a \option{\$} symbol +\footnote{If the programs were smart enough, this could probably be +omitted in most cases, but it has the advantage of making the user +think, and hopefully use a DN or UFN instead}. +So, the above ORAddresses would become +\begin{quote}\begin{verbatim} +$ /S=Robbins/O=XTEL/PRMD=X-Tel Ltd/ADMD= /C=GB/ +\end{verbatim}\end{quote} +and +\begin{quote}\begin{verbatim} +$ C.Robbins@xtel.co.uk +\end{verbatim}\end{quote} +as ORNames. +It the \option{\$} is omitted, the interfaces will try to reverse map +the mail address onto a DN --- If the user does have a directory +entry, it often succeeds! + +It is much preferable to use a DN instead of a mail address. The DN +component can be specified in one of two ways, either as a fully +qualified, QUIPU style DN: +\begin{quote}\begin{verbatim} +@c=GB@o=X-Tel Services Ltd@cn=Colin Robbins +\end{verbatim}\end{quote} +or as a UFN +\begin{quote}\begin{verbatim} +Robbins, xtel, GB +\end{verbatim}\end{quote} +Neither of these examples give an ORAddress. The interfaces will +determine this for themselves using the directory. +If you do want to specify an address, then you can use the \option{\$} +separator: +\begin{quote}\begin{verbatim} +Robbins, xtel, GB $ C.Robbins@xtel.co.uk +\end{verbatim}\end{quote} + +\subsection{The DL tool} + +The program DL can be used to create and maintain the directory +entries for list management, and is a very useful companion to the +PP enhanced version of DISH. + +To invoke DL use the \pgm{dl} command. It will read your +\file{.quipurc} to obtain your directory username and password. +The username can be changed with a \option{-u} flag, you will be +prompted for a password. +As with DISH you can request connection to a different DSA with the +\option{-c} flag. + +DL attempts to interpret what you can do to the list in terms of your +access rights, based on the DN you bound with. If you are the DSA +manager, you can use the \option{-m} flag to tell DL you have full +access rights. + +On entry to DL, typing a \option{?} will offer some limited help. + +When you enter DL you will be placed at the default position in the +DIT, as defined by the variable \verb+local_DIT+ in the +\file{dsaptailor} file. You can alter this using the \option{m} +command, and supplying a UFN: + +\begin{quote}\begin{verbatim} +> m +Currently at 'X-Tel Services Ltd' +Enter new location: cs, ucl, gb +Searching... +Found exact match(es) for 'GB' +Found good match(es) for 'ucl' +Found good match(es) for 'cs' +Moved! +> +\end{verbatim}\end{quote} + +You can find out which lists exist at a given level in the DIT with +the \option{l} option: +\begin{quote}\begin{verbatim} +> l +Found the following lists: + GB Directory Pilot + JNT PP + JNT Quipu + X.500 Pilot Support + xtel +> +\end{verbatim}\end{quote} +The \option{w} option will tell you which of those lists you are on. + +\subsection{Creating a List} + +A list can be created in one of two ways. Either an existing PP file +based list can be upgraded, or a list created from scratch. + +If you are bound to the directory as a ``normal'' user you will not +have access rights to modify the directory. So both for upgrading and +list creation, the DL program will ask the user a few simple questions +and then send a mail message to the postmaster. + +If you are bound as the DSA manager (using the \option{-m} start up +flags to DL), the DL program will attempt to make the necessary +changes to the directory for you. + +\subsubsection{Creating} + +To create a list use the \option{c} option. in the DL program. You +will be prompted for the name of the list, the owner of the list +(UFN), and textual description. + +DL will create \verb+listname-request+ and \verb+listname+ +entries in the directory. + +Finally DL advises you to alter the PP tables to add +the new list. + +\subsubsection{Upgrading} + +Upgrading is achieved using the \option{u} option in the DL program. +You will be asked for +the name of the PP file based list. + +DL will create \verb+listname-request+ and \verb+listname+ +entries in the directory. +The members of the list will be read from the file based list, and +added into the directory list. As many as possible will be reversed +mapped into directory names. + +Finally DL tells advises you to alter the PP tables to change from a +\verb+list+ to a \verb+dirlist+. + + +\subsection{Managing a List}\label{DL:1list} + +Once created the DL program can be used to manage a list. +To manage the \verb+raboof+ list you can either invoke DL with the list name +as an argument +\begin{quote}\begin{verbatim} +% dl raboof +raboof> +\end{verbatim}\end{quote} +or run DL then give the list name +\begin{quote}\begin{verbatim} +% dl +> raboof +Reading 'raboof'... +raboof> +\end{verbatim}\end{quote} +In either case the new prompt will contain the list name. +A \option{?} can be typed to obtain limited help. + +To add a member, simply enter the ORName, using the syntax described +in Section~\ref{DL:ORName} at the ``listname'' prompt. + +The \option{p} option is used to print the members of the list. If a DN +is present, {\em only} the DN is printed. +Each entry is preceded by a number. This number can be used to +reference the entry when using the \option{r} --- remove entry option, +for example: +\begin{quote}\begin{verbatim} +raboof> p + +Owner: Colin Robbins + +Submit Permissions, Entities matching the OR pattern: + X.400 Address: /C=GB/ + +Entry has no dl-policy + +Members: + 1: Steve Hardcastle-Kille, Computer Science, + University College London + 2: Colin Robbins, X-Tel Services Ltd + 3: Julian Onions, X-Tel Services Ltd + +jnt-quipu> r +give username to be removed: 2 +Remove Colin Robbins [y/n/d] ? n +no +\end{verbatim} +The \option{d} option in the \option{[y/n/d]} prompt is used to display the +directory entry (\option{y} for yes and \option{n} for no). +\end{quote} +Alternatively an ORName could be given, but as UFN is invoked, it may +take too long to find to correct user. Using numbers is quicker. + +Attributes such as the list policy, and submission policy can be +changed using the \option{m} option. + +\subsection{Maintaining a List} +From time to time mail addresses will change. One of the advantages +of the directory list is that such changes can to some extent be +tracked \footnote{If the DN changes you are still in trouble!} as long +as the directory is kept upto date. + +When accessing a particular list, the \option{c} and \option{v} +commands to the DL program can be used to check or validate the list. +The entry for each member of the list is checked for consistency. +Each ORAddress is check to see if the local PP system thinks they are +valid. If the ORName has a DN component, the given ORAddress is +checked against the address given by the directory. Using the +\option{c} option errors are reported, using the \option{v} an attempt +is made to update bad ORAddresses. + +You are advised to run ``check'' or ``validate'' on your lists regularly. +Checking the lists can be done from \pgm{cron} using the \option{-v} +option, for example: +\begin{quote}\begin{verbatim} +dl -v raboof +\end{verbatim}\end{quote} +This will warn (verbosely) of errors. The \option{-q} option is useful +to quieten DL down. + +You can check all lists this way, by not specifying a list name, for +example: +\begin{quote}\begin{verbatim} +dl -v -q -m +\end{verbatim}\end{quote} +will (quietly) check all lists. The \option{-m} flag is used here to +tell DL it is in management mode. +Normally, the invoker of DL will be told of the errors in the list. +When run at a site with a lot of lists, each with different managers, +it is often more useful to mail the list managers of the errors, +rather than mail the invoker of DL. + + +\subsection{Printing a List} + +When DL prints the members of a large list, a pager such as \pgm{more} +will be used to prevent the list scrolling past. +Sometimes this can get in the way, for example if you want to pipe the +output onto a printer. +The \option{-p} flag to DL can be used to prevent this e.g., +\begin{quote}\begin{verbatim} +dl -p raboof +\end{verbatim}\end{quote} +will cause DL to print the raboof list the the standard output, then +exit. diff --git a/doc/manual/volume3/local-bnf.bnf b/doc/manual/volume3/local-bnf.bnf new file mode 100644 index 0000000..74eef64 --- /dev/null +++ b/doc/manual/volume3/local-bnf.bnf @@ -0,0 +1,39 @@ + + ::= + | + + ::= ";" + | ";" + | "print" ";" + | "if" + | "if" "else" + | "{" "}" + + ::= "(" ")" + + ::= "(" ")" + | "==" + | "!=" + | "=" + | "==" + | "!=" + | "||" + | "&&" + | "!" + | [ "ignore" ] "file" + | [ "ignore" ] "pipe" + | "exit" [ ] + | + | + | + + ::= + | "," + + ::= quoted string of characters (e.g., "abced") + + ::= list of characters of the form [a-zA-Z_][a-zA-Z0-9_]* + + ::= "$(" list of characters and - ")" + + ::= "/" regular expression (see regexp(3)) "/" diff --git a/doc/manual/volume3/local-bnf.tex b/doc/manual/volume3/local-bnf.tex new file mode 100644 index 0000000..5e6ab5f --- /dev/null +++ b/doc/manual/volume3/local-bnf.tex @@ -0,0 +1,40 @@ +\File{local\-bnf.bnf},{10:56},{Jul 4 1991} +\L{\LB{}} +\L{\LB{\ ::= \}} +\L{\LB{}\Tab{16}{\| \ \}} +\L{\LB{}} +\L{\LB{\ ::= \ \S{}\";\"\SE{}}} +\L{\LB{}\Tab{16}{\| \S{}\";\"\SE{}}} +\L{\LB{}\Tab{16}{\| \S{}\"print\"\SE{} \ \S{}\";\"\SE{}}} +\L{\LB{}\Tab{16}{\| \S{}\"if\"\SE{} \ \}} +\L{\LB{}\Tab{16}{\| \S{}\"if\"\SE{} \ \ \S{}\"else\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \S{}\"\{\"\SE{} \ \S{}\"\}\"\SE{}}} +\L{\LB{}} +\L{\LB{\ ::= \S{}\"(\"\SE{} \ \S{}\")\"\SE{}}} +\L{\LB{}} +\L{\LB{\ ::= \S{}\"(\"\SE{} \ \S{}\")\"\SE{}}} +\L{\LB{}\Tab{16}{\| \ \S{}\"==\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"!=\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"=\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"==\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"!=\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"\|\|\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \ \S{}\"\&\&\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \S{}\"!\"\SE{} \}} +\L{\LB{}\Tab{16}{\| [ \S{}\"ignore\"\SE{} ] \S{}\"file\"\SE{} \}} +\L{\LB{}\Tab{16}{\| [ \S{}\"ignore\"\SE{} ] \S{}\"pipe\"\SE{} \}} +\L{\LB{}\Tab{16}{\| \S{}\"exit\"\SE{} [ \ ]}} +\L{\LB{}\Tab{16}{\| \}} +\L{\LB{}\Tab{16}{\| \}} +\L{\LB{}\Tab{16}{\| \}} +\L{\LB{}} +\L{\LB{\ ::= \}} +\L{\LB{}\Tab{16}{\| \ \S{}\",\"\SE{} \}} +\L{\LB{}} +\L{\LB{\ ::= quoted string of characters (e.g., \S{}\"abced\"\SE{})}} +\L{\LB{}} +\L{\LB{\ ::= list of characters of the form [a\-zA\-Z\_][a\-zA\-Z0\-9\_]*}} +\L{\LB{}} +\L{\LB{\ ::= \S{}\"\$(\"\SE{} list of characters and \- \S{}\")\"\SE{}}} +\L{\LB{}} +\L{\LB{\ ::= \S{}\"\/\"\SE{} regular expression (see regexp(3)) \S{}\"\/\"\SE{}}} diff --git a/doc/manual/volume3/local-examp.tex b/doc/manual/volume3/local-examp.tex new file mode 100644 index 0000000..f95c124 --- /dev/null +++ b/doc/manual/volume3/local-examp.tex @@ -0,0 +1,24 @@ +\File{local\-examp.mf},{10:52},{Oct 5 1990} +\L{\LB{PATH=\S{}\"\/\SE{}usr\S{}\/local\/\SE{}lib\S{}\/mh:\/\SE{}usr\S{}\/local\/\SE{}bin:\S{}\/usr\/\SE{}bin:\S{}\/bin:\/\SE{}usr\S{}\/ucb\"\SE{};}} +\L{\LB{folder = FALSE;}} +\L{\LB{if (\$(to) == \S{}\/jpo\/\SE{} \|\| \$(to) == \S{}\/onions\/\SE{}) \{}} +\L{\LB{}\Tab{8}{pipe \S{}\"rcvstore +to\"\SE{}; folder = \S{}\"to\"\SE{};}} +\L{\LB{\} else if (\$(sender) == \S{}\/bind\-request\/\SE{}) \{}} +\L{\LB{}\Tab{8}{pipe \S{}\"rcvstore +bind\"\SE{}; folder = \S{}\"bind\"\SE{};}} +\L{\LB{\} else if (\$(sender) == \S{}\/mailgroup\/\SE{}) \{}} +\L{\LB{}\Tab{8}{pipe \S{}\"rcvstore +janet\/\SE{}mailgroup\S{}\"; folder = \"\SE{}janet\S{}\/mailgroup\"\SE{};}} +\L{\LB{\} else if (\$(sender) == \S{}\/namedropper\/\SE{}) \{}} +\L{\LB{}\Tab{8}{pipe \S{}\"rcvstore +mail\/\SE{}namedroppers\S{}\"; folder = \"\SE{}namedroppers\S{}\";}} +\L{\LB{\} else if (\$(sender) == \/\SE{}pp.*\-request\S{}\/) \{}} +\L{\LB{}\Tab{8}{pipe \"\SE{}rcvstore +pp\S{}\"; folder = \"\SE{}pp\S{}\";}} +\L{\LB{\}}} +\L{\LB{if (!delivered) \{}} +\L{\LB{}\Tab{8}{pipe \"\SE{}rcvstore +inbox\S{}\";}} +\L{\LB{}\Tab{8}{if (!delivered) \{}} +\L{\LB{}\Tab{16}{ignore pipe \"\SE{}flagmail \-f \'DELIVERY FAILED\'\S{}\";}} +\L{\LB{}\Tab{16}{exit (TEMPFAIL);}} +\L{\LB{}\Tab{8}{\}}} +\L{\LB{}\Tab{8}{folder = \"\SE{}inbox\S{}\";}} +\L{\LB{\}}} +\L{\LB{if (folder)}} +\L{\LB{}\Tab{8}{ignore pipe \"\SE{}flgamail \-s \$(size) \-e \'\$(folder): \'\S{}\";}} diff --git a/doc/manual/volume3/local.aux b/doc/manual/volume3/local.aux new file mode 100644 index 0000000..6694054 --- /dev/null +++ b/doc/manual/volume3/local.aux @@ -0,0 +1,45 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {2}Local delivery in PP}{3}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.1}Local RFC\penalty \@M \ 822-based Channel}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1.1}Format of the .mailfilter File}{3}} +\newlabel{mailfilter}{{2.1.1}{3}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Commands}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Conditional Expressions}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Variables}{6}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Other Features}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1.2}Examples}{7}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.1}{\ignorespaces Example .mailfilter File}}{8}} +\newlabel{local:examp}{{2.1}{8}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.2}Mailfilter Checkup Tool}{8}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.3}New Message Notification}{9}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{Flags}{11}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.1}Use of flagmail with xalert and ttybiff}{12}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3.2}Examples}{13}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.4}Automatic Vacation Notices}{13}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.5}Forwarding Mail}{14}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2.6}Delivery Tools}{14}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.6.1}strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr}{15}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.6.2}flock}{15}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2.2}{\ignorespaces Grammar for the .mailfilter File}}{16}} +\newlabel{mailf:grammer}{{2.2}{16}} +\global\@namedef{cp@local}{ +\setcounter{page}{17} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{2} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{2} +\setcounter{section}{6} +\setcounter{subsection}{2} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{2} +\setcounter{table}{0} +} diff --git a/doc/manual/volume3/local.tex b/doc/manual/volume3/local.tex new file mode 100644 index 0000000..f835cbc --- /dev/null +++ b/doc/manual/volume3/local.tex @@ -0,0 +1,746 @@ +% -*- LaTeX -*- + +\chapter{Local delivery in PP} + +The local channel is the mechanism by which PP delivers mail to users. +There may be several of these channels tailored to specific mailbox +formats. A user may have more than one local channel associated with +him/her where this is useful, such as having two formats of mail (e.g., +X.400 and RFC~822) delivered in different ways. + + +\section{Local RFC~822-based Channel} + +The RFC~822 local channel has considerable control over the delivery +of the message. In particular, the channel has a particular search +path which is followed when the message is attempted to be delivered. +If the message is considered delivered, or rejected by any one of these +methods, then the further methods of delivery are attempted. The later +methods of delivery are only attempted if the earlier ones are +inconclusive. (This does not apply to the \file{.mailfilter} +processing which normally processes the entire file.) + +\begin{enumerate} +\item If the user has a \file{.mailfilter}\index{.mailfilter} +file in his/her home directory and the file is owned by that user and +not writable by anyone other than that user, the commands within that +file are obeyed. The syntax is defined in Section~\ref{mailfilter}. +If the user does not have a \file{.mailfilter} or the actions in it do +not deliver, reject, or temporarily fail the message, the next method is +attempted. + +\item If there is a system defined \file{.mailfilter} then the +commands in that are obeyed. Again if this does not exists, or the +actions are not conclusive, the next method is tried. + +\item If the above two methods appear inconclusive, the message is +written to a file in a well-defined place (system configured) +surrounded by delimiters. + +\end{enumerate} + +\subsection{Format of the .mailfilter File}\label{mailfilter} + +The \file{.mailfilter} file allows quite complex processing of +incoming messages to be performed. The format takes the form of a +small interpreted language in which expressions can be tested and +evaluated prior to performing actions. In particular conditional +actions are the most useful. + +The language is defined more formally in the grammar given in +Figure~\ref{mailf:grammer}. However, a more gentle introduction is +given here with some examples of usage. + +\subsubsection{Commands} + +There are two basic commands that can be performed on a message. These +commands can be performed any number of times so the message can be +delivered in several places and/or to several processes. + +The first command is \verb|file|\index{file}. This command takes an +argument which is a string and the result is to attempt to copy the +message surrounded by delimiters into the given file. This might be +as in one of the following examples: + +\begin{quote}\small\begin{verbatim} +file "mailbox"; +file "/archive/mailbox"; +\end{verbatim}\end{quote} + +A variant of this is the \verb|unixfile|\index{unixfile}. This writes +into the given file, but in sendmail or traditional UNIX-style format; +i.e., with a header line stating \verb*|From|. + +\begin{quote}\small\begin{verbatim} +unixfile ".mail"; +\end{verbatim}\end{quote} + +Note that all statements in the \file{.mailfilter} file must be +terminated with a semi-colon (``\verb+;+''). + +The second basic command is \verb|pipe|\index{pipe}. This command +starts up a process and writes the message into it as standard +input. This is shown in the next example. + +\begin{quote}\small\begin{verbatim} +pipe "rcvstore +inbox"; +pipe "lpr -p -Ppostscript"; +\end{verbatim}\end{quote} + +The system can tell if these commands have succeeded by the following +methods. If the file writing works then a flag +\verb|delivered|\index{delivered} is set to indicate success. +Similarly, if the exit status from a \verb|pipe| is zero, the delivery +is considered a success and the flag updated. Additionally, as +programs may report temporary failure, this is supported. A program +may return a temporary failure by exiting with a value between 1 and +127, in which case the delivery attempt is aborted and retried at a +later date. An exit status greater than 127 is taken as permanent failure. + +Sometimes, though, you may wish to run a command and ignore the +results; that is, to have the system not update the status of the delivery. +This can be achieved by setting a variable as described later, but for +simplicity, if you precede the command with the keyword +\verb+ignore+\index{ignore}, then no notice will be taken of the return +status. + +\begin{quote}\small\begin{verbatim} +ignore pipe "echo hello"; +ignore file "/dev/null"; +ignore pipe "rcvalert 'you have new mail'"; +\end{verbatim}\end{quote} + +One last feature of these commands, header variables (described below) +may be substituted in the strings associated with these commands. These +are not too useful for \verb|file| commands, but can be useful as +arguments for processes. Care must be taken that appropriate quoting +of these is done in case they contain special characters. As any +string containing a ``\verb|$|'' is substituted, a \$ must be inserted +by doubling it, e.g., ``\verb|$$|''. If you require a +quote ``\verb|"|'' character in the string, it must be preceeded by a +backslash character: ``$\backslash$''. +%%% Non printing characters may +%%% also be included by use of the escape mechanism +%%% ``$\backslash$\verb|nnn|'' where \verb|nnn| is an octal number. + +Normally, the commands are interpreted by +\verb|/bin/sh -c | but if the \pgm{822-local} channel is +running in restricted mode, the command is directly executed. + +\subsubsection{Conditional Expressions}\index{conditionals} + +The real power of the \file{.mailfilter} comes with conditional +expresssions. These allow the user to select particular rules +depending, for instance, on certain attributes of the message. + +The most basic form of condition is an \verb+if+\index{if}\index{else} +statement with a simple comparison. This allows you to compare two +strings for equality. This takes the form of one of the following: + +\begin{quote}\small\begin{verbatim} +if ( == ) + ; + +if ( == ) { + ; + ; +} + +if ( == ) + ; +else if ( == ) + ; +else + ; +\end{verbatim}\end{quote} + +These examples show a number of things. First, where you can have a +single expression, you may have several expressions by enclosing them +in braces\footnote{Any resemblance to the {\em C} programming +language is entirely intentional!}; this is an example of a compound +expression\index{compound statement}. + +Second, by use of the else statement, default actions can be taken. +Finally, the \verb+else if+\index{else if} allows a multi way +branching construct. + +Conditional expressions may also contain Boolean operators. The list +is described below\index{Boolean operators}. + +\[\begin{tabular}{|l | l|} +\hline + \multicolumn{1}{|c|}{\bf Operator} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt == & Is equal to\\ + \tt != & Is not equal to\\ + \tt \&\& & Logical and \\ + \tt || & Logical or\\ + \tt ! & Logical not \\ +\hline +\end{tabular}\] + +The conditional construct begs the question ``what conditions can be +tested?'' These are discussed in the next section. + +\subsubsection{Variables}\index{variables} + +There are two basic types of variables that can be accessed: + +\begin{enumerate} +\item System variables\index{variables, system}\index{system +variables}. These are variables maintained by the \pgm{822-local} channel +and may be updated after actions are taken. + +\item Header fields\index{header fields}. When delivering a message, +all the current header fields are available for examination. +\end{enumerate} + +The system variables are the simplest and there are very few of these. +The most used system variable is \verb+delivered+\index{delivered}. +This variable normally contains the status of the delivery attempt. +This is what the system thinks the state of your message is. This may +be one of the following values\index{delivery states}. + +\[\begin{tabular}{|l | p{0.6\linewidth} |} +\hline + \multicolumn{1}{|c|}{\bf Value} & + \multicolumn{1}{|c|}{\bf Meaning} \\ +\hline + \tt TRUE & The message has been delivered \\ + \tt OK & The same as above \\ + \tt FALSE & The message has not been delivered \\ + \tt PERMFAIL & The message has permanently failed to be delivered. + A delivery report should be sent back if required.\\ + \tt TEMPFAIL & The message has failed to be delivered for + some temporary reason. Another attempt may + succeed. \\ +\hline +\end{tabular}\] + +This may be used in conditional expressions to test for delivery, or +in expressions to reset the delivery state. For example: + +\begin{quote}\small\begin{verbatim} +if ( delivered == FALSE) file "foo"; + +if ( delivered != TRUE ) file "bar"; + +# If not delivered - reject the message +if ( delivered == FALSE) delivered = PERMFAIL; +\end{verbatim}\end{quote} + +Another system type variable is \verb+PATH+\index{PATH}. If this +variable is assigned a value, then it is placed in the environment as the +default path. This is used to search for commands when executing +\verb|pipe| commands. It is initially set to nothing and the user's shell +default search path is used. + +Note: This variable is not used if the 822-local channel is configured +in restricted mode. + +The second class of variables, which are more useful for automatic +filing and delivery, are the variables derived from the messages +header. These variables evaluate to the contents of the particular +field, or to the null string if there is no such variable. These +variables can be compared against quoted strings, but such usage is +not generally useful. Such comparisons require exact matches including +white space with the exception of letter case not being significant. +These variables are distinguished by always starting with a dollar +symbol (``\verb+$+'') followed by the field name in parentheses. (e.g., +\verb+$(to)+ or \verb+$(from)+). + +Much more useful is comparison against a regular +expression\index{regular expressions}. The regular +\linebreak[3]expressions used +are those in \man regexp (3). These match against substrings +of the fields by default and more complex patterns can be built up. +Regular expressions must always appear on the right hand side of the +expression and are delimited by slash marks (``\verb+/+''). An example +of such usage shows the real power of the \file{.mailfilter} file: + +\begin{quote}\small\begin{verbatim} +if ( $(from) == /namedroppers/ || + $(from) == /bind/) pipe "rcvstore +mailadmin"; +else pipe "rcvstore +inbox"; +\end{verbatim}\end{quote} + +Finally, there are some variables that may appear to be header fields +but which are actually derived from other sources. These are: +\[\begin{tabular}{l l} + \tt size & The size of the message in bytes as a string.\\ + \tt return-path & The original sender of the message.\\ + \tt mailbox & The mailbox file associated with this user.\\ + \tt recipient & The address of this recipient.\\ + \tt userid & Either the username or userid of this +recipient.\\ + \tt groupid & The group id of this recipient.\\ + \tt channelname & The name of this delivery channel.\\ + \tt hostname & The name of the host.\\ +\end{tabular}\] + +\subsubsection{Other Features} + +There are a few other features that can be used in the +\file{.mailfilter} file. These are summarised below: + +\begin{describe} +\item[\verb|exit|:] This\index{exit} statement exits the +processing of the \file{.mailfilter} file. With no argument it exits +with the current value of the \verb|delivered| variable. If an +argument is given, then that is taken as the success or failure of the +\linebreak[3]delivery attempt. The argument should be one of \verb|OK|, +\verb|TEMPFAIL|, \verb|PERMFAIL| or a variable that evaluates to one +of these. + +\item[\verb|print|:] Normally, this\index{print} statement does nothing +and is ignored. However when running the checking program, it +will echo its arguments on the standard output. This may be useful in +debugging. + +\item[\verb|\#|:] This\index{\#}\index{comment} symbol starts a +comment, which finishes at the end of the line. + +\end{describe} + +\subsection{Examples} + +The following are some simple examples of \file{.mailfilter} files. + +This first example shows just a simple delivery making use of the MH +\man rcvstore (1) utility: + +\begin{quote}\small\begin{verbatim} +pipe "rcvstore +inbox"; +\end{verbatim}\end{quote} + +The next example shows slightly more complex behaviour, whereby some +mailfiltering occurs, and an alert is posted: +\begin{quote}\small\begin{verbatim} +if ($(to) == /jpo/) + pipe "rcvstore +to"; +else + pipe "rcvstore +inbox"; +ignore pipe "flagmail -s $(size)"; +\end{verbatim}\end{quote} + +A more complex example of a \file{.mailfilter} file is shown in +Figure~\ref{local:examp}. + +\tagrind{local-examp}{Example .mailfilter File}{local:examp} + +The grammar is specified in Figure~\ref{mailf:grammer} on +page~\pageref{mailf:grammer}. + +\tagrind{local-bnf}{Grammar for the .mailfilter File}{mailf:grammer} + +\section{Mailfilter Checkup Tool}\index{checking .mailfilter} + +As writing \file{.mailfilter} files can be error prone, a tool to +check that the contents conform to the language is provided. This is +invoked with a given filename and a message on the standard input. The +file is parsed and then interpreted and the actions appropriate for +the given message are indicated. + +\begin{quote}\small\begin{verbatim} +ckmf ~/.mailfilter < msg +\end{verbatim}\end{quote} + +It is {\em strongly} recommended that you check your +\file{.mailfilter} file each time it is modified. +This will certainly pick out syntax errors and the like, however it +will not discover errors such as the following which may be common +causes of problems: +\begin{itemize} +\pagebreak[3] +\item Unable to find the program to be run (not in search path). +\item The process that is executed aborts. This may be because some +things in the environment are missing. If this is the case it is best +to wrap the process in a shell script. Alternatively, the process may +expect the standard input/ouput be connected to a terminal. This is +difficult to get around. +\end{itemize} + +An example run of \pgm{ckmf} might look like this: +\begin{quote}\small\begin{verbatim} +john% ckmf ~jpo/.mailfilter < /dev/null +pipe into process 'rcvstore +inbox' +pipe into process 'flagmail -s 0 -e 'inbox: '' +Result: delivered OK +john% +\end{verbatim}\end{quote} + +\section{New Message Notification} + +PP provides a couple of simple tools for alerting the user of new +messages arriving. Both methods share a lot of common features (and +code, for that matter). + +The basic idea of the notification is to run a process from the +delivery process which reads the message, extracts some information, +formats it, and then gives it to the user. This may be either by +displaying this formatted information on the user's terminal, or on a +client of an \xwindows/ +display. + +There are four processes involved. They are: +\begin{describe} + +\item[\verb|xalert|:] This process runs as a client of an X +windowing system server. It displays messages sent to it by +\pgm{flagmail}. If it detects that the X windowing system is not in +use, it captures messages and displays them on the terminal. + +\item[\verb|flagmail|:] This process gathers the data from the +message, formats it and \linebreak[3] attempts to pass it to +\pgm{xalert} (or a similar process obeying the same protocol). If it +fails it emulates the \pgm{ttyalert} program. + +\item[\verb|ttyalert|:] This process gathers data from a +message and simply displays it on the user's terminal if logged in. +It is only intended for large sites where all people use the same +host. + +\item[\verb|ttybiff|:] This process runs in the background normally. +It displays messages sent to it by \pgm{flagmail}. + +This program's use is deprecated as the functionality is subsumed by +\pgm{xalert}. It will probably not appear in future releases. + +\end{describe} + +Both \pgm{flagmail} and \pgm{ttyalert} use the same method of preparing +and formatting the data to be displayed. This is done by using a +format string to indicate how the information should be laid out. The +format string can contain verbatim text, header fields, and other +attributes of the message. + +Fields within the format string are indicated by percent (\verb|%|) +symbols. The general format bares some relationship to the \man +printf (3) format: + +\begin{quote}\small\begin{verbatim} +%[digits]string +\end{verbatim}\end{quote} + +The digits are optional and indicate how large the field should be +padded out to or truncated to. The string is any message field, or +one of a set of special fields. The case of the string is not sensitive. + +The special fields are: +\[\begin{tabular}{l p{0.7\linewidth}} + \multicolumn{1}{c}{\bf Field} & + \multicolumn{1}{c}{\bf Meaning} \\ + \tt body& The first few characters of the body of the message\\ + \tt size& The size in bytes of the message\\ + \tt extra& A special field set on the command line\\ + \tt from& the from field is treated in a special way\\ +\end{tabular}\] + +The \verb|body|\index{body} field is the first few characters of the +body with all new lines removed and multiple white space compressed to +single spaces. + +The \verb|size|\index{size} is set on the command line by the use of +an optional flag. This is usually done in the \file{.mailfilter} file +by use of the \verb|$(size)| variable. + +The \verb|extra|\index{extra} field is used to allow simple changes to +the default format string. This just allows a simple flag to adjust +the output from the default format string rather than rewriting the +format string. If not set, it defaults to the value \verb*|NEW: |. + +The \verb|From|\index{From} field is treated slightly specially, in +that if there is a name component in front of the opening angle +bracket, then the rest of the field is ignored. + +The default format string is the following: +\begin{quote}\small\begin{verbatim} +%extra(%size) %20from %subject << %50body +\end{verbatim}\end{quote} + +This gives output something like the following +\begin{quote}\small\begin{verbatim} +NEW: (3402) Steve Kille Re: state of unix-niftp? << I +\end{verbatim}\end{quote} + +The whole output line is truncated to the number of characters set on +the command line (defaulting to 80). This allows the later parts of +the string to be large, in the assurance that they will get chopped off if +they exceed the given size. + +An example usage in a \file{.mailfilter}\index{.mailfilter} file might +look like the following: +\begin{quote}\small\begin{verbatim} +if (delivered) + ignore pipe "flagmail -s $(size)" +\end{verbatim}\end{quote} +See the example in Figure~\ref{local:examp} on +page~\pageref{local:examp} for a more complex example of usage. + +\subsubsection{Flags} + +Both \pgm{flagmail} and \pgm{ttyalert} respond to a number of command +line options to change the behaviour. These are: +\begin{describe} +\item[\verb|-d|:] Runs the program in a debugging mode. This +stops the program from running in the background. Only useful if you are +trying to debug the program. + +\item[\verb|-e string|:] Sets the \verb|extra| variable. This is used +to override the default extra information which is normally \verb|NEW:|. + +\item[\verb|-f format|:] Sets the entire format string to the given +string. This is how you override the internal format string with +something entirely different. + +\item[\verb|-s size|:] Sets the message size parameter. + +\item[\verb|-w width|:] Sets the default output line width. The line +produced will be truncated to this width (default 80 characters). + +\item[\verb|-x|:] Forces the use of protocol. In this mode it will not +try and do its own notification if it fails to notify a server. +\end{describe} + +In addition the \pgm{flagmail} program has two other options to tailor +the interaction with \pgm{xalert} or other servers. + +\begin{describe} +\item[\verb|-h hostfile|:] Use the given file to read the host and +port to communicate with. This overrides the default of \file{.alert} +in the home directory. + +\item[\verb|-p number|:] Use the following number to override the UDP +port found in the file. +\end{describe} + +\pgm{xalert} has only some command line switches. +These are: +\begin{describe} +\item[\verb|-filename hostfile|:] use the given file to write the host and +port number in instead of the default (\file{.alert}). +\item[\verb|-user username|:] \pgm{xalert} filters out requests +destined for the given user. Normally it will not receive messages +destined for another user, but this will change \pgm{xalert}'s idea of +the current user anyway. + +\item[\verb|-port number|:] Set the UDP port number to the given +number. The default is to choose a random unused UDP port. + +\item[\verb|-s|:] Only print to the standard output; do not display +on all this user's login sessions. +\item[\verb|-t|:] Do not attempt to use the X system. +\item[\verb|-x|:] Allow use of X (default). +\item[\verb|-w width|:] Use this width when displaying messages on the +terminal. +\item[\verb|-bell/-nobell|:] Notify (or not) new message with a +bell noise (the default is \verb|-bell|). + +\item[\verb|-autoraise/-noautoraise|:] Raise (or not) the window to +the top of the stack when new messages arrive. The default is not to +raise the window. +\item[\verb|-photos/-nophotos|:] Display a photograph of the sender of +the mail on reception. This depends on if the code is compiled to look +up the entry in the directory. +\end{describe} +In addition it takes +all the standard X command line arguments. + +\pgm{ttybiff} supports the following flags similar to \pgm{xalert}: +\begin{describe} +\item[\verb|-f hostfile|:] use the given file to write the host and port +number in instead of the default. +\item[\verb|-u username|:] as for \pgm{xalert}'s \verb|-username| switch. +\item[\verb|-p port|:] as for \pgm{xalert}'s \verb|-port| switch. +\item[\verb|-s|:] only display on the standard output, not on other +terminals where the user is logged on. +\end{describe} + + +\subsection{Use of flagmail with xalert and ttybiff} + +\pgm{Xalert} works with \pgm{flagmail} or \pgm{ttybiff} to provide the +notification. \pgm{Flagmail} is responsible for building up the +format string and sending it to either \pgm{xalert} or \pgm{ttybiff}. +This is achieved using a UDP connection. \pgm{flagmail} contacts the +server program by looking for a file with a hostname and UDP port in +(by default \file{.alert}\index{.alert}). If this exists then it +attempts to contact a server on that host to display the message. If +either of these steps fails, then it reverts to the behaviour of +\pgm{ttyalert} except that there is a delay while it waits for UDP +timeouts to occur. + +The \file{.alert} has the format +\begin{quote}\small\begin{verbatim} + +\end{verbatim}\end{quote} + +\pgm{flagmail} will use this information to contact the remote +process, which can be any process which understands the \pgm{flagmail} +protocol. + +The \pgm{xalert} program is just a display process that +displays the messages sent by \pgm{flagmail}. It displays these message +in a text widget which is scrollable. There are three buttons: +\begin{describe} +\item[\verb|Quit|:] which does the obvious thing. +\item[\verb|Clear|:] which clears the message window. +\item[\verb|Options|:] which pops up a menu with a number of +sub-options. These are: + \begin{describe} + \item[\verb|Reset|:] rewrites the \file{.alert} file; it is used if + two xalerts are started or the \file{.alert} file is removed. + \item[\verb|Bell|:] Disable/enable use of the bell. The default +can be overriden in the users X resource file by setting a boolean +value for \verb|XAlert.bell|. + \item[\verb|Autoraise|:] Disable/enable the autoraise mode. The +default for this can be set via the boolean X resource \verb|XAlert.autoRaise|. + \item[\verb|Photos|:] Disable/enable display of photographs. The +default for this can be set via the boolean X resource \verb|XAlert.photos|. + \end{describe} +\end{describe} + +The \pgm{ttybiff} attempts to locate the user in the same manner as +\pgm{ttyalert} or, if that fails, to display the message on the standard +output. + +\subsection{Examples} + +Here are a few examples of use. + +First, the simple notification that should be put in the +\file{.mailfilter} file: +\begin{quote}\small\begin{verbatim} +ignore pipe "flagmail -s $(size)"; +\end{verbatim}\end{quote} +This does the most basic notification. If more control is required +over the displayed message more complex strings can be built up: +\begin{quote}\small\begin{verbatim} +if ($(subject) == /request/) { + file "request-mbox"; + ignore pipe "flagmail -s $(size) -e REQUEST"; +} +\end{verbatim}\end{quote} + +Finally, if you are adventurous, you might like to play with the +format of the message given. For instance: +\begin{quote}\small\begin{verbatim} +ignore pipe + "flagmail -s $(size) -f '%5size %15from (%20subject) **%body'"; +\end{verbatim}\end{quote} + +This would give an output in the following format for a typical message +\begin{quote}\small\begin{verbatim} +1023 Julian Onions (Re: Delivery Report ) ** Also +\end{verbatim}\end{quote} + +\section{Automatic Vacation Notices} + +PP provides a simple program to notify originators that the recipients +will not read their messages for some time. This is typically installed +when the recipient is expecting to be unable to read mail for some +time, such as going on vacation. + +The program, \pgm{rcvtrip}, is installed in the \file{.mailfilter} +file in a fashion similar to the following. + +\begin{quote}\small\begin{verbatim} +ignore pipe "rcvtrip" +\end{verbatim}\end{quote} + +The program reads the message and checks to see if the recipient is +mentioned directly in either the \verb|to| or \verb|cc| line. If so, +and the originator has not been replied to in a similar style before, +then a reply is composed. This consists of some standard text, +followed by the contents of the file \file{tripnote} in the user's home +directory. + +There are several flags to this program. +\begin{describe} +\item[\verb|-F|:] Always reply to the user, even if the message is not +sent directly to this user. +\item[\verb|-e value|:] Set the exit code depending on this value. A +value of 0 means the program always exits with failure (the default). +If the value is 1, the exit code is always good. A value of 2 will +give an exit status according to the following table: + +\begin{tabular}{|p{0.7\linewidth}|l|} +\hline + \multicolumn{1}{|c|}{\bf Condition} & + \multicolumn{1}{|c|}{\bf exit code} \\ +\hline\hline + A message was sent & 1 \\ + A message was not sent as this sender has already +received a message & 2 \\ + A message was not sent as this message was not sent directly +to this user & 3 \\ + A parse error was found & 4 \\ + Anything else & 99 \\ +\hline +\end{tabular} + +\item[\verb|-f|:] Set the text of the from field (defaults to +\verb|MESSAGE AGENT|). +\item[\verb|-l file|:] Set the database to this filename (default +\file{triplog}). +\item[\verb|-n|:] Use this file as the text of the message to send +back after the standard preamble (default \file{ttripnote}). +\item[\verb|-s|:] Use this file to determine the user's signature +(default \file{.signature}). +\item[\verb|-t text|:] Modify the preamble to use this line (several +of these may be given). +\item[\verb|-u user|:] Pretend to be this user when answering. +\end{describe} + + +\section{Forwarding Mail} +There is a simple program which will forward mail to other recipients. +This is called \pgm{resend}. This program takes a message as standard +input with extra recipients given on the command line. The program +will then submit the message as a \verb|resent| message. The new +recipients will appear in the \verb|resent-to| and \verb|resent-cc| +lines as appropriate. + +There are two flags that control the operation of this program: +\begin{describe} +\item[\verb|-t|:] The next recipients should be specified as +\verb|Resent-To:| recipients. +\item[\verb|-c|:] The next recipients should be specified as +\verb|Resent-Cc:| recipients. +\item[\verb|-u username|:] Pretend to be this user (subject to +authorisation checks). +\end{describe} + +\section{Delivery Tools} +There are one or two small tools that are provided to help with +delivery processing. + +\subsection{strip\_addr} + +The \pgm{strip\_addr} utility takes a list of addresses either on the +command line or on the standard input and issues those same addresses +in a basic form. In particular all address comments are removed as are +name and list constructs. This utility may be useful in processing +mail where only the basic address is wanted. + +\pgm{strip\_addr} takes two optional flags. These are: +\begin{describe} +\item[\verb|-p|:] Interpret the \verb|%| character as a routing +construct. If this flag is not present, the \verb|%| character will be +taken as just another character. +\item[\verb|-r|:] Strip out routes as well. +\end{describe} + +An example of use might be: +\begin{quote}\small\begin{verbatim} +strip_addr 'Julian Onions ' +jpo@there.com +\end{verbatim}\end{quote} + +\subsection{flock} +The \pgm{flock} utility takes a single file followed by a command. The +file is first locked in the current PP locking style, and then the +command is executed. When the command exits, the file is unlocked and +\pgm{flock} exits with the returned status of the command. + diff --git a/doc/manual/volume3/make b/doc/manual/volume3/make new file mode 100755 index 0000000..be14df3 --- /dev/null +++ b/doc/manual/volume3/make @@ -0,0 +1,11 @@ +#! /bin/sh + +if [ -f ../../../Make.defs ] +then + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../../../Make.defs -f Makefile ${1+"$@"} +else + PATH=/usr/ucb:/bin:/usr/bin exec \ + make -f ../Make.defs -f Makefile ${1+"$@"} +fi + diff --git a/doc/manual/volume3/utility.aux b/doc/manual/volume3/utility.aux new file mode 100644 index 0000000..202a3df --- /dev/null +++ b/doc/manual/volume3/utility.aux @@ -0,0 +1,25 @@ +\relax +\@writefile{toc}{\string\contentsline\space {chapter}{\string\numberline\space {4}Miscellaneous Utilities}{26}} +\@writefile{lof}{\string\addvspace\space {10pt}} +\@writefile{lot}{\string\addvspace\space {10pt}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.1}A /bin/mail Replacement}{26}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4.2}Message Status Checkup}{26}} +\global\@namedef{cp@utility}{ +\setcounter{page}{28} +\setcounter{equation}{0} +\setcounter{enumi}{2} +\setcounter{enumii}{0} +\setcounter{enumiii}{0} +\setcounter{enumiv}{0} +\setcounter{footnote}{0} +\setcounter{mpfootnote}{0} +\setcounter{part}{0} +\setcounter{chapter}{4} +\setcounter{section}{2} +\setcounter{subsection}{0} +\setcounter{subsubsection}{0} +\setcounter{paragraph}{0} +\setcounter{subparagraph}{0} +\setcounter{figure}{0} +\setcounter{table}{0} +} diff --git a/doc/manual/volume3/utility.tex b/doc/manual/volume3/utility.tex new file mode 100644 index 0000000..c82183b --- /dev/null +++ b/doc/manual/volume3/utility.tex @@ -0,0 +1,62 @@ +% -*- LaTeX -*- + +\chapter{Miscellaneous Utilities} + +There are a number of small utility programs provided with PP that may +be of interest to end users. These are described here. + +\section{A /bin/mail Replacement} + +PP comes with a very simple user interface for submitting messages. It +has approximately the functionality normally assumed by +{\pgm{/bin/mail}} except that reading mail is not supported, only +submission. That is, it takes a list of addresses on the command line +and reads the body of the message on the standard input. By default +all the addresses are marked as \verb|To:| recipients. The command has +a few options; each option stays in force until overriden. + +\begin{describe} +\item[\verb|-t|:] The following arguments, up to the next flag, are +\verb|To:| addresses. +\item[\verb|-c|:] The following arguments are \verb|Cc:| addresses. +\item[\verb|-s|:] The following arguments are text for the +\verb|Subject:| line. +\end{describe} + +This program is most useful in scripts and programs as a simple way of +sending a message. + +\section{Message Status Checkup} + +% -a messages from and to ow just from +% -h connect to this mta rather than local + +PP provides a tool, \pgm{checkmail}, that connects to an MTA and finds +out about messages related to the user. + +There are two flags to alter \pgm{checkmail}'s behaviour. +\begin{description} + +\item [-a:] This flag prompts \pgm{checkmail} to find out about +messages to and from the user. By default, \pgm{checkmail} only finds +out about messages from the user. + +\item [-h MTAname:] This flag prompts \pgm{checkmail} to connect to the +named MTA. By default, \pgm{checkmail} attempts to connect to an MTA +running on the local machine. + +\end{description} + +Here are two example displays from the \pgm{checkmail} tool: +\begin{quote}\small\begin{verbatim} +john% xcheckmail -h sheriff +Please wait while attempt to connect to sheriff....connected +The messages from pac on sheriff are as follows: +msg.aa03130 is pending delivery to p.pat@cs.nott.ac.uk + +john% xcheckmail -h sheriff -a +Please wait while attempt to connect to sheriff....connected +The messages to or from pac on sheriff are as follows: +msg.aa03130 is pending delivery to p.pat@cs.nott.ac.uk +msg.aa03140 is from P.Pat@cs.nott.ac.uk +\end{verbatim}\end{quote} diff --git a/doc/manual/volume3/version.sh b/doc/manual/volume3/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/manual/volume3/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/manual/volume3/volume3.aux b/doc/manual/volume3/volume3.aux new file mode 100644 index 0000000..8c7b28b --- /dev/null +++ b/doc/manual/volume3/volume3.aux @@ -0,0 +1,5 @@ +\relax +\@input{intro.aux} +\@input{local.aux} +\@input{lists.aux} +\@input{utility.aux} diff --git a/doc/manual/volume3/volume3.idx b/doc/manual/volume3/volume3.idx new file mode 100644 index 0000000..c44d866 --- /dev/null +++ b/doc/manual/volume3/volume3.idx @@ -0,0 +1,153 @@ +\indexentry{chkmf {}}{2} +\indexentry{.mailfilter}{2} +\indexentry{ckmail {}}{2} +\indexentry{flagmail {}}{2} +\indexentry{mail {}}{2} +\indexentry{malias {}}{2} +\indexentry{mlist {}}{2} +\indexentry{ttyalert {}}{2} +\indexentry{xalert {}}{2} +\indexentry{resend {}}{2} +\indexentry{strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr {}}{2} +\indexentry{mailfilter{}}{2} +\indexentry{.mailfilter}{2} +\indexentry{.mailfilter}{3} +\indexentry{.mailfilter}{3} +\indexentry{.mailfilter}{3} +\indexentry{.mailfilter}{3} +\indexentry{.mailfilter}{3} +\indexentry{.mailfilter}{3} +\indexentry{file}{4} +\indexentry{unixfile}{4} +\indexentry{.mailfilter}{4} +\indexentry{pipe}{4} +\indexentry{delivered}{4} +\indexentry{ignore}{4} +\indexentry{822-local}{5} +\indexentry{conditionals}{5} +\indexentry{.mailfilter}{5} +\indexentry{if}{5} +\indexentry{else}{5} +\indexentry{compound statement}{5} +\indexentry{else if}{5} +\indexentry{Boolean operators}{5} +\indexentry{variables}{6} +\indexentry{variables, system}{6} +\indexentry{system variables}{6} +\indexentry{822-local}{6} +\indexentry{header fields}{6} +\indexentry{delivered}{6} +\indexentry{delivery states}{6} +\indexentry{PATH}{6} +\indexentry{regular expressions}{7} +\indexentry{regexp {}}{7} +\indexentry{.mailfilter}{7} +\indexentry{.mailfilter}{7} +\indexentry{exit}{7} +\indexentry{.mailfilter}{7} +\indexentry{print}{7} +\indexentry{\#}{7} +\indexentry{comment}{7} +\indexentry{.mailfilter}{7} +\indexentry{rcvstore {}}{7} +\indexentry{.mailfilter}{8} +\indexentry{checking .mailfilter}{8} +\indexentry{.mailfilter}{8} +\indexentry{.mailfilter}{8} +\indexentry{ckmf}{9} +\indexentry{flagmail}{9} +\indexentry{xalert}{9} +\indexentry{ttyalert}{9} +\indexentry{flagmail}{9} +\indexentry{xalert}{9} +\indexentry{flagmail}{9} +\indexentry{ttyalert}{9} +\indexentry{printf {}}{10} +\indexentry{body}{10} +\indexentry{size}{10} +\indexentry{.mailfilter}{10} +\indexentry{extra}{10} +\indexentry{From}{10} +\indexentry{.mailfilter}{10} +\indexentry{.mailfilter}{10} +\indexentry{flagmail}{11} +\indexentry{ttyalert}{11} +\indexentry{flagmail}{11} +\indexentry{xalert}{11} +\indexentry{.alert}{11} +\indexentry{xalert}{11} +\indexentry{.alert}{11} +\indexentry{xalert}{11} +\indexentry{xalert}{11} +\indexentry{ttybiff}{12} +\indexentry{xalert}{12} +\indexentry{xalert}{12} +\indexentry{xalert}{12} +\indexentry{Xalert}{12} +\indexentry{flagmail}{12} +\indexentry{ttybiff}{12} +\indexentry{Flagmail}{12} +\indexentry{xalert}{12} +\indexentry{ttybiff}{12} +\indexentry{flagmail}{12} +\indexentry{.alert}{12} +\indexentry{.alert}{12} +\indexentry{ttyalert}{12} +\indexentry{.alert}{12} +\indexentry{flagmail}{12} +\indexentry{flagmail}{12} +\indexentry{xalert}{12} +\indexentry{flagmail}{12} +\indexentry{.alert}{12} +\indexentry{.alert}{12} +\indexentry{ttybiff}{13} +\indexentry{ttyalert}{13} +\indexentry{.mailfilter}{13} +\indexentry{rcvtrip}{13} +\indexentry{.mailfilter}{13} +\indexentry{tripnote}{13} +\indexentry{triplog}{14} +\indexentry{ttripnote}{14} +\indexentry{.signature}{14} +\indexentry{resend}{14} +\indexentry{strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr}{15} +\indexentry{strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr}{15} +\indexentry{flock}{15} +\indexentry{flock}{15} +\indexentry{mlist}{17} +\indexentry{mlist}{17} +\indexentry{mlist}{17} +\indexentry{mlist}{17} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{mlist}{18} +\indexentry{malias}{19} +\indexentry{malias}{19} +\indexentry{mlist}{19} +\indexentry{malias}{19} +\indexentry{users}{19} +\indexentry{dirlist}{19} +\indexentry{aliases}{19} +\indexentry{isoaliases}{19} +\indexentry{ETCDIR}{19} +\indexentry{dsaptailor}{19} +\indexentry{ETCDIR}{19} +\indexentry{dl}{22} +\indexentry{.quipurc}{22} +\indexentry{dsaptailor}{22} +\indexentry{cron}{25} +\indexentry{more}{25} +\indexentry{/bin/mail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{checkmail}{26} +\indexentry{\LaTeX {}}{28} diff --git a/doc/manual/volume3/volume3.ind b/doc/manual/volume3/volume3.ind new file mode 100644 index 0000000..eb137a6 --- /dev/null +++ b/doc/manual/volume3/volume3.ind @@ -0,0 +1,105 @@ +\begin{theindex}\makeatletter +\raggedright +\def\newindex#1{{\huge\hspace{-.5in}\parbox[t]{.5in}{\makebox[.35in][c]{\uppercase{#1}}}\vspace{-1.5ex}}} +\item \#, 7 +\item 822-local, 5, 6 +\indexspace +\newindex{a} +\item .alert, 11, 12 +\item aliases, 19 +\indexspace +\newindex{b} +\item /bin/mail, 26 +\item body, 10 +\item Boolean operators, 5 +\indexspace +\newindex{c} +\item checking .mailfilter, 8 +\item checkmail, 26 +\item chkmf, 2 +\item ckmail, 2 +\item ckmf, 9 +\item comment, 7 +\item compound statement, 5 +\item conditionals, 5 +\item cron, 25 +\indexspace +\newindex{d} +\item delivered, 4, 6 +\item delivery states, 6 +\item dirlist, 19 +\item dl, 22 +\item dsaptailor, 19, 22 +\indexspace +\newindex{e} +\item else, 5 +\item else if, 5 +\item ETCDIR, 19 +\item exit, 7 +\item extra, 10 +\indexspace +\newindex{f} +\item file, 4 +\item flagmail, 2, 9, 11, 12 +\item flock, 15 +\item From, 10 +\indexspace +\newindex{h} +\item header fields, 6 +\indexspace +\newindex{i} +\item if, 5 +\item ignore, 4 +\item isoaliases, 19 +\indexspace +\newindex{l} +\item \LaTeX {}, 28 +\indexspace +\newindex{m} +\item mail, 2 +\item .mailfilter, 2, 3, 4, 5, 7, 8, 10, 13 +\item malias, 2, 19 +\item mlist, 2, 17, 18, 19 +\item more, 25 +\indexspace +\newindex{p} +\item PATH, 6 +\item pipe, 4 +\item print, 7 +\item printf, 10 +\indexspace +\newindex{q} +\item .quipurc, 22 +\indexspace +\newindex{r} +\item rcvstore, 7 +\item rcvtrip, 13 +\item regexp, 7 +\item regular expressions, 7 +\item resend, 2, 14 +\indexspace +\newindex{s} +\item .signature, 14 +\item size, 10 +\item strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr, 15 +\item strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr {}, 2 +\item system variables, 6 +\indexspace +\newindex{t} +\item triplog, 14 +\item tripnote, 13 +\item ttripnote, 14 +\item ttyalert, 2, 9, 11, 12, 13 +\item ttybiff, 12, 13 +\indexspace +\newindex{u} +\item unixfile, 4 +\item users, 19 +\indexspace +\newindex{v} +\item variables, 6 +\subitem system, 6 +\indexspace +\newindex{x} +\item xalert, 2, 9, 11, 12 +\end{theindex} diff --git a/doc/manual/volume3/volume3.lof b/doc/manual/volume3/volume3.lof new file mode 100644 index 0000000..21ac52f --- /dev/null +++ b/doc/manual/volume3/volume3.lof @@ -0,0 +1,6 @@ +\addvspace {10pt} +\addvspace {10pt} +\contentsline {figure}{\numberline {2.1}{\ignorespaces Example .mailfilter File}}{8} +\contentsline {figure}{\numberline {2.2}{\ignorespaces Grammar for the .mailfilter File}}{16} +\addvspace {10pt} +\addvspace {10pt} diff --git a/doc/manual/volume3/volume3.lot b/doc/manual/volume3/volume3.lot new file mode 100644 index 0000000..53a2054 --- /dev/null +++ b/doc/manual/volume3/volume3.lot @@ -0,0 +1,4 @@ +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} +\addvspace {10pt} diff --git a/doc/manual/volume3/volume3.major b/doc/manual/volume3/volume3.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/manual/volume3/volume3.major @@ -0,0 +1 @@ +1 diff --git a/doc/manual/volume3/volume3.minor b/doc/manual/volume3/volume3.minor new file mode 100644 index 0000000..a862eb8 --- /dev/null +++ b/doc/manual/volume3/volume3.minor @@ -0,0 +1 @@ +85 diff --git a/doc/manual/volume3/volume3.tex b/doc/manual/volume3/volume3.tex new file mode 100644 index 0000000..07993de --- /dev/null +++ b/doc/manual/volume3/volume3.tex @@ -0,0 +1,77 @@ +% -*- LaTeX -*- +% run this through LaTeX + +% SEK - this is a PP document, designed to be easy to convert to +% an ISODE Manual Section if we want to + +\input lcustom + +\documentstyle[11pt,sfwmac,tgrind,twoside,a4]{report} + +\makeindex + +\input{dist-params} + +\newcount\volnum +\volnum=3 + +\pagenumbering{roman} + +\begin{document} + +\title{{\Huge\bf PP}\vskip 1.5em + \LARGE\sl Volume 3: Users Guide} +\author{Pete Cowen \\ +X-Tel Services Ltd \and Julian Onions \\ X-Tel Services Ltd} + + +\date{\ifdraft \versiondate/\\ \tt Draft Version \versiontag/ + \else \today\\ + (Version \ppversion/)\fi} + +\maketitle +\newpage + +\thispagestyle{empty} +\setcounter{page}{0} +\mbox{} +\newpage + +\tableofcontents + +%\listoftables + +\listoffigures + +% \include{preface} + +\newpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi +\pagenumbering{arabic} + +% \part {Introduction} +% \include{introduction} + +% \part {Using PP} +\include{intro} +\include{local} +\include{lists} +\include{utility} + +% \bibliography{bcustom,sfwdoc,networking} +% \bibliographystyle{alpha} + +\input volume3.ind + +\clearpage +\ifodd\value{page} \else + \mbox{} + \newpage +\fi + +%\typeout{you can usually ignore the message about Label(s) may have changed} + +\end{document} diff --git a/doc/manual/volume3/volume3.toc b/doc/manual/volume3/volume3.toc new file mode 100644 index 0000000..a0f3caf --- /dev/null +++ b/doc/manual/volume3/volume3.toc @@ -0,0 +1,38 @@ +\contentsline {chapter}{\numberline {1}Introduction}{1} +\contentsline {chapter}{\numberline {2}Local delivery in PP}{3} +\contentsline {section}{\numberline {2.1}Local RFC\penalty \@M \ 822-based Channel}{3} +\contentsline {subsection}{\numberline {2.1.1}Format of the .mailfilter File}{3} +\contentsline {subsubsection}{Commands}{4} +\contentsline {subsubsection}{Conditional Expressions}{5} +\contentsline {subsubsection}{Variables}{6} +\contentsline {subsubsection}{Other Features}{7} +\contentsline {subsection}{\numberline {2.1.2}Examples}{7} +\contentsline {section}{\numberline {2.2}Mailfilter Checkup Tool}{8} +\contentsline {section}{\numberline {2.3}New Message Notification}{9} +\contentsline {subsubsection}{Flags}{11} +\contentsline {subsection}{\numberline {2.3.1}Use of flagmail with xalert and ttybiff}{12} +\contentsline {subsection}{\numberline {2.3.2}Examples}{13} +\contentsline {section}{\numberline {2.4}Automatic Vacation Notices}{13} +\contentsline {section}{\numberline {2.5}Forwarding Mail}{14} +\contentsline {section}{\numberline {2.6}Delivery Tools}{14} +\contentsline {subsection}{\numberline {2.6.1}strip\unhbox \voidb@x \kern .06em \vbox {\hrule width.3em}addr}{15} +\contentsline {subsection}{\numberline {2.6.2}flock}{15} +\contentsline {chapter}{\numberline {3}Distribution List Maintenance}{17} +\contentsline {section}{\numberline {3.1}File based Distribution Lists}{17} +\contentsline {subsection}{\numberline {3.1.1}What you can and cannot do with \unhbox \voidb@x \hbox {\pit mlist}}{17} +\contentsline {subsection}{\numberline {3.1.2}How \unhbox \voidb@x \hbox {\pit mlist} can run}{18} +\contentsline {subsection}{\numberline {3.1.3}\unhbox \voidb@x \hbox {\pit malias}.}{19} +\contentsline {section}{\numberline {3.2}X.500 Directory based distribution lists}{19} +\contentsline {subsection}{\numberline {3.2.1}The Basics}{19} +\contentsline {subsection}{\numberline {3.2.2}The DIT Entries for the list}{20} +\contentsline {subsection}{\numberline {3.2.3}ORNames}{21} +\contentsline {subsection}{\numberline {3.2.4}The DL tool}{22} +\contentsline {subsection}{\numberline {3.2.5}Creating a List}{23} +\contentsline {subsubsection}{Creating}{23} +\contentsline {subsubsection}{Upgrading}{23} +\contentsline {subsection}{\numberline {3.2.6}Managing a List}{23} +\contentsline {subsection}{\numberline {3.2.7}Maintaining a List}{24} +\contentsline {subsection}{\numberline {3.2.8}Printing a List}{25} +\contentsline {chapter}{\numberline {4}Miscellaneous Utilities}{26} +\contentsline {section}{\numberline {4.1}A /bin/mail Replacement}{26} +\contentsline {section}{\numberline {4.2}Message Status Checkup}{26} diff --git a/doc/manual/volume3/volume3.vrsn b/doc/manual/volume3/volume3.vrsn new file mode 100644 index 0000000..f604e4f --- /dev/null +++ b/doc/manual/volume3/volume3.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.85}% + \gdef\versiondate/{Wed Dec 11 21:37:15 GMT 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/nordunet/Makefile b/doc/nordunet/Makefile new file mode 100644 index 0000000..a2cf66b --- /dev/null +++ b/doc/nordunet/Makefile @@ -0,0 +1,92 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps \ + .ry .py .grap .chem + +.ry.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grap.tex:; grap $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.chem.tex:; chem $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.b.tex:; itbit $< + +.xb.tex:; xtbit $< + +.xwd.tex:; xtwd $< + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grf.tex:; sh -c 'if graph < $< | plot -TeX > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.pct.pic:; pct2pic $< + +.pic.tex:; tpic $< + +.plt.tex:; sh -c 'if plot -TeX < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if tgrind -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if latex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if dvi2ps $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + + +############################################################# +# Here it is... +############################################################# + + + +############################################################# +# pp +############################################################# + +all: pp.dvi + +print: pp.ps + +# customization files, et. al., not included below +pp.dvi: pp.vrsn + +pp.vrsn: pp.tex pp.bbl version.sh figure1.tex figure2.tex + @version.sh pp + +pp-slides.dvi: pp-slides.tex figure1.tex figure2.tex console.ps + sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +biblio:; bibtex pp + +preview: pp.dvi true + texx pp.dvi + +index:; idx2ind -l pp + +clean:; rm -f pp.imp pp.ps pp.dvi pp.log \ + pp.blg _* pp-slides.dvi pp-slides.log pp-slides.ps \ + pp-slides.blg *~ + +true:; diff --git a/doc/nordunet/captcont.sty b/doc/nordunet/captcont.sty new file mode 100644 index 0000000..70f662e --- /dev/null +++ b/doc/nordunet/captcont.sty @@ -0,0 +1,16 @@ +% SubStyle file to permit the use of captions in continuations of floats. +% +% \captcont is like \caption, except that it doesn't update the counter, and +% it doesn't make an entry in the list of figures or list of tables. + +\def\captcont{\@dblarg{\@captcont\@captype}} + +\long\def\@captcont#1[#2]#3{ +% \addcontentsline{\csname ext@#1\endcsname}{#1}{\protect\numberline{\csname +% the#1\endcsname}{\ignorespaces #2}} + \par + \begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} diff --git a/doc/nordunet/console.wd.Z b/doc/nordunet/console.wd.Z new file mode 100644 index 0000000..07a53e5 --- /dev/null +++ b/doc/nordunet/console.wd.Z @@ -0,0 +1,68 @@ +® àA ga‚‘ Å€@ȱcă ³° AU+$€ç™:màpüG³¦ÁŠ ÖÜɳ§ÏŸ@ƒ +ºÑ£H“*-º´©Ó§ÿØAJ5(0x³jÝʵ«W€Ýû‡õ«Ù³h³~øwìß<`ô@àè ­Ý»Yç0X½{Ðîà ªa¡øôòõ XÄÞ…x#GVÜ÷/4 +Dä„&ÈAáà{â»ðïÈ¿Ê€I$‰„’c£­P…HÔ—WG &äÃçÐÀÿþg»o\˜Ap=W¶ó®´‹3†æ8‘×~=üH<Ü‚çdöÈÙóóZ) ·GíÛ gï½}®zÛO?tbôÁ%×}æ ~c•Uà‚­ÕÖ[ +2(!Aaõg¡UfØ“Qvø‡fxÕ„$V„%.xbŠ®È"ƒ'uÈNáåÏZ<ñóƒPþÜw" YQZ ÐD\T¤Wé‘™•‘%ÉBöýäE¹’’S2 “A”QÉ‘•[a‰ž–™”s)Lš^À›Ü nž7€2c„Fs‘@T©¦D°(NNêÜä +À¡Hdæ¢4ºæ£EzѤ•úHϘó 8Ä„8`ø„0€3pƒfä rŒSÎ1¦Âq,¯æpÏ<ƒ\b©lð3¦ ‰@Bk"@°(¯9–LkDÉm$Ø’d"ˆ ¸ !Lâc5×> -qÌE¸â†@® p;9©[»I"¼ôâq/úf™Îµ n<®$l]¤'Ä HL± rqÆoöñ¶Ü†.—ËíuD±­Ê à.Ö½3"„`ìc4cpˆ<à0.´>Ð8èúŠ#¾>3Þ ÂZÉ9‡|@pœsÃ#t€sŒÃ‰Ÿo–£i™¡Ù‘šH‚™QHoæ³7G„ôÝe•‚ÿíc3‡CDÈNúÍà_BT×å>†9Af`9D˜— +fš>Öóy¢Q.¾æéŽg™ <2Òh#Ž;éȣĠøb–Èøþ» Ü?ü¥ð|lô¾¼Ø(ÿ<^°#ýôv¹ˆý¥«f … °ùö`ANùŸ¡rš‘Çäg5€çˆ@¨Oûíw4€ê᱊Ç0€ñ a(†3>àƒüéï*@@&d@D‚õX#/ü9Bà€G#!>bäÈà' låÉ؆‘@B BñC€ ¸ðƒiÞ IXAE`¢ØàÄ~Dy8Dæ8Äa 8€ç‹c<„ÂÍßÐÑö À%Ÿ"zÆŒnŽÅÞŠÇQ°Œ¨¤o<)J)d½•Q¥.åcDJé‘ÁÁ€üf•¢ÙÔPó[‰G8Õ›rjS1Ç >!¡=¨”jGˆæ¹ @&­¨™(Ö%> Ê\yÇVà ŽàòP ,~€8Ð*Wa4" "`"tÌd + )ö‚"€L!1„#R0±¤x@Sûú× c°~­æ51¢X"| ±yhNdy€!±„˜MÆfeùׂ¶hÅ,cspUеf÷ª¢U°HÙÏÄ %ÝnŠ·ðmk( +Û\‡¸òiÆ1 Nõ¼g>1{Ìâø者ü€:¨Ã=fŒç˜'¾W\DÎE~[0N[S¯ü×+.‘L»‚ƒóy²« +.0J\R +sÔ Åp(5ÜÉ= DýÁljP… 'R€*¼uâ—x¥(¾ŠŠY\ÒÃÄ&®qŠW c瘣6žq¯‚ã!ÃCÈ-&ò‹[L¨[E2CyŠ3…ã'G&ÊÎAñªfÌ_tù._ÖŸ”‰ã0CÄÌhA3ø²¬Î#¯XÍ€óWä<€1o ÇÂð¡žõçŽùùÏ Mhäyψ®3¡=hDêÑæŠm6ã`ðw˜AÆ÷ÆŽ€ÜÄÑUÂA™|o¼T¥LDRgP¯únê´Gd}¿@ ÇÈ@BÇб(ÀÌPPŠÄ!†ˆf`Fr ØŽ9 Î€@¶ÌC4;Þ‚rÄ ä Åz㲨Ð*|ÏM±W@03X ƒÆzöZÁ…´šÞ"A€"0r$vàÜ0\™Ã0ŽW`Ð`p÷áNàÎÒ,a„EÃGÐóÀ‡‘ 2 | *-‚`ãFP„9Π Eøpè”3žá !?ÞÔ Çeà6Tš&¸¬ÔV )€Â±)仺ʔA)%€:?ýg"8@Î;”€=r9¸¤Zfaâ„h6 € +`L<^>—$0A°J`Aüœob„E²›-ˆAÀïLH„T€Uô*F²µCŪ+: Œ¦(wà5 ‹·Óýð[|ÁIù>9”é˜Á² +`}Òð ‚äì°éÂg‡g!˜@ †Ð³ÜÍ%d@L@Ÿ¨\ $àQ€aHÀÈAÌõ\çê“!2 +D!èàÔg¯B¤ +@µ÷®ÒùÆ!^Øxhzå_ü@)7Ž+ó5m21 0i3[àxXEá Ç`sÑiÐ cà Bk†2Áƒk–‚ÁÆh&w.è‚m)øgØö‚6(ä–ƒkW<\¦ræt†/TkÉSf,(hßcƒr'ˆ†hqv„‚ærMØ„ásxàs>gn pöƒ]„l=e惒†²bÖãd@á…\egècV†nZ¶…=9EÖbžƒd:¦:y¨c2Æc-Bd1d‡-Ö;…¸P(öD|hˆd´ˆ¡„bÉ󈌸F7¶dgñʇ[ñCA‰ˆ¸‰>щkè ((VG’ø…1`^F†]ÁS %Š–„¯(‹±8‹ždc­Èh‹Ñ…^A‹îƒb€4cSèCŽi‘bhSËSg^—ÚØy€b„Td°C‚¥–ÖU Œã 0@9ŸF)a&kü5ÆèMч4c3ˆ €y9(n˜ƒºÆkƒ0φ  k~¶ˆf!*{AÎèŒ 0S–‰?¦>C˜oÂnçèù9ô'Y…±ÆÈn†b‘”4c0ëp +?Ð~8UÃp Xˆ q6£ð + 0h8¥ãÐ à hÜ ò@kð <0hu7½à® À]üµa ñ @p n0 (Ià˜LƒEv"!N È‘„ÀXT ÀU‡2XÁ„ CT鎠‘P'Ë­„’© õB’¥“€öHFB +äð 2à0‡T§iƒwÍ +r ‡€ r‡—‘„€'wÀð—É!)t’è g€ Dà|€ >'C€b˜Td" N) `CÁ‘€ðTç8—PøFŽ+AJ2w°Y'ב·‰ +ˆ‰IÒoŽfŽ¸b ǧ‚Ðu9g$ÀîBŒ`hB`F >$ë8r>4rþi + w €Éd›a + P#P‰Ðy À’„øb!à gÀÐiƒtU'Á°ã €‡‚85œ1¢q¶Çð `@ ðIv§ ÏFüÓ +½aÀ +áðœ°Ì@)¸Š[ˆÒ7ƒ ý82˜‚‰ €V¥3ø=µI$0‘‘bzŽa2Œ¹XvAŒ_ª<;&‚b±ä’EÉh…Xø„Œ†SEÉ…¶‚,ø=à0>å S*n€b·ô‹[Œº¨¦¼èG(v‚x’ê=“ +§½8±©ZÁ‰£zŠ]‘ŠAA§£h¤šž¨¨ +(Æ/¢zG—ºª—8Pµ*G(vP·ØI(&†šhˆ{˜©†Q»êF(FQ¿úH(†QÉšFÙ¬}$ŠÑjF¶h¬Ç«?Á(V<׺ ÜêÞºc4¶<ÆåªdA7<é*f[†¸ê®ž´®¹ŒA¦‘F•P(hͨ¯‘†Û¸Šv„Bˆç +‹²öJžFÀâ¨ðS!ÄÑj³üµ9¾XbÙÒ1Xª˜gn9bé-€ +  + .x™@X€ P 9H@ô§¯×F)WwÍ @d<æ$Í¡v¯$*òâv Nˆp(ÌI(éy­Än]7T)*Á7²Pòp§`4‰™çÐNÀÌ€>‡ßã"à#0çp .ps9'[õ H€ùË >‡•qÞp^Éa 0à. " Ÿ€¹k‡¤†™vsÑy +@DÒtÑ•$ °2dº Ð1ñ#&@˜r›ˆ "À4µÇuu´œ +q¶>0Ç ´–é-·Ÿ0¡A`¡@’NŠù  —‡™º’ ÐA0åP½po`€ CH@ b@v ™¹*À( P‚«¼ñ ¾‡ºàR $泉-Á‡µ’Õ1D8ä``A¼³äo"@°œ½Å¿÷º “ ¸Pà•`D@‘ÂÔ3!2€±ð¶ðÉŒÀ+ìP)X /%J¡ÜX~"@ q Á´Þ2Ãp +;@^‹_Úà ð5€pàxÀèÇTì1ê ? ±â `ð£`ñÀ o`¤: èx ý€ +!²>–ƒƒ‹*n JƒƒÜA;Ÿ @¦5¨„¡K­æ`à$GDö +Ž,X…zÚÉ øÊŒ¡Òɤ ¤ŠW‹Š¹ÓÉÚJ¯~”ÉÃz<ïzJñj®Ø3®=Ëíú;¸Ìö*ɶz"‡2„Î*Ì’dð0ÌF¦ÌÈÌÌ€˜ÌÇüÌÎlˆW1Í—XÍÑLÍÐLÌÕjÌܬG6fÍ“èÍ=F(â ¬ŠtÎż*ÃÊU•ÈósÈ@°hÕ¯È~&t̛֢á$üu>âCzU$kœf"@Â['+ÐÁ_vg@:%k4«ÛœÀLÐ1 +™€Ñ `ÐÉbÐqàC)ížrAT2@˜Ð²”³–y/€`È7dlI0ƒ!0h„b3̉u&éh‚$t:ÄNÁ·ÀÍA{¼›R)YåhÇ,CC=6cÔ2@oà +fÀ‚F³’‘0}01 çry°Ÿ€½([ÂÄðοÀ x›¹‚àó° ãð»à zFtô¢€ ùÍ& +mekðða ¶"–J.õ˜i8.¢=t!µ<§í9¥}ÚªÓÙý1 ³ÓÚ˜é<¡™ÁCÛ#•ÚÏRœ Û¡E½£Î}=‡BU°ÜÌÝÜÎýÜÐÝÍM Æm=‡¢ªÝÚ½ÝÜÝÝÞýÝÜ aÎaÜجÜÒ}Þè-ÝÔ=ì Ø Þðßð-Þ²aÜ“Üéßú½Üëí9×-ßàÙMß±aܪƒßûàê}ä Íï-àþÝ.ÆB®à>Ý ~ˆÿáÞ>Ü`ÞžáëýDþá*>á“AIÄ­GÆ<¿ ܇El®MãóÚIÆÍŠ±J:ÌrÔà8DÆŒ­Ìツ‘+eÜÖ"ändÜTöãJ™IþHÆm–TŽå-¹bð±õEãdqIùåJæ4Eç Àâ_hÏSáe[çvÀçËÓã[Øæ‘‘çq>gZb0ŸôLÏ€¾ç Úç +HÐÑèAVgçKÍnìvɓ°÷“Ð+aÜJèà³°³0”À²‰¬ê€ÎT›â;à …ê0Ÿð‚óðÀÐûÀ€p0€ =b5‡`wK–Bä’ÍU”’`U•Ô€% Óݹtˆ0$ d ‘' õ" r¡-„ÐÌ-\]ÚnÜ¡JèÀp“^€XȸzÀzA°¸Pè ›çÐJxp ‹ ppœ@õ²íÝNo™⎔(€!@èÎNë.Ùâî}~1µÛ—P{»Tˆ)ðàÃ@òyĽkM€ò@ +B)LRpÈð(˜>°\ PD«„…ÙAPPq0%€¾Uñ`i ­„UpP—ŠIp\à€ ô„‘ õP&4ä˜w\C^ÍîåG@P@µ_JAî¶ö3U C{”ïZOÀ.ôd0ôª‘G äÞzNÿ3 ð$TúP¤«„NøR )oY*ÌðI%@TP@yþŒùp_{¸ ô‚÷§Oâb ÐénAâ”îÖ?—0£-ÅèópÐ{5:€Pœ@¹ÀÆ-o 8šf@VËÀ ßÀ·ÌæM €ð>ˆÏàÔ— Ü8 »9pìØ`ÆMX¥-R—È(@"ƒyŽSL­Œœê]¡Q·bÅæÜœJFz®ê¼ㆬà)ëdWèúœDÇ€~‡qcVŒïÏÅÀáaÜ ÕÕ»sH0ñ@"¨H\ÒT@sÀ Š!B÷€˜“‚;ŽË«-WÜlJ!r\ÆU,ØÙU“ó‚% î2.׿¾`òrƒm0 ú37P/; +¥Á9Á¥`¡BœƒnÎ#p¬YfÐQ‹CX€Î%Á5#ƒ!Ä jÐÏ¡…Fˆá]Ѓ^ÎÐ:HC ï‚%´ ‘pšèÈÄ l5@|pÌ3>aZÀ„lnÔ•:qNYš>kg0°>Η8*àÀ +!@¸´E)¬:ƒ°Jš_h„áY€…xî/ §œÀ1pÀ,`о`· (€ÀÁH € œÄGo€°v¥¥PQha¡ +ï BòC”ƒH.sdü¥ªó뛹J„àp½Î +ÀÈD,,€Dða`!?€ƒº¤-@p4à°>‡Hh™¬Ž¢(@ ûáÃÞ5yˆaä…#Ϊ3E"øþ "ÜŒàÏÈäà ƒfÐ 6™+קÜì‚[†5ŠAkQä>ˆqãP.·;ïˆq£4²Ñ7j¶Úè@Œ[ºñrT-…?¨p¨àTPŽJá ˆÚǺŒQÑsà˜DH‘ ¸Žg3n7ò"ƒu|ŒQ‘øܾMHÏ +ÀwDðSµ@#`Ñ%#Gâ<ªŽ`±Xa\ŠŠ'HÔQU7¥pÀ¢ +Kæ&¼ÇÝõy¤ÄZÁ¸ñ Æ?¦Ý‘¸ÓN!èǧídà„‡S0mbpö7€pÀÿÜ­ Â48n@!à·‚ÁwÜœ`/€¬ à…:d‡îBæ…ÅÇæAÌPáÂú!„Cq˜êEéB,QïòK½ˆ‡B *‚($=B,sƒ < àE8°P Œ æRˆ ŠJrÄ‚ç$81°@Ex˜†¼œ Y*Iæ ž®dÚ‰`J2ÀÕB½¸“ÄÑlI›hõ¢!ˆO)Œ4‚ã×Â@+8~ (R€P(@øŽÀ1XI¦v(œâž4ˆ±‘Í1¯cx€ò!ø€ ¤ˆã ŒƒPð à@ ƒàf’Zd‹n¨¨¨ˆ‡$ 70àfKº¸ Ãcvìs4ã’-WÒ- aTôC„'ù8 Î`ìdŠ>VÊòXËebŒŠ*mMÆî8°ì¥Wè’Á¸É= cRøƒŠÈ9̇£âš;ƒ‘¨79’͈q»q3ÊQÌà81}Ükƒ•ˆcjÌÔ(‘ܹZ(ÆíeLÝxD&Ëtt)@AŸ0€„q³rl® +…š¹ ²\™ „‘jvðX nfŸÛ—üR +MŽ@4×[q"t@Ó-MˆÐ47Üš+tì`-Á¡)!äÜväïPÀYó;d¢{W jÚ>ç’ AÀ dr3' ¤¸ñY‰v൉ŒãϬ`lƒLµ¡TòæTá›çA乤c A4Àø ô; ðÀÐ@Cච ÞBžË®Àà‚9Ð øKÚìš ÔéË +‚%ÉÀØT­„ +,E&°€P Ø|x–$⌊ò1&‚D …â< TÇU’@ àz© €,ÀÔ`3‰7¿¾;}ù¸IcQ¥Âå D»P‘ ‘\OC‘= bòr—’è>"Ð(¤¡õ3°‚FÆ +xú„:ˆ€ý°OÔiõÒ–!ˆÇÀø€[Y±pŠì—]É +â4Ès Œƒ[q +¤ðí³ÀÉ0?à ÛšLuÚ¾´4‰ +¥š¨ÓWy¹wÙ.8Ð/” „P +wÜ~¦Ü +;´Å±@î˜4·Q A€˜¶t&Pà™Es¢ô9'ú èz3‚S8fŠŠ)FtqÌAÎeZÌÝöEÛ,<ƒ$“£T·Ó(Ó(ÊDƒjô ÊÁÏHî0UkS3ÖÑ;úØ(<ˆQ“¡ÿØ©òâœ+¢«ÎRNµáa uƒÔ5Ò2§ ³¦32‹tåQG +VÃÊ +JB‘B„v4»üè+œƒ%´É€A,ש‹¤8á ˜žIêì Bžxj" QKÂ,ݤeî œÄ @(ƒQ °H æGà<ƒ!0HéÀz Áàx.àKMé0D„‚Àœ‚p&@ïÔj‡ ƒ/ª$’ˆãÁ* ‚€€ èKÛp½éÅA0 +Á'˜M¼. I59A@WŒ‚ðNUzà<\:wô)¸\@‰qæB¡lx¤wŠÐP'‹5ï©)oú ç ! òÉhJNIL€§<~DÀ÷‰)` +X€ˆ‚§ò”žÊ®ÆRãâA4³àp+ߥ áý9€9 - @,¦ƒt à<ŽÁ9pó€*Ù(‹ºI]*íGÛrJa.Vˆ! BQ Œ€4¨l…ÈKÛj@x«‹Q/2®#PCÝ¥¤¦¬Ð“R*`ZK#/Tdõ"RmtX éMœ¢{t(àÕȨG§‚•¬•‹æ89Gã`g-s”NL7 +ä…hÕ˜®ñ ÆÊ3HWæÅb´‹ÞØD<ˆ™>a²fFà˜3m+nÝëíÖ@MO¸%i=ŽliòK¹HuëxL8>ô/W`´Þ¦#›«¤–”¹šç!ÙÔa|hº@¡]=Õüà®C2ôx9H0À\¼‹Êˆ›lY^'€¹”½zÉ Yh½ bˆ"vP„úZ¶ BvÒ¯s„ƒr€ ®ÈAÜ;=©t€À8™ 8–"†ÙÌ@*ê† iëO¢Ôm*BÊ+çTÔ ¹tA€@€B¢€¾dbóè„”•#`H=ôÕyÀ^¸ º"¬€h,å Â…DXÔcû&HÙŽ2‚ˆ D!ù¬KŒ46T@Ù¬]vìy]oÁÓ˜€ˆæð}>ñøÑ?`U§¾+]¨SPb,Gø’Û1\ƒ/R5BÅê/ŒœðÁàt@.ù?B8B Ó VŒ± +ü¬-ƒmÓ„zÀEE`©ë$ýš\¡l„R‹X7\¬Äs}5’2Û\«kt}ŒÓµÕæÑ!ª\»#«u¬]ÖÖ¦p[“‚§Å±3þVžpl«Ê'­qt`ÆÖÍš0³èÄ|˜n0bZ[2OfiŘۖevÛ3è1Ïà¸5e”|¹ÓÊ2Uf¸£OnÚ9E’n·‡ÑÔ¬óV˽[ÙŠ3ÏàÓÜ·›ÛÊÁ|InÙítwÞ¾Oo«äTç”gp{F\ƒ+[ èÃ¥¸›u…žAÊp¹œ<ƒ,ð 2Ñ3;nÄ¢gp‹Ê[Ûxe]«l=·rp &\–ëYß(iUr}Òä¢Fhks1î¼½¹lÐçÒ\ž[ZknÑ%ºJÎè&]¤tñíЭ·Ø㌢[—»Y•nÐ…ºÓCê†V¬è¬ndº_×éGÎÚsÅ.%»G×ìšQ´»tÕ®ºe»MwåŽ] våîÙ¥»bp5ê\- +vÅàjuƒ­uæŽ]غw'&m=ƒ¼õ +WÁ{v‘ëlŽŒwíZWÛw…£z-¼³¿^\·koMPå˜?ÖÜ~^ qÝàÇuƒ9Ž^–ùwå`µŒ¼o7äºAa«z9oÔ}¶\WÑI[ÌË2«í¸qTÛŠ^Û›u1Qî=a”÷ŽÑrëaîg=¾LÐdžAwËZ…îØM­ÙÖúž]} 1µïÚý·¿w›A —ÍÞhyqÂQo ß‰K֯Ƽ%î·÷Š_7Ø~Ëoi­¿ßL8ò‹ø;FE\þ˜…ÿÊÖƒ"€7+r³¿Jο!`.Q¦˜› +P„¢”6Q&0fʤdà<SHÊæ0÷‘1˜%L…4 àlV0 ¦ +.øC` +echo shar: "a missing newline was added to 'console.wd.Z'" +echo shar: "1767 control characters may be missing from 'console.wd.Z'" diff --git a/doc/nordunet/figure1.pic b/doc/nordunet/figure1.pic new file mode 100644 index 0000000..f03143f --- /dev/null +++ b/doc/nordunet/figure1.pic @@ -0,0 +1,52 @@ +.PS 5 +eighth = 1/8 +boxwid = 0.5 +boxht = 0.25 +arrowhead = 7 +arrowht = eighth/2 +define user X box "User" X +define ua X box "UA" wid 7/16 X +define mta X box "MTA" X +MHE: box dotted ht 4 + eighth wid 6.25 + "Message Handling Environment" at MHE.nw + (eighth, -eighth) ljust +MHS: box ht 3.25 wid 4.5 with .s at MHE.s + (0,eighth) + "MHS" ljust at MHS.nw + (0.25, -0.25) +MTS: box dashed ht 2.5 wid 3 - eighth with .s at MHS.s + (0,eighth) + "MTS" ljust at MTS.nw + (0.25, -0.25) + + user with .e at MHS.sw + (-eighth, 1) +Ua1: ua with .w at MHS.sw + (eighth, 1) + line <-> from 2nd last box.e to last box.w + + user with .e at MHS.sw + (-eighth, 2) +Ua2: ua with .w at MHS.sw + (eighth, 2) + line <-> from 2nd last box.e to last box.w + + user with .s at MHS.n + (0, eighth) +Ua3: ua with .n at MHS.n - (0,eighth) + line <-> from 2nd last box.s to last box.n + + user with .w at MHS.se + (eighth,0.5) +Ua4: ua with .e at MHS.se + (-eighth, 0.5) + line <-> from 2nd last box.w to last box.e + +Mta1: mta with .w at MTS.sw + (eighth, 1.25) + line <-> from Ua1.e to Mta1.sw + line <-> from Ua2.e to Mta1.nw + +Mta2: mta with .n at MTS.n + (0, -eighth) + line <-> from Mta1.n to Mta2.w + line <-> from Mta2.n to Ua3.s + +Mta3: mta with .e at MTS.se + (-eighth, 1.25) + line <-> from Mta2.e to Mta3.n + line <-> from Mta1.e to Mta3.w + +Mta4: mta with .e at Ua4.w - (0.5,0) + line <-> from Mta4.e to Ua4.w + line <-> from Mta3.s to Mta4.n + +Mta5: mta with .e at Mta4.w - (0.5,0) + line <-> from Mta4.w to Mta5.e + line <-> from Mta5.n to Mta1.s +.PE diff --git a/doc/nordunet/figure1.tex b/doc/nordunet/figure1.tex new file mode 100644 index 0000000..7e127a6 --- /dev/null +++ b/doc/nordunet/figure1.tex @@ -0,0 +1,317 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{pa 0 3300}% + \special{pa 5000 3300}% + \special{dt 0.050}% + \special{pa 5000 3300}% + \special{pa 5000 0}% + \special{dt 0.050}% + \special{pa 5000 0}% + \special{pa 0 0}% + \special{dt 0.050}% + \special{pa 0 0}% + \special{pa 0 3300}% + \special{dt 0.050}% + \rlap{\kern 0.100in\lower 0.141in\hbox to0pt{Message Handling Environment\hss}}% + \special{pa 700 3200}% + \special{pa 700 600}% + \special{pa 4300 600}% + \special{pa 4300 3200}% + \special{pa 700 3200}% + \special{fp}% + \rlap{\kern 0.900in\lower 0.841in\hbox to0pt{MHS\hss}}% + \special{pa 1350 3100}% + \special{pa 3650 3100}% + \special{da 0.050}% + \special{pa 3650 3100}% + \special{pa 3650 1100}% + \special{da 0.050}% + \special{pa 3650 1100}% + \special{pa 1350 1100}% + \special{da 0.050}% + \special{pa 1350 1100}% + \special{pa 1350 3100}% + \special{da 0.050}% + \rlap{\kern 1.550in\lower 1.341in\hbox to0pt{MTS\hss}}% + \special{pa 200 2500}% + \special{pa 200 2300}% + \special{pa 600 2300}% + \special{pa 600 2500}% + \special{pa 200 2500}% + \special{fp}% + \rlap{\kern 0.400in\lower 2.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 2500}% + \special{pa 800 2300}% + \special{pa 1150 2300}% + \special{pa 1150 2500}% + \special{pa 800 2500}% + \special{fp}% + \rlap{\kern 0.975in\lower 2.441in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 2380}% + \special{pa 600 2400}% + \special{fp}% + \special{pa 650 2420}% + \special{pa 600 2400}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2420}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2380}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 200 1700}% + \special{pa 200 1500}% + \special{pa 600 1500}% + \special{pa 600 1700}% + \special{pa 200 1700}% + \special{fp}% + \rlap{\kern 0.400in\lower 1.641in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 1700}% + \special{pa 800 1500}% + \special{pa 1150 1500}% + \special{pa 1150 1700}% + \special{pa 800 1700}% + \special{fp}% + \rlap{\kern 0.975in\lower 1.641in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 1580}% + \special{pa 600 1600}% + \special{fp}% + \special{pa 650 1620}% + \special{pa 600 1600}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1620}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1580}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 2300 500}% + \special{pa 2300 300}% + \special{pa 2700 300}% + \special{pa 2700 500}% + \special{pa 2300 500}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 2325 900}% + \special{pa 2325 700}% + \special{pa 2675 700}% + \special{pa 2675 900}% + \special{pa 2325 900}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 2520 550}% + \special{pa 2500 500}% + \special{fp}% + \special{pa 2480 550}% + \special{pa 2500 500}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2480 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2520 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 4400 2900}% + \special{pa 4400 2700}% + \special{pa 4800 2700}% + \special{pa 4800 2900}% + \special{pa 4400 2900}% + \special{fp}% + \rlap{\kern 4.600in\lower 2.841in\hbox to 0pt{\hss User\hss}}% + \special{pa 3850 2900}% + \special{pa 3850 2700}% + \special{pa 4200 2700}% + \special{pa 4200 2900}% + \special{pa 3850 2900}% + \special{fp}% + \rlap{\kern 4.025in\lower 2.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 4350 2820}% + \special{pa 4400 2800}% + \special{fp}% + \special{pa 4350 2780}% + \special{pa 4400 2800}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2780}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2820}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 1450 2200}% + \special{pa 1450 2000}% + \special{pa 1850 2000}% + \special{pa 1850 2200}% + \special{pa 1450 2200}% + \special{fp}% + \rlap{\kern 1.650in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1181 2356}% + \special{pa 1150 2400}% + \special{fp}% + \special{pa 1203 2389}% + \special{pa 1150 2400}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1419 2244}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1397 2211}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1196 1628}% + \special{pa 1150 1600}% + \special{fp}% + \special{pa 1164 1652}% + \special{pa 1150 1600}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1404 1972}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1436 1948}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 2300 1400}% + \special{pa 2300 1200}% + \special{pa 2700 1200}% + \special{pa 2700 1400}% + \special{pa 2300 1400}% + \special{fp}% + \rlap{\kern 2.500in\lower 1.341in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1669 1950}% + \special{pa 1650 2000}% + \special{fp}% + \special{pa 1699 1977}% + \special{pa 1650 2000}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2281 1350}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2251 1323}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2480 1150}% + \special{pa 2500 1200}% + \special{fp}% + \special{pa 2520 1150}% + \special{pa 2500 1200}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2520 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2480 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 3150 2200}% + \special{pa 3150 2000}% + \special{pa 3550 2000}% + \special{pa 3550 2200}% + \special{pa 3150 2200}% + \special{fp}% + \rlap{\kern 3.350in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 2749 1323}% + \special{pa 2700 1300}% + \special{fp}% + \special{pa 2719 1350}% + \special{pa 2700 1300}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3301 1977}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3331 1950}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 1900 2080}% + \special{pa 1850 2100}% + \special{fp}% + \special{pa 1900 2120}% + \special{pa 1850 2100}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2120}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2080}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3050 2900}% + \special{pa 3050 2700}% + \special{pa 3450 2700}% + \special{pa 3450 2900}% + \special{pa 3050 2900}% + \special{fp}% + \rlap{\kern 3.250in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3500 2780}% + \special{pa 3450 2800}% + \special{fp}% + \special{pa 3500 2820}% + \special{pa 3450 2800}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2820}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2780}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3360 2253}% + \special{pa 3350 2200}% + \special{fp}% + \special{pa 3321 2245}% + \special{pa 3350 2200}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3240 2647}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3279 2655}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 2250 2900}% + \special{pa 2250 2700}% + \special{pa 2650 2700}% + \special{pa 2650 2900}% + \special{pa 2250 2900}% + \special{fp}% + \rlap{\kern 2.450in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3000 2820}% + \special{pa 3050 2800}% + \special{fp}% + \special{pa 3000 2780}% + \special{pa 3050 2800}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2780}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2820}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2397 2690}% + \special{pa 2450 2700}% + \special{fp}% + \special{pa 2418 2657}% + \special{pa 2450 2700}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1703 2210}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1682 2243}% + \special{pa 1650 2200}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 3.301in +} diff --git a/doc/nordunet/figure2.pic b/doc/nordunet/figure2.pic new file mode 100644 index 0000000..0e8dbf9 --- /dev/null +++ b/doc/nordunet/figure2.pic @@ -0,0 +1,15 @@ +.PS 5 +Inb: ellipse "Inbound" "Channel" + line <-> down right from Inb.se +Submit: ellipse "Submit" with .nw at last line .end + line <-> up right from Submit.ne + ellipse "UA" with .sw at last line .end + line <-> down left from Submit.sw +Qmgr: ellipse "QMGR" with .ne at last line .end + line <-> down right from Qmgr.se +Out: ellipse "Outbound" "Channel" with .nw at last line .end + line <-> down right from Submit.se +Que: box "Queue" with .nw at last line .end + (0, boxht/4) + line <-> dashed from Qmgr.e to Que.w + line <-> from 3/4 to Out.ne +.PE diff --git a/doc/nordunet/figure2.tex b/doc/nordunet/figure2.tex new file mode 100644 index 0000000..e5898bc --- /dev/null +++ b/doc/nordunet/figure2.tex @@ -0,0 +1,123 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{ar 642 428 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 0.386in\hbox to 0pt{\hss Inbound\hss}}% + \rlap{\kern 0.642in\lower 0.552in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 1247 821}% + \special{pa 1096 731}% + \special{fp}% + \special{pa 1187 882}% + \special{pa 1096 731}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1801 1496}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1861 1435}% + \special{pa 1952 1587}% + \special{fp}% + \special{ar 2406 1889 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 1.930in\hbox to 0pt{\hss Submit\hss}}% + \special{pa 2951 1435}% + \special{pa 2860 1587}% + \special{fp}% + \special{pa 3011 1496}% + \special{pa 2860 1587}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3625 882}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3565 821}% + \special{pa 3716 731}% + \special{fp}% + \special{ar 4170 428 642 427 0.000 6.283}% + \rlap{\kern 4.170in\lower 0.469in\hbox to 0pt{\hss UA\hss}}% + \special{pa 1861 2343}% + \special{pa 1952 2192}% + \special{fp}% + \special{pa 1801 2283}% + \special{pa 1952 2192}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1187 2897}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1247 2957}% + \special{pa 1096 3048}% + \special{fp}% + \special{ar 642 3351 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 3.392in\hbox to 0pt{\hss QMGR\hss}}% + \special{pa 1247 3744}% + \special{pa 1096 3653}% + \special{fp}% + \special{pa 1187 3805}% + \special{pa 1096 3653}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1801 4418}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1861 4358}% + \special{pa 1952 4509}% + \special{fp}% + \special{ar 2406 4812 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 4.770in\hbox to 0pt{\hss Outbound\hss}}% + \rlap{\kern 2.406in\lower 4.936in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 3011 2283}% + \special{pa 2860 2192}% + \special{fp}% + \special{pa 2951 2343}% + \special{pa 2860 2192}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3565 2957}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3625 2897}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3716 3690}% + \special{pa 3716 2834}% + \special{pa 5000 2834}% + \special{pa 5000 3690}% + \special{pa 3716 3690}% + \special{fp}% + \rlap{\kern 4.358in\lower 3.303in\hbox to 0pt{\hss Queue\hss}}% + \special{pa 1454 3302}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1457 3387}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1284 3351}% + \special{pa 3716 3262}% + \special{da 0.050}% + \special{pa 3546 3311}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3543 3225}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3640 3635}% + \special{pa 3716 3476}% + \special{fp}% + \special{pa 3574 3581}% + \special{pa 3716 3476}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 2936 4350}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 3002 4405}% + \special{pa 2860 4509}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 5.240in +} diff --git a/doc/nordunet/lcustom.tex b/doc/nordunet/lcustom.tex new file mode 100644 index 0000000..5ae23b3 --- /dev/null +++ b/doc/nordunet/lcustom.tex @@ -0,0 +1,350 @@ +% LaTeX customization + + +\makeatletter % for a little while + + +% plain TeX compatibility + +\def\oldstyle{\xdef\@oldstyle{\the\textfont\@ne}\mit\@oldstyle} + + +% PhD-TeX compatibility + +\def\showsummary{% + \begingroup + \def\note##1{% + \ifcase\value{##1}no ##1s\or + 1 ##1\else + \the\value{##1} ##1s\fi + }% + \typeout{LaTeX summary: \note{figure}, \note{table}, \note{footnote}.}% + \endgroup +} + +\def\smaller{\footnotesize} + + +% Float Support + +\def\topfraction{0.85} +\def\textfraction{0.20} +\def\floatpagefraction{0.85} +\def\dbltopfraction{0.85} +\def\dblfloatpagefraction{0.85} + +\def\@tagskipcommand{\vskip .5\baselineskip} + +% \tagfigure*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads TPIC output in file figureFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagfigure{\@ifstar{\@stagfigure}{\@tagfigure}} +\def\@tagfigure{\@ifnextchar[{\@@tagfigure}{\@@tagfigure[t]}} +\def\@stagfigure{\@ifnextchar[{\@@stagfigure}{\@@stagfigure[t]}} + +\def\@@tagfigure[#1]#2{% + \@@@tagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} +\def\@@stagfigure[#1]#2{% + \@@@stagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} + + +% \tagdiagram*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeX input in file diagramFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagdiagram{\@ifstar{\@stagdiagram}{\@tagdiagram}} +\def\@tagdiagram{\@ifnextchar[{\@@tagdiagram}{\@@tagdiagram[t]}} +\def\@stagdiagram{\@ifnextchar[{\@@stagdiagram}{\@@stagdiagram[t]}} + +\def\@@tagdiagram[#1]#2{\@@@tagfigure[#1]{\input diagram#2\relax}} +\def\@@stagdiagram[#1]#2{\@@@stagfigure[#1]{\input diagram#2\relax}} + +\def\@@@tagfigure[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@@stagfigure[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +% \tagtable*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FILE read LaTeX input in file tableFILE +% FLOAT float options +% CAPTION for list of tables +% LABEL for \ref and \pageref +\def\tagtable{\@ifstar{\@stagtable}{\@tagtable}} +\def\@tagtable{\@ifnextchar[{\@@tagtable}{\@@tagtable[t]}} +\def\@stagtable{\@ifnextchar[{\@@stagtable}{\@@stagtable[t]}} + +\def\@@tagtable[#1]#2#3#4{% + \begin{table}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table} +} + +\def\@@stagtable[#1]#2#3#4{% + \begin{table*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table*} +} + + +% Environments: + +% DESCRIBE - similar to DESCRIPTION, but indents extra on left margin of +% outer list + +\def\describe{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \ifnum\@listdepth=1 \advance\leftmargin by2em\fi + \let\makelabel\descriptionlabel}} +\let\enddescribe=\endlist + + +% Document style options: +% 10pt - Makes ten-point type the normal (default) type size +% draftnote - Customized draft option + +\@namedef{ds@10pt}{\def\@ptsize{0}} %%% for orthogonality + + +\newif\ifdraft \draftfalse + +\def\draftstring{{\ifdraft \tt Draft\fi}} + +\def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today\ with \fmtname\ v\fmtversion + \else + Draft \versiontag/ of \versiondate/ + \fi + \endgroup + \fi +} + +\def\versiontag/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}%6 + \versiontag/% +} +\def\versiondate/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}% + \versiondate/% +} + +\def\ds@draftnote{% + \drafttrue + \@ifundefined{ds@draft}{}{\ds@draft}% + \def\ps@plain{% + \let\@mkboth=\@gobbletwo + \def\@oddhead{\draftext\hfil}% + \def\@oddfoot{\draftstring\hfil\rm\thepage\hfil\draftstring}% + \def\@evenhead{\hfil\draftext}% + \let\@evenfoot=\@oddfoot + }% + \let\ps@@headings=\ps@headings + \def\ps@headings{% + \ps@@headings + \def\@oddfoot{\draftext\hfil}% + \def\@evenfoot{\hfil\draftext}% + }% +} + + +% Page Styles + +% \pagestyle{myfootings} similar to the myheadings command but also permits +% the user to define foot information as well as head information +% \markleftfoot{left_foot} specifies the foot for odd-numbered +% pages +% \markrightfoot{right_foot} specifies the foot for even-numbered +% pages +% N.B. DOES NOT USE MARKS TO ACCOMPLISH THIS, OWING TO CONFLICT WITH HEADING +% ROUTINES + +\def\ps@myfootings{\ps@myheadings} + +\def\markleftfoot#1{\def\@evenfoot{\hbox{}\sl#1\hfil}} +\def\markrightfoot#1{\def\@oddfoot{\hfil\sl#1\hbox{}}} + + +% \pagestyle{reprint} similar to plain page style in draft mode + +\let\reprintext=\draftext +\let\reprintstring=\draftstring + +\def\ps@reprint{% + \def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today + \else + Draft \versiontag/ + \fi + \endgroup + \fi + }% + \def\@oddhead{\reprintext\hfil\draftext}% + \def\@oddfoot{\reprintstring\hfil\rm\thepage}% + \def\@evenhead{\draftext\hfil\reprintext}% + \def\@evenfoot{\rm\thepage\hfil\reprintstring}% +} + + +% The Title + +\def\title#1{% + \gdef\@title{#1}% + \gdef\banner{% + \newpage\setcounter{page}{1}% + \begin{center}\Large#1\end{center}% + }% +} + + +% Miscellany + +\def\implies{\quad\supset\ } + +\def\tdots{\ldots\thinspace} + +\def\boxit#1{\fbox{\sc#1}} + +\def\note#1{\ifdraft\marginpar{\tt#1}\fi} + + +% Fractions (from The TUGboat v6 n1, 1985) + +\def\myfrac#1/#2{% + \leavevmode\kern.1em + \raise.5ex\mbox{\the\scriptfont\z@ #1}\kern-.1em + /\kern-.15em\lower.25ex\mbox{\the\scriptfont\z@ #2}% +} + + +% Trademarks... + +\input trademark + + +% Continuation Captions... + +\input captcont.sty + + +% Startup + +\xdef\today{% + \ifcase\month + \number\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\else + \number\month\fi + \space\number\day, {\noexpand\mit\number\year}% +} + +\begingroup + \count0=\time + \count1=\count0 + \divide\count0 by 60 + \count2=\count0 + \multiply\count0 by 60 + \advance\count1 by -\count0 + \ifnum\count2>11 + \ifnum\count2>12 \advance\count2 by -12\fi + \def\ampm{pm}% + \else + \ifnum\count2=0 \advance\count2 by 12\fi + \def\ampm{am}% + \fi + \xdef\daytime{% + \ifnum\count2<10 0\fi \the\count2:% + \ifnum\count1<10 0\fi \the\count1 + \ampm + }% +\endgroup + + +\makeatother % back to normal diff --git a/doc/nordunet/make b/doc/nordunet/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/nordunet/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/nordunet/pp-slides.aux b/doc/nordunet/pp-slides.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/nordunet/pp-slides.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/nordunet/pp-slides.tex b/doc/nordunet/pp-slides.tex new file mode 100644 index 0000000..b197e1f --- /dev/null +++ b/doc/nordunet/pp-slides.tex @@ -0,0 +1,281 @@ +% -*- LaTeX -* Although it's slitex really + +\documentstyle[blackandwhite,pagenumbers,small,oval,psfig,tgrind]{NRslides} + +\raggedright + +\begin{document} +\title {PP - X.400 for the masses?} + +\author{Julian P.~Onions\\ +jpo@cs.nott.ac.uk\\[.5in] +X-Tel Services Ltd.\\ +Nottingham University\\ +Nottingham NG7 2RD\\ +ENGLAND} + +\date {October 9, 1990} + +\maketitle + + \begin{bwslide} +\ctitle {CONTENTS} +\begin{nrtc} +\item What is PP? + +\item The PP Architecture + +\item The PP Queue + +\item Submission + +\item Scheduling and Control + +\item Channels + +\item Status and Availability +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{What is PP} +\begin{nrtc} +\item Basically, A Mail transfer system (MTA in the jargon). + +\item Largely protocol independent, but deals with X.400 + and existing mail formats. + +\item Written by people at UCL and Nottingham + +\item Design aims include:- + \begin{itemize} + + \item High performance/throughput + \item Support for message conversion. + \item Support for multi-media + \item Clean interface for user interfaces. + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Why PP} +\begin{nrtc} +\item At the time there was no suitable alternative. + +\item Most implementations were in the ``toy'' category. + +\item Too expensive + +\item Only did X.400 - no gatewaying, or else added as an +afterthought. + +\item Worked to minimal profiles. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Some goals for PP} +\begin{nrtc} +\item Scheduling of messages in an optimal way, such that many +thousands of messages a day can be processed. + +\item Robustness. + +\item Support for RFC-822, X.400(84) and X.400(88) and others. + +\item Reformatting between body part types in a general manner. + +\item Provision of management, authorisation and monitoring tools. + +\item Use of standardised services such as X.500. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} +\begin{nrtc} +\item PP is based on a system of cooperating processes. + +\item Each process has a specific task to achieve. + +\item Most of these processes are ``dumb''. + +\item The ``intelligence'' of the system is provided by two processes. + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} + +\vskip .5in + +\diagram[p]{figure2} + +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Queue} +\begin{nrtc} +\item All messages are placed in a queue on disc. + +\item For each message there are two components + \begin{itemize} + \item A Control file holding all the envelope information. + \item The Message structure holding the Message data. + \end{itemize} +\item The Control file is text encoded. + +\item The Message is either a single file, or a directory hierarchy. + +\item The Message may undergo a number of transformations whilst in + the queue +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Submission} +\begin{nrtc} +\item The first intelligent process is {\em submit}. + +\item All messages entering the queue pass through this process. + +\item It validates the message in a number of ways: + \begin{itemize} + \item Ensures the originator can be reached. + \item Ensures the destination is known. + \item Works out a conversion path from incoming format to outgoing. + \item Applies access controls if required. + \end{itemize} +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Scheduling and Controlling} +\begin{nrtc} +\item The other ``intelligent'' process is the queue manager, {\em qmgr}. + +\item Keeps an in memory map of the queue. + +\item Drives all channel programs using network IPC. + +\item Makes all the scheduling decision about messages in the queue. + +\item Sorts the queue in ``optimal'' ways. + +\item Allows connections to interrogate queue status +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Queue Monitoring} + +\vskip .5in + +\psfig{file=console.ps,height=6in} + +\end{bwslide} + + \begin{bwslide} +\ctitle{Channels} +\begin{nrtc} +\item Channels in PP process messages. + +\item May reformat a message by conversion e.g. + \begin{itemize} + \item Mapping X.400 to RFC-822 message + \item Converting Telex to Ascii + \end{itemize} +\item May attempt delivery e.g. + \begin{itemize} + \item Drive the SMTP or X.400 protocols + \item Deliver to users + \end{itemize} +\item May restructure the message + \begin{itemize} + \item Convert a file into a directory hierarchy + \item Convert multiple body parts into one + \end{itemize} +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{PP management} +\begin{nrtc} +\item The MTA console provides a good monitor of whats going on. +\item All address that are handled are logged in a special log which +an be processed to give statistics (and charging) information. +\item Authorisation can be controlled by user, host, content-type size +and route. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 was released on September 21st, 1990. + +\item It is providing a real service at a number of universities and + will shortly be providing the UK WEP service. + +\item PP is freely available for use and should be the backbone of + JANET as it transitions to X.400 protocols. + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 provides the following channels currently + + \begin{itemize} + \item SMTP with DNS support + \item X.400 (1984) + \item UUCP mail + \item JNT grey book mail + \item Distribution list expansion and maintenance + \item RFC822 local delivery and delivery time processing + \item RFC822 and X.400 conversion + \item X-windows based management console + \item Message authorisation checking + \item X.400(1988) P1 protocol (beta test) + \item X.500 distribution lists (beta test) + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{What is planned for the future} +\begin{nrtc} +\item Fax gateway to convert outgoing messages to faxes and vice +versa. + +\item More use of the X.500 directory, for routing and directory +name lookup. + +\item P7 Message store with remote access + +\item Improvements in throughput and robustness + +\item Some work on System Five portability and a DECNET channel by +people outside the PP group. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Availability and Support} +\begin{nrtc} +\item Source code is free by FTP/FTAM etc. +\item A distribution charge for a tape + +\item Available by FTP/FTAM from ucl, psi and eunet. + +\item Full support is also available if you require it from X-Tel. +\end{nrtc} +\end{bwslide} + +\end{document} diff --git a/doc/nordunet/pp.aux b/doc/nordunet/pp.aux new file mode 100644 index 0000000..ca7c320 --- /dev/null +++ b/doc/nordunet/pp.aux @@ -0,0 +1,36 @@ +\relax +\citation{ISODE} +\citation{CCITT.MHS} +\citation{RFC822} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1}Introduction}{1}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2}MTA management issues}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1}Management}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2}Is the mail being delivered?}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3}Why is this message not being delivered?}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.4}Who am I going to let use my MTA?}{3}} +\citation{MMDFII} +\citation{PP.MTA} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.5}What evidence have I got to prove this service works?}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3}The design of PP}{4}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1}The Process Structure}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.1}Submit}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.2}Qmgr}{4}} +\citation{SMTP} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2}The Queue}{5}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3}Channels}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.1}Outbound Channels}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.2}Inbound Channels}{6}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.3}Formatting and protocol conversion channels}{6}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4}PP Status}{6}} +\bibdata{bcustom,networking,software} +\bibcite{CCITT.MHS}{CCI88} +\bibcite{RFC822}{Cro82} +\bibcite{MMDFII}{III84} +\bibcite{PP.MTA}{Kil88} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.1}The future}{7}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {4.1.1}Reliability, robustness and efficiency}{7}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {4.1.2}Use of directory}{7}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {4.1.3}Message Store}{7}} +\bibcite{SMTP}{Pos82} +\bibcite{ISODE}{Ros88} +\bibstyle{alpha} diff --git a/doc/nordunet/pp.bbl b/doc/nordunet/pp.bbl new file mode 100644 index 0000000..dd3f5e4 --- /dev/null +++ b/doc/nordunet/pp.bbl @@ -0,0 +1,40 @@ +\begin{thebibliography}{CCI88} + +\bibitem[CCI88]{CCITT.MHS} +{Message Handling: System and Service Overview}. +\newblock International Telegraph and Telephone Consultative Committee, 1988. +\newblock Recommendation X.400. + +\bibitem[Cro82]{RFC822} +David~H. Crocker. +\newblock {Standard for the Format of ARPA Internet Text Messages}. +\newblock Request for Comments 822, DDN Network Information Center, SRI + International, August 1982. + +\bibitem[III84]{MMDFII} +Douglas P.~Kingston III. +\newblock {MMDFII: A Technical Review}. +\newblock In {\em Proceedings, Summer Usenix Conference and Exhibition}, pages + 32--41, June 1984. +\newblock Salt Lake City, Utah. + +\bibitem[Kil88]{PP.MTA} +Stephen~E. Kille. +\newblock {PP -- A Message Transfer Agent}. +\newblock In Einar Stefferud, editor, {\em {Proceedings, Fourth International + Symposium on Computer Message Systems}}, September 1988. +\newblock Costa Mesa, California. + +\bibitem[Pos82]{SMTP} +Jon~B. Postel. +\newblock {Simple Mail Transfer Protocol}. +\newblock Request for Comments 821, DDN Network Information Center, SRI + International, August 1982. +\newblock See also \milstd/ 1781. + +\bibitem[Ros88]{ISODE} +Marshall~T. Rose. +\newblock {\em {The ISO Development Environment: User's Manual}}. +\newblock The Wollongong Group, 3.4 (beta) edition, February 1988. + +\end{thebibliography} diff --git a/doc/nordunet/pp.major b/doc/nordunet/pp.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/nordunet/pp.major @@ -0,0 +1 @@ +1 diff --git a/doc/nordunet/pp.minor b/doc/nordunet/pp.minor new file mode 100644 index 0000000..4099407 --- /dev/null +++ b/doc/nordunet/pp.minor @@ -0,0 +1 @@ +23 diff --git a/doc/nordunet/pp.tex b/doc/nordunet/pp.tex new file mode 100644 index 0000000..6833250 --- /dev/null +++ b/doc/nordunet/pp.tex @@ -0,0 +1,361 @@ +% -*- LaTeX -*- + +\input lcustom + +\documentstyle[11pt,a4]{article} + +\begin{document} + +\title{PP -- X.400 for the Masses} +\author{Julian P.~Onions\\[0.1in] +X-Tel Service Ltd.\\ +Nottingham University\\[0.1in] +jpo@cs.nott.ac.uk} +\date{Tuesday 9 October 1990} + +\maketitle + +\begin{abstract} +This paper describes the design, implementation and expected use of +the PP message transport system. This is a message transfer system +that can relay a variety of protocols, and gateway between them. + +This paper is in three main sections, It consists of an Introduction +to PP. It then takes a step back and considers what is useful in a +``real'' MTA. Finally it goes into some details on how PP works. +\end{abstract} + +\section{Introduction} + +This paper describes the design and implementation of PP\footnote{PP +is not an acronym. Despite many rumours to the contrary, the author is +sticking to this position!.}. PP is a generic Message Transfer Agent +capable of carrying a number of message formats. It has been written +as a joint project by University College London and Nottingham +University and is designed to run on \unix/ systems. It makes +use of the ISODE package\cite{ISODE}. Its design is heavily +influenced however, by the need to carry X.400 MHS\cite{CCITT.MHS} and +RFC-822\cite{RFC822} based mail. The major goals of PP include: +\begin{itemize} +\item Robustness. PP is designed for heavy use. It should be +capable of transferring high levels of traffic in an optimal way. + +\item A clean interface for submission and delivery. PP does not +provide a user agent but does provide a library interface which allows +user agents to be added to PP easily. + +\item Sophisticated message processing to optimise delivery and +remote transfers. + +\item Support for message conversion in an integrated way. + +\item Support for multiple addressing formats (initially two). + +\item Support for multi-media mail. + +\item Support for arbitrary message structures. + +\item Designed for large systems. PP is not designed to run on your +PC or even on a workstation. It is designed to be a central mail +processing hub for a group of computers. It is not a small piece of +software! +\end{itemize} + +\section{MTA management issues} +As indicated above, PP is designed to deal with a large variety of +problems. The questions that comes to mind is ``why bother spending +all those years doing this?''. + +The answer is partly historical, but is still mostly relevant. When PP +was first thought about, there was very little that could be picked up +``off the shelf'' to deal with X.400 mail. Whats more, the products we +had seen were just not suitable for the sort of environment we wanted +to run a mail system in. Most of the products then, and still now to +an extent, were what might be considered ``toy'' systems. Yes, they +would take an X.400 message and deliver it to a recipient, but there +is more to a reliable MTA than this. PP put management and monitoring +of the MTA very high on its list of desirable features. The following +sections illustrate why this is necessary. + +\subsection{Management} + +For reliability and robustness, as a manager of such a thing, you need +to know the answers to many questions when the MTA is running in +normal operation. Unfortunately, if you want reliable service, an MTA +cannot be treated as a ``black box''. You need to be able to look +inside the workings of the delivery system to be assured that all is +working well. + +Some of the points that are crucial to a well run MTA are discussed here. + +\subsection{Is the mail being delivered?} +This is the most crucial point. A manager must be confident that the +MTA is doing it's job. To be sure of the answer, the manager typically +needs to know. +\begin{itemize} +\item How large is the queue of messages awaiting delivery? A +manager will have some idea of the average number of messages that +should normally be in the queue, if this figures varies too much, then +something has probably changed which needs investigation. +\item How old is the oldest message? +If the oldest message is very old, then clearly something somewhere is +not working correctly. +\item When did the system last deliver a message to that host? This +can help pinpoint problems with networks. +\item When did the system last receive a message? This can give an +idea of whether the MTA is accepting mail still or not. +\end{itemize} +If the system does not provide a way of getting such information then +there can be little confidence that the MTA is behaving properly. + +\subsection{Why is this message not being delivered?} +Once it is discovered that a message is not being delivered, the next +step is to discover why. Most often this is because of network or host +failures. Occasionally though, there is something more serious wrong, +and it is important that you can find out what this is. + +When a message is not being delivered, you need to be able to +\begin{itemize} +\item examine the logging information to try and determine why it +can't be delivered. +\item force an attempt at delivery if there is no logging +information so you can watch what is happening. +\item increase the logging trace and retry the message. +\end{itemize} + +\subsection{Who am I going to let use my MTA?} +To run an MTA as a service, you need to have control over who is using +the MTA. It may be that you have expensive links to other MTA's that +you would prefer not to send high volumes of traffic over. Maybe you +charge (in some sense - not necessarily in money) for use of the +system. Perhaps there are classes of users that should have high, or +lower priority. + +If any of these cases are true, then you will need some method for +controlling the users. You need to be flexible in how you specify this +control. The variables you need access to make policy decisions on +probably include: +\begin{itemize} +\item The recipient +\item The originator +\item The recipients hosts, and route to that host. +\item The originator host, and route from the host. +\item The size of the message +\item The content types of the message +\end{itemize} + +With these facts at your disposal, you can make sensible decisions on +what messages to allow and what to reject, and for those message you +allow, what particular transmission you are going to allow. This +allows you to make decisions like +\begin{itemize} +\item Students will not be allowed international access. +\item Use of IPSS will only be allowed for messages under 5k, +otherwise they will be routed by less direct and expensive means. +\item We will not relay messages from host h1 to host h2. +\end{itemize} + +\subsection{What evidence have I got to prove this service works?} +Once the service is running, it is very useful to gather statistics on +usage. This can show where the main traffic is coming from and going +to, which can feedback into improving the service. It is also useful +for either generating, or predicting bills for the service. + + +\section{The design of PP} + +The design of PP was influenced in part by the RFC-822 mail system +MMDF\cite{MMDFII}. In this model, extensive use is made of separate +processes to do different jobs. This allows each element to be built +and tested separately and encourages modularity. A fuller description +of the design of PP can be found in \cite{PP.MTA}. + +\subsection{The Process Structure} + +PP has a single queue of messages on which a number of processes +operate. There are two critical processes which undertake complex +functions, the rest of the processes are essentially ``dumb''. + +\subsubsection{Submit} +The first key process is that entitled {\em submit}. This process +guards the entrance to the queue. All messages entering the queue pass +through this process. It performs a variety of checks on the message +to ensure it can either be delivered or returned; works out the +routing for the message; calculates the reformatting of the message if +necessary; and applies other criteria such as authorisation and +authentication. By checking as much as possible at this point later +processes have to do less and completely undeliverable messages can be +stopped from entering the queue. + +As all message must pass though submit, all messages are checked at +this stage. This is where the authorisation policies are enforced. +Where possible, submit will always try and accept a message and return +it if necessary. Typically this leads to better error messages as +submit can take complete charge of generating the delivery report. + +Submit will refuse to accept a message when it can't parse or route +back to the originator. In this case, submit attempts to signal back +to the remote site that this message will not be accepted. In some +protocols, such as X.400(84), this is not possible. IN this case, +submit gives up and the message as a whole is forwarded to the +postmaster to sort out. Fortunately, such occurrences are fairly rare. + +\subsubsection{Qmgr} +The second key process is the {\em QMGR}, or queue manager. This +process is responsible for all the scheduling operations of the +messages in the queue. The QMGR holds a representation of the queue in +memory and so can perform complex and optimal scheduling of messages. +This scheduling consists of either delivering the message locally or +remotely or else converting the message within the queue (e.g. +gatewaying between protocols). + +As the QMGR holds a complete representation of the queue in memory it +also provides an information service. It can be queried by suitable +tools to display the state of the queue and such tools can even +control the behaviour of the QMGR. This is the second half of the +management framework. As the QMGR has a full overall picture of what +is going on in the queue - on a second to second basis, good global +decisions are possible. + +An X-windows based MTA console is provided with PP which can attach +to remote qmgr's and display the status in graphic detail, where +possible using colour to highlight problems. With suitable +authentication, the MTA console can also control the qmgr's behaviour. + +\subsection{The Queue} + +The queue of messages is held in two components. The first is an +address file which contains the envelope information about the +message. This is held in a text encoded form and is a generic envelope +structure which can hold both X.400 and RFC-822 messages. The text +encoding is a big advantage as it allows manipulation of the queues in +an emergency by a text editor. Whilst this should not normally be +necessary it is much easier than providing special management tools +to cover every eventuality. + +The second component is the message content. This includes the headers +and body parts. If no processing is necessary for the message this is +kept as a single file. However, if conversion is necessary, the +content is broken up into parts, each part being placed in a separate +file. Each time a message content is transformed, a new directory is +created and the appropriate files are changed. This allows simple +filters (such as {\em sed} even) to do the conversions. + + +\subsection{Channels} + +Most other processes in PP are termed {\em channels}. A channel takes +as input a message and outputs a different form of that message. +Channels are controlled directly by the QMGR by means of a networked +protocol. Each channel does a specific job. Channels come in three +basic forms as described below. + +\subsubsection{Outbound Channels} +This style of channel is usually a protocol engine. It takes a message +out of the queue and delivers it. This delivery may be local as in the +case of delivering to a mailbox; or remote such as driving the +SMTP\cite{SMTP} or X.400 protocols. Each channel reads the internal +format of the queued message and converts it to the protocol specific +format. The QMGR informs a channel which message to deliver and the +channel reports on the status of the message. This allows the QMGR to +discover whether the delivery attempt was successful, the remote site +did not respond or whether the message cannot be delivered. This +information is then used by the QMGR to schedule further deliveries. + +\subsubsection{Inbound Channels} +Inbound channels perform the opposite function to outbound channels. +They take care of the various protocols necessary to receive a +message, either from a user agent (local submission) or across a +network. Their main task is mapping from the protocol specific form of +the message to the form used withing the queue. This form is then +passed by a private protocol to submit which enqueue the message and +then informs the QMGR of the new message. + +\subsubsection{Formatting and protocol conversion channels} +These channels transform the message in some way without delivering +it. They are treated in exactly the same way as outbound channels and +are scheduled by the QMGR. These channels come in two basic types. +\begin{itemize} +\item Channels that change the directory structure. These either map +from the single file into a directory hierarchy, or the reverse. + +\item Simple reformatting. These channels might change, say, a teletex +body part into an ascii body part. When gatewaying is being performed, +such a channel might convert RFC-822 headers into X.400 headers. +\end{itemize} + +\section{PP Status} + +PP currently contains the following parts. + +\begin{description} +\item[Core] The basic core of the system including the QMGR, +submit and a number of support tools. + +\item[X.400 1984] The X.400 1984 protocols are supported. + +\item[SMTP] Smtp protocols are supported, including use of the +name server protocols for address resolution. + +\item[Grey Book] Grey book mail transfer is working, using the +unix-niftp blue book transfer system to provide non-spooled mail +transfer over JANET. + +\item[List] A list channel to offload the processing of +distribution lists. This helps speed up submission to large +distribution lists and allows list management. + + +\item[MTA Console] An X-windows based console display which +interrogates the QMGR and displays the current state of the +queues. It emphasises problems in the queue and allows parameters to +be adjusted interactively. + +\item[Tools] Various auxiliary programs to configure the system and +provide debugging support. + +\end{description} + +PP also contains the following experimental modules. +\begin{description} +\item[X.400 1988] The 1988 version of X.400 is in a beta test +form. The 1988 version of X.400 is uncommon at present so interworking +testing is limited. This will include secure messaging and extensions. + +\item[Directory Lists] An experimental channel that store distribution +lists in the X.500 directory is provided. This will be emphasised more +in future releases. + +\end{description} + +\subsection{The future} +Work is already under way on the next version of PP. The next version +has three main thrusts. + +\subsubsection {Reliability, robustness and efficiency} +These are general goals, without any specific actions to be taken. In +general we hope the level of reliability and robustness of the +software to increase with each future release. At the same time, some +effort will be expended on streamlining the code and improving +throughput and decreasing machine load. + +\subsubsection {Use of directory} +The next version of PP will make much larger use of the X.500 +directory. It will use the distribution list channel indicated above. +it will also be able to map Directory Names into O/R names by use of +the directory. Finally, work will be done on use of the directory for +routing. + +\subsubsection{Message Store} +A Message Store for PP is currently being written. It will allow +both P7 and P7+ access to messages. This will allow workstations and +portable computers to retrieve and store messages remotely. A user +agent for Unix with these features in mind is being written as a +separate project. + +\bibliography{bcustom,networking,software} +\bibliographystyle{alpha} + +\showsummary + +\end{document} diff --git a/doc/nordunet/pp.vrsn b/doc/nordunet/pp.vrsn new file mode 100644 index 0000000..70ab2ac --- /dev/null +++ b/doc/nordunet/pp.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.23}% + \gdef\versiondate/{Thu Sep 13 11:56:46 BST 1990}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/nordunet/trademark.tex b/doc/nordunet/trademark.tex new file mode 100644 index 0000000..dbd5af8 --- /dev/null +++ b/doc/nordunet/trademark.tex @@ -0,0 +1,75 @@ +% Trademarks... + +\def\gobble#1{} +\def\tradeORGfont{\sc} % used for organizations (e.g., ACM) +\def\tradeNAMfont{\sf} % used for names (e.g., Ada) + +\def\tradeorg#1{% + \tradeaux{#1}{\expandafter\gobble\string#1}\empty\tradeORGfont +} +\def\tradeorgn#1#2{% + \tradeaux{#1}{#2}\empty\tradeORGfont +} +\def\tradename#1#2#3{\tradeaux{#1}{#2}{#3}\tradeNAMfont} +\def\trademark#1#2{% + \tradeaux{#1}{\expandafter\gobble\string#1}{#2}\tradeNAMfont +} + +\def\tradeaux#1#2#3#4{% + \def#1/{\relax}% % in case #3 references #1 + \setbox0=\hbox{#3}% % when we make the \hbox + \ifdim\wd0>0pt + \gdef#1/{% + \tradeaux{#1}{#2}\empty{#4}% + #1/\footnote{#1/ is a trademark of #3.}% + }% + \else + \gdef#1/{{#4#2}}% + \fi +} + +\tradeorg\acm +\tradeorg\ansi +\tradename\Ada{Ada} + {the Department of Defense (\Ada/ Joint Program Office)} +\tradename\balance{Balance} {Sequent Computer Systems, Incorporated} +\tradeorg\bsd +\tradename\butterfly{Butterfly}{Bolt, Beranek, and Newman, Incorporated} +\tradeorg\ccitt +\tradename\cms{CMS} {International Business Machines, Incorporated} +\tradename\cpm{CP/M} {Digital Research Corporation} +\tradename\chrysalis{Chrysalis}{Bolt, Beranek, and Newman, Incorporated} +\tradename\decnet{DECnet} {Digital Equipment Corporation} +\tradeorgn\dod{DoD} +\tradename\dynix{DYNIX} {Sequent Computer Systems, Incorporated} +\tradename\ethernet{Ethernet} {the Xerox Corporation} +\tradename\eunice{Eunice} \empty +\tradename\exos{EXOS} {Excelan, Incorporated} +\tradename\ibmpc{IBM PC} {International Business Machines, Incorporated} +\tradename\ibmpcat{IBM PC/AT} {International Business Machines, Incorporated} +\tradeorg\ieee +\tradename\iPSC{iPSC} {Intel Corporation} +\tradename\lattice{Lattice} {Lattice, Incorporated} +\tradename\locus{Locus} {Locus Computing Corporation} +\def\microvax/{$\mu$\vax/} +\def\microvms/{$\mu$\vms/} +\tradeorg\milstd +\tradename\msdos{MS-DOS} {Microsoft Corporation} +\tradename\mvs{MVS} {International Business Machines, Incorporated} +\tradename\pcdos{PC-DOS} {International Business Machines, Incorporated} +\tradename\pcinterface{PC-Interface}% + {Locus Computing Corporation} +\tradename\pdp{PDP} {Digital Equipment Corporation} +\tradename{\tops20}{Tops20} {Digital Equipment Corporation} +\tradename\trustedmail{Trusted\ Mail}% + {Trusted Technologies, Incorporated} +\tradename\tseries{T-Series} {Floating Point Systems} +\tradename\ultrix{ULTRIX} {Digital Equipment Corporation} +\tradename\unibus{UNIBUS} {Digital Equipment Corporation} +\tradename\unix{UNIX} {AT\&T Bell Laboratories} +\tradename\vax{VAX} {Digital Equipment Corporation} +\tradename\vaxstation{VAXstation}% + {Digital Equipment Corporation} +\tradename\vm{VM} {International Business Machines, Incorporated} +\tradename\vms{VMS} {Digital Equipment Corporation} +\tradename\xenix{Xenix} {Microsoft Corporation} diff --git a/doc/nordunet/version.sh b/doc/nordunet/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/nordunet/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/sun-89/Makefile b/doc/sun-89/Makefile new file mode 100644 index 0000000..bc3ca29 --- /dev/null +++ b/doc/sun-89/Makefile @@ -0,0 +1,89 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps \ + .ry .py .grap .chem .wd + +.ry.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grap.tex:; grap $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.chem.tex:; chem $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.b.tex:; itbit $< + +.xb.tex:; xtbit $< + +.xwd.tex:; xtwd $< + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grf.tex:; sh -c 'if graph < $< | plot -TeX > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.pct.pic:; pct2pic $< + +.pic.tex:; tpic $< + +.plt.tex:; sh -c 'if plot -TeX < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if tgrind -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if latex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if dvi2ps $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.wd.ps:; sh -c 'if xpr -device ps < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + + +############################################################# +# pp +############################################################# + +all: pp.dvi pp-slides.dvi + +print: pp.ps + +# customization files, et. al., not included below +pp.dvi: pp.vrsn + +pp.vrsn: pp.tex pp.bbl version.sh figure1.tex figure2.tex + @version.sh pp + +pp-slides.dvi: pp-slides.tex figure1.tex figure2.tex console.ps + sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +biblio:; bibtex pp + +preview: pp.dvi true + texx pp.dvi + +index:; idx2ind -l pp + +clean:; rm -f pp.imp pp.ps pp.dvi pp.log \ + pp.blg _* pp-slides.dvi pp-slides.log pp-slides.ps \ + pp-slides.blg *~ *.ps + +true:; diff --git a/doc/sun-89/captcont.sty b/doc/sun-89/captcont.sty new file mode 100644 index 0000000..70f662e --- /dev/null +++ b/doc/sun-89/captcont.sty @@ -0,0 +1,16 @@ +% SubStyle file to permit the use of captions in continuations of floats. +% +% \captcont is like \caption, except that it doesn't update the counter, and +% it doesn't make an entry in the list of figures or list of tables. + +\def\captcont{\@dblarg{\@captcont\@captype}} + +\long\def\@captcont#1[#2]#3{ +% \addcontentsline{\csname ext@#1\endcsname}{#1}{\protect\numberline{\csname +% the#1\endcsname}{\ignorespaces #2}} + \par + \begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} diff --git a/doc/sun-89/console.wd b/doc/sun-89/console.wd new file mode 100644 index 0000000000000000000000000000000000000000..babc4e4092b35014e8989f379cb27dce3b92b7bd GIT binary patch literal 49811 zcmeHQe{3Apoqw}4w#UJBW^F?Qx5VSkl13atCfpAPa$)Rjh>3iVq9FAoS{#}?PU3pq z5UPe=j?UWKc$cQcOUpr|TyX;`Kd#rR*MF$m9upkShC&k5QYs46t`icjsC5!J5;fra zeBb=oS$5YuJNu9##V^XvoA={0pZA?N?|tX{eQ(SdyOS~2g#QuzmvHzB{(k{+3OHx_ zM~)kD{?S0?s6PHj?!y1SNBk-Le-Qtb?O)#Vr7xrqV{DEGx*CVZp~*?Ja|HZa0xG6vvb8TpE{ruLSaQe%(J>$C%)RVrDvzaX z&6;kJ3`M%!GZt|MY(@8yxCZAtD~+C?c+gm7#vnfp@_W{iiX*=m$xpHqO|Au(O0AG0 zzd-jx<@zt(52K42cCJErP^1;YgCdP!x)FX>_D4P<81LO#vtgq1%AT!*EYtc{>U5WU zur;;{`poVjt>>Hk&GZQA5k-ko@?Og7;jcEo@n{~S}?zN1mlUeAH3`Fv+y`!){HdO^X4zVG)toZ&4q?NYcf@%^N>NF zo>dI0D+=$uS!Ml|xAts3F>ZCn*w)R@9qe2ak{eZnex;~;RwlDU2}6yu+yn7QeeInB zUOv9V96myLTibtEC*E&nmHvF(FozVvYi^6wiFbhGCA0UTz57@WGh==2eREbGS#_!> zwRL=~DaN+_cw+arSJ!htUiJEO9VmsWvgq;ZwR4=`8|OGb(c|AK!R;LvjCWQr-Vwog zqMx@H&vAZ-1oL}SFy544Jd6jDiSaOIkBLwa>I(AFS=M6$La||-*Ot(j^8Q(tG*Mj? z-eKVV@aWG+6xOrt@%0ZacG?}5pbY)gm~3C(pJB<|&0_=kcvvL69<|rVo=n`7VMgxe zMp`M9DF&-ct zJgI$4Kjl{ogtuW`cTzvf#uR-|8Rh6=nzPmR`E ztzvn?Ti{nwJXJFmV44d2!?cS9-;ns zhTq@KGe1ax*Pw36L-+4JJqAi9yY}C%|N6xLtcPgtW8**G@{d2=vE>O}k1wN)``)_a zh5I1OHYOcB^asP}-3U;^dx`UdQk%gGf?-*-90V&~Oz>NjNM_eA%R$8lzkSL6%u0yO zg#3^J$52xn(?Bb7Su)BaHr_Pn_v~XM8OX^R1Hbn8ns_9#$Yd=81KAB%{2gvM@D3c9 z%i%OE$-uE1SDl}b2^6QK0NuA4Y(Y>TS-)3_8J$|G= z6L;i?4DeH*vBgIG3i5lN_rJd78+JlYeY(}M;o{2&R)CYqu1aiq;`YR5$n^;}-gf1-GPD;NPp*uw*r)4V-K_DlL#HdB*MSeCr|VC>6a&(An_?Cz4ZBS^N5W%$@?Gp*uk=UAN?{2 z)D7r=UO@lz1@u2VIQ(Ac^5ZA;V|lUSh%dc#e6jm7RZ!tCqw&RKWfd;YAS*YpLJ57D zKLgL4VQe=L2+ozC#ZTy`5c86F#Ft*muTWH#f6e)MDZYAM8by5R^W(ik@+*wyzIp`X zg+hrc<2~1}3Z*R%p*T_~Q3a3BAH{X+IHU0Z_qPs&;;JhA`;cF8VjX9y{GMQbqV?w~ z!Tf$BSbhft^LtY;zgGqGn-$FOwetMj=XKWW+-}O;oaLoa_=NS zL)mZx+B?qWry~PlivN=SxZg4(Jz&?$ig~^xZ_Q20^V8T=gig6 zZtS`FVFnEo3Z{Cz+sT4Pxum6^PA-U*HGj0*T&4*7M{$xk&o|L97`KBtrXv=STf7aFxVTR=T zqmhA87W|~BVyEnnvJ6%%>ENeq$YUY5mM|3H4L;eXtC_em$xI3IB;GBzH#!=5d*k(s;^>ZUdmX&ZPque8e{I>ioFp~le%SLz*PD0P z+Mzr?0yy39T-fC$n zi==9*@*BMWt)QNTz}g(;aFU;@YPY&XUBq+T6jimDA)(z)K>tg)T@dX(>VH1)w&Iks zoMSgsSv$>5p~u3HHwY;^g=u`*&-)*G7!Rz8R6{6-mXpxUrt~W)?xpCu#ir;b&k2KC z^swD1O>0->!k$asA$xa`6V(4oFBCGxdH)DmyR@2k{rQ)I<#$}L{5}-S z?}%W2{QbA|MukkNs9#mV`>OkV)6rK}m0u4fzsh*w-j4=-oc!@%a0>?`pxK zmGQWKidotYu0Dwg5Yv_~_%bMOv#UYk=(AVCzTwG_W{N53Yz{$E9b+*h@BlN=_(&6X z+~b^-$SG1HTW~`5%0V`5F|uqr@>8=a=54Z;MfudX5xUnXGxv>+rH4oZf}+&+7oT}} ziMDZ+@;9+94ISEyA;|4Ju)Qa<+C8*hE_v|;pH?8^AP%Vv&ET*=LlkuCkd?caXp z#Lq3mfD*Yi`sVu`vDGO}Yinn%S6&nEi$vOOJQ|Lu=T;^$s}}t*eBz9*HtT5 z{E!P4isr7CWb*z5@*uxl`(-!SN~8>XWqb=v!}?XacYn8yKYp!A)<$;hHP|P6xP5Zz zn(b$gPfx7k8Pdd|Z(ny!&(?#3q(ly$IPu~aJNI5=+bdhY-1EU{$>0A-W2E3&8_~4hzq204r7Vd8)9+lDueHrEW`LY8==fex5zsxt@htaR*!wbW&l2B;;L#L~hU32;Z zUds4mCVFJWxSJaSi#bK0qFAUW$Ji1BMPitL zUm?8aORgAD)qXg=`&s|Xw-53O^L8V0{ny)}hH*ti>)52N-1M-kXqss=V`9P|8e{rk zS6pAw1+sDAy-j#neVD`y3l-5|*zKq@3UMetIVeN6KE$B4#FH?hk)j#VnZy(t*AauY z2tcHW65a<0_h?L)yV1B<5%#WTok^S#Y!TeqY zp2+b)^mtXlzhC9KuavD-^6yuwP$gZ1KQGMtc_mo!{3`hOD-o!YuF2fLU!_#=Y|ZiS z2d^=INzL}}&tIs9T+LozTtkidi)xPleEw3wb2Z1mAH2r=B^`d1zT9aw)u<58+Wvik zc-+4)ndO^dHI`4Wn5xw1z0~9zhjHC5|4PYF(*y23-mPQ7iO==pE!r}^a_d)8y+5}$ z8pqE}TUMi_uEg z+yXp&jNns~4=`H54Srazt#{_*T5i_%?@O7?z=Py3$RsaZp4`=#NM5FFT6a;xYE;0l zSL6J$L(46Er7#--9zHeLrhfuA0^e!sr~A>SOO&U{+`lgkpBia>25V(z%)i{bIwc(( zT*`jc^EU2>(h0mNdGBvyZ>7@XX6tG_)wFE)Bie~W&sa^XM*ol+`Rcz@e|g`M?~m!| zFMNHmgzo1BTJG-zs}VvVg9Zi9m4>)Z2^0z)8z%<(GhZKD^!(DJ-~{wPyI;Bq)sC9X z{ri%|EjacMUu|tiIbNz7h%aB0xqrWipD&x^`Od3GHJSVO1&)8*zb|mS=l*@6cq08D zT1fwXr5i)hepMs*|DdJ`R4FQf;y>e#2?re8Ulqi6ii2_z#M{Zn*^MdJy?R zpM*N;E+lQIvltts$=dn)p?x3~XQ~<=m!HYCSp(%M&>8rZ#S6sGnpl4uP2o3A+-TjC zGOW+uwqt+|I$yU;OvlmW=1DxS>`E3ly;HDFmy zGE4m8z;nKCX+r-4UXFoZ06ffZQs!$dyU+)d4FeA<$z4jOb=P;Pz4q5FbA*>?INT5f zkN6G0KY{hx((EVhSj<+vC{JB7aVhZZuUqP=>DD`%TJ^i9<)@i#DJgF#ZUD3SC}2V*ts-+ zlu9pTiqro>)-J6^c(}i%86i_N`1i%?r+oi@NH(R_G+FHaOR^`5l^@@~UrIb=iU$9_ zSblu}en>W@)iitmerZO?6wThhUrzty1A|#+F~RIS*V63$`vUR!{{3?LB(adpmQphF zkN154ex>*G5O{q5zCeC_|9&O=WJB%k<@rej}pHmhv%0GpilDs`;tk^hBeNqz)!OIeFU$Her4M?o;$GqUtZss zI)Qn;zxVL;;r0J)Y+O5YY`@uZ?cO97n_qmt8c?6Kor?ob(CW02Nt5d|MBkU`>8e_kp4G>@_M0;8%Zr>0%zD(Kn@zVEco>DtMzJFifc+dCm3&azVso^zT=Ce*OOLvqgfha8iT+JRlz5zh7xQ_4|9ujMSwhU4CWW&uKgjfyejn z3*=|}_siHP$zmCTpFMw=Y@`+2_NQ#eHpzvnZG<;SXE+ZiKij`Q8htpgX?rlEyStR2 zR*sUt+ntts0^-^JeKP`s7c5>y{7mM<3(C*-?@!z{`SSMD&u_$DKI3@m_}W*YR=#`+ z{?&`Wzx?TKKeK|jm+#+~(#dRI-IAK3RpFbUNDY`!+f4YA)jcb=x-`Q7azl zS348C9&AZ|gKyH@gu_6lMfu+S@OP_ue1vUZ4g75X{?4l=TGzZq^6O;3O3li9EvS`S z4_l2*_sqPNdb}HIW=--NE$EW|81)x71jOU}_doLd(yJB^A@FSfzNhY)zSe_!1AXZ!a(t7LH`#Qb6V_lse?vk-V<_wUnsII;FWvHSPMub&LJ zfBz%>)H^-*?Yj&9eeY(4h&cDRl0J!VLv(r%Ga^>COE~(yP&}I7%nBEl8JX0)V0p0$ z5tmY8 zJC~pBG>qth@I3k1(|Fvyyv`ynznbvKzBaLT!nk$g)}xr$Z-;&I7uJop8iVWCA6m?XcOV}*KzJm-p|O5b*V1h|S$Scf#6nZzrxKo$ zjYulanZyF&ar@+B0~yCYxt#2iSVpNN8oztRh}+&g@M@6X&L54Kv3pa0B*hW-$r-bC z8#~?j!wKAvJA1ZE6USOl@h_2~(enmh|MPXhf~k`CKi9&|g0>y0@6{qp+XY)P_J?RuL1eg2Y) ze2fW&$G^{CUZ3nPNe;k|f1kg+zdIBj|2}^S5iX}tc(#APtUehE&-U+|gH8MoCD@7? zQ~@Gbgg1zUAo`2#-yiK>!sqi(I?Ciy@;N$qx&bI?S4<9qXZ!a}T{TIa^zqYOejZ*R zezyH@|Ix`;@5M%lUfPdi9JTt4yLZf{B<%ROGPdKiJZ@gS99Ij%&-U*R#U)is(sxa< zA4ej!@^W46mWC3>#c}Y1ez^iI4uWU<_lK9s&Cy;70sC>J_AXia^R9bQ1!mbwv1Fz^f3UR!=Um$&TdNaD{PDAy$6?317n^s+?(W9@$gJ8M>q-A2(>fDS zpS1n^er3|zk5km2K`)>_N&273i`zen8xMtN`}gr4;{|U&PO9iKbQR0JRHdV4f1kgk zA}=3`-#qroPx$EQWwG-I_wU!m$zR#ozwb|~EAH$+uM5LpnfBYC+w$Z7eLv;8;^O5e_WS(K z{{6bz=&$VT-}fig6?gXU*M;G)?Cjt7C)E{q_V3q);jirM-}fig6<_f0*CjrDKjK{9 z-@V}9ujdY*`}g-;?|%#Y7W!Xs3DEN4v>N&I#IE1q{{7Mm zg-p@#eSWe0xPLz+o6>6H?N{8tUwWaCDfGQQvGNnWe}Vh=L$D`^I^>f4@|) zAyb_F@gZxMRy!a4`(po|2>pE*T6roa(0U)Sct-`}?H7!9STLUGzaJ&Ky`u5>-{TY0 z`G7+2M`HWmNx^s%g7N6@gNb~8>F-;K#QUY-zpr+DR#;~tAbg)+EZz~pc(dm?p6I{F YX9;evXuNmMaeh|OlJWXa&O5yS2d5L@3jhEB literal 0 HcmV?d00001 diff --git a/doc/sun-89/figure1.pic b/doc/sun-89/figure1.pic new file mode 100644 index 0000000..50eac1e --- /dev/null +++ b/doc/sun-89/figure1.pic @@ -0,0 +1,52 @@ +.PS 5 +eighth = 1/8 +boxwid = 0.5 +boxht = 0.25 +arrowhead = 7 +arrowht = eighth/2 +define user X box "User" X +define ua X box "UA" wid 7/16 X +define mta X box "MTA" X +MHE: box dotted ht 4 + eighth wid 6.25 + "Message Handling Environment" at MHE.nw + (eighth, -eighth) ljust +MHS: box ht 3.25 wid 4.5 with .s at MHE.s + (0,eighth) + "MHS" ljust at MHS.nw + (0.25, -0.25) +MTS: box dashed ht 2.5 wid 3 - eighth with .s at MHS.s + (0,eighth) + "MTS" ljust at MTS.nw + (0.25, -0.25) + + [ user ] with .e at MHS.sw + (-eighth, 1) +Ua1: [ ua ] with .w at MHS.sw + (eighth, 1) + line <-> from 2nd last box.e to last box.w + + [ user ] with .e at MHS.sw + (-eighth, 2) +Ua2: [ ua ] with .w at MHS.sw + (eighth, 2) + line <-> from 2nd last box.e to last box.w + + [ user ] with .s at MHS.n + (0, eighth) +Ua3: [ ua ] with .n at MHS.n - (0,eighth) + line <-> from 2nd last box.s to last box.n + + [ user ] with .w at MHS.se + (eighth,0.5) +Ua4: [ ua ] with .e at MHS.se + (-eighth, 0.5) + line <-> from 2nd last box.w to last box.e + +Mta1: [ mta ] with .w at MTS.sw + (eighth, 1.25) + line <-> from Ua1.e to Mta1.sw + line <-> from Ua2.e to Mta1.nw + +Mta2: [ mta ] with .n at MTS.n + (0, -eighth) + line <-> from Mta1.n to Mta2.w + line <-> from Mta2.n to Ua3.s + +Mta3: [ mta ] with .e at MTS.se + (-eighth, 1.25) + line <-> from Mta2.e to Mta3.n + line <-> from Mta1.e to Mta3.w + +Mta4: [ mta ] with .e at Ua4.w - (0.5,0) + line <-> from Mta4.e to Ua4.w + line <-> from Mta3.s to Mta4.n + +Mta5: [ mta ] with .e at Mta4.w - (0.5,0) + line <-> from Mta4.w to Mta5.e + line <-> from Mta5.n to Mta1.s +.PE diff --git a/doc/sun-89/figure1.tex b/doc/sun-89/figure1.tex new file mode 100644 index 0000000..e0dce50 --- /dev/null +++ b/doc/sun-89/figure1.tex @@ -0,0 +1,38 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \rlap{\kern 1.250in\lower 1.291in\hbox to0pt{Message Handling Environment\hss}}% + \rlap{\kern 1.250in\lower 1.291in\hbox to0pt{MHS\hss}}% + \rlap{\kern 1.250in\lower 1.291in\hbox to0pt{MTS\hss}}% + \special{pa 0 1250}% + \special{pa 1250 625}% + \special{fp}% + \special{pa 0 1250}% + \special{pa 1250 1875}% + \special{fp}% + \special{pa 625 1875}% + \special{pa 1875 625}% + \special{fp}% + \special{pa 1250 1250}% + \special{pa 1250 0}% + \special{fp}% + \special{pa 625 625}% + \special{pa 1875 1875}% + \special{fp}% + \special{pa 0 1250}% + \special{pa 2500 1250}% + \special{fp}% + \special{pa 1875 625}% + \special{pa 3125 1875}% + \special{fp}% + \special{pa 4375 1875}% + \special{pa 625 625}% + \special{fp}% + \kern 4.376in + }\vss}% + \kern 1.876in +} diff --git a/doc/sun-89/figure2.pic b/doc/sun-89/figure2.pic new file mode 100644 index 0000000..0e8dbf9 --- /dev/null +++ b/doc/sun-89/figure2.pic @@ -0,0 +1,15 @@ +.PS 5 +Inb: ellipse "Inbound" "Channel" + line <-> down right from Inb.se +Submit: ellipse "Submit" with .nw at last line .end + line <-> up right from Submit.ne + ellipse "UA" with .sw at last line .end + line <-> down left from Submit.sw +Qmgr: ellipse "QMGR" with .ne at last line .end + line <-> down right from Qmgr.se +Out: ellipse "Outbound" "Channel" with .nw at last line .end + line <-> down right from Submit.se +Que: box "Queue" with .nw at last line .end + (0, boxht/4) + line <-> dashed from Qmgr.e to Que.w + line <-> from 3/4 to Out.ne +.PE diff --git a/doc/sun-89/figure2.tex b/doc/sun-89/figure2.tex new file mode 100644 index 0000000..e5898bc --- /dev/null +++ b/doc/sun-89/figure2.tex @@ -0,0 +1,123 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{ar 642 428 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 0.386in\hbox to 0pt{\hss Inbound\hss}}% + \rlap{\kern 0.642in\lower 0.552in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 1247 821}% + \special{pa 1096 731}% + \special{fp}% + \special{pa 1187 882}% + \special{pa 1096 731}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1801 1496}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1861 1435}% + \special{pa 1952 1587}% + \special{fp}% + \special{ar 2406 1889 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 1.930in\hbox to 0pt{\hss Submit\hss}}% + \special{pa 2951 1435}% + \special{pa 2860 1587}% + \special{fp}% + \special{pa 3011 1496}% + \special{pa 2860 1587}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3625 882}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3565 821}% + \special{pa 3716 731}% + \special{fp}% + \special{ar 4170 428 642 427 0.000 6.283}% + \rlap{\kern 4.170in\lower 0.469in\hbox to 0pt{\hss UA\hss}}% + \special{pa 1861 2343}% + \special{pa 1952 2192}% + \special{fp}% + \special{pa 1801 2283}% + \special{pa 1952 2192}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1187 2897}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1247 2957}% + \special{pa 1096 3048}% + \special{fp}% + \special{ar 642 3351 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 3.392in\hbox to 0pt{\hss QMGR\hss}}% + \special{pa 1247 3744}% + \special{pa 1096 3653}% + \special{fp}% + \special{pa 1187 3805}% + \special{pa 1096 3653}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1801 4418}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1861 4358}% + \special{pa 1952 4509}% + \special{fp}% + \special{ar 2406 4812 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 4.770in\hbox to 0pt{\hss Outbound\hss}}% + \rlap{\kern 2.406in\lower 4.936in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 3011 2283}% + \special{pa 2860 2192}% + \special{fp}% + \special{pa 2951 2343}% + \special{pa 2860 2192}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3565 2957}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3625 2897}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3716 3690}% + \special{pa 3716 2834}% + \special{pa 5000 2834}% + \special{pa 5000 3690}% + \special{pa 3716 3690}% + \special{fp}% + \rlap{\kern 4.358in\lower 3.303in\hbox to 0pt{\hss Queue\hss}}% + \special{pa 1454 3302}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1457 3387}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1284 3351}% + \special{pa 3716 3262}% + \special{da 0.050}% + \special{pa 3546 3311}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3543 3225}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3640 3635}% + \special{pa 3716 3476}% + \special{fp}% + \special{pa 3574 3581}% + \special{pa 3716 3476}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 2936 4350}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 3002 4405}% + \special{pa 2860 4509}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 5.240in +} diff --git a/doc/sun-89/lcustom.tex b/doc/sun-89/lcustom.tex new file mode 100644 index 0000000..5ae23b3 --- /dev/null +++ b/doc/sun-89/lcustom.tex @@ -0,0 +1,350 @@ +% LaTeX customization + + +\makeatletter % for a little while + + +% plain TeX compatibility + +\def\oldstyle{\xdef\@oldstyle{\the\textfont\@ne}\mit\@oldstyle} + + +% PhD-TeX compatibility + +\def\showsummary{% + \begingroup + \def\note##1{% + \ifcase\value{##1}no ##1s\or + 1 ##1\else + \the\value{##1} ##1s\fi + }% + \typeout{LaTeX summary: \note{figure}, \note{table}, \note{footnote}.}% + \endgroup +} + +\def\smaller{\footnotesize} + + +% Float Support + +\def\topfraction{0.85} +\def\textfraction{0.20} +\def\floatpagefraction{0.85} +\def\dbltopfraction{0.85} +\def\dblfloatpagefraction{0.85} + +\def\@tagskipcommand{\vskip .5\baselineskip} + +% \tagfigure*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads TPIC output in file figureFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagfigure{\@ifstar{\@stagfigure}{\@tagfigure}} +\def\@tagfigure{\@ifnextchar[{\@@tagfigure}{\@@tagfigure[t]}} +\def\@stagfigure{\@ifnextchar[{\@@stagfigure}{\@@stagfigure[t]}} + +\def\@@tagfigure[#1]#2{% + \@@@tagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} +\def\@@stagfigure[#1]#2{% + \@@@stagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} + + +% \tagdiagram*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeX input in file diagramFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagdiagram{\@ifstar{\@stagdiagram}{\@tagdiagram}} +\def\@tagdiagram{\@ifnextchar[{\@@tagdiagram}{\@@tagdiagram[t]}} +\def\@stagdiagram{\@ifnextchar[{\@@stagdiagram}{\@@stagdiagram[t]}} + +\def\@@tagdiagram[#1]#2{\@@@tagfigure[#1]{\input diagram#2\relax}} +\def\@@stagdiagram[#1]#2{\@@@stagfigure[#1]{\input diagram#2\relax}} + +\def\@@@tagfigure[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@@stagfigure[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +% \tagtable*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FILE read LaTeX input in file tableFILE +% FLOAT float options +% CAPTION for list of tables +% LABEL for \ref and \pageref +\def\tagtable{\@ifstar{\@stagtable}{\@tagtable}} +\def\@tagtable{\@ifnextchar[{\@@tagtable}{\@@tagtable[t]}} +\def\@stagtable{\@ifnextchar[{\@@stagtable}{\@@stagtable[t]}} + +\def\@@tagtable[#1]#2#3#4{% + \begin{table}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table} +} + +\def\@@stagtable[#1]#2#3#4{% + \begin{table*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table*} +} + + +% Environments: + +% DESCRIBE - similar to DESCRIPTION, but indents extra on left margin of +% outer list + +\def\describe{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \ifnum\@listdepth=1 \advance\leftmargin by2em\fi + \let\makelabel\descriptionlabel}} +\let\enddescribe=\endlist + + +% Document style options: +% 10pt - Makes ten-point type the normal (default) type size +% draftnote - Customized draft option + +\@namedef{ds@10pt}{\def\@ptsize{0}} %%% for orthogonality + + +\newif\ifdraft \draftfalse + +\def\draftstring{{\ifdraft \tt Draft\fi}} + +\def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today\ with \fmtname\ v\fmtversion + \else + Draft \versiontag/ of \versiondate/ + \fi + \endgroup + \fi +} + +\def\versiontag/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}%6 + \versiontag/% +} +\def\versiondate/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}% + \versiondate/% +} + +\def\ds@draftnote{% + \drafttrue + \@ifundefined{ds@draft}{}{\ds@draft}% + \def\ps@plain{% + \let\@mkboth=\@gobbletwo + \def\@oddhead{\draftext\hfil}% + \def\@oddfoot{\draftstring\hfil\rm\thepage\hfil\draftstring}% + \def\@evenhead{\hfil\draftext}% + \let\@evenfoot=\@oddfoot + }% + \let\ps@@headings=\ps@headings + \def\ps@headings{% + \ps@@headings + \def\@oddfoot{\draftext\hfil}% + \def\@evenfoot{\hfil\draftext}% + }% +} + + +% Page Styles + +% \pagestyle{myfootings} similar to the myheadings command but also permits +% the user to define foot information as well as head information +% \markleftfoot{left_foot} specifies the foot for odd-numbered +% pages +% \markrightfoot{right_foot} specifies the foot for even-numbered +% pages +% N.B. DOES NOT USE MARKS TO ACCOMPLISH THIS, OWING TO CONFLICT WITH HEADING +% ROUTINES + +\def\ps@myfootings{\ps@myheadings} + +\def\markleftfoot#1{\def\@evenfoot{\hbox{}\sl#1\hfil}} +\def\markrightfoot#1{\def\@oddfoot{\hfil\sl#1\hbox{}}} + + +% \pagestyle{reprint} similar to plain page style in draft mode + +\let\reprintext=\draftext +\let\reprintstring=\draftstring + +\def\ps@reprint{% + \def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today + \else + Draft \versiontag/ + \fi + \endgroup + \fi + }% + \def\@oddhead{\reprintext\hfil\draftext}% + \def\@oddfoot{\reprintstring\hfil\rm\thepage}% + \def\@evenhead{\draftext\hfil\reprintext}% + \def\@evenfoot{\rm\thepage\hfil\reprintstring}% +} + + +% The Title + +\def\title#1{% + \gdef\@title{#1}% + \gdef\banner{% + \newpage\setcounter{page}{1}% + \begin{center}\Large#1\end{center}% + }% +} + + +% Miscellany + +\def\implies{\quad\supset\ } + +\def\tdots{\ldots\thinspace} + +\def\boxit#1{\fbox{\sc#1}} + +\def\note#1{\ifdraft\marginpar{\tt#1}\fi} + + +% Fractions (from The TUGboat v6 n1, 1985) + +\def\myfrac#1/#2{% + \leavevmode\kern.1em + \raise.5ex\mbox{\the\scriptfont\z@ #1}\kern-.1em + /\kern-.15em\lower.25ex\mbox{\the\scriptfont\z@ #2}% +} + + +% Trademarks... + +\input trademark + + +% Continuation Captions... + +\input captcont.sty + + +% Startup + +\xdef\today{% + \ifcase\month + \number\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\else + \number\month\fi + \space\number\day, {\noexpand\mit\number\year}% +} + +\begingroup + \count0=\time + \count1=\count0 + \divide\count0 by 60 + \count2=\count0 + \multiply\count0 by 60 + \advance\count1 by -\count0 + \ifnum\count2>11 + \ifnum\count2>12 \advance\count2 by -12\fi + \def\ampm{pm}% + \else + \ifnum\count2=0 \advance\count2 by 12\fi + \def\ampm{am}% + \fi + \xdef\daytime{% + \ifnum\count2<10 0\fi \the\count2:% + \ifnum\count1<10 0\fi \the\count1 + \ampm + }% +\endgroup + + +\makeatother % back to normal diff --git a/doc/sun-89/make b/doc/sun-89/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/sun-89/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/sun-89/pp-slides.aux b/doc/sun-89/pp-slides.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/sun-89/pp-slides.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/sun-89/pp-slides.tex b/doc/sun-89/pp-slides.tex new file mode 100644 index 0000000..744be23 --- /dev/null +++ b/doc/sun-89/pp-slides.tex @@ -0,0 +1,253 @@ +% -*- LaTeX -* Although it's slitex really + +\documentstyle[blackandwhite,pagenumbers,small,oval,psfig,tgrind]{NRslides} + +\raggedright + +\begin{document} +\title {Electronic Mail -- X.400 and PP} + +\author{Julian P.~Onions\\ +jpo@cs.nott.ac.uk\\[.5in] +Communications Research Group\\ +Computer Science Department\\ +Nottingham University +} + +\date {September 7/8, 1989} + +\maketitle + + \begin{bwslide} +\ctitle {CONTENTS} +\begin{nrtc} +\item What is PP? + +\item An Introduction to X.400 + +\item The X.400 Model + +\item The X.400 Message + +\item X.400 Addressing + +\item The PP Architecture + +\item The PP Queue + +\item Submission + +\item Scheduling and Control + +\item Channels + +\item Status and Availability +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{What is PP} +\begin{nrtc} +\item Basically, A Mail transfer system (MTA in the jargon). + +\item Largely protocol independent, but deals with X.400 + and existing mail formats. + +\item Written by people at UCL and Nottingham + +\item Design aims include:- + \begin{itemize} + + \item High performance/throughput + \item Support for message conversion. + \item Support for multi-media + \item Clean interface for user interfaces. + \end{itemize} + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{A (quick) Introduction to X.400} +\begin{nrtc} +\item X.400 is a family of protocols that form an international +standard for electronic mail. + +\item Based on three layers + \begin{itemize} + \item The User + \item The User Agent (UA) + \item The Message Transfer Agent (MTA) + \end{itemize} +\item Defined in terms of a language called ASN.1 + +\item PP is an instance of an MTA +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The X.400 Model} + +\vskip .5in +\diagram[p]{figure1} +\end{bwslide} + + \begin{bwslide} +\ctitle{The X.400 Message} +\begin{nrtc} +\item The Message is divided into three parts: + \begin{itemize} + \item The envelope; + \item the header; and + \item and a list of body parts. + \end{itemize} + +\item The envelope (P1 protocol) is used by MTA's to work out how to + deliver the message. + +\item The header (P2 protocol) is constructed by the user. + +\item The body parts can be in any of numerous formats. + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{X.400 Addressing} +\begin{nrtc} +\item X.400 Addresses are binary lists of attribute values. + +\item They look pretty horrible + +\item X.400 is designed to interact with the X.500 directory service. + +\item This hides these address to a large extent. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} +\begin{nrtc} +\item PP is based on a system of cooperating processes. + +\item Each process has a specific task to achieve. + +\item Most of these processes are ``dumb''. + +\item The ``intelligence'' of the system is provided by two processes. + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} + +\vskip .5in + +\diagram[p]{figure2} + +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Queue} +\begin{nrtc} +\item All messages are placed in a queue on disc. + +\item For each message there are two components + \begin{itemize} + \item A Control file holding all the envelope information. + \item The Message structure holding the Message data. + \end{itemize} +\item The Control file is text encoded. + +\item The Message is either a single file, or a directory hierarchy. + +\item The Message may undergo a number of transformations whilst in + the queue +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Submission} +\begin{nrtc} +\item The first intelligent process is {\em submit}. + +\item All messages entering the queue pass through this process. + +\item It validates the message in a number of ways: + \begin{itemize} + \item Ensures the originator can be reached. + \item Ensures the destination is known. + \item Works out a conversion path from incoming format to outgoing. + \item Applies access controls if required. + \end{itemize} +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Scheduling and Controlling} +\begin{nrtc} +\item The other ``intelligent'' process is the queue manager, {\em qmgr}. + +\item Keeps an in memory map of the queue. + +\item Drives all channel programs using network IPC. + +\item Makes all the scheduling decision about messages in the queue. + +\item Sorts the queue in ``optimal'' ways. + +\item Allows connections to interrogate queue status +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Queue Monitoring} + +\vskip .5in + +\psfig{file=console.ps,height=6in} + +\end{bwslide} + + \begin{bwslide} +\ctitle{Channels} +\begin{nrtc} +\item Channels in PP process messages. + +\item May reformat a message by conversion e.g. + \begin{itemize} + \item Mapping X.400 to RFC-822 message + \item Converting Telex to Ascii + \end{itemize} +\item May attempt delivery e.g. + \begin{itemize} + \item Drive the SMTP or X.400 protocols + \item Deliver to users + \end{itemize} +\item May restructure the message + \begin{itemize} + \item Convert a file into a directory hierarchy + \item Convert multiple body parts into one + \end{itemize} +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Status and Availability} +\begin{nrtc} + +\item Currently, PP is in alpha test at three sites + +\item Has transferred many thousands of messages + +\item Will be entering beta test to a slightly wider audience soon. + +\item Should be released at the end of this year. + +\item PP is freely available for use and should be the backbone of + JANET as it transitions to X.400 protocols. +\end{nrtc} +\end{bwslide} + +\end{document} diff --git a/doc/sun-89/pp.aux b/doc/sun-89/pp.aux new file mode 100644 index 0000000..13d384e --- /dev/null +++ b/doc/sun-89/pp.aux @@ -0,0 +1,36 @@ +\relax +\citation{ISODE} +\citation{CCITT.MHS} +\citation{RFC822} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1}Introduction}{1}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {1}{\ignorespaces The X.400 Model}}{2}} +\newlabel{x400:model}{{1}{2}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2}X.400 Message Handling Service}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1}The X.400 Model}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2}The X.400 Message}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3}X.400 Addressing}{3}} +\citation{MMDFII} +\citation{PP.MTA} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.4}Services and Other Protocols}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3}The design of PP}{4}} +\@writefile{lof}{\string\contentsline\space {figure}{\string\numberline\space {2}{\ignorespaces The PP Process Structure}}{5}} +\newlabel{pp:process}{{2}{5}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1}The Process Structure}{5}} +\citation{SMTP} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.2}The Queue}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.3}Channels}{6}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.1}Outbound Channels}{6}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.2}Inbound Channels}{7}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.3.3}Formatting and protocol conversion channels}{7}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4}PP Status}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.1}The current version}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.2}The released version}{7}} +\bibdata{bcustom,networking,software} +\bibcite{CCITT.MHS}{CCI88} +\bibcite{RFC822}{Cro82} +\bibcite{MMDFII}{III84} +\bibcite{PP.MTA}{Kil88} +\bibcite{SMTP}{Pos82} +\bibcite{ISODE}{Ros88} +\bibstyle{alpha} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.3}Availability}{8}} diff --git a/doc/sun-89/pp.bbl b/doc/sun-89/pp.bbl new file mode 100644 index 0000000..dd3f5e4 --- /dev/null +++ b/doc/sun-89/pp.bbl @@ -0,0 +1,40 @@ +\begin{thebibliography}{CCI88} + +\bibitem[CCI88]{CCITT.MHS} +{Message Handling: System and Service Overview}. +\newblock International Telegraph and Telephone Consultative Committee, 1988. +\newblock Recommendation X.400. + +\bibitem[Cro82]{RFC822} +David~H. Crocker. +\newblock {Standard for the Format of ARPA Internet Text Messages}. +\newblock Request for Comments 822, DDN Network Information Center, SRI + International, August 1982. + +\bibitem[III84]{MMDFII} +Douglas P.~Kingston III. +\newblock {MMDFII: A Technical Review}. +\newblock In {\em Proceedings, Summer Usenix Conference and Exhibition}, pages + 32--41, June 1984. +\newblock Salt Lake City, Utah. + +\bibitem[Kil88]{PP.MTA} +Stephen~E. Kille. +\newblock {PP -- A Message Transfer Agent}. +\newblock In Einar Stefferud, editor, {\em {Proceedings, Fourth International + Symposium on Computer Message Systems}}, September 1988. +\newblock Costa Mesa, California. + +\bibitem[Pos82]{SMTP} +Jon~B. Postel. +\newblock {Simple Mail Transfer Protocol}. +\newblock Request for Comments 821, DDN Network Information Center, SRI + International, August 1982. +\newblock See also \milstd/ 1781. + +\bibitem[Ros88]{ISODE} +Marshall~T. Rose. +\newblock {\em {The ISO Development Environment: User's Manual}}. +\newblock The Wollongong Group, 3.4 (beta) edition, February 1988. + +\end{thebibliography} diff --git a/doc/sun-89/pp.major b/doc/sun-89/pp.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/sun-89/pp.major @@ -0,0 +1 @@ +1 diff --git a/doc/sun-89/pp.minor b/doc/sun-89/pp.minor new file mode 100644 index 0000000..209e3ef --- /dev/null +++ b/doc/sun-89/pp.minor @@ -0,0 +1 @@ +20 diff --git a/doc/sun-89/pp.tex b/doc/sun-89/pp.tex new file mode 100644 index 0000000..e38bd20 --- /dev/null +++ b/doc/sun-89/pp.tex @@ -0,0 +1,346 @@ +% -*- LaTeX -*- + +\input lcustom + +\documentstyle[11pt,a4]{article} + +\begin{document} + +\title{Electronic Mail -- X.400 and PP} +\author{Julian P.~Onions\\[0.1in] +Communications Research Group\\ +Nottingham University} +\date{7/8th September} + +\maketitle + +\begin{abstract} +This paper describes the design, implementation and progress of the PP +message transport system. This is a message transfer system that can +relay a variety of protocols, and gateway between them. + +The paper gives a very brief introduction to the X.400 mail standard; +followed by an overview of the PP message system and concludes with a +statement on progress of the work. +\end{abstract} + +\section{Introduction} + +This paper describes the design and implementation of PP\footnote{PP +is not an acronym. Despite many rumours to the contrary, the author is +sticking to this position!.}. PP is a generic Message Transfer Agent +capable of carrying a number of message formats. It has been written +as a joint project by University College London and Nottingham +University and is designed to run on \unix/ systems. It makes +use of the ISODE package\cite{ISODE}. Its design is heavily +influenced however, by the need to carry X.400 MHS\cite{CCITT.MHS} and +RFC-822\cite{RFC822} based mail. The major goals of PP include: +\begin{itemize} +\item Robustness. PP is designed for heavy use. It should be +capable of transferring high levels of traffic in an optimal way. + +\item A clean interface for submission and delivery. PP does not +provide a user agent but does provide a library interface which allows +user agents to be added to PP easily. + +\item Sophisticated message processing to optimise delivery and +remote transfers. + +\item Support for message conversion in an integrated way. + +\item Support for multiple addressing formats (initially two). + +\item Support for multi-media mail. + +\item Support for arbitrary message structures. + +\item Designed for large systems. PP is not designed to run on your +PC or even on a workstation. It is designed to be a central mail +processing hub for a group of computers. It is not a small piece of +software! +\end{itemize} + +The rest of this paper consists of a brief introduction to X.400, a +description of the PP architecture and a statement of the current +state of play. + +\section{X.400 Message Handling Service} + +X.400 is the international standard for message handling systems, +defined jointly by ISO and CCITT. X.400 itself is not a single +standard but a family of standards which includes standards such as +\[\begin{tabular}{l l} +X.400& System Service and Overview\\ +X.402& Basic Service Elements and Option User Facilities\\ +X.411& Abstract Service Definitions and Procedures\\ +X.413& Message Store Abstract Service\\ +X.419& Protocol Specifications\\ +X.420& Interpersonal Messaging System\\ +\end{tabular}\] + +\subsection{The X.400 Model} + +X.400 defines a model for electronic mail which has three layers, as +shown in Figure~\ref{x400:model}. The top most layer is the user, who +performs actions such as composing, reading and filing mail. At the +next level is the User Agent (UA). This is the interface to the +message transfer system. It is a piece of hardware or software which +aids the user in composing and reading mail. All interaction with the +system goes through this module. At the bottom is the Message Transfer +Layer. This is an interconnection of Message Transfer Agents (MTA) (such +as PP) which together route the message to its final destination. + +\tagfigure{1}{The X.400 Model}{x400:model} + +\subsection{The X.400 Message} + +The X.400 message is typically composed of three parts. Each part is +encoded in a machine independent format call Abstract Syntax Notation +One (ASN.1). ASN.1 is used throughout X.400 and OSI networking in +general. ASN.1 is binary in nature and allows complex structures to be +built up by defining them in terms of collection of a few basic primitives. + +The message composed by the user consists of a structured header with +the usual electronic mail components such as To, From, Subject etc. +The header structure is defined by a protocol +termed P2. This protocol governs the end-to-end transfer of the +message, and is the part that the users are aware of. + +This header has attached a number of body parts, each of which can be +a different format. This allows the interchange of any several +standard document types plus other privately defined body parts, the +simplest and most common being ascii. + +When submitted to the message transfer layer, an outer envelope is +constructed which contains all the information necessary to deliver +the message. This protocol is termed P1. It is an important separation +of functionality that the message contents need never be looked at by +the MTA's, indeed if secure messaging is being used and the message is +encrypted this is not possible. + +So, the structure of the message is analogous to paper mail. The P1 +envelope is the equivalent of the paper envelope, used by the postal +service for delivery. The P2 header is equivalent to a standard letter +heading and the body parts are the equivalent of the pages of the +letter. + +\subsection{X.400 Addressing} + +X.400 defines an address as a list of attribute value pairs. A +typical address might look like this: +\[\begin{tabular}{l l} +Country& GB\\ +Adminstrative Domain& GOLD 400\\ +Private Domain& UK.AC\\ +Organisation& Nottingham University\\ +Organisational Unit& Computer Science\\ +Personal Name/Given& Julian\\ +Personal Name/Surname& Onions\\ +\end{tabular}\] +However, it is intended that X.400 should make use of another OSI +standard X.500, the directory service. This allows complex queries and +name lookup to be done across the world and so will resolve shorter +forms of address to full X.400 addresses. It can also help with +ambiguous queries and general searching for recipients based on +whatever data is available. A typical X.500 address might look like: +\[\begin{tabular}{l l} +Country& GB\\ +Organisation& Nottingham University\\ +Organisational Unit& Computer Science\\ +Common Name& Julian Onions\\ +\end{tabular}\] + +\subsection{Services and Other Protocols} + +There have so far been two version of the X.400 standard. The 1984 +version and the 1988 version. The 1984 version was rather restrictive +in what it allowed and several improvements were made in the 1988 +version. X.400 currently supports the following services: +\begin{itemize} +\item Delivery reports -- both positive and negative. +\item Conversion between body parts +\item Secure messageing. Protocols are provided to allow many forms +of security including + \begin{itemize} + \item Basic message modification + \item Masquerading as other users + \item Proof of delivery and submission + \item Traffic analysis + \end{itemize} +\item Distribution list support. +\item A flexible way to extend the protocols and body parts. +\item Message Stores. +\item Interfaces with other facilities including Fax, Telex and the +postal system. +\end{itemize} + +Also defined in the X.400 standards are protocols to remotely access +the mail system (P3) and to remotely access message stores (P7). + +\section{The design of PP} + +The design of PP was influenced in part by the RFC-822 mail system +MMDF\cite{MMDFII}. In this model, extensive use is made of separate +processes to do different jobs. This allows each element to be built +and tested separately and encourages modularity. A fuller description +of the design of PP can be found in \cite{PP.MTA}. + +\subsection{The Process Structure} + +The basic PP process structure is shown in Figure~\ref{pp:process}. PP +has a single queue of messages on which a number of processes operate. +There are two critical processes which undertake complex functions, +the rest of the processes are essentially ``dumb''. + +\tagfigure{2}{The PP Process Structure}{pp:process} + +The first key process is that entitled {\em submit}. This process +guards the entrance to the queue. All messages entering the queue pass +through this process. It performs a variety of checks on the message +to ensure it can either be delivered or returned; works out the +routing for the message; calculates the reformatting of the message if +necessary; and applies other criteria such as authorisation and +authentication. By checking as much as possible at this point later processes +have to do less and completely undeliverable messages can be stopped +from entering the queue. + +The second key process is the {\em QMGR}, or queue manager. This +process is responsible for all the scheduling operations of the +messages in the queue. The QMGR holds a representation of the queue in +memory and so can perform complex and optimal scheduling of messages. +This scheduling consists of either delivering the message locally or +remotely or else converting the message within the queue (e.g. +gatewaying between protocols). + +As the QMGR holds a complete representation of the queue in memory it +also provides an information service. It can be queried by suitable +tools to display the state of the queue and such tools can even +control the behaviour of the QMGR. + +\subsection{The Queue} + +The queue of messages is held in two components. The first is an +address file which contains the envelope information about the +message. This is held in a text encoded form and is a generic envelope +structure which can hold both X.400 and RFC-822 messages. The text +encoding is a big advantage as it allows manipulation of the queues in +an emergency by a text editor. Whilst this should not normally be +necessary it is much easier than providing special management tools +to cover every eventuality. + +The second component is the message content. This includes the headers +and body parts. If no processing is necessary for the message this is +kept as a single file. However, if conversion is necessary, the +content is broken up into parts, each part being placed in a separate +file. Each time a message content is transformed, a new directory is +created and the appropriate files are changed. This allows simple +filters (such as {\em sed} even) to do the conversions. + + +\subsection{Channels} + +Most other processes in PP are termed {\em channels}. A channel takes +as input a message and outputs a different form of that message. +Channels are controlled directly by the QMGR by means of a networked +protocol. Each channel does a specific job. Channels come in three +basic forms as described below. + +\subsubsection{Outbound Channels} +This style of channel is usually a protocol engine. It takes a message +out of the queue and delivers it. This delivery may be local as in the +case of delivering to a mailbox; or remote such as driving the +SMTP\cite{SMTP} or X.400 protocols. Each channel reads the internal +format of the queued message and converts it to the protocol specific +format. The QMGR informs a channel which message to deliver and the +channel reports on the status of the message. This allows the QMGR to +discover whether the delivery attempt was successful, the remote site +did not respond or whether the message cannot be delivered. This +information is then used by the QMGR to schedule further deliveries. + +\subsubsection{Inbound Channels} +Inbound channels perform the opposite function to outbound channels. +They take care of the various protocols necessary to receive a +message, either from a user agent (local submission) or across a +network. Their main task is mapping from the protocol specific form of +the message to the form used withing the queue. This form is then +passed by a private protocol to submit which enqueue the message and +then informs the QMGR of the new message. + +\subsubsection{Formatting and protocol conversion channels} +These channels transform the message in some way without delivering +it. They are treated in exactly the same way as outbound channels and +are scheduled by the QMGR. These channels come in two basic types. +\begin{enumerate} +\item Channels that change the directory structure. These either map +from the single file into a directory hierarchy, or the reverse. + +\item Simple reformatting. These channels might change, say, a teletex +body part into an ascii body part. When gatewaying is being performed, +such a channel might convert RFC-822 headers into X.400 headers. + +\end{enumerate} + +\section{PP Status} + +\subsection{The current version} + +At the time of writing this (August 1989) PP has been in alpha test +(version 3.0) for approximately a month at a limited number of sites. +In this time is has transferred several thousand message (mostly +without problems!) and has successfully gatewayed many messages +between RFC-822 and X.400. + +PP was successfully demonstrated at the Cebit show where it +interworked with a number of other X.400 products. It continues to +interwork with a number of sites both via X.400 and RFC822 based +protocols. + +The beta version of this code will be released to a larger number of +sites in the Autumn. + +\subsection{The released version} +The released version of PP should be available around the end of the +year. It will contain the following major modules :- + +\begin{description} +\item[Core] The basic core of the system including the QMGR, +submit and a number of support tools. + +\item[X.400 1984] The X.400 1984 protocols will be fully supported. + +\item[SMTP] Smtp protocols will be supported, including use of the +name server protocols for address resolution. + +\item[Grey Book] Grey book mail transfer is being tested for the next +release. This will work with the unix-niftp blue book transfer system +to provide non-spooled mail transfer over JANET. + +\item[List] A list channel to offload the processing of +distribution lists. This helps speed up submission to large +distribution lists and allows list management. + +\item[X.400 1988] The 1988 version of X.400 should be present in the +released version in a beta test form. The 1988 version of X.400 is +uncommon at present so interworking testing is limited. This will +include secure messaging and extensions. + +\item[MTA Console] An X-windows based console display which +interrogates the QMGR and displays the current state of the +queues. It emphasises problems in the queue and allows parameters to +be adjusted interactively. + +\item[Tools] Various auxiliary programs to configure the system and +provide debugging support. + +\end{description} + +\subsection{Availability} +PP will be available later this year in the public domain. It is +planned to continue development for some time. + +\bibliography{bcustom,networking,software} +\bibliographystyle{alpha} + +\showsummary + +\end{document} diff --git a/doc/sun-89/pp.vrsn b/doc/sun-89/pp.vrsn new file mode 100644 index 0000000..8f3b1f1 --- /dev/null +++ b/doc/sun-89/pp.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.20}% + \gdef\versiondate/{Wed Sep 18 08:25:44 BST 1991}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/sun-89/trademark.tex b/doc/sun-89/trademark.tex new file mode 100644 index 0000000..dbd5af8 --- /dev/null +++ b/doc/sun-89/trademark.tex @@ -0,0 +1,75 @@ +% Trademarks... + +\def\gobble#1{} +\def\tradeORGfont{\sc} % used for organizations (e.g., ACM) +\def\tradeNAMfont{\sf} % used for names (e.g., Ada) + +\def\tradeorg#1{% + \tradeaux{#1}{\expandafter\gobble\string#1}\empty\tradeORGfont +} +\def\tradeorgn#1#2{% + \tradeaux{#1}{#2}\empty\tradeORGfont +} +\def\tradename#1#2#3{\tradeaux{#1}{#2}{#3}\tradeNAMfont} +\def\trademark#1#2{% + \tradeaux{#1}{\expandafter\gobble\string#1}{#2}\tradeNAMfont +} + +\def\tradeaux#1#2#3#4{% + \def#1/{\relax}% % in case #3 references #1 + \setbox0=\hbox{#3}% % when we make the \hbox + \ifdim\wd0>0pt + \gdef#1/{% + \tradeaux{#1}{#2}\empty{#4}% + #1/\footnote{#1/ is a trademark of #3.}% + }% + \else + \gdef#1/{{#4#2}}% + \fi +} + +\tradeorg\acm +\tradeorg\ansi +\tradename\Ada{Ada} + {the Department of Defense (\Ada/ Joint Program Office)} +\tradename\balance{Balance} {Sequent Computer Systems, Incorporated} +\tradeorg\bsd +\tradename\butterfly{Butterfly}{Bolt, Beranek, and Newman, Incorporated} +\tradeorg\ccitt +\tradename\cms{CMS} {International Business Machines, Incorporated} +\tradename\cpm{CP/M} {Digital Research Corporation} +\tradename\chrysalis{Chrysalis}{Bolt, Beranek, and Newman, Incorporated} +\tradename\decnet{DECnet} {Digital Equipment Corporation} +\tradeorgn\dod{DoD} +\tradename\dynix{DYNIX} {Sequent Computer Systems, Incorporated} +\tradename\ethernet{Ethernet} {the Xerox Corporation} +\tradename\eunice{Eunice} \empty +\tradename\exos{EXOS} {Excelan, Incorporated} +\tradename\ibmpc{IBM PC} {International Business Machines, Incorporated} +\tradename\ibmpcat{IBM PC/AT} {International Business Machines, Incorporated} +\tradeorg\ieee +\tradename\iPSC{iPSC} {Intel Corporation} +\tradename\lattice{Lattice} {Lattice, Incorporated} +\tradename\locus{Locus} {Locus Computing Corporation} +\def\microvax/{$\mu$\vax/} +\def\microvms/{$\mu$\vms/} +\tradeorg\milstd +\tradename\msdos{MS-DOS} {Microsoft Corporation} +\tradename\mvs{MVS} {International Business Machines, Incorporated} +\tradename\pcdos{PC-DOS} {International Business Machines, Incorporated} +\tradename\pcinterface{PC-Interface}% + {Locus Computing Corporation} +\tradename\pdp{PDP} {Digital Equipment Corporation} +\tradename{\tops20}{Tops20} {Digital Equipment Corporation} +\tradename\trustedmail{Trusted\ Mail}% + {Trusted Technologies, Incorporated} +\tradename\tseries{T-Series} {Floating Point Systems} +\tradename\ultrix{ULTRIX} {Digital Equipment Corporation} +\tradename\unibus{UNIBUS} {Digital Equipment Corporation} +\tradename\unix{UNIX} {AT\&T Bell Laboratories} +\tradename\vax{VAX} {Digital Equipment Corporation} +\tradename\vaxstation{VAXstation}% + {Digital Equipment Corporation} +\tradename\vm{VM} {International Business Machines, Incorporated} +\tradename\vms{VMS} {Digital Equipment Corporation} +\tradename\xenix{Xenix} {Microsoft Corporation} diff --git a/doc/sun-89/version.sh b/doc/sun-89/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/sun-89/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/tailor/Makefile b/doc/tailor/Makefile new file mode 100644 index 0000000..7f131aa --- /dev/null +++ b/doc/tailor/Makefile @@ -0,0 +1,91 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps \ + .ry .py .grap .chem + +.ry.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grap.tex:; grap $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.chem.tex:; chem $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.b.tex:; itbit $< + +.xb.tex:; xtbit $< + +.xwd.tex:; xtwd $< + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grf.tex:; sh -c 'if graph < $< | plot -TeX > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.pct.pic:; pct2pic $< + +.pic.tex:; tpic $< + +.plt.tex:; sh -c 'if plot -TeX < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if tgrind -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if latex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if dvi2ps $(DFLAGS) $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + + +############################################################# +# Here it is... +############################################################# + +all: i-all +print: i-print + + +############################################################# +# tailor +############################################################# + +install:; + +i-all: tailor.dvi + +i-print: tailor.dvi true + dvisp $(DFLAGS) tailor + + +# customization files, et. al., not included below +tailor.dvi: tailor.vrsn + +tailor.vrsn: tailor.tex version.sh + @version.sh + +preview: tailor.dvi true + xdvi tailor.dvi + +index:; idx2ind -l tailor + +clean:; rm -f tailor.imp tailor.ps tailor.dvi tailor.log \ + tailor.blg _* + +true:; diff --git a/doc/tailor/make b/doc/tailor/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/tailor/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/tailor/tailor.tex b/doc/tailor/tailor.tex new file mode 100644 index 0000000..64c8f9d --- /dev/null +++ b/doc/tailor/tailor.tex @@ -0,0 +1,203 @@ +\documentstyle [11pt,a4] {article} +\author {S.E. Kille} +\date {\today} +\title {A system for tailoring C programs} + + +\begin {document} +\maketitle + +\begin {abstract} +This document defines a proposed design for tailoring C programs. +It is specifically intended for ISODE, QUIPU, and PP. +\end {abstract} + + +\section {Introduction} + + +It seems wrong to require a C format, a tailor format, and hand generated +code to map between them. I propose that we devise a format which specifies +both, and can be used to generate what is needed. + + +We need to be able to specify the following: + +\begin {itemize} +\item +NUMBER types, which will be mapped onto int + +\item STRING types, which will be mapped onto char* + +\item ENUMERATED types, which will be mapped onto int + +\item FLAG types, which will be mapped onto int + +\item LIST types. These are structure types, which are linked into a list. +Thus, a "next" and a "key" is always generated. +Can contain STRING, ENUMERATED or FLAG. +and also DEF, which points to a previously defined type (typically to get at +taiored defines for ENUMERATED, or to point at identified LIST types) + +\end {itemize} + +\section {BNF Defintion} + +The following BNF for the single file is proposed. Tokens are separated by +LWSP or braces. + +\begin {verbatim} + + ::= + ::= | + ::= "--" + | "#" + | + + ::= "PREFIX" + + ::= | | | | | + | + + ::= | "," + ::= ["(" ")"] + + ::= "NUMBER" + + ::= "ENUM" + + ::= "FLAG" + + ::= "STRING" + + ::= "ENUMVALUES" + + ::= "FLAGVALUES" + + ::= "LIST" "{" "}" + + ::= | + + ::= | | | | + + ::= "PTR" +\end{verbatim} + +\section {Behaviour} + + +\begin {itemize} +\item +An h file is made with +Typedefs for any structures generated, and +extern references to all variables. + + +\item +A C file with variable definitions, initialiased to zero + + +\item +Documentation on the format of the tailor file. This should be unix manual +or LaTeX. {\tt } is interspersed into the mechanically +generated structure. + +\item A routine {\tt \_tai()} to parse a tailor file and initialise +each variables. + +\item {\tt \_tai\_build()} to take +tailor file, and generate a file of static definitios +(esssentially to replace 3., with values frozen in). This would allow a +site to ``compile in'' an operational tailor file, and thus gain performance. +Only deltas would need to be runtime tailored. + +\item Code to print/log the value of tailored variables ({\tt \_\_print()}). + +\item Code to call all of the functions in 7 (list-config) - a sort of +print\_config ({\tt \_tai\_print()}). + +\item +Code to select structures from lists + ({\tt \_nm2struct()) }). + +\end {itemize} + +Some more notes on building the structures: + +\begin {itemize} +\item For variables or structure items, the name of the variable is used, or +the bracketed value if present. + +\item For ENUMVALUES, the definitions for ENUM are associated with the +strings concerned. If bracketed values are present, these are references to +external \#defines. Otherwise, {\tt \_} is allocated +incrementally, and the \#defines created. +Similarly for ENUMFLAGS. +\end {itemize} + + +\section {Examples} + +Example format + +\begin {verbatim} + STRING authwarn +\end{verbatim} + + +generates char* authwarn; and recognises 'authwarn "joe foobar"' in a tailor +file. + +\begin {verbatim} + NUMBER mcount(maxcount) +\end{verbatim} + +generates 'int maxcount;' and recognises 'mcount 22' + +\begin {verbatim} + +ENUMVALUES logvalues bst(LLOG_BST), fst(LLOG_FST) + +log LIST { + STRING show (ll_show) + ENUM level(ll_level) logvalues + } + +chan(ch_struct) LIST { + STRING show(ch_show) + PTR log(ch_log) log + ENUM loglevel(ch_level) logvalues + } + + +generates strucutures: + +log { + struct *log log_next; + char *log_key; + char* ll_show; + char ll_level; +}; + +ch_struct { + struct *ch_struct ch_struct_next; + char *ch_struct_key; + char *ch_show; + struct *log ch_log; + char ch_level; +} +\end{verbatim} + +It generates routines chan\_nm2struct (key) and log\_nm2struct (key). +One might initialise logs by (e.g.) authlog = log\_nm2struct ("auth"); + +It would recognise formats: + +\begin {verbatim} +log auth show="authorisation log", level=bst + +chan xchan show="funny channel", log=auth, level=fst +\end{verbatim} + + +\end {document} diff --git a/doc/tailor/version.sh b/doc/tailor/version.sh new file mode 100755 index 0000000..b9f5520 --- /dev/null +++ b/doc/tailor/version.sh @@ -0,0 +1,21 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor > "'tmp.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +cat tmp.vrsn >> $1.vrsn +rm tmp.vrsn +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/uknet90/Makefile b/doc/uknet90/Makefile new file mode 100644 index 0000000..ffc902e --- /dev/null +++ b/doc/uknet90/Makefile @@ -0,0 +1,93 @@ +######################################################################### +# Instructions to Make, for generation of nice-looking papers using LaTeX +######################################################################### + +.SUFFIXES: .b .xb .xwd .c .grf .pct .pic .plt .s .web .tex .dvi .imp .ps \ + .ry .py .grap .chem + +.ry.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.py.tex:; sh -c 'if tgrind -d grindefs -f -lasn1 $< |\ + sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grap.tex:; grap $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.chem.tex:; chem $< > $*.pic + tpic $*.pic + rm -f $*.pic + +.b.tex:; itbit $< + +.xb.tex:; xtbit $< + +.xwd.tex:; xtwd $< + +.c.tex:; sh -c 'if tgrind -f -lc $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.grf.tex:; sh -c 'if graph < $< | plot -TeX > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.pct.pic:; pct2pic $< + +.pic.tex:; tpic $< + +.plt.tex:; sh -c 'if plot -TeX < $< > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.s.tex:; sh -c 'if tgrind -f -la68k $< | sed -e 1d -e \$$d > $@; \ + then exit 0; else rm $@; exit 1; fi' + +.web.tex:; sh -c 'if weave $<; then exit 0; else rm $@; exit 1; fi' + +.tex.dvi:; sh -c 'if latex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +.dvi.imp:; dviimp $(DFLAGS) -i $@ $< + +.dvi.ps:; sh -c 'if dvialw $(DFLAGS) $< ; \ + then exit 0; else rm $@; exit 1; fi' + mv $*.alw $@ + + +############################################################# +# Here it is... +############################################################# + + + +############################################################# +# pp +############################################################# + +all: pp.dvi pp-slides.dvi + +print: pp.ps pp-slides.ps + +# customization files, et. al., not included below +pp.dvi: pp.vrsn + +pp.vrsn: pp.tex pp.bbl version.sh figure1.tex figure2.tex + @version.sh pp + +pp-slides.dvi: pp-slides.tex + sh -c 'if slitex \\nonstopmode\\input $<; \ + then exit 0; else rm $@; exit 1; fi' + +biblio:; bibtex pp + +preview: pp.dvi true + xtex pp.dvi + +index:; idx2ind -l pp + +clean:; rm -f pp.imp pp.ps pp.dvi pp.log \ + pp.blg _* pp-slides.dvi pp-slides.log pp-slides.ps \ + pp-slides.blg *~ + +true:; diff --git a/doc/uknet90/bcustom.bib b/doc/uknet90/bcustom.bib new file mode 100644 index 0000000..2c10b96 --- /dev/null +++ b/doc/uknet90/bcustom.bib @@ -0,0 +1,39 @@ +% BibTeX customization + +% people +@string{mtr = "Marshall T. Rose"} +@string{jpo = "Julian P. Onions"} + +% places +@string{bbn = "Bolt, Beranek, and Newman, Inc."} +@string{ccitt = "International Telegraph and Telephone Consultative Committee"} +@string{cis = "Department of Computer and Information Sciences"} +@string{ee = "Department of Electrical Engineering"} +@string{ics = "Department of Information and Computer Science"} +@string{iso/iec = "International Organization for Standardization/International Electrotechnical Institute"} +@string{nic = "DDN Network Information Center"} +@string{nrtc = "Northrop Research and Technology Center"} +@string{rand = "The Rand Corporation"} +@string{sri = "SRI International"} +@string{twg = "The Wollongong Group"} +@string{uci = "University of California, Irvine"} +@string{ucl = "University College London"} +@string{udel = "University of Delaware"} +@string{unott = "University of Nottingham"} + +% journals +@string{connexions = "ConneXions"} +@string{cn/isdn = "Computer Networks and ISDN Systems"} +@string{ccr = "Computer Communication Review"} +@string{ieeecom = "IEEE Transactions on Communications"} +@string{ieeecm = "IEEE Communications Magazine"} +@string{jsac = "IEEE Journal on Selected Areas in Communications"} + +% handbooks +@string{ddn = "DDN Protocol Handbook, + Volume One: \dod/ Military Standard Protocols, + DDN Network Information Center, SRI International"} + +% types +@string{idea = "IDEA"} +@string{rfc = "Request for Comments"} diff --git a/doc/uknet90/captcont.sty b/doc/uknet90/captcont.sty new file mode 100644 index 0000000..70f662e --- /dev/null +++ b/doc/uknet90/captcont.sty @@ -0,0 +1,16 @@ +% SubStyle file to permit the use of captions in continuations of floats. +% +% \captcont is like \caption, except that it doesn't update the counter, and +% it doesn't make an entry in the list of figures or list of tables. + +\def\captcont{\@dblarg{\@captcont\@captype}} + +\long\def\@captcont#1[#2]#3{ +% \addcontentsline{\csname ext@#1\endcsname}{#1}{\protect\numberline{\csname +% the#1\endcsname}{\ignorespaces #2}} + \par + \begingroup + \@parboxrestore + \normalsize + \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par + \endgroup} diff --git a/doc/uknet90/figure1.pic b/doc/uknet90/figure1.pic new file mode 100644 index 0000000..f03143f --- /dev/null +++ b/doc/uknet90/figure1.pic @@ -0,0 +1,52 @@ +.PS 5 +eighth = 1/8 +boxwid = 0.5 +boxht = 0.25 +arrowhead = 7 +arrowht = eighth/2 +define user X box "User" X +define ua X box "UA" wid 7/16 X +define mta X box "MTA" X +MHE: box dotted ht 4 + eighth wid 6.25 + "Message Handling Environment" at MHE.nw + (eighth, -eighth) ljust +MHS: box ht 3.25 wid 4.5 with .s at MHE.s + (0,eighth) + "MHS" ljust at MHS.nw + (0.25, -0.25) +MTS: box dashed ht 2.5 wid 3 - eighth with .s at MHS.s + (0,eighth) + "MTS" ljust at MTS.nw + (0.25, -0.25) + + user with .e at MHS.sw + (-eighth, 1) +Ua1: ua with .w at MHS.sw + (eighth, 1) + line <-> from 2nd last box.e to last box.w + + user with .e at MHS.sw + (-eighth, 2) +Ua2: ua with .w at MHS.sw + (eighth, 2) + line <-> from 2nd last box.e to last box.w + + user with .s at MHS.n + (0, eighth) +Ua3: ua with .n at MHS.n - (0,eighth) + line <-> from 2nd last box.s to last box.n + + user with .w at MHS.se + (eighth,0.5) +Ua4: ua with .e at MHS.se + (-eighth, 0.5) + line <-> from 2nd last box.w to last box.e + +Mta1: mta with .w at MTS.sw + (eighth, 1.25) + line <-> from Ua1.e to Mta1.sw + line <-> from Ua2.e to Mta1.nw + +Mta2: mta with .n at MTS.n + (0, -eighth) + line <-> from Mta1.n to Mta2.w + line <-> from Mta2.n to Ua3.s + +Mta3: mta with .e at MTS.se + (-eighth, 1.25) + line <-> from Mta2.e to Mta3.n + line <-> from Mta1.e to Mta3.w + +Mta4: mta with .e at Ua4.w - (0.5,0) + line <-> from Mta4.e to Ua4.w + line <-> from Mta3.s to Mta4.n + +Mta5: mta with .e at Mta4.w - (0.5,0) + line <-> from Mta4.w to Mta5.e + line <-> from Mta5.n to Mta1.s +.PE diff --git a/doc/uknet90/figure1.tex b/doc/uknet90/figure1.tex new file mode 100644 index 0000000..7e127a6 --- /dev/null +++ b/doc/uknet90/figure1.tex @@ -0,0 +1,317 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{pa 0 3300}% + \special{pa 5000 3300}% + \special{dt 0.050}% + \special{pa 5000 3300}% + \special{pa 5000 0}% + \special{dt 0.050}% + \special{pa 5000 0}% + \special{pa 0 0}% + \special{dt 0.050}% + \special{pa 0 0}% + \special{pa 0 3300}% + \special{dt 0.050}% + \rlap{\kern 0.100in\lower 0.141in\hbox to0pt{Message Handling Environment\hss}}% + \special{pa 700 3200}% + \special{pa 700 600}% + \special{pa 4300 600}% + \special{pa 4300 3200}% + \special{pa 700 3200}% + \special{fp}% + \rlap{\kern 0.900in\lower 0.841in\hbox to0pt{MHS\hss}}% + \special{pa 1350 3100}% + \special{pa 3650 3100}% + \special{da 0.050}% + \special{pa 3650 3100}% + \special{pa 3650 1100}% + \special{da 0.050}% + \special{pa 3650 1100}% + \special{pa 1350 1100}% + \special{da 0.050}% + \special{pa 1350 1100}% + \special{pa 1350 3100}% + \special{da 0.050}% + \rlap{\kern 1.550in\lower 1.341in\hbox to0pt{MTS\hss}}% + \special{pa 200 2500}% + \special{pa 200 2300}% + \special{pa 600 2300}% + \special{pa 600 2500}% + \special{pa 200 2500}% + \special{fp}% + \rlap{\kern 0.400in\lower 2.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 2500}% + \special{pa 800 2300}% + \special{pa 1150 2300}% + \special{pa 1150 2500}% + \special{pa 800 2500}% + \special{fp}% + \rlap{\kern 0.975in\lower 2.441in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 2380}% + \special{pa 600 2400}% + \special{fp}% + \special{pa 650 2420}% + \special{pa 600 2400}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2420}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 750 2380}% + \special{pa 800 2400}% + \special{fp}% + \special{pa 200 1700}% + \special{pa 200 1500}% + \special{pa 600 1500}% + \special{pa 600 1700}% + \special{pa 200 1700}% + \special{fp}% + \rlap{\kern 0.400in\lower 1.641in\hbox to 0pt{\hss User\hss}}% + \special{pa 800 1700}% + \special{pa 800 1500}% + \special{pa 1150 1500}% + \special{pa 1150 1700}% + \special{pa 800 1700}% + \special{fp}% + \rlap{\kern 0.975in\lower 1.641in\hbox to 0pt{\hss UA\hss}}% + \special{pa 650 1580}% + \special{pa 600 1600}% + \special{fp}% + \special{pa 650 1620}% + \special{pa 600 1600}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1620}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 750 1580}% + \special{pa 800 1600}% + \special{fp}% + \special{pa 2300 500}% + \special{pa 2300 300}% + \special{pa 2700 300}% + \special{pa 2700 500}% + \special{pa 2300 500}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.441in\hbox to 0pt{\hss User\hss}}% + \special{pa 2325 900}% + \special{pa 2325 700}% + \special{pa 2675 700}% + \special{pa 2675 900}% + \special{pa 2325 900}% + \special{fp}% + \rlap{\kern 2.500in\lower 0.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 2520 550}% + \special{pa 2500 500}% + \special{fp}% + \special{pa 2480 550}% + \special{pa 2500 500}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2480 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 2520 650}% + \special{pa 2500 700}% + \special{fp}% + \special{pa 4400 2900}% + \special{pa 4400 2700}% + \special{pa 4800 2700}% + \special{pa 4800 2900}% + \special{pa 4400 2900}% + \special{fp}% + \rlap{\kern 4.600in\lower 2.841in\hbox to 0pt{\hss User\hss}}% + \special{pa 3850 2900}% + \special{pa 3850 2700}% + \special{pa 4200 2700}% + \special{pa 4200 2900}% + \special{pa 3850 2900}% + \special{fp}% + \rlap{\kern 4.025in\lower 2.841in\hbox to 0pt{\hss UA\hss}}% + \special{pa 4350 2820}% + \special{pa 4400 2800}% + \special{fp}% + \special{pa 4350 2780}% + \special{pa 4400 2800}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2780}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 4250 2820}% + \special{pa 4200 2800}% + \special{fp}% + \special{pa 1450 2200}% + \special{pa 1450 2000}% + \special{pa 1850 2000}% + \special{pa 1850 2200}% + \special{pa 1450 2200}% + \special{fp}% + \rlap{\kern 1.650in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1181 2356}% + \special{pa 1150 2400}% + \special{fp}% + \special{pa 1203 2389}% + \special{pa 1150 2400}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1419 2244}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1397 2211}% + \special{pa 1450 2200}% + \special{fp}% + \special{pa 1196 1628}% + \special{pa 1150 1600}% + \special{fp}% + \special{pa 1164 1652}% + \special{pa 1150 1600}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1404 1972}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 1436 1948}% + \special{pa 1450 2000}% + \special{fp}% + \special{pa 2300 1400}% + \special{pa 2300 1200}% + \special{pa 2700 1200}% + \special{pa 2700 1400}% + \special{pa 2300 1400}% + \special{fp}% + \rlap{\kern 2.500in\lower 1.341in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 1669 1950}% + \special{pa 1650 2000}% + \special{fp}% + \special{pa 1699 1977}% + \special{pa 1650 2000}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2281 1350}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2251 1323}% + \special{pa 2300 1300}% + \special{fp}% + \special{pa 2480 1150}% + \special{pa 2500 1200}% + \special{fp}% + \special{pa 2520 1150}% + \special{pa 2500 1200}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2520 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 2480 950}% + \special{pa 2500 900}% + \special{fp}% + \special{pa 3150 2200}% + \special{pa 3150 2000}% + \special{pa 3550 2000}% + \special{pa 3550 2200}% + \special{pa 3150 2200}% + \special{fp}% + \rlap{\kern 3.350in\lower 2.141in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 2749 1323}% + \special{pa 2700 1300}% + \special{fp}% + \special{pa 2719 1350}% + \special{pa 2700 1300}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3301 1977}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 3331 1950}% + \special{pa 3350 2000}% + \special{fp}% + \special{pa 1900 2080}% + \special{pa 1850 2100}% + \special{fp}% + \special{pa 1900 2120}% + \special{pa 1850 2100}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2120}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3100 2080}% + \special{pa 3150 2100}% + \special{fp}% + \special{pa 3050 2900}% + \special{pa 3050 2700}% + \special{pa 3450 2700}% + \special{pa 3450 2900}% + \special{pa 3050 2900}% + \special{fp}% + \rlap{\kern 3.250in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3500 2780}% + \special{pa 3450 2800}% + \special{fp}% + \special{pa 3500 2820}% + \special{pa 3450 2800}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2820}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3800 2780}% + \special{pa 3850 2800}% + \special{fp}% + \special{pa 3360 2253}% + \special{pa 3350 2200}% + \special{fp}% + \special{pa 3321 2245}% + \special{pa 3350 2200}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3240 2647}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 3279 2655}% + \special{pa 3250 2700}% + \special{fp}% + \special{pa 2250 2900}% + \special{pa 2250 2700}% + \special{pa 2650 2700}% + \special{pa 2650 2900}% + \special{pa 2250 2900}% + \special{fp}% + \rlap{\kern 2.450in\lower 2.841in\hbox to 0pt{\hss MTA\hss}}% + \special{pa 3000 2820}% + \special{pa 3050 2800}% + \special{fp}% + \special{pa 3000 2780}% + \special{pa 3050 2800}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2780}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2700 2820}% + \special{pa 2650 2800}% + \special{fp}% + \special{pa 2397 2690}% + \special{pa 2450 2700}% + \special{fp}% + \special{pa 2418 2657}% + \special{pa 2450 2700}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1703 2210}% + \special{pa 1650 2200}% + \special{fp}% + \special{pa 1682 2243}% + \special{pa 1650 2200}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 3.301in +} diff --git a/doc/uknet90/figure2.pic b/doc/uknet90/figure2.pic new file mode 100644 index 0000000..0e8dbf9 --- /dev/null +++ b/doc/uknet90/figure2.pic @@ -0,0 +1,15 @@ +.PS 5 +Inb: ellipse "Inbound" "Channel" + line <-> down right from Inb.se +Submit: ellipse "Submit" with .nw at last line .end + line <-> up right from Submit.ne + ellipse "UA" with .sw at last line .end + line <-> down left from Submit.sw +Qmgr: ellipse "QMGR" with .ne at last line .end + line <-> down right from Qmgr.se +Out: ellipse "Outbound" "Channel" with .nw at last line .end + line <-> down right from Submit.se +Que: box "Queue" with .nw at last line .end + (0, boxht/4) + line <-> dashed from Qmgr.e to Que.w + line <-> from 3/4 to Out.ne +.PE diff --git a/doc/uknet90/figure2.tex b/doc/uknet90/figure2.tex new file mode 100644 index 0000000..e5898bc --- /dev/null +++ b/doc/uknet90/figure2.tex @@ -0,0 +1,123 @@ +\catcode`@=11 +\expandafter\ifx\csname graph\endcsname\relax \alloc@4\box\chardef\insc@unt\graph\fi +\catcode`@=12 +\setbox\graph=\vtop{% + \baselineskip=0pt \lineskip=0pt \lineskiplimit=0pt + \vbox to0pt{\hbox{% + \special{pn 8}% + \special{ar 642 428 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 0.386in\hbox to 0pt{\hss Inbound\hss}}% + \rlap{\kern 0.642in\lower 0.552in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 1247 821}% + \special{pa 1096 731}% + \special{fp}% + \special{pa 1187 882}% + \special{pa 1096 731}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1801 1496}% + \special{pa 1952 1587}% + \special{fp}% + \special{pa 1861 1435}% + \special{pa 1952 1587}% + \special{fp}% + \special{ar 2406 1889 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 1.930in\hbox to 0pt{\hss Submit\hss}}% + \special{pa 2951 1435}% + \special{pa 2860 1587}% + \special{fp}% + \special{pa 3011 1496}% + \special{pa 2860 1587}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3625 882}% + \special{pa 3716 731}% + \special{fp}% + \special{pa 3565 821}% + \special{pa 3716 731}% + \special{fp}% + \special{ar 4170 428 642 427 0.000 6.283}% + \rlap{\kern 4.170in\lower 0.469in\hbox to 0pt{\hss UA\hss}}% + \special{pa 1861 2343}% + \special{pa 1952 2192}% + \special{fp}% + \special{pa 1801 2283}% + \special{pa 1952 2192}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1187 2897}% + \special{pa 1096 3048}% + \special{fp}% + \special{pa 1247 2957}% + \special{pa 1096 3048}% + \special{fp}% + \special{ar 642 3351 642 427 0.000 6.283}% + \rlap{\kern 0.642in\lower 3.392in\hbox to 0pt{\hss QMGR\hss}}% + \special{pa 1247 3744}% + \special{pa 1096 3653}% + \special{fp}% + \special{pa 1187 3805}% + \special{pa 1096 3653}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1801 4418}% + \special{pa 1952 4509}% + \special{fp}% + \special{pa 1861 4358}% + \special{pa 1952 4509}% + \special{fp}% + \special{ar 2406 4812 642 427 0.000 6.283}% + \rlap{\kern 2.406in\lower 4.770in\hbox to 0pt{\hss Outbound\hss}}% + \rlap{\kern 2.406in\lower 4.936in\hbox to 0pt{\hss Channel\hss}}% + \special{pa 3011 2283}% + \special{pa 2860 2192}% + \special{fp}% + \special{pa 2951 2343}% + \special{pa 2860 2192}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3565 2957}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3625 2897}% + \special{pa 3716 3048}% + \special{fp}% + \special{pa 3716 3690}% + \special{pa 3716 2834}% + \special{pa 5000 2834}% + \special{pa 5000 3690}% + \special{pa 3716 3690}% + \special{fp}% + \rlap{\kern 4.358in\lower 3.303in\hbox to 0pt{\hss Queue\hss}}% + \special{pa 1454 3302}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1457 3387}% + \special{pa 1284 3351}% + \special{fp}% + \special{pa 1284 3351}% + \special{pa 3716 3262}% + \special{da 0.050}% + \special{pa 3546 3311}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3543 3225}% + \special{pa 3716 3262}% + \special{fp}% + \special{pa 3640 3635}% + \special{pa 3716 3476}% + \special{fp}% + \special{pa 3574 3581}% + \special{pa 3716 3476}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 2936 4350}% + \special{pa 2860 4509}% + \special{fp}% + \special{pa 3002 4405}% + \special{pa 2860 4509}% + \special{fp}% + \kern 5.001in + }\vss}% + \kern 5.240in +} diff --git a/doc/uknet90/jpo.bib b/doc/uknet90/jpo.bib new file mode 100644 index 0000000..26455fe --- /dev/null +++ b/doc/uknet90/jpo.bib @@ -0,0 +1,65 @@ +% ``jpo'' bibliography database + + +@techreport{TP0.bridge, + author = "Julian P. Onions and Marshall T. Rose", + title = "{ISO-TP0 bridge between TCP and X.25}", + type = rfc, + number = 1086, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@inproceedings{Amigo.DL, + author = "Steve Benford and Julian Onions", + title = "{Pilot Distribution Lists -- Agents and Directories}", + booktitle= "{Proceedings, Third International Symposium on + Computer Message Systems}", + publisher= {North Holland}, + month = apr, + year = 1987, + note = {Munich, Germany}, +} + +@inproceedings{Amigo.DL.IMP, + author = "Steve Benford and Julian Onions and Manfred Bogen and + Bernd Wagner", + title = "{The Implementation of Amigo Distribution Lists}", + publisher= {North Holland}, + year = 1988, + month = apr, + booktitle= {Proceedings of the EUTECO Conference} +} + +@book{Amigo.MHSbook, + title = "{Distributed Group Communication -- The AMIGO + Information Model.}", + author = "Hugh Smith and Julian Onions and Steve Benford", + year = 1989, + publisher= "Ellis Horwood", + address = "Chichester, England" +} + +@inproceedings{Applications.Cookbook, + author = "Julian P. Onions and Marshall T. Rose", + title = "{The Application Cookbook}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{X400.Tutorial, + author = jpo, + title = "{Components of OSI: X.400}", + journal = connexions, + volume = 3, + number = 5, + month = may, + year = 1989, + pages = {2--8} +} diff --git a/doc/uknet90/lcustom.tex b/doc/uknet90/lcustom.tex new file mode 100644 index 0000000..5ae23b3 --- /dev/null +++ b/doc/uknet90/lcustom.tex @@ -0,0 +1,350 @@ +% LaTeX customization + + +\makeatletter % for a little while + + +% plain TeX compatibility + +\def\oldstyle{\xdef\@oldstyle{\the\textfont\@ne}\mit\@oldstyle} + + +% PhD-TeX compatibility + +\def\showsummary{% + \begingroup + \def\note##1{% + \ifcase\value{##1}no ##1s\or + 1 ##1\else + \the\value{##1} ##1s\fi + }% + \typeout{LaTeX summary: \note{figure}, \note{table}, \note{footnote}.}% + \endgroup +} + +\def\smaller{\footnotesize} + + +% Float Support + +\def\topfraction{0.85} +\def\textfraction{0.20} +\def\floatpagefraction{0.85} +\def\dbltopfraction{0.85} +\def\dblfloatpagefraction{0.85} + +\def\@tagskipcommand{\vskip .5\baselineskip} + +% \tagfigure*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads TPIC output in file figureFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagfigure{\@ifstar{\@stagfigure}{\@tagfigure}} +\def\@tagfigure{\@ifnextchar[{\@@tagfigure}{\@@tagfigure[t]}} +\def\@stagfigure{\@ifnextchar[{\@@stagfigure}{\@@stagfigure[t]}} + +\def\@@tagfigure[#1]#2{% + \@@@tagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} +\def\@@stagfigure[#1]#2{% + \@@@stagfigure[#1]{\input figure#2\relax\centerline{\box\graph}}} + + +% \tagdiagram*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FLOAT float options +% FILE reads LaTeX input in file diagramFILE +% CAPTION for list of figures +% LABEL for \ref and \pageref +\def\tagdiagram{\@ifstar{\@stagdiagram}{\@tagdiagram}} +\def\@tagdiagram{\@ifnextchar[{\@@tagdiagram}{\@@tagdiagram[t]}} +\def\@stagdiagram{\@ifnextchar[{\@@stagdiagram}{\@@stagdiagram[t]}} + +\def\@@tagdiagram[#1]#2{\@@@tagfigure[#1]{\input diagram#2\relax}} +\def\@@stagdiagram[#1]#2{\@@@stagfigure[#1]{\input diagram#2\relax}} + +\def\@@@tagfigure[#1]#2#3#4{% + \begin{figure}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure} +} + +\def\@@@stagfigure[#1]#2#3#4{% + \begin{figure*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small#2% + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{figure*} +} + + +% \tagtable*[FLOAT]{FILE}{CAPTION}{LABEL} +% * optional +% FILE read LaTeX input in file tableFILE +% FLOAT float options +% CAPTION for list of tables +% LABEL for \ref and \pageref +\def\tagtable{\@ifstar{\@stagtable}{\@tagtable}} +\def\@tagtable{\@ifnextchar[{\@@tagtable}{\@@tagtable[t]}} +\def\@stagtable{\@ifnextchar[{\@@stagtable}{\@@stagtable[t]}} + +\def\@@tagtable[#1]#2#3#4{% + \begin{table}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\textwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table} +} + +\def\@@stagtable[#1]#2#3#4{% + \begin{table*}[#1] + \hrule + \@tagskipcommand + \begin{minipage}\columnwidth + \small\input table#2\relax + \end{minipage} + \vskip .5\baselineskip plus .5\baselineskip + \begingroup + \setbox\z@=\hbox{#4}% + \ifdim\wd\z@>\z@ + \caption{#3}% + \label{#4}% + \else + \captcont{#3}% + \fi + \endgroup + \vskip 2pt + \hrule + \end{table*} +} + + +% Environments: + +% DESCRIBE - similar to DESCRIPTION, but indents extra on left margin of +% outer list + +\def\describe{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \ifnum\@listdepth=1 \advance\leftmargin by2em\fi + \let\makelabel\descriptionlabel}} +\let\enddescribe=\endlist + + +% Document style options: +% 10pt - Makes ten-point type the normal (default) type size +% draftnote - Customized draft option + +\@namedef{ds@10pt}{\def\@ptsize{0}} %%% for orthogonality + + +\newif\ifdraft \draftfalse + +\def\draftstring{{\ifdraft \tt Draft\fi}} + +\def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today\ with \fmtname\ v\fmtversion + \else + Draft \versiontag/ of \versiondate/ + \fi + \endgroup + \fi +} + +\def\versiontag/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}%6 + \versiontag/% +} +\def\versiondate/{% + \gdef\versiontag/{\#0}% + \gdef\versiondate/{\today}% + \@input{\jobname.vrsn}% + \versiondate/% +} + +\def\ds@draftnote{% + \drafttrue + \@ifundefined{ds@draft}{}{\ds@draft}% + \def\ps@plain{% + \let\@mkboth=\@gobbletwo + \def\@oddhead{\draftext\hfil}% + \def\@oddfoot{\draftstring\hfil\rm\thepage\hfil\draftstring}% + \def\@evenhead{\hfil\draftext}% + \let\@evenfoot=\@oddfoot + }% + \let\ps@@headings=\ps@headings + \def\ps@headings{% + \ps@@headings + \def\@oddfoot{\draftext\hfil}% + \def\@evenfoot{\hfil\draftext}% + }% +} + + +% Page Styles + +% \pagestyle{myfootings} similar to the myheadings command but also permits +% the user to define foot information as well as head information +% \markleftfoot{left_foot} specifies the foot for odd-numbered +% pages +% \markrightfoot{right_foot} specifies the foot for even-numbered +% pages +% N.B. DOES NOT USE MARKS TO ACCOMPLISH THIS, OWING TO CONFLICT WITH HEADING +% ROUTINES + +\def\ps@myfootings{\ps@myheadings} + +\def\markleftfoot#1{\def\@evenfoot{\hbox{}\sl#1\hfil}} +\def\markrightfoot#1{\def\@oddfoot{\hfil\sl#1\hbox{}}} + + +% \pagestyle{reprint} similar to plain page style in draft mode + +\let\reprintext=\draftext +\let\reprintstring=\draftstring + +\def\ps@reprint{% + \def\draftext{% + \ifdraft + \begingroup + \tt + \ifodd\c@page + \LaTeX set \today + \else + Draft \versiontag/ + \fi + \endgroup + \fi + }% + \def\@oddhead{\reprintext\hfil\draftext}% + \def\@oddfoot{\reprintstring\hfil\rm\thepage}% + \def\@evenhead{\draftext\hfil\reprintext}% + \def\@evenfoot{\rm\thepage\hfil\reprintstring}% +} + + +% The Title + +\def\title#1{% + \gdef\@title{#1}% + \gdef\banner{% + \newpage\setcounter{page}{1}% + \begin{center}\Large#1\end{center}% + }% +} + + +% Miscellany + +\def\implies{\quad\supset\ } + +\def\tdots{\ldots\thinspace} + +\def\boxit#1{\fbox{\sc#1}} + +\def\note#1{\ifdraft\marginpar{\tt#1}\fi} + + +% Fractions (from The TUGboat v6 n1, 1985) + +\def\myfrac#1/#2{% + \leavevmode\kern.1em + \raise.5ex\mbox{\the\scriptfont\z@ #1}\kern-.1em + /\kern-.15em\lower.25ex\mbox{\the\scriptfont\z@ #2}% +} + + +% Trademarks... + +\input trademark + + +% Continuation Captions... + +\input captcont.sty + + +% Startup + +\xdef\today{% + \ifcase\month + \number\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\else + \number\month\fi + \space\number\day, {\noexpand\mit\number\year}% +} + +\begingroup + \count0=\time + \count1=\count0 + \divide\count0 by 60 + \count2=\count0 + \multiply\count0 by 60 + \advance\count1 by -\count0 + \ifnum\count2>11 + \ifnum\count2>12 \advance\count2 by -12\fi + \def\ampm{pm}% + \else + \ifnum\count2=0 \advance\count2 by 12\fi + \def\ampm{am}% + \fi + \xdef\daytime{% + \ifnum\count2<10 0\fi \the\count2:% + \ifnum\count1<10 0\fi \the\count1 + \ampm + }% +\endgroup + + +\makeatother % back to normal diff --git a/doc/uknet90/make b/doc/uknet90/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/uknet90/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/uknet90/networking.bib b/doc/uknet90/networking.bib new file mode 100644 index 0000000..22fbe33 --- /dev/null +++ b/doc/uknet90/networking.bib @@ -0,0 +1,1768 @@ +% ``Networking'' bibliography database for BiB-TeX + + +@techreport{ARP, + author = "David C. Plummer", + title = "{An Ethernet Address Resolution Protocol}", + type = rfc, + number = 825, + institution= nic, + address = sri, + month = sep, + year = 1982 +} + +@techreport{ARPA.MHS, + author = "Stephen E. Kille", + title = "{Mapping between X.400 and RFC822}", + type = rfc, + number = 987, + institution= nic, + address = sri, + month = jun, + year = 1986, + note = {Also available as UCL Technical Report number~120 + and Mailgroup Note number~19} +} + +@techreport{ARPA.mapping.MHS, + author = mtr, + title = "{Mapping Service Elements between ARPA and MHS}", + institution= nrtc, + month = nov, + year = 1985, + note = {Unpublished (superceded by IFIP WG6.5 report)} +} + +@techreport{Assigned.Numbers, + author = "Joyce K. Reynolds", + title = "{Assigned Numbers}", + type = rfc, + number = 1010, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@incollection{ARM, + author = "Michael A. Padlipksy", + title = "{A Perspective on the ARPANET Reference Model}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 5, + pages = {89--115}, + publisher= {Prentice-hall}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as Internet Request for Comments 871} +} + +@inproceedings{ASDC.DIPS, + author = "Jaime Delgado and Manuel Medina", + title = "{Use of the Abstract Service Definition + Conventions for Distributed Information + Processing Systems Specification}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {217--231}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{Building.Applications, + author = mtr, + title = "{Building Distributed Applications in an OSI + Framework}", + journal = connexions, + volume = 2, + number = 3, + month = mar, + year = 1988, + pages = {2--7}, + note = {ISSN 0894-5926} +} + +@inproceedings{Applications.Cookbook, + author = "Julian P. Onions and Marshall T. Rose", + title = "{The Application Cookbook}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {247--265}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@book{Carl.Faberge, + author = "Alexander von Solodkoff", + title = "{The Art of Carl Faberg\'{e}}", + publisher= {Crown Publishers, Inc.}, + address = {New York}, + year = 1988, + note = {ISBN 0--517--571242} +} + +@book{Masterpieces.Faberge, + author = "Alexander von Solodkoff", + editor = "Chrisopher Forbes", + title = "{Masterpieces from the House of Faberg\'{e}}", + publisher= {Harry N.~Abrams, Inc.}, + address = {New York}, + year = 1989, + note = {ISBN 0--8109--8089--4} +} + +@misc{CCITT.ACS.Service, + key = {CCITT}, + title = "{Association Control Service Definition for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.217} +} + +@misc{CCITT.ACS.Protocol, + key = {CCITT}, + title = "{Association Control Protocol Specification for + CCITT Applications}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.227} +} + +@misc{CCITT.Directory, + key = {CCITT}, + title = "{The Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.500} +} + +@misc{CCITT.MHS, + key = {CCITT}, + title = "{Message Handling: System and Service Overview}", + year = 1988, + howpublished= ccitt, + note = {Recommendation X.400} +} + +@misc{CCITT.TP.Service, + key = {CCITT}, + title = "{Transport Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.214} +} + +@misc{CCITT.TP.Protocol, + key = {CCITT}, + title = "{Transport Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Service, + key = {CCITT}, + title = "{Session Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.224} +} + +@misc{CCITT.SP.Protocol, + key = {CCITT}, + title = "{Session Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.225} +} + +@misc{CCITT.PP.Service, + key = {CCITT}, + title = "{Presentation Service Definition for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.216} +} + +@misc{CCITT.PP.Protocol, + key = {CCITT}, + title = "{Presentation Protocol Specification for Open Systems + Interconnection (OSI) for CCITT Applications}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.226} +} + +@misc{CCITT.PP.Syntax, + key = {CCITT}, + title = "{Specification of Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.208} +} + +@misc{CCITT.PP.Encoding, + key = {CCITT}, + title = "{Specification of Basic Encoding + Rules for Abstract Syntax Notation One}", + mon = dec, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.209} +} + +@misc{CCITT.ROS.Service, + key = {CCITT}, + title = "{Remote Operations: Model, Notation and Service + Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.219} +} + +@misc{CCITT.ROS.Protocol, + key = {CCITT}, + title = "{Remote Operations: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.229} +} + +@misc{CCITT.RTS.Service, + key = {CCITT}, + title = "{Reliable Transfer: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.218} +} + +@misc{CCITT.RTS.Protocol, + key = {CCITT}, + title = "{Reliable Transfer: Protocol Specification}", + month = mar, + year = 1988, + howpublished= ccitt, + note = {Recommendation X.228} +} + +@techreport{CMOT, + author = "Unni Warrier and Larry Besaw", + title = "{Common Management Information Services and + Protocol over TCP/IP (CMOT)}", + type = rfc, + number = 1095, + institution= nic, + address = sri, + month = apr, + year = 1989 +} + +@book{Computer.Networks, + author = "Andrew S. Tanenbaum", + title = "{Computer Networks}", + publisher= {Prentice-hall}, + series = {Prentice Hall Software Series}, + year = 1988, + note = {ISBN 0--13--162959--X} +} + +@inproceedings{Congestion.Control, + author = "Van Jacobson", + title = "{Congestion Avoidance and Control}", + booktitle= "{Proceedings, SIGCOMM '88 Workshop}", + pages = {314--329}, + organization= {ACM SIGCOMM}, + publisher= {ACM Press}, + month = aug, + year = 1988, + note = {Stanford, CA} +} + +@techreport{Courier.BSD, + author = "Eric C. Cooper", + title = "{Writing Distributed Programs with Courier}", + institution= {Computer Science Division~---~EECS}, + address = {University of California, Berkeley}, + month = mar, + year = 1982 +} + +@techreport{DNS, + author = "Paul V. Mockapetris", + title = "{Domain Names --- Concepts and Facilities}", + type = rfc, + number = 1033, + institution= nic, + address = sri, + month = Nov, + year = 1987 +} + +@misc{DoD.OSI, + key = {DDN}, + title = "{The Department of Defense Open Systems + Interconnection (OSI) Implementation Strategy}", + month = may, + year = 1988, + note = {The MITRE Corporation} +} + +@misc{ECMA.ROS, + key = {ECMA}, + title = "{Remote Operations: Concepts, Notation and + Connection-Oriented Mappings}", + month = dec, + year = 1985, + note = {ECMA TR/31} +} + +@techreport{EON, + author = "Robert A. Hagens and Nancy E. Hall and + Marshall T. Rose", + title = "{Use of the DARPA/NSF Internet as a Subnet for + Experimentation with the OSI Network Layer}", + type = rfc, + number = 1070, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@techreport{EON.addressing, + author = "Ross Callon and Hans-Werner Braun", + title = "{Guidelines for the use of Internet-IP + addresses in the ISO Connectionless-Mode Network + Protocol}", + type = rfc, + number = 1069, + institution= nic, + address = sri, + month = feb, + year = 1989 +} + +@article{Fletcher.Checksum, + author = "John G. Fletcher", + title = "{An Arithmetic Checksum for Serial Transmissions}", + journal = ieeecom, + volume = {COM--30}, + number = 1, + month = jan, + year = 1982 +} + +@article{Fletcher.Pitfalls, + author = "Anastase Nakassis", + title = "{Fletcher's Error Detection Algorithm: How to + implement it efficiently and how to avoid the most + common pitfalls}", + journal = ccr, + volume = 18, + number = 5, + month = oct, + year = 1988, + pages = {63--68} +} + +@techreport{FTP, + key = {FTP}, + author = {Jon B. Postel}, + title = "{File Transfer Protocol}", + type = rfc, + number = 959, + institution= nic, + address = sri, + month = oct, + year = 1985, + note = {See also \milstd/ 1780} +} + +@incollection{Gateways.Heffalumps, + author = "Michael A. Padlipksy", + title = "{Gateways, Architectures, and Heffalumps}", + booktitle= "{The Elements of Networking Style and Other Essays + and Animadversions on the Art of Intercomputer + Networking}", + chapter = 10, + pages = {167--176}, + publisher= {Prentice-hall}, + address = {Englewood Cliffs, New Jersey}, + year = 1985, + note = {Also available as Internet Request for Comments 875} +} + +@misc{US.GOSIP, + key = {USGOSIP}, + title = "{U.S.~Government Open Systems Interconnection + Profile (GOSIP)}", + month = aug, + year = 1988, + note = {U.S.~Federal Information Processing Standards + Publication~146} +} + +@misc{UK.GOSIP, + key = {UKGOSIP}, + title = "{U.K.~Government OSI Profile}", + month = jan, + year = 1988, + note = {Version~3.0} +} + +@techreport{HEMS, + author = "Craig Partridge and Glenn Trewit", + title = "{The High-Level Entity Management System}", + type = rfc, + number = {1021--1024}, + institution= nic, + address = sri, + month = oct, + year = 1987 +} + +@article{Host.Multicasting, + author = "Stephen E. Deering", + title = "{Multicast Routing in Internetworks and + Extended LANs}", + journal = ccr, + volume = 18, + number = 4, + month = aug, + year = 1988, + pages = {55--64} +} + +@techreport{Interim.Addresses, + author = "Stephen E. Kille", + title = "{An interim approach to use of Network Addresses}", + type = "Research Note", + number = {RN/89/13}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@article{ISODE.Horizontal, + author = mtr, + title = "{ISODE: Horizontal Integration in Networking}", + journal = connexions, + volume = 1, + number = 1, + month = may, + year = 1987, + pages = {8--12}, + note = {ISSN 0894-5926} +} + +@techreport{IP, + key = {IP}, + author = {Jon B. Postel}, + title = "{Internet Protocol}", + type = rfc, + number = 791, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1777} +} + +@misc{IP.Requirements, + key = {NSF}, + title = "{Requirement for Internet Gateways~---~Draft}", + month = may, + year = 1986, + note = {Internet Request for Comments 985, prepared by + the Gateway Requirements Subcommitee of the National + Science Foundation's Network Technical Advisory Group, + David L.~Mills, chair} +} + +@misc{ISO.ALS, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Application Layer Structure}", + month = mar, + year = 1987, + howpublished= iso/iec, + note = {Draft Proposal 9534} +} + +@misc{ISO.ACS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Service Definition for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8649} +} + +@misc{ISO.ACS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~--~Protocol Specification for the + Association Control Service Element}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Revised Final Text of Draft International + Standard 8650} +} + +@misc{ISO.Directory, + key = {ISO}, + title = "{Information Processing Systems~---~Open + Systems Interconnection~---~The + Directory~---~Overview of Concepts, Models, + and Service}", + month = dec, + year = 1988, + howpublished= iso/iec, + note = {International Standard 9594-1} +} + +@misc{ISO.DLP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Data Link Service Definition}", + month = dec, + year = 1987, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8886--2} +} + +@misc{ISO.LAN, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802} +} + +@misc{ISO.LAN.LLC, + key = {ISO}, + title = "{Information Processing Systems~---~Local Area + Networks~---~Logical Link Control}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8802--2} +} + +@misc{ISO.FTAM, + key = {ISO}, + title = "{Information Processing Systems~---~File + Transfer, Access, and Management}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8571} +} + +@misc{ISO.LAN.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 over Local Area + Networks to Provide the OSI Connection-mode + Network Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8881} +} + +@misc{ISO.MOTIS, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~MOTIS~---~Message Handling: + System and Service Overview}", + month = dec, + year = 1988, + howpublished= iso/iec, + note = {International Standard 10021-1} +} + +@misc{ISO.NP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service Definition}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348} +} + +@misc{ISO.NP.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 1: Connectionless-mode + Transmission}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 1} +} + +@misc{ISO.NP.Addressing, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Network Service + Definition~---~Addendum 2: Network Layer Addresisng}", + month = apr, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8348/AD 2} +} + +@misc{ISO.NP.CLNP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol for providing the + Connectionless-mode Network Service and Provision + of Underlying Service}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {Consolidated Final Text of Draft International + Standard 8473} +} + +@misc{ISO.NP.X25, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Use of X.25 to Provide the + OSI Connection-mode Network Service}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8878} +} + +@misc{ISO.X25.PLP, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~X.25 Packet Level Protocol}", + month = sep, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8208} +} + +@misc{ISO.X25.LAPB, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~High-level Data Link Control + Procedures~---~Description of the X.25 + LAPB-compatible DTE Data Link Procedures}", + month = dec, + year = 1986, + howpublished= iso/iec, + note = {International Standard 7776} +} + +@misc{ISO.NP.IONL, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Internal Organization of + the Network Layer}", + month = may, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8648} +} + +@misc{ISO.NS.Principles, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 1: General Principles}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--1} +} + +@misc{ISO.NS.CONS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 2: Provision and Support of + the connection-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--2} +} + +@misc{ISO.NS.CLNS, + key = {ISO}, + title = "{Information Processing Systems~---~Data + Communications~---~Protocol Combinations to + Provide and Support the OSI Network + Service~---~Part 3: Provision and Support of + the connectionless-mode network service}", + month = jun, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 8880--3} +} + +@misc{ISO.PP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Service Definition}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8822} +} + +@misc{ISO.PP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Connection Oriented Presentation + Protocol Specification}", + month = apr, + year = 1988, + howpublished= iso/iec, + note = {Final Text of Draft International Standard 8823} +} + +@misc{ISO.PP.Syntax, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Abstract Syntax + Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8824} +} + +@misc{ISO.PP.Encoding, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Specification of Basic Encoding + Rules for Abstract Syntax Notation One (ASN.1)}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8825} +} + +@misc{ISO.ASN1.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8824/DAD 1} +} + +@misc{ISO.BER.Extensions, + key = {ISO}, + title = "{Information Processing~---~Open Systems + Interconnection~---~Abstract Syntax + Notation One (ASN.1)~---~Draft Addendum 1: + Extensions to ASN.1 Basic Encoding Rules}", + mon = dec, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8825/DAD 1} +} + +@misc{ISO.ROS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~1: Model, Notation and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-1} +} + +@misc{ISO.ROS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Remote Operations + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9072-2} +} + +@misc{ISO.RTS.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~1: Model and Service Definition}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-1} +} + +@misc{ISO.RTS.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Text + Communication~---~Reliable Transfer + Part~2: Protocol Specification}", + month = mar, + year = 1988, + howpublished= iso/iec, + note = {Working Document for International Standard 9066-2} +} + +@misc{ISO.SP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8326} +} + +@misc{ISO.SP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {International Standard 8327} +} + +@misc{ISO.SS.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 1: + Session Symmetric Synchronization for the + Session Service}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 1} +} + +@misc{ISO.SP.Symmetric, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 1: + Session Symmetric Synchronization for the + Session Protocol}", + month = jul, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 1} +} + +@misc{ISO.SS.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Service Definition~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8326/DAD 2} +} + +@misc{ISO.SP.UserData, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Basic Connection Oriented + Session Protocol Specification~---~Addendum 2: + Incorporation of Unlimited User Data}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft Addendum 8327/DAD 2} +} + +@misc{ISO.TP.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Service Definition}", + mon = jun, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8072} +} + +@misc{ISO.TP-CL.Service, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Service + Definition~---~Addendum 1: Connectionless-mode + Transmission}", + mon = dec, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8072/AD 1} +} + +@misc{ISO.TP.Protocol, + key = {ISO}, + title = "{Information Processing Systems~---~Open Systems + Interconnection~---~Transport Protocol Specification}", + mon = jul, + year = 1986, + howpublished= iso/iec, + note = {International Standard 8073} +} + +@misc{ISO.VT, + key = {ISO}, + title = "{Information Processing Systems~---~Virtual Terminal + Service: Basic Class}", + month = aug, + year = 1987, + howpublished= iso/iec, + note = {Draft International Standard 9040} +} + +@article{ISO.on.DDN, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{OSI Transport Services on top of the TCP}", + journal = cn/isdn, + volume = 12, + number = 3, + year = 1986, + note = {Also available as NRTC Technical Paper \#700.} +} + +@article{Internet.Architecture, + author = "Vinton G. Cerf and Edward A. Cain", + title = "{The DoD Internet Architecture Model}", + journal = cn/isdn, + volume = 7, + number = 10, + month = oct, + year = 1983, + pages = {307--318} +} + +@techreport{Internet.NM, + author = "Vinton G. Cerf", + title = "{IAB Recommendations for the Development of + Internet Network Management Standards}", + type = rfc, + number = 1052, + institution= nic, + address = sri, + month = apr, + year = 1988 +} + +@techreport{Internet.NM-2, + author = "Vinton G. Cerf", + title = "{Report of the Second Ad Hoc Network Management + Review Group}", + type = rfc, + number = 1109, + institution= nic, + address = sri, + month = aug, + year = 1989 +} + +@techreport{Internet.SMI, + author = "Marshall T. Rose and Keith McCloghrie", + title = "{Structure and Identification of Management + Information for TCP/IP based internets}", + type = rfc, + number = 1065, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@techreport{Internet.MIB, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Management Information Base Network Management + of TCP/IP based internets}", + type = rfc, + number = 1066, + institution= nic, + address = sri, + month = aug, + year = 1988 +} + +@article{Interoperability.Testing, + author = mtr, + title = "{Interoperability Testing: + The Final Test of Open Systems}", + journal = connexions, + volume = 3, + number = 7, + month = jul, + year = 1989, + pages = {12--14}, + note = {ISSN 0894-5926} +} + +@inproceedings{Layers, + author = "Danny Cohen and Jon B. Postel", + title = "{The ISO Reference Model and Other Protocol + Architectures}", + booktitle= {Proceedings of the IFIP Congress}, + year = 1983, + note = {Paris, France} +} + +@inproceedings{Management.TCP-IP, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + booktitle= "{Proceedings of the Digital Equipment Computer + Users Society}", + pages = {167--169}, + month = "Fall", + year = 1988 +} + +@article{Management.TCP-IP.Again, + author = "Keith McCloghrie and Marshall T. Rose", + title = "{Network Management of TCP/IP-based Internets}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {3--9}, + note = {ISSN 0894-5926} +} + +@misc{MHS, + key = {CCITT}, + title = "{Message Handling Systems: System Model-Service + Elements}", + month = oct, + year = 1984, + note = ccitt +} + +@misc{MHS.Elements, + key = {CCITT}, + title = "{Message Handling Systems: Basic Service Elements + and Optional User Facilities}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.401} +} + +@misc{MHS.Conversion, + key = {CCITT}, + title = "{Message Handling Systems: Encoded Information Type + Conversion Rules}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.408} +} + +@misc{MHS.Notation, + key = {CCITT}, + title = "{Message Handling Systems: Presentation Transfer + Syntax and Notation}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.409} +} + +@misc{MHS.RTS, + key = {CCITT}, + title = "{Message Handling Systems: Remote Operations and + Reliable Transfer Server}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.410} +} + +@misc{MHS.P1, + key = {CCITT}, + title = "{Message Handling Systems: Message Transfer Layer}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.411} +} + +@misc{MHS.P2, + key = {CCITT}, + title = "{Message Handling Systems: Interpersonal Messaging + User Agent}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.420} +} + +@misc{MHS.Teletex, + key = {CCITT}, + title = "{Message Handling Systems: Access Protocol for + Teletex Terminals}", + month = oct, + year = 1984, + howpublished= ccitt, + note = {Recommendation X.430} +} + +@techreport{NETBLT, + author = "David D. Clark and Mark L. Lambert and Lixia Zhang", + title = "{NETBLT: A Bulk Data Transfer Protocol}", + type = rfc, + number = 998, + institution= nic, + address = sri, + month = mar, + year = 1987 +} + +@manual{NFS, + title = "Network File System Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@misc{NRC.Report, + key = {NRC}, + title = "{Transport Protocols for Department of Defense Data + Networks}", + howpublished= {National Academy Press}, + month = feb, + year = 1985, + note = {Report to the Department of Defense and + the National Bureau of Standards by the Committee on + Computer-Computer Communication Protocols, Board on + Telecommunications and Computer Applications + Commission on Engineering and Technical Systems, + National Research Council, + C. Chaplin Cutler, chair + (Executive Summary available as Internet Request + for Comments 939)} +} + +@article{Netman.Demo, + author = "George Marshall", + title = "{The NetMan Demonstration at INTEROP '88}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {20}, + note = {ISSN 0894-5926} +} + +@article{NSFnet.Backbone, + author = "David L. Mills and Hans-Werner Braun", + title = "{The NSFNET Backbone Network}", + journal = ccr, + volume = 17, + number = 5, + month = aug, + year = 1987, + pages = {191--196} +} + +@techreport{Official.Protocols, + author = "{IAB}", + title = "{IAB Official Protocol Standards}", + type = rfc, + number = 1100, + institution= nic, + address = sri, + month = apr, + year = 1989, + note = {Internet Activities Board} +} + +@article{OSI.ALS, + author = mtr, + title = "{The Application Layer Structure}", + journal = connexions, + volume = 4, + number = 1, + month = jan, + year = 1990, + pages = {2--9}, + note = {ISSN 0894-5926} +} + +@misc{OSI.Model, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Basic Reference Model}", + mon = oct, + year = 1984, + howpublished= iso/iec, + note = {Interational Standard 7498} +} + +@misc{OSI.CL-Model, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Basic Reference + Model~---~Addendum 1: Connectionless-mode + Transmission}", + mon = sep, + year = 1987, + howpublished= iso/iec, + note = {Interational Standard 7498/AD 1} +} + +@misc{OSI.Conventions, + key = {OSI}, + title = "{Information Processing Systems~---~Open Systems + Interconnection: Service Conventions}", + mon = sep, + year = 1987, + howpublished= iso/iec, + note = {Technical Report 8509} +} + +@misc{OSI.Implementors, + key = {NIST}, + title = "{Stable Implementation Agreements for Open + Systems Interconnection Protocols}", + month = dec, + year = 1988, + note = {Version 2, Edition 1} +} + +@article{OSI.POSIX, + author = mtr, + title = "{OSI Protocols within an openly available, + POSIX-conformant, Berkeley UNIX environment}", + journal = connexions, + volume = 2, + number = 10, + month = oct, + year = 1988, + pages = {11--13}, + note = {ISSN 0894-5926} +} + +@book{Open.Book, + author = mtr, + title = "{The Open Book: A Practical Perspective on Open + Systems Interconnection}", + publisher= {Prentice-hall}, + year = 1990, + note = {ISBN 0--13--643016--3} +} + +@inproceedings{PP.MTA, + author = "Stephen E. Kille", + title = "{PP~---~A Message Transfer Agent}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {115--128}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@article{Protocol.Conversion, + author = "Green, Jr., Paul E.", + title = "{Protocol Conversion}", + journal = ieeecom, + volume = {COM--34}, + number = 3, + month = mar, + year = 1986, + pages = {257--268} +} + +@techreport{PSAP.on.TCP.old, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = idea, + number = 17, + institution= nic, + address = sri, + month = mar, + year = 1988 +} + +@techreport{PSAP.on.TCP, + author = mtr, + title = "{ISO Presentation Services on top of + TCP/IP-based internets}", + type = rfc, + number = 1085, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{QUIPU.Design, + author = "Stephen E. Kille", + title = "{The Design of QUIPU}", + type = "Research Note", + number = {RN/89/19}, + institution= {Department of Computer Science}, + address = ucl, + month = mar, + year = 1989 +} + +@inproceedings{QUIPU.Directory, + author = "Stephen E. Kille", + title = "{The QUIPU Directory Service}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {173--185}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} + +@techreport{RawPacket, + author = mtr, + title = "{Low Tech Connections in to the ARPA Internet: + The RawPacket Split-Gateway}", + number = 216, + institution= ics, + address = uci, + month = feb, + year = 1984 +} + +@techreport{RFC822, + author = "David H. Crocker", + title = "{Standard for the Format of ARPA Internet Text + Messages}", + type = rfc, + number = 822, + institution= nic, + address = sri, + month = aug, + year = 1982 +} + +@article{Session.Hints, + author = "Fausto Caneschi", + title = "{Hints for the Interpretation of the ISO + Session Layer}", + journal = ccr, + volume = 16, + number = 4, + month = aug, + year = 1986, + pages = {34--72} +} + +@techreport{Silly.Window, + author = "David D. Clark", + title = "{Window and Acknowledgement Strategy in TCP}", + type = rfc, + number = 813, + institution= nic, + address = sri, + month = jul, + year = 1982 +} + +@techreport{SMTP, + key = {SMTP}, + author = {Jon B. Postel}, + title = "{Simple Mail Transfer Protocol}", + type = rfc, + number = 821, + institution= nic, + address = sri, + month = aug, + year = 1982, + note = {See also \milstd/ 1781} +} + +@manual{SNA, + title = "{Systems Network Architecture Technical Overview}", + key = {IBM}, + organization= {International Business Machines, Incorporated, + Data Processing Division}, + address = {White Plains, New York}, + month = mar, + year = 1982, + note = {Document Number GC30--3073--0} +} + +@techreport{SGMP, + author = "James R. Davin and Jeffrey D. Case and Mark S. + Fedor and Martin L. Schoffstall", + title = "{A Simple Gateway Monitoring Protocol}", + type = rfc, + number = 1028, + institution= nic, + address = sri, + month = nov, + year = 1987 +} + +@inproceedings{SNA.convert.XNS, + author = "Kenneth O. Zoline and William P. Lidinksy", + title = "{An Approach for Interconnecting SNA and XNS + Networks}", + booktitle= "{Proceedings, Ninth Data Communications Symposium}", + pages = {184--198}, + organization= {ACM Special Interest Group on Communications}, + publisher= {IEEE Computer Society Press}, + month = sep, + year = 1985 +} + +@techreport{SNMP, + author = "Jeffrey D. Case and Mark S. Fedor and Martin L. + Schoffstall and James R. Davin", + title = "{A Simple Network Management Protocol}", + type = rfc, + number = 1098, + institution= nic, + address = sri, + month = apr, + year = 1989 +} + +@article{SNMP.Design, + author = "Jeffrey D. Case and James R. Davin + and Mark S. Fedor and Martin L. Schoffstall", + title = "{Network Management and the Design of SNMP}", + journal = connexions, + volume = 3, + number = 3, + month = mar, + year = 1989, + pages = {22--26}, + note = {ISSN 0894-5926} +} + +@techreport{String.Addresses, + author = "Stephen E. Kille", + title = "{A string encoding of Presentation Address}", + type = "Research Note", + number = {RN/89/14}, + institution= {Department of Computer Science}, + address = ucl, + month = feb, + year = 1989 +} + +@techreport{TCP, + key = {TCP}, + author = {Jon B. Postel}, + title = "{Transmission Control Protocol}", + type = rfc, + number = 793, + institution= nic, + address = sri, + month = sep, + year = 1981, + note = {See also \milstd/ 1778} +} + +@article{TCP.convert.ISO, + author = "Inge Groenbaek", + title = "{Conversion Between the TCP and ISO Transport + Protocols as a Method of Achieving Interoperability + Between Data Communication Systems}", + journal = jsac, + volume = {SAC-4}, + number = 2, + month = mar, + year = 1986, + pages = {288--296} +} + +@article{TCP.convert.OSI, + author = "Michael Witt", + title = "{Moving from DoD to OSI Protocols: A First Step}", + journal = ccr, + volume = 16, + number = 2, + month = {April/May}, + year = 1986, + pages = {1--7} +} + +@inproceedings{TCP.transition.ISO, + author = "Irene Hu", + title = "{Managing the Transition from TCP/IP to ISO + Protcols}", + booktitle= "{Proceedings, Uniforum 1987 Conference}", + pages = {59--74}, + organization= {/usr/group}, + month = jan, + year = 1987 +} + +@article{TCP.wars, + author = mtr, + title = "{Comments on ``Comments on `Congestion Control + in TCP/IP Internetworks'\,''}", + journal = ccr, + volume = 15, + number = 5, + month = {October/November}, + year = 1985, + pages = {2--9} +} + +@inproceedings{TCP.losing.MILSTD, + author = "Deepinder P. Sidhu and Thomas P. Blumer", + title = "{Some Problems with the Specification of the + Military Standard Transmission Control Protocol}", + booktitle= {Proceedings, Fourth International Workshop on Protocol + Specification, Testing, and Verification}, + editor = "Y.~Yemini and et.~al.", + pages = {375--381}, + organization= {IFIP WG 6.1}, + publisher= {North-Holland Publishing Company}, + month = jun, + year = 1985, + note = {Skytop Lodge, Pennsylvania} +} + +@inproceedings{RTT.Improve, + author = "Phil Karn and Craig Partridge", + title = "{Improving Round-Trip Time Estimates in + Reliable Transport Protocols}", + booktitle= "{Proceedings, SIGCOMM '87 Workshop}", + pages = {2--7}, + organization= {ACM SIGCOMM}, + publisher= {ACM Press}, + month = aug, + year = 1987, + note = {Stowe, Vermont} +} + +@book{Standards.Process, + author = "Carl F. Cargill", + title = "{Information Technology Standardization: + Theory, Process, and Organizations}", + publisher= {Digital Press}, + address = {Maynard, Massachusetts}, + year = 1989, + note = {ISBN 1--55558--022--X} +} + +@techreport{TELNET, + key = {TELNET}, + author = {Jon B. Postel}, + title = "{TELNET Protocol Specification}", + type = rfc, + number = 854, + institution= nic, + address = sri, + month = may, + year = 1983, + note = {See also \milstd/ 1782} +} + +@techreport{TP0.bridge, + author = "Julian P. Onions and Marshall T. Rose", + title = "{ISO-TP0 bridge between TCP and X.25}", + type = rfc, + number = 1086, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@article{Transition.and.Coexistence, + author = mtr, + title = "{Transition and coexistence for TCP/IP to OSI}", + journal = connexions, + volume = 2, + number = 12, + month = dec, + year = 1988, + pages = {2--5}, + note = {ISSN 0894-5926} +} + +@article{Transition.and.Coexistence.Strategies, + author = mtr, + title = "{Transition and Coexistence Strategies for + TCP/IP to OSI}", + journal = jsac, + volume = {COM--37}, + year = 1989, + note = {(to appear)} +} + +@article{Transport.Bridges, + author = mtr, + title = "{Transport-level ``bridges'' from TCP/IP to OSI/ISO}", + journal = connexions, + volume = 2, + number = 1, + month = jan, + year = 1988, + pages = {2--6}, + note = {ISSN 0894-5926} +} + +@techreport{TSAP.on.TCP.old, + author = "Dwight E. Cass and Marshall T. Rose", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 983, + institution= nic, + address = sri, + month = apr, + year = 1986 +} + +@techreport{TSAP.on.TCP, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{ISO Transport Services on top of the TCP}", + type = rfc, + number = 1006, + institution= nic, + address = sri, + month = may, + year = 1987 +} + +@techreport{UDP, + key = {UDP}, + author = {Jon B. Postel}, + title = "{User Datagram Protocol}", + type = rfc, + number = 768, + institution= nic, + address = sri, + month = aug, + year = 1980 +} + +@inproceedings{Upcalls, + author = "David D. Clark", + title = "{The Structuring of systems using Upcalls}", + booktitle= "{Proceedings, Ninth Symposium on Operating + System Principles}", + pages = {171--180}, + month = dec, + year = 1985, + note = {Orcas Island, Washington} +} + +@misc{White.Book, + author = "{JNT}", + title = "{Transition to OSI Standards}", + howpublished= {U.K.~Joint Network Team}, + month = jul, + year = 1987, + note = {Final Report of the Academic Community OSI + Transition Group} +} + +@techreport{Whois, + key = {Whois}, + author = {Ken Harrenstien and Mary K. Stahl and Elizabeth J. + Feinler}, + title = "{NICNAME/WHOIS}", + type = rfc, + number = 954, + institution= nic, + address = sri, + month = oct, + year = 1985 +} + +@article{X.window, + author = "Robert W. Scheifler and Jim Gettys", + title = "{The X Window System}", + journal = tog, + volume = 5, + number = 2, + month = apr, + year = 1986, + pages = {79--109}, + note = {Special Issue on User Interface Software} +} + +@manual{XDR, + title = "External Data Representation Protocol Specification", + key = {SMI}, + organization= {Sun Microsystems, Inc.}, + address = {Mountain View, California}, + month = feb, + year = 1986, + note = {Part Number 800-1324-03} +} + +@inproceedings{XDR.Comparison, + author = "Craig Partridge and Marshall T. Rose", + title = "{A Comparison of External Data Formats}", + booktitle= "{Proceedings, Fourth International Symposium on + Computer Message Systems}", + editor = "Einar Stefferud", + pages = {233--245}, + month = sep, + year = 1988, + note = {Costa Mesa, California} +} diff --git a/doc/uknet90/pp-slides.aux b/doc/uknet90/pp-slides.aux new file mode 100644 index 0000000..f23e546 --- /dev/null +++ b/doc/uknet90/pp-slides.aux @@ -0,0 +1 @@ +\relax diff --git a/doc/uknet90/pp-slides.tex b/doc/uknet90/pp-slides.tex new file mode 100644 index 0000000..30be3a3 --- /dev/null +++ b/doc/uknet90/pp-slides.tex @@ -0,0 +1,455 @@ +% -*- LaTeX -* Although it's slitex really + +\documentstyle[blackandwhite,pagenumbers,small,oval,psfig,tgrind]{NRslides} + +\raggedright + +\begin{document} +\title {PP - The Fun and the Pain} + +\author{Julian P.~Onions\\ +j.onions@xtel.co.uk\\[.5in] +X-Tel Services Ltd.\\ +Nottingham University\\ +Nottingham NG7 2RD\\ +ENGLAND} + +\date {December 18th, 1990} + +\maketitle + + \begin{bwslide} +\ctitle {CONTENTS} +PART I +\begin{nrtc} +\item What is PP? + +\item The PP Architecture + +\item The PP Queue + +\item Submission + +\item Scheduling and Control + +\item Channels + +\item Status and Availability +\end{nrtc} +PART II +\begin{nrtc} +\item The scheduling story +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\part*{PART I\\ +Basic PP description} +\end{bwslide} + +\begin{bwslide} +\ctitle{What is PP} +\begin{nrtc} +\item Basically, A Mail transfer system (MTA in the jargon). + +\item Largely protocol independent, but deals with X.400 + and existing mail formats. + +\item Written by people at UCL and Nottingham + +\item Design aims include:- + \begin{itemize} + + \item High performance/throughput + \item Support for message conversion. + \item Support for multi-media + \item Clean interface for user interfaces. + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Why PP} +\begin{nrtc} +\item At the time there was no suitable alternative. + +\item Most implementations were in the ``toy'' category. + +\item Too expensive + +\item Only did X.400 - no gatewaying, or else added as an +afterthought. + +\item Worked to minimal profiles. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Some goals for PP} +\begin{nrtc} +\item Scheduling of messages in an optimal way, such that many +thousands of messages a day can be processed. + +\item Robustness. + +\item Support for RFC-822, X.400(84) and X.400(88) and others. + +\item Reformatting between body part types in a general manner. + +\item Provision of management, authorisation and monitoring tools. + +\item Use of standardised services such as X.500. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} +\begin{nrtc} +\item PP is based on a system of cooperating processes. + +\item Each process has a specific task to achieve. + +\item Most of these processes are ``dumb''. + +\item The ``intelligence'' of the system is provided by two processes. + +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Architecture} + +\vskip .5in + +\diagram[p]{figure2} + +\end{bwslide} + + \begin{bwslide} +\ctitle{The PP Queue} +\begin{nrtc} +\item All messages are placed in a queue on disc. + +\item For each message there are two components + \begin{itemize} + \item A Control file holding all the envelope information. + \item The Message structure holding the Message data. + \end{itemize} +\item The Control file is text encoded. + +\item The Message is either a single file, or a directory hierarchy. + +\item The Message may undergo a number of transformations whilst in + the queue +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Submission} +\begin{nrtc} +\item The first intelligent process is {\em submit}. + +\item All messages entering the queue pass through this process. + +\item It validates the message in a number of ways: + \begin{itemize} + \item Ensures the originator can be reached. + \item Ensures the destination is known. + \item Works out a conversion path from incoming format to outgoing. + \item Applies access controls if required. + \end{itemize} +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Scheduling and Controlling} +\begin{nrtc} +\item The other ``intelligent'' process is the queue manager, {\em qmgr}. + +\item Keeps an in memory map of the queue. + +\item Drives all channel programs using network IPC. + +\item Makes all the scheduling decision about messages in the queue. + +\item Sorts the queue in ``optimal'' ways. + +\item Allows connections to interrogate queue status + +\item More about this later... +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Channels} +\begin{nrtc} +\item Channels in PP process messages. + +\item May reformat a message by conversion e.g. + \begin{itemize} + \item Mapping X.400 to RFC-822 message + \item Converting Telex to Ascii + \end{itemize} +\item May attempt delivery e.g. + \begin{itemize} + \item Drive the SMTP or X.400 protocols + \item Deliver to users + \end{itemize} +\item May restructure the message + \begin{itemize} + \item Convert a file into a directory hierarchy + \item Convert multiple body parts into one + \end{itemize} +\item Housekeeping +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{PP management} +\begin{nrtc} +\item The MTA console provides a good monitor of whats going on. +\item All address that are handled are logged in a special log which +an be processed to give statistics (and charging) information. +\item Authorisation can be controlled by user, host, content-type size +and route. +\end{nrtc} +\end{bwslide} + + \begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 was released on September 21st, 1990. + +\item It is providing a real service at a number of universities and + will shortly be providing the UK WEP service. + +\item PP is freely available for use and should be the backbone of + JANET as it transitions to X.400 protocols. + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Current Status} +\begin{nrtc} +\item PP-5.0 provides the following channels currently + + \begin{itemize} + \item SMTP with DNS support + \item X.400 (1984) + \item UUCP mail + \item JNT grey book mail + \item Distribution list expansion and maintenance + \item RFC822 local delivery and delivery time processing + \item RFC822 and X.400 conversion + \item X-windows based management console + \item Message authorisation checking + \item X.400(1988) P1 protocol (beta test) + \item X.500 distribution lists (beta test) + \end{itemize} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{What is planned for the future} +\begin{nrtc} +\item Fax gateway to convert outgoing messages to faxes and vice +versa. + +\item More use of the X.500 directory, for routing and directory +name lookup. + +\item P7 Message store with remote access + +\item Improvements in throughput and robustness + +\item Some work on System Five portability and a DECNET channel by +people outside the PP group. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Availability and Support} +\begin{nrtc} +\item Source code is free by FTP/FTAM etc. +\item A distribution charge for a tape + +\item Available by FTP/FTAM from ucl, psi and eunet. + +\item Full support is also available if you require it from X-Tel. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\part*{PART II\\ +Fun and Games with Scheduling} +\end{bwslide} + +\begin{bwslide} +\ctitle{How to schedule a queue of messages} +\begin{nrtc} +\item Firstly, it's harder than you think, even when you take this +maxim into account + +\item Secondly, as Martin Padlipsky said, +\begin{quote}\em +``Optimality differs according to context''. +\end{quote} + +\item So -- apply a few general constraints: + \begin{enumerate} + \item Once you have a connection -- give it all you've got. + \item Reading the entire queue is expensive -- so don't if + you can help it. + \item When there is nothing to do -- don't do anything. + \item If there is something to do -- get on with it. + \item Keep in mind management. + \end{enumerate} + +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The first cut} +\begin{nrtc} +\item The first version of the qmgr was a shell script! +\item This was 152 lines long and ``cute'' +\item It read the queue every 5 seconds or so. +\item Directly started processes. +\item Was fun and easy to understand. +\item Of the list above, it did 1. +\item Lasted about 2 weeks as far as I recall +\item Other than that - it was essentially useless. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Lets get serious} +\begin{nrtc} +\item Next version was a C program. +\item It was fairly small and compact. +\item It had an attitude problem - it didn't believe anyone. +\item It read the queue frequently. +\item It communicated via UDP with submit +\item It directly executed programs. +\item Of the list above, it did 1 and 4. +\item It lasted a few months as I recall. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The current version} +\begin{nrtc} +\item Its the third version - a big plus for Frederick Brooks fans. +\item It is rather detached from reality. +\item It does all its communication via IPC (ROS). +\item It does not even have to run on the same machine as the rest. +\item I believe it does all 5 things mentioned above. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Tuning the scheduling - first cut} +\begin{nrtc} +\item First -- get it working with a single message. This includes: + \begin{itemize} + \item Make sure the message is processed as fast as possible + \item When the message is gone - the qmgr should do nothing. + \item The management facilities work + \end{itemize} +\item Next -- make sure it works with a few messages. This involves: + \begin{itemize} + \item Ensuring no fighting breaks out. + \item Check that unlocking a message allows it to be processed. + \end{itemize} +\item Then -- take a deep breath and try it for real! +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Did it work} +\begin{nrtc} +\item Yes -- at least for a while! +\item Until -- a glut of messages arrived. +\item Qmgr goes wild scheduling everything it can +\item Load average rises exponentially... +\item Phone starts ringing... +\item kernel tables overflow... +\item Lynching mobs are formed... +\item Ooops -- fixes required quickly. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle {The fixes} +\begin{nrtc} +\item First: check life insurance policy. +\item Second: Impose a limit on the maximum number of channels +\item This makes the system bounded. +\item Third: get the scheduling better so the limit is not required + so much. +\item Improvements involve + \begin{itemize} + \item Stop channel thrashing. + \item Cluster failures. + \item Stop spurious channel start ups. + \end{itemize} +\end{nrtc} +\end{bwslide} + +\begin{bwslide} + +\ctitle{Wider experience} +\begin{nrtc} +\item Next step, UCL. +\item Seemed to work fine there. +\item Some minor tweaks in performance +\item Some large tweaks in management information. +\item Pretty good all in all. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{Feeling confident now!} +\begin{nrtc} +\item Brought into service at ULCC on nsfnet-relay duty. +\item Works well initially. +\item The disaster - thanksgiving outage wipes us out! +\item 11,000+ Messages in the queue - more arriving every second. +\item An \verb|ls| of the queue takes several minutes. +\item \verb|qmgr-load| grows to 50Mb and takes over an hour to run! +\item VM exhausted by the \verb|qmgr-load| $\rightarrow$ + \verb|qmgr| interaction. +\item Panic sets in, airports and ports are alerted. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} +\ctitle{The fix - and the lessons} +\begin{nrtc} +\item \verb|qmgr-load| $\rightarrow$ \verb|qmgr| interaction made + into small batches. +\item Obvious really in hindsight. +\item Some scheduling of channels still to be done. +\item Avoid flip-flop channel effects +\item Group channels into related clusters +\item Parcel out processes on a percentage basis perhaps. +\end{nrtc} +\end{bwslide} + +\begin{bwslide} + +\ctitle{Summary and Conclusions} +\begin{nrtc} +\item First -- its been mostly fun. +\item We think we have a good system. +\item We reckon we can handle about 1 message/second currently +\item With some tuning that should cope with about 10 message/second +\item This is just less than a million a day! +\item What more could you want? (this is a statement not a question!) +\end{nrtc} +\end{bwslide} + +\end{document} diff --git a/doc/uknet90/pp.aux b/doc/uknet90/pp.aux new file mode 100644 index 0000000..dba3a6d --- /dev/null +++ b/doc/uknet90/pp.aux @@ -0,0 +1,39 @@ +\relax +\citation{ISODE} +\citation{CCITT.MHS} +\citation{RFC822} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {1}Introduction}{1}} +\citation{MMDFII} +\citation{PP.MTA} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {2}The design of PP}{2}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.1}The Process Structure}{2}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.1.1}Submit}{2}} +\citation{SMTP} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.1.2}Qmgr}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.2}The Queue}{3}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {2.3}Channels}{3}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.1}Outbound Channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.2}Inbound Channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.3}Formatting and protocol conversion channels}{4}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {2.3.4}Housekeeping and maintenance channels}{4}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {3}PP Status}{4}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {3.1}The future}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.1}Reliability, robustness and efficiency}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.2}Use of directory}{5}} +\@writefile{toc}{\string\contentsline\space {subsubsection}{\string\numberline\space {3.1.3}Message Store}{6}} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {4}Message Scheduling}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.1}The first cut}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.2}Take 2}{6}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.3}The current version}{7}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.4}Tuning performance - initial}{8}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.5}Tuning performance - for real}{9}} +\@writefile{toc}{\string\contentsline\space {subsection}{\string\numberline\space {4.6}... in the light of experience}{10}} +\bibdata{bcustom,networking,software} +\bibcite{CCITT.MHS}{CCI88} +\bibcite{RFC822}{Cro82} +\bibcite{MMDFII}{III84} +\bibcite{PP.MTA}{Kil88} +\bibcite{SMTP}{Pos82} +\bibcite{ISODE}{Ros90} +\bibstyle{alpha} +\@writefile{toc}{\string\contentsline\space {section}{\string\numberline\space {5}Conclusions}{11}} diff --git a/doc/uknet90/pp.bbl b/doc/uknet90/pp.bbl new file mode 100644 index 0000000..4fd1485 --- /dev/null +++ b/doc/uknet90/pp.bbl @@ -0,0 +1,40 @@ +\begin{thebibliography}{CCI88} + +\bibitem[CCI88]{CCITT.MHS} +{Message Handling: System and Service Overview}. +\newblock International Telegraph and Telephone Consultative Committee, 1988. +\newblock Recommendation X.400. + +\bibitem[Cro82]{RFC822} +David~H. Crocker. +\newblock {Standard for the Format of ARPA Internet Text Messages}. +\newblock Request for Comments 822, DDN Network Information Center, SRI + International, August 1982. + +\bibitem[III84]{MMDFII} +Douglas P.~Kingston III. +\newblock {MMDFII: A Technical Review}. +\newblock In {\em Proceedings, Summer Usenix Conference and Exhibition}, pages + 32--41, June 1984. +\newblock Salt Lake City, Utah. + +\bibitem[Kil88]{PP.MTA} +Stephen~E. Kille. +\newblock {PP~---~A Message Transfer Agent}. +\newblock In Einar Stefferud, editor, {\em {Proceedings, Fourth International + Symposium on Computer Message Systems}}, pages 115--128, September 1988. +\newblock Costa Mesa, California. + +\bibitem[Pos82]{SMTP} +Jon~B. Postel. +\newblock {Simple Mail Transfer Protocol}. +\newblock Request for Comments 821, DDN Network Information Center, SRI + International, August 1982. +\newblock See also \milstd/ 1781. + +\bibitem[Ros90]{ISODE} +Marshall~T. Rose. +\newblock {\em {The ISO Development Environment: User's Manual}}, 6.0 edition, + January 1990. + +\end{thebibliography} diff --git a/doc/uknet90/pp.major b/doc/uknet90/pp.major new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/doc/uknet90/pp.major @@ -0,0 +1 @@ +1 diff --git a/doc/uknet90/pp.minor b/doc/uknet90/pp.minor new file mode 100644 index 0000000..f64f5d8 --- /dev/null +++ b/doc/uknet90/pp.minor @@ -0,0 +1 @@ +27 diff --git a/doc/uknet90/pp.tex b/doc/uknet90/pp.tex new file mode 100644 index 0000000..82c7bc7 --- /dev/null +++ b/doc/uknet90/pp.tex @@ -0,0 +1,570 @@ +% -*- LaTeX -*- + +\input lcustom + +\documentstyle[11pt,a4]{article} + +\begin{document} + +\title{PP -- The Fun and the Pain} +\author{Julian P.~Onions\\[0.1in] +X-Tel Service Ltd.\\ +Nottingham University\\[0.1in] +jpo@xtel.co.uk} +\date{Tuesday 18th December 1990} + +\maketitle + +\begin{abstract} +This paper describes the design and implementation of +the PP message transport system. This is a message transfer system +that can relay a variety of protocols, and gateway between them. + +The paper describes what PP is now and some of its plans for +development. The second half of the paper is a report on some of the +experiences gained watching and tinkering with PP. +\end{abstract} + +\section{Introduction} + +This paper describes the design and implementation of PP\footnote{PP +is not an acronym. Despite many rumours to the contrary, the author is +sticking to this position!.}. PP is a generic Message Transfer Agent +capable of carrying a number of message formats. It has been written +as a joint project by University College London and Nottingham +University and is designed to run on \unix/ systems. It makes +use of the ISODE package\cite{ISODE}. Its design is heavily +influenced however, by the need to carry X.400 MHS\cite{CCITT.MHS} and +RFC-822\cite{RFC822} based mail. The major goals of PP include: +\begin{itemize} +\item Robustness. PP is designed for heavy use. It should be +capable of transferring high levels of traffic in an optimal way. + +\item A clean interface for submission and delivery. PP does not +provide a user agent but does provide a library interface which allows +user agents to be added to PP easily. + +\item Sophisticated message processing to optimise delivery and +remote transfers. + +\item Support for message conversion in an integrated way. + +\item Support for multiple addressing formats (initially two). + +\item Support for multi-media mail. + +\item Support for arbitrary message structures. + +\item Designed for large systems. PP is not designed to run on your +PC or even on a workstation. It is designed to be a central mail +processing hub for a group of computers. It is not a small piece of +software! +\end{itemize} + +As indicated above, PP is designed to deal with a large variety of +problems. The questions that comes to mind is ``why bother spending +all those years doing this?''. + +The answer is partly historical, but is still mostly relevant. When PP +was first thought about, there was very little that could be picked up +``off the shelf'' to deal with X.400 mail. What's more, the products we +had seen were just not suitable for the sort of environment we wanted +to run a mail system in. Most of the products then, and still now to +an extent, were what might be considered ``toy'' systems. Yes, they +would take an X.400 message and deliver it to a recipient, but there +is more to a reliable MTA than this. PP put management and monitoring +of the MTA very high on its list of desirable features. We believe +this has been attained - although not perfectly yet (what is). + +\section{The design of PP} + +The design of PP was influenced in part by the RFC-822 mail system +MMDF\cite{MMDFII}. In this model, extensive use is made of separate +processes to do different jobs. This allows each element to be built +and tested separately and encourages modularity. A fuller description +of the design of PP can be found in \cite{PP.MTA}. + +\subsection{The Process Structure} + +PP has a single queue of messages on which a number of processes +operate. There are two critical processes which undertake complex +functions, the rest of the processes are essentially ``dumb''. + +\subsubsection{Submit} +The first key process is that entitled {\em submit}. This process +guards the entrance to the queue. All messages entering the queue pass +through this process. It performs a variety of checks on the message +to ensure it can either be delivered or returned; works out the +routing for the message; calculates the reformatting of the message if +necessary; and applies other criteria such as authorisation and +authentication. By checking as much as possible at this point later +processes have to do less and completely undeliverable messages can be +stopped from entering the queue. + +As all message must pass though submit, all messages are checked at +this stage. This is where the authorisation policies are enforced. +Where possible, submit will always try and accept a message and return +it if necessary. Typically this leads to better error messages as +submit can take complete charge of generating the delivery report. + +Submit will refuse to accept a message when it can't parse or route +back to the originator. In this case, submit attempts to signal back +to the remote site that this message will not be accepted. In some +protocols, such as X.400(84), this is not possible. In this case, +submit gives up and the message as a whole is forwarded to the +postmaster to sort out. Fortunately, such occurrences are fairly rare. + +\subsubsection{Qmgr} +The second key process is the {\em \verb|qmgr|}, or queue manager. This +process is responsible for all the scheduling operations of the +messages in the queue. The \verb|qmgr| holds a representation of the queue in +memory and so can perform complex and optimal scheduling of messages. +This scheduling consists of either delivering the message locally or +remotely or else converting the message within the queue (e.g. +gatewaying between protocols). + +As the \verb|qmgr| holds a complete representation of the queue in memory it +also provides an information service. It can be queried by suitable +tools to display the state of the queue and such tools can even +control the behaviour of the \verb|qmgr|. This is the second half of the +management framework. As the \verb|qmgr| has a full overall picture of what +is going on in the queue - on a second to second basis, good global +decisions are possible. + +An X-windows based MTA console is provided with PP which can attach +to remote \verb|qmgr|'s and display the status in graphic detail, where +possible using colour to highlight problems. With suitable +authentication, the MTA console can also control the \verb|qmgr|'s behaviour. + +\subsection{The Queue} + +The queue of messages is held in two components. The first is an +address file which contains the envelope information about the +message. This is held in a text encoded form and is a generic envelope +structure which can hold both X.400 and RFC-822 messages. The text +encoding is a big advantage as it allows manipulation of the queues in +an emergency by a text editor. Whilst this should not normally be +necessary it is much easier than providing special management tools +to cover every eventuality. + +The second component is the message content. This includes the headers +and body parts. If no processing is necessary for the message this is +kept as a single file. However, if conversion is necessary, the +content is broken up into parts, each part being placed in a separate +file. Each time a message content is transformed, a new directory is +created and the appropriate files are changed. This allows simple +filters (such as {\em sed} even) to do the conversions. + + +\subsection{Channels} + +Most other processes in PP are termed {\em channels}. A channel takes +as input a message and outputs a different form of that message. +Channels are controlled directly by the \verb|qmgr| by means of a networked +protocol. Each channel does a specific job. Channels come in four +basic forms as described below. + +\subsubsection{Outbound Channels} +This style of channel is usually a protocol engine. It takes a message +out of the queue and delivers it. This delivery may be local as in the +case of delivering to a mailbox; or remote such as driving the +SMTP\cite{SMTP} or X.400 protocols. Each channel reads the internal +format of the queued message and converts it to the protocol specific +format. The \verb|qmgr| informs a channel which message to deliver and the +channel reports on the status of the message. This allows the \verb|qmgr| to +discover whether the delivery attempt was successful, the remote site +did not respond or whether the message cannot be delivered. This +information is then used by the \verb|qmgr| to schedule further deliveries. + +\subsubsection{Inbound Channels} +Inbound channels perform the opposite function to outbound channels. +They take care of the various protocols necessary to receive a +message, either from a user agent (local submission) or across a +network. Their main task is mapping from the protocol specific form of +the message to the form used withing the queue. This form is then +passed by a private protocol to submit which enqueue the message and +then informs the \verb|qmgr| of the new message. + +\subsubsection{Formatting and protocol conversion channels} +These channels transform the message in some way without delivering +it. They are treated in exactly the same way as outbound channels and +are scheduled by the \verb|qmgr|. These channels come in two basic types. +\begin{itemize} +\item Channels that change the directory structure. These either map +from the single file into a directory hierarchy, or the reverse. + +\item Simple reformatting. These channels might change, say, a teletex +body part into an ascii body part. When gatewaying is being performed, +such a channel might convert RFC-822 headers into X.400 headers. +\end{itemize} + +\subsubsection{Housekeeping and maintenance channels} +These channels do not usually have anything to do with delivery, but +perform meta tasks. These include loading the \verb|qmgr|, deleting +messages, timeing out messages and removing junk from the queue. + +\section{PP Status} + +PP currently contains the following parts. + +\begin{description} +\item[Core] The basic core of the system including the \verb|qmgr|, +submit and a number of support tools. + +\item[X.400 1984] The X.400 1984 protocols are supported. + +\item[SMTP] Smtp protocols are supported, including use of the +name server protocols for address resolution. + +\item[Grey Book] Grey book mail transfer is working, using the +unix-niftp blue book transfer system to provide non-spooled mail +transfer over JANET. + +\item[List] A list channel to offload the processing of +distribution lists. This helps speed up submission to large +distribution lists and allows list management. + + +\item[MTA Console] An X-windows based console display which +interrogates the \verb|qmgr| and displays the current state of the +queues. It emphasises problems in the queue and allows parameters to +be adjusted interactively. + +\item[UUCP] There is some support for UUCP though this has not really +been tested in a large UUCP environment. + +\item[Tools] Various auxiliary programs to configure the system and +provide debugging support. + +\end{description} + +PP also contains the following experimental modules. +\begin{description} +\item[X.400 1988] The 1988 version of X.400 is in a beta test +form. The 1988 version of X.400 is uncommon at present so interworking +testing is limited. This will include secure messaging and extensions. + +\item[Directory Lists] An experimental channel that store distribution +lists in the X.500 directory is provided. This will be emphasised more +in future releases. + +\end{description} + +\subsection{The future} +Work is already under way on the next version of PP. The next version +has three main thrusts. + +\subsubsection {Reliability, robustness and efficiency} +These are general goals, without any specific actions to be taken. In +general we hope the level of reliability and robustness of the +software to increase with each future release. At the same time, some +effort will be expended on streamlining the code and improving +throughput and decreasing machine load (the usual motherhood and apple +pie goals...). + +\subsubsection {Use of directory} +The next version of PP will make much larger use of the X.500 +directory. It will use the distribution list channel indicated above. +it will also be able to map Directory Names into O/R names by use of +the directory. Finally, work will be done on use of the directory for +routing. + +\subsubsection{Message Store} +A Message Store for PP is currently being written. It will allow +both P7 and P7+ access to messages. This will allow workstations and +portable computers to retrieve and store messages remotely. A user +agent for Unix with these features in mind is being written as a +separate project. + +\section{Message Scheduling} +Much of the PP system revolves around the \verb|qmgr| process which as +described above schedules the messages in the queue. The development +of this aspect of PP has been through many iterations, and is quite +interesting (at least to the author). + +\subsection{The first cut} +The first version of the \verb|qmgr| was a shell script! +It was 152 lines long by the time it was dropped, and originally had a +simplicity and understandability that was rather elegant (if I do say +so myself). All in all it was cute, and did the job reasonably well +for a week or two. + +At this stage though PP was very different to its current form +and no serious message process was being done. This version was only +used for experimentation, and I certainly would never have trusted my +mail with it. This version was never intended as anything other than +the proverbial {\em quick hack} to get things going. To my rather +faded memory it scheduled less than 100 messages in its short +lifetime. + +It was obvious though that this method was of limited potential. It +did not have the capability for interrogation. It did hold an in-core +copy of the queue as a shell variable but it refreshed this copy every +few minutes (can you say \verb|echo msg.*|). It was also clear that +with really big queues the lack of management and sophisticated +backoff and retry strategies alone would just not cut it. +Besides, who would have any credibility for a 15Mb mail system +claiming performance upwards of a message per second controlled by 100 +lines of shell! + +\subsection{Take 2} +The next version of the \verb|qmgr| was a C program. This was a small +program, I forget exactly the size. It did queue management in a +rather cavalier fashion. It scheduled messages by the simply +fork/exec'ing processes to deal with delivery. It read the queue +directly on start up and received UDP packets from submit to notify it +that new messages had arrived. The UDP packet contained a simple +string which was the queue name of the message. The \verb|qmgr| would then go +and read in this message, add it to the internal queues and start +scheduling it. + +It was cavalier in the respect that it did not trust anyone. The UDP +packet was a hint that a message had arrived. The \verb|qmgr| would +independently check this by attempting to read from the queue. Also, +as UDP is inherently unreliable - and also because the \verb|qmgr| had an +{\em attitude problem} - it would reread the entire queue frequently +to check what it thought was correct and that it hadn't missed +anything. + +This scheme works ok after a fashion. However, the frequent queue +reading we knew by experience would be a real performance killer. Most +of the queueing systems that we were familiar with have had as a +bottleneck the reading of the queue. UUCP has long had this problem, +with some very ingenious work-arounds to avoid quadratic behaviour with +large queues. MMDF had a similar problem, although to a lesser extent. +Normally MMDF will try and sort the mail queue optimally, but above a +threshold (300 messages) it admits defeat and gets very relaxed about +the whole thing, taking each message as it finds it without any +attempt at optimality. + +Another problem was this UDP issue. I liked it as it was simple, but +if we wanted to get away from the frequent queue reading, this +process would have to be reliable. We could obviously move to TCP for +reliability and then we could pass all the information we needed to +the \verb|qmgr|. But how to pass the data? We could have used something like +XDR and RPC from sun, which would probably do the job very well. +However, at the time I was deeply involved in work with ISODE and +getting ASN.1 tools together. We therefore decided - hey, we're +suppose to be pushing OSI, lets see if it can cut it. This leads on to ... + +\subsection{The current version} +The book {\em The Mythical Man Month} makes a great play of the fact +that the third and presumably subsequent versions of a piece of +software are usually the better versions. The first version being a +rather cautious attempt to see if you can do the job, having minimal +functionality and being a sort of prrof of concept case. The second +version is then usually a wild extravaganza of crazy ideas that you +thought up while writing the first version and just {\em had} to put +in. The third version then falls somewhere between these two. I am +rather proud therefore that there have been three rewrites of this +part of the system. + +The current version of the \verb|qmgr| is rather detached from reallity in +some respects. It never interacts directly with anything. Indeed the +\verb|qmgr| can run on a different machine to the rest of the system. +The \verb|qmgr| issues commands to other programs for all its +operations. In this way it is usually very responsive as it never has +to do serious amounts of work itself. When started up, the \verb|qmgr| +first schedules a channel called \verb|qmgr-load| which reads the +queue and passes its findings to the \verb|qmgr|. The \verb|qmgr| then +processes the messages in the queue calling different channels until +finally on each message the \verb|msg-clean| process is called to +remove each message. Every 6 hours or so, the \verb|qmgr| will +reschedule \verb|qmgr-load| to just check the queue is what it really +thinks it is. It also schedules irregularly a process called +\verb|trash| which will crawl around the queue looking for dead +messages or general junk. + +The \verb|qmgr| receives news of new messages via ROS operations from submit +and believes this information. From this it can be seen that the \verb|qmgr| +is not a trusted process. It just schedules the channels it thinks it +should on the basis of the information it receives. Each channel is +responsible for checking that the \verb|qmgr|'s request is reasonable. +This scheme appears to work fairly well. + +\subsection{Tuning performance - initial} +It turns out that scheduling is never as easy as you thought it might +be - even if you take this maxim into account! To begin with, I was +running the \verb|qmgr| on an empty queue and introducing one message at a +time to see that it scheduled things as it should. It took many +iterations before I had everything sorted out so that the \verb|qmgr| always +scheduled things that were ready to run. There is a fairly complex +interaction between address that have been cached for a while, +messages that are locked as they are being processed and the +intelligence of scheduling. Eventually this was solved, such that +messages appeared to do what they were suppose to. + +The next step was to introduce it into service. We ran it on a machine +at Nottingham processing maybe 100 messages a day delivering to a +handful of brave recipients. It turns out that 100 messages a day is +not too dissimilar to the one message at a time scenario. Things seem +to run fine. Then one day a glut of messages arrived at the same time +as several local messages were submitted. The machine (a sun 3/60 with +8Mb) practically died. The \verb|qmgr| was a little over eager - +scheduling everything it could We had 10-15 processes hammering away +at the queue and performance was non-existent. + +The first step to correct this was to put a limit on the total number +of simultaneous channels that could be run. By setting this figure to +one you can get back to linear behaviour and a figure of about 3 is +suitable for most reasonably small sites. The next thing that was +noticed was that with 2 messages were introduced into the queue, the +following happened. +\begin{quote}\small\begin{verbatim} +process1: deliver message1 to recipient +process1: message1 delivered +process2: start up and initialise +process1: deliver message2 to recipient +process2: delete message1 +process2: shutdown +process1: message2 delivered +process2: start up an initialise +process2: delete message1 +process2: shutdown +\end{verbatim}\end{quote} +As the delivery time is slightly longer than the time to delete a +message, the deletion process is started up and stopped many times. A +simple fix for this is to cache a channel for a few seconds when it +shuts down. By enforcing an idle period of, say, 20 seconds, between +the same process running, this cuts down thrashing of one process. +Another useful technique is to round up cache times. If you cache a +message, then you round that time off to the nearest whole minute. +This means when the channel restarts to retry these messages is may +have a number to try - rather than starting up for just one message +and again a few seconds later for another. + +\subsection{Tuning performance - for real} +The next step in the evolution was when PP was pressed into service at +UCL. Here there are many messages processed (about 30,000+ a week). +As far as I recall, this really didn't affect scheduling policy that +much. Most of the bugs had been shaken out and although the queues had +grown to perhaps 1-300 messages things still worked reasonably well. +What it did show up was that more management control was needed. Much +work was done with the \verb|MTAconsole| at this stage to allow a +variety of new controls and some graphical details on performance. + +It was pushed a little more heavily one week when most of UCL's +machines were down for air-conditioning maintenance. At this point +delivery to local users could not proceed as the relevant NFS +partitions were not present. It would have been nice to do some more +useful cacheing in this case, such as detecting that a whole disc was +missing so disabling delivery to a whole range of users. Unfortunately +this sort of thing is rather difficult to detect in software - +especially in a portable way. All you generally know is that a +chdir(2) or open(2)failed. + +Anyway, the \verb|qmgr| continued to run ok with a few minor tweaks here and +there - mainly to provide new statistics for the console process. + +And then... it was brought up at nsfnet-relay. + +Whereas at UCL the queues might peak at 1000 messages occasionally, +this sort of figure is the typical ``quiet'' day at nsfnet-relay. We +were rather staggered seeing at first hand the sort of traffic they +processed. The ULCC people had received a copy of the UCL system and +had been playing around with it to see if it did what was required. +Then one particularly heavy day, there was just too much traffic for +the MMDF and grey-book system to take. As some traffic had been +filtered through the PP system at nsfnet-relay already, it was decided +to switch to PP to clear the backlog. This was done, and a backlog of +5000 messages was cleared together with a constant stream of new +traffic within about a day. As everything appeared to be working ok +the system was left in production. + +This worked fine, although watching things carefully it was clear that +things were not being processed optimally. Of the 6 channels the \verb|qmgr| +had to work with it would start off by allocating the following. +\begin{quote} +\small +\begin{verbatim} +smtp: 2 +greybook: 2 +msg-clean: 1 +822touk: 1 +\end{verbatim} +\end{quote} +However, after a while, some of the channels cleared - or else all +hosts were deemed unreachable currently. The channel would then +shutdown and be reallocated. Then, at this point they would do other +work such as reformatting and messages would build up in one of the +outbound queues. Once the reformatting was complete, Channels would be +allocated to the outbound channel. As there were many messages on this +channel, as other channels finished they would be allocated to this +channel. This would result in an allocation such as: +\begin{quote} +\small +\begin{verbatim} +greybook: 5 +msg-clean: 1 +\end{verbatim} +\end{quote} +Eventually the greybook queue would clear, but by this time the smtp +queue had built up so processing switched to that. +This continued in a sort of bistable flip-flop routine. This is not +particularly serious - although probably not the sort of behaviour that +is required. + +The real disaster occurred a week or so later. It seems to have +happened after the US thanksgiving holiday. We suspect that during +this time a number of machines in the U.S. were either taken down or +crashed, making the mail pile up at nsfnet-relay. Then, when they came +back up - there was an enormous flood of mail. At one stage we had +over 11,000 messages in the queue. A simple ls(1) in the queue +directory took several minutes! PP continued to work through this +queue though, and was making some progress. Every night however, the +machine is taken down for 30 minutes or so to perform a full backup. +When the machine restarted, the \verb|qmgr| scheduled the +\verb|qmgr-load| process as normal. However, there were so many +messages in the directory (and unix behaves rather quadratically with +large directories) that this process took over an hour to read in all +the files. By this time the process had grown to about 50Mb in size. +Then it tried to transfer the queue to the +\verb|qmgr|, which also had to grow to 50Mb's to accomodate it. There was only +100Mb of VM configured - so not suprisingly the \verb|qmgr| ran out of +memory. Despite this it continued to run which I was quite pleased +about! + +This was desperate. The nsfnet-relay machine is not one that you can +say ``Oh well, never mind - thats one for the record books'', it {\em +has} to be fixed. There was a panic days work to convert the +qmgr-loader into an incremental process that loaded 50 messages at a +time rather than all at once. Meanwhile, a small debugging program we +had around that was used to load individual messages into the queue +was pressed into service. Together with ls and xargs it succeeded in +loading up the +\verb|qmgr| in about 2 hours total. The backlog of messages was cleared in +about two days total. + +In hindsight, this was an obvious problem waiting to happen, but it +was an issue that was hardly discussed until it happened. + +\subsection{... in the light of experience} +After the experiences with nsfnet-relay, we are adapting some of the +software. It is clear that more statistics are needed (such as number +of messages processed and messages processed/second). It also seems as +though the \verb|qmgr| is using too much of its memory when running. From +observation, it uses about 1Mb of memory to hold just over 1000 +messages (e.g. the \verb|qmgr| at the peak traffic on nsfnet-relay was of the +order 11Mb). However, it also seems to use most of this memory most of +the time. This causes heavy paging traffic. With some subtle changes +to the internal data structures I believe it is possible to reduce the +working set size considerably - which will give other processes a +chance! + +\section{Conclusions} +PP has been an interesting project and we are now getting some real +feedback on the design decisions taken early on. It seems to be mostly +up to the job asked of it - even in the busiest environments. We +worked out using back-of-the-envelope calculations, that it can +process about a message/second at the present time - on input and +output. We think with a few of the changes hinted at above we can move +this to 10 messages/second without too much effort. This works out at +just less than a million messages a day. We hope this will be +sufficient for most peoples usage. (You could always buy another machine!) + +\bibliography{bcustom,networking,software} +\bibliographystyle{alpha} + +\showsummary + +\end{document} diff --git a/doc/uknet90/pp.vrsn b/doc/uknet90/pp.vrsn new file mode 100644 index 0000000..e9a786b --- /dev/null +++ b/doc/uknet90/pp.vrsn @@ -0,0 +1,6 @@ +\begingroup + \catcode`\#=12 + \gdef\versiontag/{#1.27}% + \gdef\versiondate/{Tue Dec 11 12:35:38 GMT 1990}% +\endgroup +\typeout{Version \versiontag/ of \versiondate/} diff --git a/doc/uknet90/queuefig.fig b/doc/uknet90/queuefig.fig new file mode 100644 index 0000000..eac4ecf --- /dev/null +++ b/doc/uknet90/queuefig.fig @@ -0,0 +1,46 @@ +#FIG 2.0 +80 2 +1 1 0 1 0 0 0 0 0.000 1 0.000 581 368 96 50 581 368 676 417 +1 1 0 1 0 0 0 0 0.000 1 0.000 139 370 96 50 139 370 234 419 +2 1 1 1 0 0 0 0 4.000 1 1 + 0 0 1.000 4.000 8.000 + 0 0 1.000 4.000 8.000 + 237 369 485 369 236 369 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 531 412 438 536 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 192 412 276 524 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 279 281 187 327 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 358 280 514 332 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 479 159 399 239 9999 9999 +2 1 0 1 0 0 0 0 0.000 1 0 + 0 0 1.000 4.000 8.000 + 145 162 241 234 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 435 599 435 519 276 519 276 599 435 599 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 399 279 399 199 240 199 240 279 399 279 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 560 158 560 78 401 78 401 158 560 158 9999 9999 +2 4 0 1 0 0 0 0 0.000 6 0 0 + 238 161 238 81 79 81 79 161 238 161 9999 9999 +2 4 0 0 0 0 0 0 0.000 6 0 0 + 239 159 239 81 79 81 79 159 239 159 9999 9999 +2 4 0 0 0 0 0 0 0.000 6 0 0 + 239 160 239 79 78 79 78 160 239 160 9999 9999 +2 2 0 1 0 0 0 0 0.000 0 0 + 299 209 299 209 299 209 299 209 299 209 9999 9999 +4 0 0 12 0 0 0 0.000 1 9 90 323 564 Outbound channel +4 0 0 12 0 0 0 0.000 1 11 33 566 371 Queue +4 0 0 12 0 0 0 0.000 1 12 28 109 373 Qmgr +4 0 0 12 0 0 0 0.000 1 9 35 283 245 Submit +4 0 0 12 0 0 0 0.000 1 9 47 438 124 Local UA +4 0 0 12 0 0 0 0.000 1 9 84 119 122 Inbound Channel diff --git a/doc/uknet90/sfwdoc.bib b/doc/uknet90/sfwdoc.bib new file mode 100644 index 0000000..fb59687 --- /dev/null +++ b/doc/uknet90/sfwdoc.bib @@ -0,0 +1,346 @@ +% ``Software'' bibliography database for BiB-TeX + + +@manual{AmSTeX, + author = "Michael Spivak", + title = "{Summary of \AmSTeX{}}", + month = sep, + year = 1983 +} + +@manual{BFLY.NRTC, + title = "{Using the BB\&N Butterfly at NRTC}", + author = "John L. Romine and Marshall T. Rose", + organization= nrtc, + month = may, + year = 1986 +} + +@manual{BibTeX, + author = "Oren Patashnik", + title = "{\BibTeX{}ing}", + month = may, + year = 1983 +} + +@manual{BSD.NET, + title = "{4.2BSD Networking Implementation Notes}", + author = "Samuel J. Leffler and William N. Joy and + Robert S. Fabry", + organization= {Computer Systems Research Group, + Computer Science Division}, + address = {Department of Electrical Engineering and Computer + Science, University of California, Berkeley}, + month = jul, + year = 1983 +} + +@book{C.Language, + author = "Brian W. Kernighan and Dennis M. Ritchie", + title = "{The C Programming Language}", + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + series = {Software Series}, + year = 1978 +} + +@manual{Emacs, + author = "James Gosling", + title = "{UNIX EMACS, UCI Version}", + month = may, + year = 1982 +} + +@manual{EtherTIP, + title = "{Using the Bridge CS/1 at NRTC}", + author = mtr, + organization= nrtc, + month = may, + year = 1986 +} + +@inproceedings{Face.Nation, + author = "Rob Pike and David L. Presotto", + title = "{Face the Nation}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {81--86}, + month = jun, + year = 1985, + note = {Portland, Oregon} +} + +@techreport{ISO.Environment, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{The ISO Development Environment at NRTC: User's + Manual}", + type = {Technical Paper}, + number = {\#702}, + institution= nrtc, + month = sep, + year = 1986 +} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {4.0}, + author = mtr, + organization= twg, + month = aug, + year = 1988 +} + +@book{LaTeXbook, + author = "Leslie Lamport", + title = "{\LaTeX{}: A Document Preparation System}", + publisher= {Addison-Wesley}, + address= {Reading, Massachusetts}, + year = 1985 +} + +@manual{MH.4, + title = "{Changes to the Rand MH Message Handling System: + MH.4}", + edition = {\mh4}, + author = mtr, + month = jul, + year = 1984, + note = {MH documentation set} +} + +@manual{MH.5, + title = "{Changes to the Rand MH Message Handling System: + MH.5}", + edition = {\mh5}, + author = mtr, + month = jan, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.6, + title = "{Changes to the Rand MH Message Handling System: + MH.6}", + author = mtr, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.ADM, + title = "{The Rand MH Message Handling System: + Administrator's Guide}", + author = mtr, + organization= ics, + address = uci, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.BB, + title = "{The Rand MH Message Handling System: + The UCI BBoards Facility}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.Beginners, + title = "{MH for Beginners}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.MM, + title = "{MH for MM Users}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@techreport{MH.POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{MH.XPOP, + author = mtr, + title = "{Post Office Protocol~---~Version 3: + Extended Service Offerings}", + type = rfc, + number = 1082, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@manual{MH.USR, + title = "{The Rand MH Message Handling System: + User's Manual}", + author = "Marshall T. Rose and John L. Romine", + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.TUT, + title = "{The Rand MH Message Handling System: + Tutorial}", + author = "Marshall T. Rose and Jerry N. Sweet", + month = may, + year = 1985, + note = {MH documentation set} +} + +@inproceedings{MMDF, + author = "David H. Crocker and E.S. Szurkowski and + David J. Farber", + title = "{An Internetwork Memo Distribution + Facility~---~MMDF}", + booktitle= "{Proceedings, Sixth Data Communications Symposium}", + pages = {18--25}, + month = nov, + year = 1979, + note = {Asilomar} +} + +@inproceedings{MMDFII, + author = "Douglas P. Kingston~III", + title = "{MMDFII: A Technical Review}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {32--41}, + month = jun, + year = 1984, + note = {Salt Lake City, Utah} +} + +@manual{PhDTeX, + author = "E. Timothy Morgan", + title = "{A Dissertation Style for \AmSTeX{}}", + month = sep, + year = 1984, + note = {Department of Information and Computer Science, + University of California, Irvine} +} + +@techreport{PIC, + author = "Brian W. Kernighan", + title = "{PIC --- A Graphics Language for Typesetting User + Manual}", + type = {Computing Science Technical Report}, + number = 85, + institution= {Bell Laboratories}, + address = {Murray Hill, New Jersey}, + month = mar, + year = 1982 +} + +@manual{SendMail, + title = "{SENDMAIL~---~An Internetwork Mail Router}", + author = "Eric Allman", + organization= {Britton-Lee, Inc.}, + address = {Berkeley, California}, + month = jul, + year = 1983 +} + +@manual{Slides, + title = "{Using \SLiTeX{} to Make Slides at NRTC}", + author = mtr, + organization= nrtc, + month = apr, + year = 1986 +} + +@manual{STREAMS, + key = {ATT}, + title = "{STREAMS Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@book{SVID, + key = {SVID}, + title = "{System V Interface Definition}", + publisher= {AT\&T Bell Laboratories}, + edition = {$2^{\underline{\mbox{\scriptsize nd}}}$}, + year = 1986 +} + +@book{TeXbook, + author = "Donald E. Knuth", + title = "{The \TeX{}book}", + publisher= {Addison-Wesley}, + address = {Reading, Massachusetts}, + year = 1983 +} + +@techreport{TeX.Roff, + author = "Michael Urban", + title = "{A Guide to \TeX{} for the Troff User}", + institution= {TRW Software Productivity Project}, + month = oct, + year = 1984 +} + +@misc{TeX.Trip, + author = "Donald E. Knuth", + title = "{A Test File for \TeX{}}", + month = jul, + year = 1983, + note = {Version 0.999} +} + +@manual{TLI, + key = {ATT}, + title = "{Network Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@manual{UCI.map, + title = "{The UCI RoadMap}", + author = mtr, + organization= nrtc, + month = jun, + year = 1986 +} + +@article{WEB.TUT, + author = "Donald E. Knuth", + title = "{Literate Programming}", + journal = {The Computer Journal}, + year = 1983 +} + +@manual{WEB.USR, + author = "Donald E. Knuth", + title = "{WEB USER MANUAL}", + year = 1983 +} diff --git a/doc/uknet90/software.bib b/doc/uknet90/software.bib new file mode 100644 index 0000000..75c7fb8 --- /dev/null +++ b/doc/uknet90/software.bib @@ -0,0 +1,345 @@ +% ``Software'' bibliography database for BiB-TeX + + +@manual{AmSTeX, + author = "Michael Spivak", + title = "{Summary of \AmSTeX{}}", + month = sep, + year = 1983 +} + +@manual{BFLY.NRTC, + title = "{Using the BB\&N Butterfly at NRTC}", + author = "John L. Romine and Marshall T. Rose", + organization= nrtc, + month = may, + year = 1986 +} + +@manual{BibTeX, + author = "Oren Patashnik", + title = "{\BibTeX{}ing}", + month = may, + year = 1983 +} + +@manual{BSD.NET, + title = "{4.2BSD Networking Implementation Notes}", + author = "Samuel J. Leffler and William N. Joy and + Robert S. Fabry", + organization= {Computer Systems Research Group, + Computer Science Division}, + address = {Department of Electrical Engineering and Computer + Science, University of California, Berkeley}, + month = jul, + year = 1983 +} + +@book{C.Language, + author = "Brian W. Kernighan and Dennis M. Ritchie", + title = "{The C Programming Language}", + publisher= {Prentice-Hall, Inc.}, + address = {Englewood Cliffs, New Jersey}, + series = {Software Series}, + year = 1978 +} + +@manual{Emacs, + author = "James Gosling", + title = "{UNIX EMACS, UCI Version}", + month = may, + year = 1982 +} + +@manual{EtherTIP, + title = "{Using the Bridge CS/1 at NRTC}", + author = mtr, + organization= nrtc, + month = may, + year = 1986 +} + +@inproceedings{Face.Nation, + author = "Rob Pike and David L. Presotto", + title = "{Face the Nation}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {81--86}, + month = jun, + year = 1985, + note = {Portland, Oregon} +} + +@techreport{ISO.Environment, + author = "Marshall T. Rose and Dwight E. Cass", + title = "{The ISO Development Environment at NRTC: User's + Manual}", + type = {Technical Paper}, + number = {\#702}, + institution= nrtc, + month = sep, + year = 1986 +} + +@manual{ISODE, + title = "{The ISO Development Environment: User's Manual}", + edition = {6.0}, + author = mtr, + month = jan, + year = 1990 +} + +@book{LaTeXbook, + author = "Leslie Lamport", + title = "{\LaTeX{}: A Document Preparation System}", + publisher= {Addison-Wesley}, + address= {Reading, Massachusetts}, + year = 1985 +} + +@manual{MH.4, + title = "{Changes to the Rand MH Message Handling System: + MH.4}", + edition = {\mh4}, + author = mtr, + month = jul, + year = 1984, + note = {MH documentation set} +} + +@manual{MH.5, + title = "{Changes to the Rand MH Message Handling System: + MH.5}", + edition = {\mh5}, + author = mtr, + month = jan, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.6, + title = "{Changes to the Rand MH Message Handling System: + MH.6}", + author = mtr, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH6.5, + title = "{Changes to the Rand MH Message Handling System: + MH \#6.5 for 4.3BSD UNIX}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.ADM, + title = "{The Rand MH Message Handling System: + Administrator's Guide}", + author = mtr, + organization= ics, + address = uci, + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.BB, + title = "{The Rand MH Message Handling System: + The UCI BBoards Facility}", + author = mtr, + month = may, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.Beginners, + title = "{MH for Beginners}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@manual{MH.MM, + title = "{MH for MM Users}", + author = "Mary Hegardt and Tim Morgan", + organization= ics, + address = uci, + month = apr, + year = 1986, + note = {MH documentation set} +} + +@techreport{MH.POP, + author = mtr, + title = "{Post Office Protocol~---~Version 3}", + type = rfc, + number = 1081, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@techreport{MH.XPOP, + author = mtr, + title = "{Post Office Protocol~---~Version 3: + Extended Service Offerings}", + type = rfc, + number = 1082, + institution= nic, + address = sri, + month = dec, + year = 1988 +} + +@manual{MH.USR, + title = "{The Rand MH Message Handling System: + User's Manual}", + author = "Marshall T. Rose and John L. Romine", + month = nov, + year = 1985, + note = {MH documentation set} +} + +@manual{MH.TUT, + title = "{The Rand MH Message Handling System: + Tutorial}", + author = "Marshall T. Rose and Jerry N. Sweet", + month = may, + year = 1985, + note = {MH documentation set} +} + +@inproceedings{MMDF, + author = "David H. Crocker and E.S. Szurkowski and + David J. Farber", + title = "{An Internetwork Memo Distribution + Facility~---~MMDF}", + booktitle= "{Proceedings, Sixth Data Communications Symposium}", + pages = {18--25}, + month = nov, + year = 1979, + note = {Asilomar} +} + +@inproceedings{MMDFII, + author = "Douglas P. Kingston~III", + title = "{MMDFII: A Technical Review}", + booktitle= {Proceedings, Summer Usenix Conference and Exhibition}, + pages = {32--41}, + month = jun, + year = 1984, + note = {Salt Lake City, Utah} +} + +@manual{PhDTeX, + author = "E. Timothy Morgan", + title = "{A Dissertation Style for \AmSTeX{}}", + month = sep, + year = 1984, + note = {Department of Information and Computer Science, + University of California, Irvine} +} + +@techreport{PIC, + author = "Brian W. Kernighan", + title = "{PIC --- A Graphics Language for Typesetting User + Manual}", + type = {Computing Science Technical Report}, + number = 85, + institution= {Bell Laboratories}, + address = {Murray Hill, New Jersey}, + month = mar, + year = 1982 +} + +@manual{SendMail, + title = "{SENDMAIL~---~An Internetwork Mail Router}", + author = "Eric Allman", + organization= {Britton-Lee, Inc.}, + address = {Berkeley, California}, + month = jul, + year = 1983 +} + +@manual{Slides, + title = "{Using \SLiTeX{} to Make Slides at NRTC}", + author = mtr, + organization= nrtc, + month = apr, + year = 1986 +} + +@manual{STREAMS, + key = {ATT}, + title = "{STREAMS Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@book{SVID, + key = {SVID}, + title = "{System V Interface Definition}", + publisher= {AT\&T Bell Laboratories}, + edition = {$2^{\underline{\mbox{\scriptsize nd}}}$}, + year = 1986 +} + +@book{TeXbook, + author = "Donald E. Knuth", + title = "{The \TeX{}book}", + publisher= {Addison-Wesley}, + address = {Reading, Massachusetts}, + year = 1983 +} + +@techreport{TeX.Roff, + author = "Michael Urban", + title = "{A Guide to \TeX{} for the Troff User}", + institution= {TRW Software Productivity Project}, + month = oct, + year = 1984 +} + +@misc{TeX.Trip, + author = "Donald E. Knuth", + title = "{A Test File for \TeX{}}", + month = jul, + year = 1983, + note = {Version 0.999} +} + +@manual{TLI, + key = {ATT}, + title = "{Network Programmer's Guide}", + organization= {AT\&T}, + year = 1988, + note = {UNIX System V/386} +} + +@manual{UCI.map, + title = "{The UCI RoadMap}", + author = mtr, + organization= nrtc, + month = jun, + year = 1986 +} + +@article{WEB.TUT, + author = "Donald E. Knuth", + title = "{Literate Programming}", + journal = {The Computer Journal}, + year = 1983 +} + +@manual{WEB.USR, + author = "Donald E. Knuth", + title = "{WEB USER MANUAL}", + year = 1983 +} diff --git a/doc/uknet90/trademark.tex b/doc/uknet90/trademark.tex new file mode 100644 index 0000000..dbd5af8 --- /dev/null +++ b/doc/uknet90/trademark.tex @@ -0,0 +1,75 @@ +% Trademarks... + +\def\gobble#1{} +\def\tradeORGfont{\sc} % used for organizations (e.g., ACM) +\def\tradeNAMfont{\sf} % used for names (e.g., Ada) + +\def\tradeorg#1{% + \tradeaux{#1}{\expandafter\gobble\string#1}\empty\tradeORGfont +} +\def\tradeorgn#1#2{% + \tradeaux{#1}{#2}\empty\tradeORGfont +} +\def\tradename#1#2#3{\tradeaux{#1}{#2}{#3}\tradeNAMfont} +\def\trademark#1#2{% + \tradeaux{#1}{\expandafter\gobble\string#1}{#2}\tradeNAMfont +} + +\def\tradeaux#1#2#3#4{% + \def#1/{\relax}% % in case #3 references #1 + \setbox0=\hbox{#3}% % when we make the \hbox + \ifdim\wd0>0pt + \gdef#1/{% + \tradeaux{#1}{#2}\empty{#4}% + #1/\footnote{#1/ is a trademark of #3.}% + }% + \else + \gdef#1/{{#4#2}}% + \fi +} + +\tradeorg\acm +\tradeorg\ansi +\tradename\Ada{Ada} + {the Department of Defense (\Ada/ Joint Program Office)} +\tradename\balance{Balance} {Sequent Computer Systems, Incorporated} +\tradeorg\bsd +\tradename\butterfly{Butterfly}{Bolt, Beranek, and Newman, Incorporated} +\tradeorg\ccitt +\tradename\cms{CMS} {International Business Machines, Incorporated} +\tradename\cpm{CP/M} {Digital Research Corporation} +\tradename\chrysalis{Chrysalis}{Bolt, Beranek, and Newman, Incorporated} +\tradename\decnet{DECnet} {Digital Equipment Corporation} +\tradeorgn\dod{DoD} +\tradename\dynix{DYNIX} {Sequent Computer Systems, Incorporated} +\tradename\ethernet{Ethernet} {the Xerox Corporation} +\tradename\eunice{Eunice} \empty +\tradename\exos{EXOS} {Excelan, Incorporated} +\tradename\ibmpc{IBM PC} {International Business Machines, Incorporated} +\tradename\ibmpcat{IBM PC/AT} {International Business Machines, Incorporated} +\tradeorg\ieee +\tradename\iPSC{iPSC} {Intel Corporation} +\tradename\lattice{Lattice} {Lattice, Incorporated} +\tradename\locus{Locus} {Locus Computing Corporation} +\def\microvax/{$\mu$\vax/} +\def\microvms/{$\mu$\vms/} +\tradeorg\milstd +\tradename\msdos{MS-DOS} {Microsoft Corporation} +\tradename\mvs{MVS} {International Business Machines, Incorporated} +\tradename\pcdos{PC-DOS} {International Business Machines, Incorporated} +\tradename\pcinterface{PC-Interface}% + {Locus Computing Corporation} +\tradename\pdp{PDP} {Digital Equipment Corporation} +\tradename{\tops20}{Tops20} {Digital Equipment Corporation} +\tradename\trustedmail{Trusted\ Mail}% + {Trusted Technologies, Incorporated} +\tradename\tseries{T-Series} {Floating Point Systems} +\tradename\ultrix{ULTRIX} {Digital Equipment Corporation} +\tradename\unibus{UNIBUS} {Digital Equipment Corporation} +\tradename\unix{UNIX} {AT\&T Bell Laboratories} +\tradename\vax{VAX} {Digital Equipment Corporation} +\tradename\vaxstation{VAXstation}% + {Digital Equipment Corporation} +\tradename\vm{VM} {International Business Machines, Incorporated} +\tradename\vms{VMS} {Digital Equipment Corporation} +\tradename\xenix{Xenix} {Microsoft Corporation} diff --git a/doc/uknet90/version.sh b/doc/uknet90/version.sh new file mode 100755 index 0000000..1b473ee --- /dev/null +++ b/doc/uknet90/version.sh @@ -0,0 +1,19 @@ +if [ "x$1" = x ]; then echo 'usage: version.sh top-level-file' 1>&2; exit 1; fi + +if [ ! -r $1.major ]; then + echo 1 > $1.major + rm -f $1.minor +fi +if [ ! -r $1.minor ]; then echo 0 > $1.minor; fi + +echo '\begingroup' > $1.vrsn +echo ' \catcode`\#=12' >> $1.vrsn + +echo `cat $1.major $1.minor` | \ +awk ' { major = $1; minor = $2 + 1}\ +END { printf " \\gdef\\versiontag/{#%d.%d}%%\n", major, minor >> "'$1.vrsn'"; \ + printf "%d\n", minor > "'$1.minor'"; }' + +echo ' \gdef\versiondate/{'`date`'}%' >> $1.vrsn +echo '\endgroup' >> $1.vrsn +echo '\typeout{Version \versiontag/ of \versiondate/}' >> $1.vrsn diff --git a/doc/unix-niftp/Makefile b/doc/unix-niftp/Makefile new file mode 100644 index 0000000..7707ad5 --- /dev/null +++ b/doc/unix-niftp/Makefile @@ -0,0 +1,13 @@ +# +# makefile for unix niftp document +# +# + +nroff: unix-niftp-pp.txt +unix-niftp-pp.txt: unix-niftp-pp.ms + nroff -ms $? > $@ + +clean: + rm -f unix-niftp-pp.txt + +install tidy depend:; diff --git a/doc/unix-niftp/make b/doc/unix-niftp/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/doc/unix-niftp/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/doc/unix-niftp/unix-niftp-pp.ms b/doc/unix-niftp/unix-niftp-pp.ms new file mode 100644 index 0000000..c114c9e --- /dev/null +++ b/doc/unix-niftp/unix-niftp-pp.ms @@ -0,0 +1,258 @@ +.ds Un \s-2\fIUNIX-NIFTP\fP\s+2 +.de Eg +.sp +.in +5 +.nf +.. +.de Ee +.sp +.fi +.in -5 +.. +.de Ts +.in +5 +.sp +.nf +.. +.de Te +.sp +.in -5 +.fi +.. +.TL +Configuring \*(Un for use with PP. +.AU +Julian Onions +J.Onions@xtel.co.uk +.AI +X-Tel Services Ltd +Nottingham University +Nottingham NG7 2RD +.SH +Introduction +.LP +This short note is intended to be a stop-gap that covers what you need +to know to install \*(Un for operation with PP. It is not +intended to be a tutorial on \*(Un, partly because I don't know enough +and partly because I don't have time. +.LP +The \*(Un package is powerful and has many options, this note is not +meant to be exhaustive or to even try covering all options. It is +simply to get you started. There are many improvements and different +configurations that you could have, but to discover these you will +have to read the README files, the code and ask on the unix-niftp list +(unix-niftp@cs.nott.ac.uk \- unix-niftp-request@cs.nott.ac.uk to join).. +.SH +Compilation +.LP +Currently, both PP and \*(Un think they are in charge of compilation, +therefore there is a slight bootstrap problem. The best method +currently therefore is the following. +.IP 1. +Compile PP without the greybook channel. This is done by not +specifying \*Qgrey\*U in the OPTIONALCHANS variable in Make.defs. +.IP 2. +Compile \*(Un +.IP 3. +Compile PP with the greybook channel (e.g. add it back to OPTIONALCHANS). +.LP +To configure and compile, \*(Un, you basically run \fIConfigure\fP and +answer the questions it asks. Make sure you request use of PP in the +unspooled mode. Other questions such as the place for binaries etc are +up to you. if you don't understand the question \fIConfigure\fP is asking, +hit return and it will normally \*Qdo the right thing\*U. +.Eg +% sh Configure +... lots of questions ... +.Ee +.LP +Once the configuration process is over, type \fImake\fP and wait. +.Eg +% make +.Ee +There should be no problems at this stage. +.LP +After this completes, you should next type \*Q\fImake fullinstall\fP\*U +which should install everything in the correct place. It will also ask +you for a master password. This is only used for ftp transfers, and +you can type anything you like here if you are going to using +\*(Un for PP mail only. Otherwise you should choose a good password, +and forget it! +.Eg +% make fullinstall +.Ee +.SH +Configuring the runtime system +.LP +The next step is to configure the run time support system and database +that \*(Un needs. +This consists of first creating a tailor file (usually stored in +/etc/niftptailor) and secondly building a dbm database of hosts. +.SH 2 +Tailoring the system. +.LP +A sample tailor file can be found in Appendix A. However, the +necessary lines you will need are the following. +.Eg +QUEUE PP level=7,prog=psun +.Ee +This line defines the PP queue. The name \*QPP\*U is what PP will use as +its queue name. The level is for logging in the niftp logs. Suitable +levels vary from \*Q1\*U, minimal logging, through \*Q7\*U - some logging, +to \*Q-1\*U - all logging. +The prog bit is superfluous, but doesn't hurt. +.Eg +NET janet queue=qj,address="000021001029/%E%X%D/%T" +.Ee +This line identifies the network \*Qjanet\*U for outgoing calls. +When the PP greybook channel makes a call, it consults the info field +of the channel to determine the network. This is used to work out what +address to use in outgoing calls. +The queue key sets the queue, but I don't know why. +The address key/value sets up the calling and called addresses +respectively. These are constructed in a printf like manner with +literal characters copied and %'s marking substitutions. +The following substitutions are legal, +but the default above is suitable - with the appropriate DTE of +course. +.Ts +.ta \w'%X\0\0'u +%E The relevant YBTS string for the calling address (e.g. FTP.MAIL) +%X Separator between calling and called address +%D Destination DTE number +%T Destination YBTS string (e.g. FTP, FTP.MAIL) +%O The variable set by OURNAME. +%P pink book context +.Te +So, the above string with DTE of 00000511160005 and a YB string of +UCL-CS.FTP.MAIL we would generate +.Ts +.ta \w'calling address:\0\0'u +calling address: 000021001029/FTP.MAIL +called address: 00000511160005/UCL-CS.FTP.MAIL +.Te +.Eg +LISTEN pj address="FTP.MAIL",level=7,prog=qsun,channel=janet +.Ee +This line registers a listener for incoming mail. The address, +\*QFTP.MAIL\*U is not explicitly used in this situation -0 but is a +useful reminder. The level specifies a logging level of \*Q7\*U, and +claims to be from the janet network. This implies that it will be +channel \*Qgb-janet\*U when passing on to PP. +.LP +This is all that is essential for PP to make use of \*(Un. There are +some external things to set up as explained later however. +However, there are a number of useful variables you can set that help +if you wish to move things around (such as log directories for +example). Some of the more useful ones are given in Appendix B. +.SH 2 +Building the database. +.LP +The easiest way of building the database is with the c-nrs program. In +fact, this is so easy that I'm not going to describe other methods! +So, first get hold of the c-nrs package and build that. Once this is +done, you can then generate the \*(Un database by the following +commands. +.Eg +nrs dbm1.cf > dbm1 +nrs dbm1.cf 'output reverse' >> dbm1 +dbencode < dbm1 +.Ee +What could be simpler! +.SH +Testing the system for outgoing message. +.LP +With all this done, the system should now work for outgoing calls. +Make sure you have done a \*Qmake install\*U in PP's Chans/grey +directory to get the greybook channel installed. Now mail a message to +a host that makes use of the grey book channel and see if it works. +If it doesn't you will hopefully get a useful diagnostic. This will +appear usually in either the PP log directory in a file such as +\*Qgreyout\*U or in the \*(Un log directory in \*Qlog.pPP\*U. +.LP +A useful test that things are set up is to run the \*(Un program +\fIlookdbm\fP. This looks up names in the database. +.Eg +% bin/lookdbm uk.ac.ucl.cs +.Ee +This checks that the tailoring is correct and the database is present. +.SH +Setting up the incoming system. +.LP +This is best done by running a daemon such as ybtsd. This daemon is +started at boot time usually and listens for Yellow Book transport +calls. When one is received, it looks at the Yellow Book address and +determines what program to call to process this. This matching up is +done through the file ybts-auth. This is usually in an \*Qetc\*U +directory. It can be /etc/ybts-auth, /usr/local/etc/ybts-auth or +/etc/sunlink/cbs/ybts-auth. +.LP +To configure PP to accept incoming calls you need to do the following. +In the PP chans directory, make a symbolic link from greyin to the +name of the LISTEN name in the \*(Un file. This is \*Qpj\*U in the above +example. +.Eg +% ln -s greyin pj +.Ee +Now arrange for the ybtsd to invoke this process for incoming FTP.MAIL +requests. A suitable line in the ybts-auth file might be +.Eg +/usr/pp/chans/pj:ftp.mail:* +.Ee +The first part being the pathname of the symbolic link you just +created, the second being the YBTS address (ftp.mail) and the third +field saying any calling address is allowed to invoke this. +.LP +This should now be set up to allow incoming and outgoing mail. +.bp +.SH +Appendix A \- sample tailor file +.LP +.Eg +# known about queues +QUEUE qj level=7,prog=psun +QUEUE PP level=7,prog=psun + + +# various configuration details for each network +NET janet queue=qj,address="YOUR-DTE-HERE/%E%X%D/%T" + +# Domains that we know about +DOMAIN "uk.ac", "uk","uk.co" + +# The listener information +LISTEN pj address="FTP.MAIL",level=107,prog=qsun,channel=janet +.Ee +.bp +.SH +Appendix B \- useful tailor variables +.LP +The following is a list of the more useful things that you can tailor. +This list is not exhaustive! +.IP BINDIR 10 +The directory where binaries private to the \*(Un are looked for. +.Eg +BINDIR /usr/lib/niftp +.Ee +.IP DOMAIN +A list of domain prefixes. When looking for an NRS name, the software +will try adding these names to what it is looking for should the first +lookup fail. +.Eg +DOMAIN "uk.ac", "uk.co" +.Ee +.IP LOGDIR +The directory in which the log files are created and written. +.Eg +LOGDIR /usr/spool/niftp/logs +.Ee +.IP OURNAME +Sets the %O string. +.Eg +OURNAME 000021001029 +.Ee +.IP TABLE +The DBM database that contains the NRS name to address translations. +.Eg +TABLE /usr/spool/niftp/nrsdbm +.Ee diff --git a/examples/INTERNET/Makefile b/examples/INTERNET/Makefile new file mode 100644 index 0000000..01b3017 --- /dev/null +++ b/examples/INTERNET/Makefile @@ -0,0 +1,114 @@ +# Installation file for the INTERNET basic setup +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +TABLES = \ + aliases \ + auth.channel \ + auth.mta \ + auth.qmgr \ + auth.user \ + ch.list \ + ch.local \ + ch.shell \ + ch.uucp \ + ch.x400in84 \ + ch.x400in88 \ + ch.x400out84 \ + ch.x400out88 \ + channel \ + domain \ + foo \ + or \ + or2rfc \ + rfc1148gate \ + rfc2or \ + users + +WARNINGS = \ + warning.1 \ + warning.2 + +BUILD = $(TABLES) $(WARNINGS) README isoentities.add tailor x500.sample +EXT = I +WARNDIR = $(TBLDIR)/warnings + +############################################################ +# +# Building Rules +# +############################################################ + +default: build + +install: build inst-tailor inst-tables inst-warnings + + +inst-tailor: tailor + @sh -c "if [ -f $(TAILOR) ];\ + then echo $(TAILOR) already exists - installation aborted; exit 1;\ + else exit 0; \ + fi" + cp tailor $(TAILOR) + +inst-tables: $(TABLES) + @for i in $(TABLES);\ + do \ + if [ -f $(TBLDIR)/$$i ]; \ + then \ + echo mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak; \ + mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(TBLDIR); \ + cp $$i $(TBLDIR) || exit 1; \ + done + +inst-warnings: $(WARNINGS) + sh -c "if [ -d $(WARNDIR) ];\ + then echo "$(WARNDIR) does not exit - creating it"; \ + mkdir $(WARNDIR);\ + $(CHOWN) pp $(WARNDIR);\ + $(CHMOD) 755 $(WARNDIR);\ + fi + @for i in $(WARNINGS); \ + do \ + if [ -f $(WARNDIR)/$$i ]; \ + then \ + echo mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak; \ + mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(WARNDIR); \ + cp $$i $(WARNDIR) || exit 1; \ + done + + +rebuild: clean build + +clean: ; rm -f $(BUILD) + +build: $(BUILD) +$(BUILD): + -@rm -f $@ + @sh -c "if [ -f ../master/$@-$(EXT) ]; then \ + echo ln ../master/$@-$(EXT) $@; \ + ln ../master/$@-$(EXT) $@ || exit 1; \ + else \ + echo ln ../master/$@ $@; \ + ln ../master/$@ $@ || exit 1; \ + fi" + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/INTERNET/make b/examples/INTERNET/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/examples/INTERNET/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/JANET/Makefile b/examples/JANET/Makefile new file mode 100644 index 0000000..15722c4 --- /dev/null +++ b/examples/JANET/Makefile @@ -0,0 +1,114 @@ +# Installation file for the JANET basic setup +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +TABLES = \ + aliases \ + auth.channel \ + auth.mta \ + auth.qmgr \ + auth.user \ + ch.list \ + ch.local \ + ch.shell \ + ch.uucp \ + ch.x400in84 \ + ch.x400in88 \ + ch.x400out84 \ + ch.x400out88 \ + channel \ + domain \ + foo \ + or \ + or2rfc \ + rfc1148gate \ + rfc2or \ + users + +WARNINGS = \ + warning.1 \ + warning.2 + +BUILD = $(TABLES) $(WARNINGS) README isoentities.add tailor x500.sample +EXT = J +WARNDIR = $(TBLDIR)/warnings + +############################################################ +# +# Building Rules +# +############################################################ + +default: build + +install: build inst-tailor inst-tables inst-warnings + + +inst-tailor: tailor + @sh -c "if [ -f $(TAILOR) ];\ + then echo $(TAILOR) already exists - installation aborted; exit 1;\ + else exit 0; \ + fi" + cp tailor $(TAILOR) + +inst-tables: $(TABLES) + @for i in $(TABLES);\ + do \ + if [ -f $(TBLDIR)/$$i ]; \ + then \ + echo mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak; \ + mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(TBLDIR); \ + cp $$i $(TBLDIR) || exit 1; \ + done + +inst-warnings: $(WARNINGS) + sh -c "if [ -d $(WARNDIR) ];\ + then echo "$(WARNDIR) does not exit - creating it"; \ + mkdir $(WARNDIR);\ + $(CHOWN) pp $(WARNDIR);\ + $(CHMOD) 755 $(WARNDIR);\ + fi + @for i in $(WARNINGS); \ + do \ + if [ -f $(WARNDIR)/$$i ]; \ + then \ + echo mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak; \ + mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(WARNDIR); \ + cp $$i $(WARNDIR) || exit 1; \ + done + + +rebuild: clean build + +clean: ; rm -f $(BUILD) + +build: $(BUILD) +$(BUILD): + -@rm -f $@ + @sh -c "if [ -f ../master/$@-$(EXT) ]; then \ + echo ln ../master/$@-$(EXT) $@; \ + ln ../master/$@-$(EXT) $@ || exit 1; \ + else \ + echo ln ../master/$@ $@; \ + ln ../master/$@ $@ || exit 1; \ + fi" + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/JANET/make b/examples/JANET/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/examples/JANET/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/LOCALSMTP/Makefile b/examples/LOCALSMTP/Makefile new file mode 100644 index 0000000..ceb1add --- /dev/null +++ b/examples/LOCALSMTP/Makefile @@ -0,0 +1,114 @@ +# Installation file for the LOCALSMTP basic setup +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +TABLES = \ + aliases \ + auth.channel \ + auth.mta \ + auth.qmgr \ + auth.user \ + ch.list \ + ch.local \ + ch.shell \ + ch.uucp \ + ch.x400in84 \ + ch.x400in88 \ + ch.x400out84 \ + ch.x400out88 \ + channel \ + domain \ + foo \ + or \ + or2rfc \ + rfc1148gate \ + rfc2or \ + users + +WARNINGS = \ + warning.1 \ + warning.2 + +BUILD = $(TABLES) $(WARNINGS) README isoentities.add tailor x500.sample +EXT = L +WARNDIR = $(TBLDIR)/warnings + +############################################################ +# +# Building Rules +# +############################################################ + +default: build + +install: build inst-tailor inst-tables inst-warnings + + +inst-tailor: tailor + @sh -c "if [ -f $(TAILOR) ];\ + then echo $(TAILOR) already exists - installation aborted; exit 1;\ + else exit 0; \ + fi" + cp tailor $(TAILOR) + +inst-tables: $(TABLES) + @for i in $(TABLES);\ + do \ + if [ -f $(TBLDIR)/$$i ]; \ + then \ + echo mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak; \ + mv $(TBLDIR)/$$i $(TBLDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(TBLDIR); \ + cp $$i $(TBLDIR) || exit 1; \ + done + +inst-warnings: $(WARNINGS) + sh -c "if [ -d $(WARNDIR) ];\ + then echo "$(WARNDIR) does not exit - creating it"; \ + mkdir $(WARNDIR);\ + $(CHOWN) pp $(WARNDIR);\ + $(CHMOD) 755 $(WARNDIR);\ + fi + @for i in $(WARNINGS); \ + do \ + if [ -f $(WARNDIR)/$$i ]; \ + then \ + echo mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak; \ + mv $(WARNDIR)/$$i $(WARNDIR)/$$i.bak || exit 1; \ + fi; \ + echo cp $$i $(WARNDIR); \ + cp $$i $(WARNDIR) || exit 1; \ + done + + +rebuild: clean build + +clean: ; rm -f $(BUILD) + +build: $(BUILD) +$(BUILD): + -@rm -f $@ + @sh -c "if [ -f ../master/$@-$(EXT) ]; then \ + echo ln ../master/$@-$(EXT) $@; \ + ln ../master/$@-$(EXT) $@ || exit 1; \ + else \ + echo ln ../master/$@ $@; \ + ln ../master/$@ $@ || exit 1; \ + fi" + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/LOCALSMTP/make b/examples/LOCALSMTP/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/examples/LOCALSMTP/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..5a9c845 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,37 @@ +# Channel master makefile +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +SUBDIRS = master LOCALSMTP INTERNET JANET + +############################################################ +# +# Building Rules +# +############################################################ + +target: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE)); done + +tidy define depend clean lint: + @for i in ${SUBDIRS} ; \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@); done + +install:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/README b/examples/README new file mode 100644 index 0000000..10a2bfb --- /dev/null +++ b/examples/README @@ -0,0 +1,21 @@ +This directory contains several configurations. This includes +some real configurations, and some "unreal" configurations. + +Currently, the real configurations reflect what is being used +at X-Tel. + +The unreal configurations are meant to help you get started the first +time, they are not meant for serious use. They will get you started +but after that you must hand configure to your specific requirements. +The sample unreal configuration are targeted towards the following: + +LOCALSMTP - a site with local deliver and limited smtp capabilities. + Local mail will be delivered locally, all other mail will be + pushed by smtp to a site which can deal with it. + +JANET - a site on JANET with access to the NRS database and some local + smtp capability. + +INTERNET - a site on the internet with access to the full Domain Name + Server tree and full SMTP interconnectivity. + diff --git a/examples/make b/examples/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/examples/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/master/Makefile b/examples/master/Makefile new file mode 100644 index 0000000..abb4497 --- /dev/null +++ b/examples/master/Makefile @@ -0,0 +1,79 @@ +# Master Makefile. +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +FILES = README-I README-J README-L aliases auth.channel auth.mta \ + auth.qmgr auth.user ch.list ch.local ch.shell ch.uucp ch.x400in84 \ + ch.x400in88 ch.x400out84 ch.x400out88 channel-I channel-J channel-L \ + domain-I domain-J domain-L foo isoentities.add or or2rfc rfc2or \ + tailor-I tailor-J tailor-L users + + +############################################################ +# +# Building Rules +# +############################################################ + +build: $(FILES) + @echo "All built" + +clean: + rm -f README-? sed.cmds tailor-? tailor-?.rest + +install:; + +README-I: README-master Makefile sed.cmds + sed -e '/^%BEGIN(I)/d' -e '/^%END(I)/d' -e '/^%BEGIN/,/^%END/d' \ + -f sed.cmds \ + README-master | nroff > $@ + +README-J: README-master Makefile sed.cmds + sed -e '/^%BEGIN(J)/d' -e '/^%END(J)/d' -e '/^%BEGIN/,/^%END/d' \ + -f sed.cmds \ + README-master | nroff > $@ + +README-L: README-master Makefile sed.cmds + sed -e '/^%BEGIN(L)/d' -e '/^%END(L)/d' -e '/^%BEGIN/,/^%END/d' \ + -f sed.cmds \ + README-master | nroff > $@ + +sed.cmds: ../../Make.defs Makefile + echo "s:%TAILOR%:$(TAILOR):" > $@ + echo "s:%TABLES%:$(TBLDIR):" >> $@ + echo "s:%CMDDIR%:$(CMDDIR):" >> $@ + echo "s:%TOOLS%:$(TOOLDIR):" >> $@ + +tailor-I: tailor-I.head tailor-I.rest + cat tailor-I.head tailor-I.rest > $@ +tailor-I.rest: tailor.common + sed -e '/^%BEGIN(I)/d' -e '/^%END(I)/d' -e '/^%BEGIN/,/^%END/d' \ + $? > $@ + +tailor-J: tailor-J.head tailor-J.rest + cat tailor-J.head tailor-J.rest > $@ +tailor-J.rest:tailor.common + sed -e '/^%BEGIN(J)/d' -e '/^%END(J)/d' -e '/^%BEGIN/,/^%END/d' \ + $? > $@ + +tailor-L: tailor-L.head tailor-L.rest + cat tailor-L.head tailor-L.rest > $@ +tailor-L.rest:tailor.common + sed -e '/^%BEGIN(L)/d' -e '/^%END(L)/d' -e '/^%BEGIN/,/^%END/d' \ + $? > $@ + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/master/README b/examples/master/README new file mode 100644 index 0000000..548118b --- /dev/null +++ b/examples/master/README @@ -0,0 +1 @@ +This directory contains the building blocks for the sample configurations. diff --git a/examples/master/README-master b/examples/master/README-master new file mode 100644 index 0000000..e6ffafd --- /dev/null +++ b/examples/master/README-master @@ -0,0 +1,189 @@ +.de LP +.in 0 +.sp +.. +.de IP +.sp +.in 0 +.in +5 +.ti -5 +.ta +5 +\\$1\t\c +.. +.de DS +.sp +.nf +.in +3 +.. +.de DE +.sp +.fi +.in -3 +.. +.LP +%BEGIN(J) +This configuration is meant to be a simplistic Janet configuration. It +does only the basics to get the system going. A proper janet site +needs tables building directly from the nrs database. +.LP +This configuration relies on the grey book channel having been built. +This should be built in conjunction with the unix-niftp package. The +full channel and domain table should be built by the c-nrs processor +in PP mode. +%END(J) +%BEGIN(I) +The configuration presented here is intended to be that used by a +"normal" internet site. This means that the site should have a direct +IP connection to the Internet and make use of the DNS. +%END(I) +%BEGIN(L) +The configuration presented here is intended to be that used by a +a site with local smtp capability. The configuration will allow +delivery to a few local users and send all remote traffic to a single +host. +%END(L) +.LP +This is intended to be a first step that will get messages delivered to +a few selected people and make very little use of the more advanced +features. +.LP +To configure this version for use, do the following. +.nr Ct 0 1 +.IP \n+(Ct. +Run make install in this directory. This will install the files in the +correct places. +.DS +% ./make install +.DE +.IP \n+(Ct. +Edit the installed tailor file (%TAILOR%) to configure the site specific +parameters near the beginning of this file. +.DS +% vi %TAILOR% +.DE +.IP \n+(Ct. +Add the contents of the file isoentities.add to your system wide +isoentities file (usually either in /usr/etc). You will probably need +to be root to do this step. +.DS +% su +Password: +# vi /usr/etc/isoentities +.DE +This step is useful as a backup anyway, but if you have all your +applications registered in the X.500 directory, you should add such an +entry to that too. A sample entry is given in x500.sample. This should +be added (after editing) at the same position as your other local applications. +.DS +% dish -u +Welcome to Dish (DIrectory SHell) +Enter password for "": +Dish -> moveto cn= +Dish -> add "cn=pp qmgr" -objectclass "applicationEntity & quipuObject" +.DE +.IP \n+(Ct. +Change directory to the tables directory (%TABLES%). +.DS +% cd %TABLES% +.DE +.IP \n+(Ct. +Edit the users file and add a few local users using the format +given in that file. +.DS +% vi users +.DE +.IP \n+(Ct. +Edit the ch.local file and add the same users to that file. +.DS +% vi ch.local +.DE +%BEGIN(J) +.IP \n+(Ct. +Edit the channel and domain table and make the changes suggested +there. +.DS +% vi channel domain +.DE +%END(J) +%BEGIN(L) +.IP \n+(Ct. +Edit the channel and domain tables. In particular replace the strings +LOC-DOM-MTA, LOC-DOM-SITE and SMTP-RELAY with suitable hostnames. +.DS +% vi channel domain +.DE +%END(L) +.IP \n+(Ct. +Run dbmbuild (found in directory %CMDDIR%). +.DS +% %CMDDIR%/dbmbuild -v +.DE +.IP \n+(Ct. +Run ckconfig (found in the directory %CMDDIR%) and see if everything looks +reasonable. +.DS +% %CMDDIR%/ckconfig +.DE +.IP \n+(Ct. +Start the pptsapd and the qmgr +.DS +% %CMDDIR%/pptsapd >& /dev/null +% %CMDDIR%/qmgr >& /dev/null +.DE +.IP \n+(Ct. +Add an appropriate line to the /etc/inetd.conf file to allow smtp +incoming connections. An example might be +.DS +smtp stream tcp nowait pp /usr/pp/cmds/chans/smtpsrvr smtpsrvr smtp +.DE +After this you will need to do a kill -HUP on the inetd process to get +it to reread the configuration file. +If you are running another smtp service (e.g sendmail), make sure this +is no longer running. +.DS +% su +Password: +# vi /etc/inetd.conf +# ps -x +# kill -HUP +.DE +.LP +PP should now be ready for use. At this point it is worth testing out +a few things. Some simple tests are as follows: +.LP +Submit a message to local user you configured in and see if it is +delivered. This is easiest done by using the PP supplied mail program. +This is normally installed in the %CMDDIR% directory. A command such as +.DS +% %CMDDIR%/mail -s test pp < /etc/motd +.DE +is a good start. +.LP +Submit a message to some other local machine using the same syntax as +above. +.LP +If that works too, try a message to someone further afield. Use the +same method, just pick a remote address for testing. +.LP +This configuration is meant only to get you started. Once this is +running you will almost certainly want to do some of the following. +.IP o +Add all your users to the users and ch.local table by means of some +shell/awk script from local databases. +.IP o +Create some lists to be expanded by the list channel. +.IP o +Rebuild the domain and channel tables to take account of local knowledge. +.IP o +Add in the ability to use X.400. This is at present rather too +complicated to automate. +%BEGIN(J) +.IP o +For the addressign of all sites on JANET, you should process the nrs +database. There is a program available to do this, c-nrs. It is +available from pb@cam.cl and has a PP mode which will produce suitable +output for PP. +%END(J) +.LP +Full details for all these procedures are laid out in Volume 1 of the +PP manual. diff --git a/examples/master/aliases b/examples/master/aliases new file mode 100644 index 0000000..82d0a95 --- /dev/null +++ b/examples/master/aliases @@ -0,0 +1,23 @@ +############################################################ +# +# Alias table. +# +# This table has all the alias and renaming stuff in it. +# +# See volume 1 for full details. Simple aliases are put in as +# ":" "alias" +# +############################################################ +# +# Should always be an alias for postmaster +postmaster:alias pp +# +# Example of user mapping... +# +# jb is replaced by J.Bloggs in headers and addresses +# This affects the user table and the ch.local table, essentially, +# jb no longer exists after this, all references are to J.Bloggs +# +jb:synonym J.Bloggs +# +# diff --git a/examples/master/auth.channel b/examples/master/auth.channel new file mode 100644 index 0000000..7e9fdc4 --- /dev/null +++ b/examples/master/auth.channel @@ -0,0 +1,5 @@ +############################################################ +# +# AUTH.CHANNEL table not used in simple configuration +# +############################################################ diff --git a/examples/master/auth.mta b/examples/master/auth.mta new file mode 100644 index 0000000..00608fa --- /dev/null +++ b/examples/master/auth.mta @@ -0,0 +1,5 @@ +############################################################ +# +# AUTH.MTA table not used in simple configuration +# +############################################################ diff --git a/examples/master/auth.qmgr b/examples/master/auth.qmgr new file mode 100644 index 0000000..b601f08 --- /dev/null +++ b/examples/master/auth.qmgr @@ -0,0 +1,7 @@ +############################################################ +# +# Auth.qmgr - only browsing connections allowed +# +############################################################ + +anon:rights=limited diff --git a/examples/master/auth.user b/examples/master/auth.user new file mode 100644 index 0000000..dc2d570 --- /dev/null +++ b/examples/master/auth.user @@ -0,0 +1,5 @@ +############################################################ +# +# AUTH.USER table not used in simple configuration +# +############################################################ diff --git a/examples/master/ch.list b/examples/master/ch.list new file mode 100644 index 0000000..157155c --- /dev/null +++ b/examples/master/ch.list @@ -0,0 +1,12 @@ +############################################################ +# +# List channel table +# +# +# An example list, foo-list is shown here. +# +# ":" "," "file=" "," +# +############################################################ + +foo-list:pp,file=foo-list,An example list diff --git a/examples/master/ch.local b/examples/master/ch.local new file mode 100644 index 0000000..6bdd718 --- /dev/null +++ b/examples/master/ch.local @@ -0,0 +1,18 @@ +############################################################ +# +# Local channel table. +# +# This table maps address into usernames. For a simple +# configuration just keep addresses and usernames +# equivalent. Then to add new users to the system, just add +# a line of the form +# ":" = +# Most commonly username= +# +############################################################ +pp:username=pp +# +# Example user, J.Bloggs +# Deliver with uid jb +# +J.Bloggs:username=jb diff --git a/examples/master/ch.shell b/examples/master/ch.shell new file mode 100644 index 0000000..d7b7dc8 --- /dev/null +++ b/examples/master/ch.shell @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.shell table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/ch.uucp b/examples/master/ch.uucp new file mode 100644 index 0000000..ae94f4a --- /dev/null +++ b/examples/master/ch.uucp @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.uucp table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/ch.x400in84 b/examples/master/ch.x400in84 new file mode 100644 index 0000000..bd42c36 --- /dev/null +++ b/examples/master/ch.x400in84 @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.x400in84 table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/ch.x400in88 b/examples/master/ch.x400in88 new file mode 100644 index 0000000..edfb4ee --- /dev/null +++ b/examples/master/ch.x400in88 @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.x400in88 table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/ch.x400out84 b/examples/master/ch.x400out84 new file mode 100644 index 0000000..552cc26 --- /dev/null +++ b/examples/master/ch.x400out84 @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.x400out84 table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/ch.x400out88 b/examples/master/ch.x400out88 new file mode 100644 index 0000000..699736d --- /dev/null +++ b/examples/master/ch.x400out88 @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.x400out88 table is not used in this minimal setup +# +############################################################ diff --git a/examples/master/channel-I b/examples/master/channel-I new file mode 100644 index 0000000..8daed66 --- /dev/null +++ b/examples/master/channel-I @@ -0,0 +1,48 @@ +############################################################ +# +# For the internet case, all these top domains are resolved +# directly by the DNS system, and all are assumed to be +# delivered by smtp +# +############################################################ +arpa:(smtp) +at:(smtp) +au:(smtp) +bitnet:(smtp) +ca:(smtp) +cdn:(smtp) +cern.ch:(smtp) +cern:(smtp) +ch:(smtp) +chunet:(smtp) +com:(smtp) +de:(smtp) +dk:(smtp) +dunet:(smtp) +earn:(smtp) +edu:(smtp) +es:(smtp) +fi:(smtp) +fr:(smtp) +funet:(smtp) +gb:(smtp) +gov:(smtp) +ie:(smtp) +iris:(smtp) +isanet:(smtp) +kr:(smtp) +mil:(smtp) +net:(smtp) +nl:(smtp) +nz:(smtp) +org:(smtp) +osiride:(smtp) +pt:(smtp) +riup:(smtp) +se:(smtp) +sunet:(smtp) +surfnet:(smtp) +uninett:(smtp) +us:(smtp) +uk:(smtp) +uucp:(smtp) diff --git a/examples/master/channel-J b/examples/master/channel-J new file mode 100644 index 0000000..f09cd97 --- /dev/null +++ b/examples/master/channel-J @@ -0,0 +1,59 @@ +############################################################ +# +# This is an example channel table file for a JANET site. it contains +# mappings of the basic top level domains to some relays. It is almost +# certainly out of date and is incomplete. It should be replaced by +# an NRS generated one as soon as possible +# +############################################################ +# +# If you have local smtp capabilities - change the following name to +# a suitable host. Add more if required. +# +local-smtp-host-name:local-smtp-host-name(smtp) +# +# +#Add some more local janet sites here! +# +cs.nott.ac.uk:cs.nott.ac.uk(gb-janet) +cs.ucl.ac.uk:cs.ucl.ac.uk(gb-janet),cs.ucl.ac.uk(gb-pss) +# +# Top level relays +# +ie:earn-relay.ac.uk(gb-janet) +arpa:nsf.ac.uk(gb-janet) +nz:nsf.ac.uk(gb-janet) +at:ean.ac.uk(gb-janet) +au:ean.ac.uk(gb-janet) +bitnet:earn-relay.ac.uk(gb-janet) +ca:ean.ac.uk(gb-janet) +cdn:ean.ac.uk(gb-janet) +cern:ean.ac.uk(gb-janet) +ch:ean.ac.uk(gb-janet) +cern.ch:ean.ac.uk(gb-janet) +chunet:ean.ac.uk(gb-janet) +com:nsf.ac.uk(gb-janet) +de:ean.ac.uk(gb-janet) +dunet:ean.ac.uk(gb-janet) +earn:earn-relay.ac.uk(gb-janet) +edu:nsf.ac.uk(gb-janet) +es:ean.ac.uk(gb-janet) +fi:ean.ac.uk(gb-janet) +fr:cs.ucl.ac.uk(gb-janet) +funet:ean.ac.uk(gb-janet) +gb:cs.ucl.ac.uk(gb-janet) +gov:nsf.ac.uk(gb-janet) +iris:ean.ac.uk(gb-janet) +isanet:ean.ac.uk(gb-janet) +kr:ean.ac.uk(gb-janet) +mil:nsf.ac.uk(gb-janet) +net:nsf.ac.uk(gb-janet) +org:nsf.ac.uk(gb-janet) +osiride:ean.ac.uk(gb-janet) +pt:ean.ac.uk(gb-janet) +riup:ean.ac.uk(gb-janet) +se:ean.ac.uk(gb-janet) +sunet:ean.ac.uk(gb-janet) +surfnet:ean.ac.uk(gb-janet) +uninett:ean.ac.uk(gb-janet) +us:nsf.ac.uk(gb-janet) diff --git a/examples/master/channel-L b/examples/master/channel-L new file mode 100644 index 0000000..ca528b6 --- /dev/null +++ b/examples/master/channel-L @@ -0,0 +1,50 @@ +############################################################ +# +# This is a partial mapping for domains. It is not complete but +# covers most of those in common usage. +# +# SMTP-RELAY should be replaced by a host reachable by SMTP that +# can do the routing for you. +# +############################################################ +SMTP-RELAY:SMTP-RELAY(smtp) +arpa:SMTP-RELAY(smtp) +at:SMTP-RELAY(smtp) +au:SMTP-RELAY(smtp) +bitnet:SMTP-RELAY(smtp) +ca:SMTP-RELAY(smtp) +cdn:SMTP-RELAY(smtp) +cern.ch:SMTP-RELAY(smtp) +cern:SMTP-RELAY(smtp) +ch:SMTP-RELAY(smtp) +chunet:SMTP-RELAY(smtp) +com:SMTP-RELAY(smtp) +de:SMTP-RELAY(smtp) +dk:SMTP-RELAY(smtp) +dunet:SMTP-RELAY(smtp) +earn:SMTP-RELAY(smtp) +edu:SMTP-RELAY(smtp) +es:SMTP-RELAY(smtp) +fi:SMTP-RELAY(smtp) +fr:SMTP-RELAY(smtp) +funet:SMTP-RELAY(smtp) +gb:SMTP-RELAY(smtp) +gov:SMTP-RELAY(smtp) +ie:SMTP-RELAY(smtp) +iris:SMTP-RELAY(smtp) +isanet:SMTP-RELAY(smtp) +kr:SMTP-RELAY(smtp) +mil:SMTP-RELAY(smtp) +net:SMTP-RELAY(smtp) +nl:SMTP-RELAY(smtp) +nz:SMTP-RELAY(smtp) +org:SMTP-RELAY(smtp) +osiride:SMTP-RELAY(smtp) +pt:SMTP-RELAY(smtp) +riup:SMTP-RELAY(smtp) +se:SMTP-RELAY(smtp) +sunet:SMTP-RELAY(smtp) +surfnet:SMTP-RELAY(smtp) +uninett:SMTP-RELAY(smtp) +us:SMTP-RELAY(smtp) +uucp:SMTP-RELAY(smtp) diff --git a/examples/master/domain-I b/examples/master/domain-I new file mode 100644 index 0000000..849f59b --- /dev/null +++ b/examples/master/domain-I @@ -0,0 +1,51 @@ +############################################################ +# +# The domain table. This lists all known domains. By default an exact +# match is required, but a "*." preceeding an entry allows any number of +# subdomains. This table is set up most of the major top level domains +# are wildcarded. +# +############################################################ +LOC-DOM-MTA:local +LOC-DOM-SITE:local +*.arpa:key=arpa +*.at:key=at +*.au:key=au +*.bitnet:key=bitnet +*.ca:key=ca +*.cdn:key=cdn +*.cern.ch:key=cern.ch +*.cern:key=cern +*.ch:key=ch +*.chunet:key=chunet +*.com:key=com +*.de:key=de +*.dk:key=dk +*.dunet:key=dunet +*.earn:key=earn +*.edu:key=edu +*.es:key=es +*.fi:key=fi +*.fr:key=fr +*.funet:key=funet +*.gb:key=gb +*.gov:key=gov +*.ie:key=ie +*.iris:key=iris +*.isanet:key=isanet +*.kr:key=kr +*.mil:key=mil +*.net:key=net +*.nl:key=nl +*.nz:key=nz +*.org:key=org +*.osiride:key=osiride +*.pt:key=pt +*.riup:key=riup +*.se:key=se +*.sunet:key=sunet +*.surfnet:key=surfnet +*.uninett:key=uninett +*.us:key=us +*.uk:key=uk +*.uucp:key=uucp diff --git a/examples/master/domain-J b/examples/master/domain-J new file mode 100644 index 0000000..6fb07d5 --- /dev/null +++ b/examples/master/domain-J @@ -0,0 +1,64 @@ +############################################################ +# +# The domain table. This lists all known domains. By default an exact +# match is required, but a "*." preceeding an entry allows any number of +# subdomains. This table is set up most of the major top level domains +# are wildcarded. +# +# First few entries are specific hosts that should be tailored. +# +############################################################ +# +#Add entries here for local hosts - see channel table +# +LOC-DOM-MTA:local +LOC-DOM-SITE:local +# +# Add some more local janet sites here - should match entries in +# the channel table +# +xtel.co.uk:mta=xtel.co.uk +cs.ucl.ac.uk:mta=cs.ucl.ac.uk +# +# Top level domains +# +*.arpa:key=arpa +*.at:key=at +*.au:key=au +*.bitnet:key=bitnet +*.ca:key=ca +*.cdn:key=cdn +*.cern.ch:key=cern.ch +*.cern:key=cern +*.ch:key=ch +*.chunet:key=chunet +*.com:key=com +*.de:key=de +*.dk:key=dk +*.dunet:key=dunet +*.earn:key=earn +*.edu:key=edu +*.es:key=es +*.fi:key=fi +*.fr:key=fr +*.funet:key=funet +*.gb:key=gb +*.gov:key=gov +*.ie:key=ie +*.iris:key=iris +*.isanet:key=isanet +*.kr:key=kr +*.mil:key=mil +*.net:key=net +*.nl:key=nl +*.nz:key=nz +*.org:key=org +*.osiride:key=osiride +*.pt:key=pt +*.riup:key=riup +*.se:key=se +*.sunet:key=sunet +*.surfnet:key=surfnet +*.uninett:key=uninett +*.us:key=us +*.uucp:key=uucp diff --git a/examples/master/domain-L b/examples/master/domain-L new file mode 100644 index 0000000..90bf66e --- /dev/null +++ b/examples/master/domain-L @@ -0,0 +1,51 @@ +############################################################ +# +# The domain table. This lists all known domains. By default an exact +# match is required, but a "*." preceeding an entry allows any number of +# subdomains. This table is set up most of the major top level domains +# are wildcarded. +# +############################################################ +LOC-DOM-MTA:local +LOC-DOM-SITE:local +SMTP-RELAY:mta=SMTP-RELAY +*.arpa:key=arpa +*.at:key=at +*.au:key=au +*.bitnet:key=bitnet +*.ca:key=ca +*.cdn:key=cdn +*.cern.ch:key=cern.ch +*.cern:key=cern +*.ch:key=ch +*.chunet:key=chunet +*.com:key=com +*.de:key=de +*.dk:key=dk +*.dunet:key=dunet +*.earn:key=earn +*.edu:key=edu +*.es:key=es +*.fi:key=fi +*.fr:key=fr +*.funet:key=funet +*.gb:key=gb +*.gov:key=gov +*.ie:key=ie +*.iris:key=iris +*.isanet:key=isanet +*.kr:key=kr +*.mil:key=mil +*.net:key=net +*.nl:key=nl +*.nz:key=nz +*.org:key=org +*.osiride:key=osiride +*.pt:key=pt +*.riup:key=riup +*.se:key=se +*.sunet:key=sunet +*.surfnet:key=surfnet +*.uninett:key=uninett +*.us:key=us +*.uucp:key=uucp diff --git a/examples/master/foo b/examples/master/foo new file mode 100644 index 0000000..ed4f642 --- /dev/null +++ b/examples/master/foo @@ -0,0 +1 @@ +pp diff --git a/examples/master/isoentities.add b/examples/master/isoentities.add new file mode 100644 index 0000000..f2a7309 --- /dev/null +++ b/examples/master/isoentities.add @@ -0,0 +1,23 @@ +# +# Isoentnties addition for the qmgr monitor program +# +# + +# +# Change, +# mylocalhostname - this should be the name of the host on which the +# qmgr is to run +# Network-address should be the Network address in string format for this +# entity. It must contain a TCP port or X.25 PID. +# Examples of this might be +# Internet=128.243.20.1+18000 +# LOCAL-ETHER=128.243.20.1+18000 +# Janet=000021000018+PID+04018100 +# A Complete example might be +# john "pp-qmgr" 1.17.6.2.1 \ +# LOCAL-ETHER=john+18000 +# +# + +mylocalhostname "pp qmgr" 1.17.6.2.1 \ + INTERNET=mylocalhostname+18000 diff --git a/examples/master/make b/examples/master/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/examples/master/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/master/or b/examples/master/or new file mode 100644 index 0000000..8c8f890 --- /dev/null +++ b/examples/master/or @@ -0,0 +1,5 @@ +############################################################ +# +# OR table not used in simple configuration +# +############################################################ diff --git a/examples/master/or2rfc b/examples/master/or2rfc new file mode 100644 index 0000000..26f1f25 --- /dev/null +++ b/examples/master/or2rfc @@ -0,0 +1,5 @@ +############################################################ +# +# OR2RFC table not used in simple configuration +# +############################################################ diff --git a/examples/master/rfc1148gate b/examples/master/rfc1148gate new file mode 100644 index 0000000..3d5da42 --- /dev/null +++ b/examples/master/rfc1148gate @@ -0,0 +1 @@ +# This file is not used in the example configurations. diff --git a/examples/master/rfc2or b/examples/master/rfc2or new file mode 100644 index 0000000..cbb79b2 --- /dev/null +++ b/examples/master/rfc2or @@ -0,0 +1,5 @@ +############################################################ +# +# RFC2OR table not used in simple configuration +# +############################################################ diff --git a/examples/master/tailor-I.head b/examples/master/tailor-I.head new file mode 100644 index 0000000..ab94a89 --- /dev/null +++ b/examples/master/tailor-I.head @@ -0,0 +1,53 @@ +############################################################ +# +# Tailor file for PP +# +# This version for Internet site +# +############################################################ + +############################################################ +# +# The following variables will need tailoring +# +############################################################ +# +# The loc_dom_mta is the host that the MTA will reside on and execute from +# It is a fully qualified domain name and represent the physical machine +# Examples might be +# cheetah.nyser.net +# violet.berkeley.edu +# +loc_dom_mta mylocalhost.localdomain.us +# +# The Sitename is what the rest of the world sees you as. This is typically +# a domain shorter than the full domain name. It is the name used to represent +# your site or group as a whole. This name normally hides the individual +# machine names +# Examples might be +# berkeley.edu +# nyser.net +# +loc_dom_site localdomain.us +# +# The postmaster should include the local site name +# e.g. postmaster@berkeley.edu or postmaster@nyser.net +# +postmaster postmaster@localdomain.us +# +# The pplogin should be the username of the owner of pp. +# +pplogin pp +# +# The qmgrhost should be the same as the name found in isoentities file. +# This can be the same as loc_dom_mta name +# +qmgrhost mylocalhost +# +# The local or name should be the name of your site in X.400 terms. +# This is attribute value based, and starts with organisational units and +# works up to country. If you are unsure, you can leave it with just +# a country component and blank admd, e.g. "/ADMD= /C=US/" +# +loc_or "/ou=research/o=Berkeley University/prmd=Internet/admd= /c=US/" + diff --git a/examples/master/tailor-J.head b/examples/master/tailor-J.head new file mode 100644 index 0000000..d3df8f5 --- /dev/null +++ b/examples/master/tailor-J.head @@ -0,0 +1,53 @@ +############################################################ +# +# Tailor file for PP +# +# This version for Janet site +# +############################################################ + +############################################################ +# +# The following variables will need tailoring +# +############################################################ +# +# The loc_dom_mta is the host that the MTA will reside on and execute from +# It is a fully qualified domain name and represent the physical machine +# Examples might be +# lancaster.xtel.co.uk +# bells.cs.ucl.ac.uk +# +loc_dom_mta mylocalhost.localdomain.uk +# +# The Sitename is what the rest of the world sees you as. This is typically +# a domain shorter than the full domain name. It is the name used to represent +# your site or group as a whole. This name normally hides the individual +# machine names +# Examples might be +# xtel.co.uk +# cs.ucl.ac.uk +# +loc_dom_site localdomain.uk +# +# The postmaster should include the local site name +# e.g. postmaster@berkeley.edu or postmaster@nyser.net +# +postmaster postmaster@localdomain.uk +# +# The pplogin should be the username of the owner of pp. +# +pplogin pp +# +# The qmgrhost should be the same as the name found in isoentities file. +# This can be the same as loc_dom_mta name +# +qmgrhost mylocalhost +# +# The local or name should be the name of your site in X.400 terms. +# This is attribute value based, and starts with organisational units and +# works up to country. If you are unsure, leave it with just a country +# a country component and blank admd, e.g. "/ADMD= /C=GB/" +# +loc_or "/ou=research/o=Brumchester University/prmd=UK.AC/admd= /c=GB/" + diff --git a/examples/master/tailor-L.head b/examples/master/tailor-L.head new file mode 100644 index 0000000..f7f6cab --- /dev/null +++ b/examples/master/tailor-L.head @@ -0,0 +1,54 @@ +############################################################ +# +# Tailor file for PP +# +# This version for sites with local smtp +# +############################################################ + +############################################################ +# +# The following variables will need tailoring +# +############################################################ +# +# The loc_dom_mta is the host that the MTA will reside on and execute from +# It is a fully qualified domain name and represent the physical machine +# Examples might be +# cheetah.nyser.net +# violet.berkeley.edu +# john.cs.nott.ac.uk +# +loc_dom_mta mylocalhost.localdomain.us +# +# The Sitename is what the rest of the world sees you as. This is typically +# a domain shorter than the full domain name. It is the name used to represent +# your site or group as a whole. This name normally hides the individual +# machine names +# Examples might be +# berkeley.edu +# nyser.net +# cs.nott.ac.uk +# +loc_dom_site localdomain +# +# The postmaster should include the local site name +# e.g. postmaster@berkeley.edu or postmaster@cs.nott.ac.uk +# +postmaster postmaster@localdomain +# +# The pplogin should be the username of the owner of pp. +# +pplogin pp +# +# The qmgrhost should be the same as the name found in isoentities file. +# This can be the same as loc_dom_mta name +# +qmgrhost mylocalhost +# +# The local or name should be the name of your site in X.400 terms. +# This is attribute value based, and starts with organisational units and +# works up to country. If you are unsure, leave it with just a country +# a country component and blank admd, e.g. "/ADMD= /C=US/" +# +loc_or "/ou=CS/o=NOTT/prmd=UK.AC/admd=GOLD 400/c=GB/" diff --git a/examples/master/tailor.common b/examples/master/tailor.common new file mode 100644 index 0000000..aeb68b5 --- /dev/null +++ b/examples/master/tailor.common @@ -0,0 +1,188 @@ +############################################################ +# +# That is the end of the things you must tailor - the rest are +# probably ok - but you should check. +# +############################################################ + +delim1 "\1\1\1\1\12" +delim2 "\1\1\1\1\12" + +authchannel free +authloglevel high +wrndfldir warnings + +# Body types + +%BEGIN(J)% +headertype 822 822-jnt 822-us 822-uk +%END(J)% +%BEGIN(I)% +headertype 822 822-us +%END(I)% +%BEGIN(L)% +headertype 822 822-us +%END(L)% +bodypart ia5 + + +# **-- Mapping tables --** +# +# All of these table MUST have the names given here +tbl aliases show="Aliases: mapping -> local id", +tbl users show="Users: mapping local id -> disposition", +tbl domain show="Mapping domain key ->full domain/MTA", +tbl or show="Mapping O/R Address -> MTA",flags=dbm +tbl channel show="Binding MTA -> Channels",flags=dbm +tbl or2rfc show="RFC 987: X.400 -> RFC 822",flags=dbm +tbl rfc2or show="RFC 987: RFC 822 -> X.400",flags=dbm +tbl rfc1148gate show="Gateways that perform RFC 1148 conversions", +tbl auth.channel show="Authorisation: channel policy",flags=dbm +tbl auth.mta show="Authorisation: mta based",flags=dbm +tbl auth.user show="Authorisation: user based",flags=dbm +tbl auth.qmgr show="Authorisation: qmgr control",flags=linear +# **-- Channel tables --** +# +# Needed by individual channels, not submit +tbl local file="ch.local", + show="local id -> user id + home directory", + flags=dbm +tbl shell file="ch.shell", show="info for shell chan" + flags=dbm +tbl list file="ch.list", + show="Lists: distribution lists", + flags=dbm +tbl uucp file="ch.uucp" show="UUCP: rfc822 -> uucp", flags=dbm + +chan 822-local prog=local, + show="Local Delivery channel",type=both, + sort="user time",adr=822,adr-order=usapref, + hdrin=822,hdrout=822-us bptin="ia5",bptout="ia5", + content-out=822,outtable=local,access=mts,drchan=dr2rfc + +chan smtp prog=smtp,show="with SMTP (PP)",type=both, + adr=822,hdrout=822-us, bptout="ia5", + content-out=822,drchan=dr2rfc + +%BEGIN(J) +chan gb-janet prog="greyout -P",show="via JANET with NIFTP (PP)", + type=out, adr=822,adr-order=ukpref, + hdrout=822-jnt, bptout="ia5",out-info=janet, + content-out=822,drchan=dr2rfc + +chan gb-pss prog="greyout -P",key=ipss, + show="via PSS with NIFTP (PP)",type=both, + adr=822,adr-order=ukpref,outinfo=pss, + hdrout=822-jnt, bptout="ia5", + content-out=822, drchan=dr2rfc +%END(J) + +chan list prog=list,show="List channel",type=both, + outtable=list,drchan=dr2rfc,out-info=linked,sort="user time" + +chan uucp prog=uucp-out,key="uucp-out,rmail", + show="UUCP outbound channel",type=both, + adr=822,adr-order=usapref,outtable=uucp + out-info="uux=/tmp/uux,host=xtel" + +chan dr2rfc prog=dr2rfc,show="Dr2rfc channel",type=out, +%BEGIN(J)% + adr=822,adr-order=ukpref, +%END(J)% +%BEGIN(I)% + adr=822,adr-order=usapref, +%END(I)% +%BEGIN(L)% + adr=822,adr-order=usapref, +%END(L)% + bptin=ia5,hdrin=822 + content-out=822,out-info="return=all" + +chan shell prog=shell,type=out,access=mts + show="Shell channel", +%BEGIN(J)% + outtable=shell, hdrout=822-uk +%END(J)% +%BEGIN(I)% + outtable=shell, hdrout=822-us +%END(I)% +%BEGIN(L)% + outtable=shell, hdrout=822-us +%END(L)% + bptout="ia5", content-out=822 + +# QMGR special channels (load/manage/clean) + +chan qmgr-load prog=qmgr-load,show="Loading the QMGR", + type=qmgrload + +chan msg-clean prog=msg-clean,show="Removing finished message" + type=delete + +chan trash prog=trash,show="Removing trash" + type=debris,out-info=5h + +chan timeout prog=timeout,show="Timeout messages" + type=timeout + +chan warning prog=warnings,show="Send warning messages", + type=warn + +chan splitter prog=splitter,type=split, + show="Divide message into single" + + +# **-- shaper channels --** + +# Flatteners + +chan 822flatten prog=rfc934,type=shaper,content-out=822 + +# Unflatteners + +# Header Filters +%BEGIN(J)% +chan 822touk prog=fcontrol,type=shaper, + hdrin=822, hdrout=822-uk, + out-info="rfc822norm -jnt -bigend" +chan 822tojnt prog=fcontrol,type=shaper, + hdrin=822,hdrout=822-jnt, + out-info="rfc822norm -jnt -bigend -jntsender $(822SENDER)" +%END(J)% +chan 822tous prog=fcontrol,type=shaper,hdrin=822, + hdrout=822-us, + out-info="rfc822norm -822 -littleend" + +# **-- Logging for the rest of the prog --** +# +authlog level=notice, size=-1 +operlog level=notice, size=400 +normlog level=notice, size=400, sflags=zero + +822flatten normlog file=filter +%BEGIN(J)% +822touk normlog file=filter +%END(J)% +822tous normlog file=filter +dr2rfc normlog file=filter +fcontrol normlog file=filter +rfc822norm normlog file=filter +trash normlog file=filter + +list normlog file=lists + +qmgr normlog file=qmgr +qmgr-load normlog file=qmgr + +smtp normlog file=smtp +smtpsrvr normlog file=smtp +%BEGIN(J)% +greyout normlog file=greybook +gb-janet normlog file=greybook +%END(J)% +submit normlog file=submit + +local normlog file=local +msg-clean normlog file=msg-clean + +pptsapd normlog file=pptsapd, dlevel=notice diff --git a/examples/master/users b/examples/master/users new file mode 100644 index 0000000..368782e --- /dev/null +++ b/examples/master/users @@ -0,0 +1,15 @@ +############################################################ +# +# This file registers all the users that PP knows to deliver +# to. It has on the LHS the local address with domain +# components removed. On the RHS the channel to use to +# deliver the mail. For the present, you should put all +# local users in here with the channel "822-local" as the +# delivery channel +# +############################################################ +pp:822-local +# +# Here is the mapping showing how local delivery for J.Bloggs is done +# +J.Bloggs:822-local diff --git a/examples/master/warning.1 b/examples/master/warning.1 new file mode 100644 index 0000000..5091b66 --- /dev/null +++ b/examples/master/warning.1 @@ -0,0 +1,16 @@ +Your message, + ID $(p1-id) + UA-ID $(ua-id) +has not yet been delivered to the following recipients: + +$(822recips) + +The message is queued for processing on $(locmta). + +Delays are usually created by hosts being down, less often by network +outages. + +Delivery attempts will continue and no action on your part is +required. If the message cannot be delivered in the next $(hours-left) hours +it will be returned to you. + diff --git a/examples/master/warning.2 b/examples/master/warning.2 new file mode 100644 index 0000000..a45c2da --- /dev/null +++ b/examples/master/warning.2 @@ -0,0 +1,15 @@ +Your message, + ID $(p1-id) + UA-ID $(ua-id) +has still not yet been delivered to the following recipients: + +$(822recips) + +The message is queued for processing on $(locmta). + +Delays are usually created by hosts being down, less often by network +outages. + +Delivery attempts will continue and no action on your part is +required. If the message cannot be delivered in the next $(hours-left) hours +it will be returned to you. diff --git a/examples/master/x500.sample b/examples/master/x500.sample new file mode 100644 index 0000000..b3d40dc --- /dev/null +++ b/examples/master/x500.sample @@ -0,0 +1,5 @@ +objectClass= top & applicationEntity & quipuObject +cn= pp qmgr +description= {T.61}Submit to Qmgr - iaed must NOT listen on this one ! +presentationAddress= '1001'H/Internet=lancaster.xtel.co.uk+18000 +supportedApplicationContext= 0.9.2342.60200172.201.1 diff --git a/examples/xtel/Make.defs b/examples/xtel/Make.defs new file mode 100644 index 0000000..4815b66 --- /dev/null +++ b/examples/xtel/Make.defs @@ -0,0 +1,188 @@ +# Default Configuration values for other Makefiles +# +# You should look through all of them, but in particular lines the first +# too sections. +# Tailor this May need to be tailored to your system +# Check this Ensure that this is OK +# +# NOTE: SUN MAKE AND SOME NEWER MAKES TOO TAKE OF TRAILING SPACES IN A +# MACRO DEFINITION. HENCE YOU SHOULD EITHER REMOVE THE TRAILING COMMENTS +# OR MAKE SURE THE COMMENT STARTS DIRECTLY AFTER THE DEFINITION FOR THOSE +# MACROS WHERE THIS IS IMPORTANT (e.g pathnames). +# +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# + +############################################################ +# +# Things you really should tailor +# +############################################################ + +# List of channels that you may require. Choose from those in the +# Chans/ directory. Each should be a directory name within Chans. +#OPTIONALCHANS = shell lists 822-local smtp uucp \ +# x40084 x40088 grey fax +OPTIONALCHANS = shell lists 822-local smtp uucp x40084 x40088\ + decnet dr2rfc fax filtercontrol grey msg-clean qmgr-load \ + slocal splitter testchan timeout trashman warnings +# List of filters that you may require. Choose from those in the Format/ +# directory. +#OPTIONALFILTERS= ascii2fax +OPTIONALFILTERS = ascii2fax asn p2explode p2flatten p2norm \ + rfc1148 rfc822norm rfc934 + +# List of faxdrivers you want compiles. Choose from those in under the +# Chans/fax directory +FAXDRIVERS = ps250 dexNet200 + +#size of page to produce when converting to g3fax encoding +#not defined produces US size pages 216 mm by 273 mm (width, height) +#-DA4 produces A4 size pages 210mm by 297mm +FAXPAGESIZE = -DA4 + +# This is the external libraries required by all programs. +# Should include isode at the least. dbm maybe also. +LIBSYS = -ldsap -lisode -lm # -lgdbm + +#for nice xalert +LIBPHOTO = /usr/local/etc/g3fax/libphoto.a + +# Compilation things. +# C compiler, cc or gcc. +CC = cc # cc +# other cc if using gcc on sparc... +OLDCC = cc +CCOPTIONS = -g +LIBCCOPTIONS = -O +LDOPTIONS = -g + + +############################################################ +# +# These things may need changing +# +############################################################ + +# The PP base directory from private binaries et al. +PPDIR = /xtel/u3/pp + + +# A private directory for host specific files - set to PPDIR if you +# are not sharing things. +PRIDIR = $(PPDIR) + + +# The spool directory for mail. +SPLDIR = /xtel/u3/spool/pp + + +# The base directory for Manual pages /usr/man or /usr/local/man or similar +MANDIR = /usr/local/man +# options for installing manual pages... +# includes -bsd42 -bsd44 -ros -sys5 -aix -local -l -hpux +# see script man/inst-man.sh for more details +MANOPTS = -bsd42 + +# The public access binary directory. +USRBINDIR = /usr/local/bin + + +# The username to install PP binaries under +PPUSER = pp + + +# Do we have X11 installed; leave blank otherwise +X11 = true +#The X libraries. May need -lXext for X11R4 +LIBX = -lXaw -lXmu -lXext -lXt -lX11 +APPDEFAULTS = /usr/local/lib/X11/app-defaults + +# SMTP DNS support - either empty or the resolver library +LIBRESOLV = #-lresolv + + +# These commands have a habit of moving around +CHOWN = /etc/chown +CHMOD = chmod + + + +# If grey book is defined - these need to be correct - otherwise ignore +# Niftp src directory - niftp should be built beforehand. +NIFTPSRC = /xtel/pp/niftp/src +# The niftp interface in use. +NIFTPINTERFACE = sun + +############################################################ +# +# These things are probably OK as they are... +# +############################################################ + +MAKE = ./make +SHELL = /bin/sh + +TXTDIR = $(PPDIR) +PRIDIR = $(PPDIR) +# +# These are all sub dirs +TAILOR = $(PRIDIR)/tailor +BINDIR = $(PPDIR)/bin +CMDDIR = $(PPDIR)/cmds +TBLDIR = $(TXTDIR)/tables +LOGDIR = $(SPLDIR)/logs +QUEDIR = $(SPLDIR)/queues +CHANDIR = $(CMDDIR)/chans +FORMDIR = $(CMDDIR)/format +TOOLDIR = $(CMDDIR)/tools + +# ISODE dependencies +PEPY = pepy +PYFLAGS = +ROSY = rosy +RYFLAGS = +POSY = posy +POFLAGS = +PEPSY = pepsy +PEPSYHDRS = /usr/local/include/isode/pepsy +#PEPSY = /xtel/isode/isode-beta/pepsy/xpepsy +# Other Libraries and programs + +# Archive Configuration +AR = ar +ARFLAGS = +RANLIB = ranlib + +# Lint Config +LINT = lint +LINTFLAGS = -haxbc +LINTISODE = /usr/local/lib/lint/llib-lisode.ln + +# program protections? +PGMPROT = 755 +ROOTUSER = root + +# Other things +BACKUP = : +INSTALL = cp + +# Documentation support +LATEX = latex +TGRIND = tgrind +GRINDEFS = grindefs +WEAVE = weave +DVI2PS = dvi2ps +DVIIMP = dviimp +DVISP = dvisp +DFLAGS = + +# misc +DEPEND = /xtel/pp/bin/depend diff --git a/examples/xtel/Makefile b/examples/xtel/Makefile new file mode 100644 index 0000000..d89c1db --- /dev/null +++ b/examples/xtel/Makefile @@ -0,0 +1,77 @@ +# Make new xtel example +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +TABLES = aliases auth.user auth.channel auth.mta \ + auth.qmgr ch.fax ch.list ch.local ch.mslocal \ + ch.shell ch.uucp ch.x400in84 ch.x400out84 \ + ch.x400in88 ch.x400out88 channel domain or or2rfc \ + rfc1148gate rfc2or users + +WARNINGS = warning.1 warning.2 +WARNDIR = $(TBLDIR)/warnings + +############################################################ +# +# Building Rules +# +############################################################ + +all default: import + +import: tailor Make.defs config.h tables warnings + +tailor: $(TAILOR) + cp $? $@ + +Make.defs: ../../Make.defs + cp $? $@ + +config.h: ../../h/config.h + cp $? $@ + +tables: ; + @for i in $(TABLES); \ + do make cp-table THETABLE=$$i; \ + done + +cp-table: $(THETABLE) +$(THETABLE): $(TBLDIR)/$(THETABLE) + head -500 $? > $@ + +warnings:; + @for i in $(WARNINGS); \ + do make cp-warn WARNMSG=$$i; \ + done + +cp-warn: $(WARNMSG) +$(WARNMSG): $(WARNDIR)/$(WARNMSG) + cp $? $@ + +install:; + +clean: tidy + rm -f Make.defs tailor config.h $(TABLES) +tidy: + rm -f $(OBJS) core a.out Makefile.old + +lint: ; + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/examples/xtel/aliases b/examples/xtel/aliases new file mode 100644 index 0000000..8e3b589 --- /dev/null +++ b/examples/xtel/aliases @@ -0,0 +1,176 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Tue Dec 3 16:20:40 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +/I=A/S=Young/:alias "/I=A/S=Young/OU=bigears/O=Concurrent Computer Corporation/PRMD=CCUR/ADMD=ATTMAIL/C=ZZ/" x400 +joe.soap:alias joe@rigel.xtel.co.uk 822 +swproof:alias /S=proof/O=SW/PRMD=WIZARDS/ADMD=ITALY/C=IT/ x400 + +postmaster:alias jpo +postperson:alias jpo +postie:alias jpo +isode:alias jpo +root:alias jpo +X:alias jpo +ftp-owner:alias jpo + +quipu:alias cjr + +faxmaster:alias p.cowen + +#misc alias + +daemon:alias postmaster +support:alias xtel +empirica:alias /ATTN=Simon\ Robinson\ and\ Werner\ Korte/FAX=empirica/S=fax/ x400 +greatbelt:alias /ATTN=Simon\ Gjedde/FAX=greatbelt/S=fax/ x400 +# list synonyms + +xtel-outbound:synonym xtel +jnt-pp-support:synonym jnt-pp +jnt-ds-support:synonym jnt-quipu +x.500:synonym x500 +gb-directory-pilot:synonym gb-dir-pilot +uk-directory-pilot:synonym gb-dir-pilot +uk-dir-pilot:synonym gb-dir-pilot +x-tel:synonym xtel + +# list requests +pp-course-request:alias a.whitaker + +jnt-quipu-request:alias c.robbins +jnt-pp-request:alias c.robbins +xtel2-request:alias c.robbins +directory-pilot-request:alias c.robbins +isode-steering-request:alias c.robbins +x500-request:alias c.robbins +dl-test-request:alias c.robbins +gb-dir-pilot-request:alias c.robbins +bug-isode-request:alias c.robbins +isode-beta-request:alias j.onions +isode-dist-request:alias j.onions +xua-users-request:alias g.lunt +eurocoop-request:alias a.shepherd +a.monitor:synonym ActivityMonitor +actmon:synonym ActivityMonitor +am:synonym ActivityMonitor + +XUA-support-request:alias g.lunt +xconfer-request:alias g.lunt + +test-list-request:alias p.cowen + +wp3-request:alias h.smith + +xtel-request:alias jpo + +# lists we don't have - but people think we do... +pp-support:synonym pp-support@cs.ucl.ac.uk 822 +pp-people:synonym pp-people@cs.ucl.ac.uk 822 +quipu-support:synonym quipu-support@cs.ucl.ac.uk 822 +quipu:synonym quipu@cs.ucl.ac.uk 822 + +ontos-users-request:alias a.shepherd + +# personal synonyms + +pp:synonym P.Pat +postman.pat: synonym P.Pat + +julian:synonym j.onions +julian.Onions:synonym j.onions +jpo:synonym j.onions +onions:synonym j.onions + +graeme:synonym g.lunt +graeme.lunt:synonym g.lunt +gal:synonym g.lunt +g.lunt-request:synonym g.a.lunt +lunt:synonym g.lunt + +nlc:synonym n.cook +neil:synonym n.cook +neil.cook:synonym n.cook +cook:synonym n.cook +n.cook-request:synonym n.l.cook + +tony:synonym a.roadknight +Anthony.Roadknight:synonym a.roadknight +tony.Roadknight:synonym a.roadknight +t.Roadknight:synonym a.roadknight +avr:synonym a.roadknight +a.roadknight-request:synonym a.v.roadknight +roadknight:synonym a.roadknight + +colin:synonym c.robbins +colin.robbins:synonym c.robbins +crobbins:synonym C.Robbins +cjr:synonym c.robbins +robbins:synonym c.robbins +robins:synonym c.robbins +c.robins:synonym c.robins + +antonia:synonym a.whitaker +antonia.whitaker:synonym a.whitaker +whitaker:synonym a.whitaker +whittaker:synonym a.whitaker +a.whittaker:synonym a.whittaker + +pete.cowen:synonym p.cowen +peter.cowen:synonym p.cowen +pete.cowan:synonym p.cowen +peter.cowan:synonym p.cowen +pete:synonym p.cowen +pac:synonym p.cowen +cowen:synonym p.cowen +cowan:synonym p.cowen +cohen:synonym p.cowen +p.cohen:synonym p.cohen +p.cowan:synonym p.cowen +p.cowen:synonym p.cowen@x400.xtel.co.uk 822 + +pip:synonym p.hennessy +pippa:synonym p.hennessy +pah:synonym p.hennessy +pip.hennessy:synonym p.hennessy +pippa.hennessy:synonym p.hennessy +p.hennessy-request:synonym p.a.hennessy +hennessy:synonym p.hennessy + +jason:synonym j.kitchen +jason.kitchen:synonym j.kitchen +kitchen:synonym j.kitchen +j.kitchen-request:synonym j.p.kitchen + +M.Roe:synonym mrr@cl.cam.ac.uk 822 +mrr:synonym M.Roe +mike.roe:synonym M.Roe + +aworsley:synonym a.worsley +andrew.worsley:synonym a.worsley + +h.smith:synonym hugh +hugh.smith:synonym hugh +hsmith:synonym hugh +hugh-request:synonym hts +smith:synonym hugh + +ashepherd:synonym a.shepherd +gas:synonym a.shepherd + +# redirects + +#p.hennessy:alias p.hennessy@cs.nott.ac.uk 822 + +a.worsley:alias worsley@ditmela.oz.au 822 + +#hts:alias hugh@cs.nott.ac.uk 822 + +# w.prinz:alias prinz@f3.gmd.dbp.de 822 + diff --git a/examples/xtel/auth.channel b/examples/xtel/auth.channel new file mode 100644 index 0000000..1ef51b6 --- /dev/null +++ b/examples/xtel/auth.channel @@ -0,0 +1,22 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Thu Oct 10 15:04:04 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# AUTH.CHANNEL table not used in simple configuration +# +############################################################ +*->gb-janet:negative +*->gb-pss:negative +*->x40084:negative +*->x40088:negative +*->smtp:negative,test,warnsender=foo +822-local->*:negative +*->bugs-local:block diff --git a/examples/xtel/auth.mta b/examples/xtel/auth.mta new file mode 100644 index 0000000..061645d --- /dev/null +++ b/examples/xtel/auth.mta @@ -0,0 +1,16 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Thu Oct 10 15:04:05 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# AUTH.MTA table not used in simple configuration +# +############################################################ +cs.ucl.ac.uk:default=both,gb-janet=in,gb-pss=in,x40084=none diff --git a/examples/xtel/auth.qmgr b/examples/xtel/auth.qmgr new file mode 100644 index 0000000..cb5f640 --- /dev/null +++ b/examples/xtel/auth.qmgr @@ -0,0 +1,18 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Wed Oct 31 10:26:29 GMT 1990 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# Auth.qmgr - only browsing connections allowed +# +############################################################ + +anon:rights=limited +pp:passwd=dp2k0xmCTlk7E,rights=full diff --git a/examples/xtel/auth.user b/examples/xtel/auth.user new file mode 100644 index 0000000..7dd710f --- /dev/null +++ b/examples/xtel/auth.user @@ -0,0 +1,20 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Mon Sep 23 10:37:55 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# AUTH.USER table not used in simple configuration +# +############################################################ +adam:default=none,slocal=both +p.cowen:default=both,bugs-local=both +j.onions:default=both,bugs-local=both +c.robbins:default=both,bugs-local=both +p.pat:default=both,bugs-local=both diff --git a/examples/xtel/ch.fax b/examples/xtel/ch.fax new file mode 100644 index 0000000..98a9531 --- /dev/null +++ b/examples/xtel/ch.fax @@ -0,0 +1,57 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Fri Dec 13 15:26:49 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +#local formatting information + +#-adobe-courier-medium-o-normal--25-* +keyfont: /xtel/pp/pp-beta/Format/ascii2fax/zfonts/bh-lucida-bold-r-normal-sans-26 + +#-adobe-courier-bold-r-normal--25-* +valuefont: /xtel/pp/pp-beta/Format/ascii2fax/zfonts/bh-lucida-medium-i-normal-sans-26 + +#-adobe-courier-medium-r-normal--18-* +textfont: /xtel/pp/pp-beta/Format/ascii2fax/zfonts/bh-lucida-medium-r-normal-sans-26 + +xstart: 1.5in +ystart: 2.5in +tab: 2.5in + +coverpage: /xtel/pp/pp-beta/Format/ascii2fax/zfonts/xtel.bm +int_prefix: 010 +localOrg: X-Tel Services Ltd,\nUniversity of Nottingham,\nUniversity Park,\nNottingham,\nNG7 2RD +localNumber: +44 602 790278 +postscript: This fax was automatically generated by PP software. + +#recipient information +#lancaster.xtel.co.uk: 0,A local print +local: 0, A local print +nott: 783450,Computer Science,\nNottingham University +cripps: 588138,Cripps Computer Centre,\nNottingham University +ucl: 071 387 1397,UCL,\nGower Street,\nLondon WC1E 6BT +sun: 027 668 6735,Sun Microsystems,\nWatchmoor Park,\nRiverside Way,\nCamberley,\nSurrey GU15 3YL +empirica: +49 228 210 279,Empirica\nKaiserstr. 37\nD-5300 Bonn 1 +aarhus: +45 86 135 725,Aarhus Universitet +gmd: +49 2241 14 2084,GMD +greatbelt: +45 33 931 025,Great Belt A.S. +telefon: +45 86 299 068,Jydsk Telefon +stc: 0279 451 434,STC Technology +ta: +49 911 322 6282,TA Research\nFuerther Str. 212\nD-8500 Nuernberg 80 +stc-basildon: 081 945 5727,STC Integrated Networks\nChester Hall Lane\nBasildon +DTI: 071 215 1966,DTI\n151 Buckingham Road\nSW1W 9SS +mrose: +1 415-968-2510,Marshall T. Rose,\n420 Whisman Court\nMountain View, CA 94043-2112\nUS + +PTTResearch: +31 50 122415,\nPTT Research\nWinschoterdiep oz 46\nEuropaviljoen +openconnexion: +61 3 6539494,\nOpen Connexion,\nLevel 41, ANZ Tower\n55 Collins Street\nMelbourne\nVictoria 3000 +cni: +39 544-81337,CNi Informatica,\nVia dell'Artigianato,1\n40811 Alfonsine (Ra)\nITALY +hbr: +31 20 623 51 07,Wagons-lits Reizen,\nInkomend Toerisme,\nDam 19,\n1012 JS Amsterdam +level7: 0344 868442,Level-7 Ltd,\nCentennial Court,\nEasthampstead Road,\nBracknell,Berkshire +valbecc: 0625 539905,Valbecc Limited,\n115 Wilmslow Road,\nHandforth +ontos: +1 617-272-8101,ONTOS Inc,\nBoston, Mass. +juha: +358 31 2432211,Datanet diff --git a/examples/xtel/ch.list b/examples/xtel/ch.list new file mode 100644 index 0000000..9db2375 --- /dev/null +++ b/examples/xtel/ch.list @@ -0,0 +1,34 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Fri Aug 30 13:29:17 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# List channel table +# +# +# An example list, foo-list is shown here. +# +# ":" "," "file=" "," +# +############################################################ + +#xtel:jpo,file=lists/xtel,X-tel people +#p.cowen:pac,p.a.cowen|ms-p.a.cowen,Peter Cowen +g.lunt:gal,g.a.lunt|ms-g.a.lunt,Graeme Lunt +a.roadknight:avr,a.v.roadknight|ms-a.v.roadknight,Tony Roadknight +p.hennessy:pah,p.a.hennessy|ms-p.a.hennessy,Pippa Hennessy +j.kitchen:jason,j.p.kitchen|ms-j.p.kitchen,Jason Kitchen +n.cook:nlc,n.l.cook|ms-n.l.cook,Neil Cook +hugh:hugh,hts|ms-hugh,Hugh Smith +#pp-course:antonia,file=lists/pp-course,PP course people +test-list:foo,file=lists/test-list,A test list +bug-isode:cjr|jpo,file=lists/bug-isode,ISODE bug mailing list +isode-beta:cjr|jpo,file=lists/isode-beta,ISODE BETA mailing list +isode-dist:cjr|jpo,file=lists/isode-dist,ISODE distribution sites mailing list diff --git a/examples/xtel/ch.local b/examples/xtel/ch.local new file mode 100644 index 0000000..c44c67c --- /dev/null +++ b/examples/xtel/ch.local @@ -0,0 +1,34 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Fri Nov 22 12:02:29 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +#x-tel members +P.Pat:pp +c.robbins:cjr +j.onions:jpo +g.lunt:gal +g.a.lunt:gal +a.roadknight:avr +a.v.roadknight:avr +p.cowen:pac +p.hennessy:pah +p.a.hennessy:pah +j.kitchen:jason +j.p.kitchen:jason +hts:hugh +n.cook:nlc +n.l.cook:nlc +adam:pac +a.whitaker:antonia +a.worsley:aworsley +a.shepherd:gas +quipu-bugs:username=pp home=/xtel/pp/bugs +pp-bugs:username=pp home=/xtel/pp/bugs +isode-bugs:username=pp home=/xtel/pp/bugs +dev-null:username=pp, mailbox=/dev/null diff --git a/examples/xtel/ch.mslocal b/examples/xtel/ch.mslocal new file mode 100644 index 0000000..4d19a97 --- /dev/null +++ b/examples/xtel/ch.mslocal @@ -0,0 +1,29 @@ +# +# This file maps names to accounts and directories for the message store +################################################## +#x-tel members +P.Pat:pp +c.robbins:cjr +j.onions:jpo +g.lunt:gal +g.a.lunt:gal +a.roadknight:avr +a.v.roadknight:avr +p.hennessy:pah +p.a.hennessy:pah +p.cowen:pac +a.whitaker:antonia +a.worsley:aworsley +ms-aworsley:aworsley /tmp +ms-avr:aworsley /tmp +ms-gal:aworsley /tmp +ms-g.a.lunt:gal +ms-a.v.roadknight:avr +ms-hugh:hugh +ms-p.a.hennessy:pah +ms-j.p.kitchen:jason +ms-n.l.cook:nlc +m.roe:mrr +pactest:pp +adam:local,username=pac +activitymonitor:gas,home=/xtel/users/gas/actmon diff --git a/examples/xtel/ch.shell b/examples/xtel/ch.shell new file mode 100644 index 0000000..8565822 --- /dev/null +++ b/examples/xtel/ch.shell @@ -0,0 +1,17 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Tue Jun 4 10:15:30 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +############################################################ +# +# The ch.shell table is not used in this minimal setup +# +############################################################ + +lynx:pp,0|solo,/usr/ucb/lpr -Plynx diff --git a/examples/xtel/ch.uucp b/examples/xtel/ch.uucp new file mode 100644 index 0000000..ae94f4a --- /dev/null +++ b/examples/xtel/ch.uucp @@ -0,0 +1,5 @@ +############################################################ +# +# The ch.uucp table is not used in this minimal setup +# +############################################################ diff --git a/examples/xtel/ch.x400in84 b/examples/xtel/ch.x400in84 new file mode 100644 index 0000000..628aa0f --- /dev/null +++ b/examples/xtel/ch.x400in84 @@ -0,0 +1,9 @@ +default:lpass="pimms",lmta="UK.CO.XTEL" +TELEX+00737346+RFC-1006+03+128.243.20.197:rmta="UK.AC.NOTT.CS",rpass="pimms",rname="UK.AC.NOTT.CS" +TELEX+00728722+X.25(80)+02+00000511160080:rmta="UK.AC.UCL.CS",rpass=" ",rname="UK.AC.UCL.CS" +TELEX+00728722+X.25(80)+02+000040010250:rmta="UK.AC.MHS-RELAY",rpass="mhs",rname="mhs-relay.ac.uk" +TELEX+00728722+X.25(80)+02+000010695800:rmta="UK.CO.SSS.E",rpass=pp,rname=e.sss.co.uk +TELEX+00737346+RFC-1006+03+128.243.9.1:rmta="UK.CO.XTEL",rpass=pimms,rname=xtel.co.uk +TELEX+00737346+RFC-1006+03+128.243.9.2:rmta="UK.CO.XTEL",rpass=pimms,rname=xtel.co.uk +"597"/TELEX+00737346+RFC-1006+03+128.102.128.50:rmta="atlas.arc.nasa.gov",rname=atlas.arc.nasa.gov +TELEX+00737346+RFC-1006+03+128.102.128.50:rmta="atlas.arc.nasa.gov",rname=atlas.arc.nasa.gov diff --git a/examples/xtel/ch.x400in88 b/examples/xtel/ch.x400in88 new file mode 100644 index 0000000..d1de479 --- /dev/null +++ b/examples/xtel/ch.x400in88 @@ -0,0 +1,12 @@ +default:lpass=pimms,lmta="UK.CO.XTEL" +TELEX+00737346+RFC-1006+03+128.243.20.197:rmta="UK.AC.NOTT.CS",rpass="pimms",rname="UK.AC.NOTT.CS" +TELEX+00728722+X.25(80)+02+00000511160080:rmta="UK.AC.UCL.CS",rpass=" ",rname=cs.ucl.ac.uk +TELEX+00737346+RFC-1006+03+128.16.5.31:rmta="UK.AC.UCL.CS",rpass=" ",rname=cs.ucl.ac.uk +"592"/TELEX+00728722+X.25(80)+02+00000511160080:rmta="UK.AC.UCL.CS",rpass=" ",rname=cs.ucl.ac.uk +"592"/TELEX+00728722+X.25(80)+02+00000511168080:rmta="UK.AC.UCL.CS",rpass=" ",rname=cs.ucl.ac.uk +TELEX+00737346+RFC-1006+03+128.243.9.1:rmta="UK.CO.XTEL",rpass=pimms,rname=xtel.co.uk +TELEX+00737346+RFC-1006+03+128.250.90.100:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rname=mel.dir.csiro.au,lpass=" " +TELEX+00737346+RFC-1006+03+144.110.64.15:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rname=mel.dir.csiro.au,lpass=" " +TELEX+00728722+X.25(80)+02+00000511160010:rmta="UK.AC.UCL.CS",rpass=" ",rname=talikser.cs.ucl.ac.uk +TELEX+00737346+RFC-1006+03+128.102.128.50:rmta="atlas.arc.nasa.gov",rname=atlas.arc.nasa.gov +"597"/TELEX+00737346+RFC-1006+03+128.102.128.50:rmta="atlas.arc.nasa.gov",rname=atlas.arc.nasa.gov diff --git a/examples/xtel/ch.x400out84 b/examples/xtel/ch.x400out84 new file mode 100644 index 0000000..5b76967 --- /dev/null +++ b/examples/xtel/ch.x400out84 @@ -0,0 +1,21 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Mon Nov 11 10:53:06 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +# X.400 84 connections - outbound +default:lpass="pimms",lmta="UK.CO.XTEL",type=1984 + +cs.nott.ac.uk:rmta="UK.AC.NOTT.CS",rpsap='"591"/LOCAL-ETHER=trellis',rpass="pimms" +cs.ucl.ac.uk:rmta="UK.AC.UCL.CS",rpass=" ",rpsap='"591"/Janet=00000511160080' +bells.cs.ucl.ac.uk:rmta="UK.AC.UCL.CS",rpass=" ",rpsap='"591"/Janet=00000511160080' +mhs-relay.ac.uk:rpsap='"591"/Janet=000040010250',rmta="UK.AC.MHS-RELAY",rpass="mhs" +mhs.ac.uk:rpsap='"591"/Janet=000040010250',rmta="UK.AC.MHS-RELAY",rpass="mhs" +e.sss.co.uk:rpsap='"591"/Janet=000010695800',rmta="UK.CO.SSS.E",rpass=pp +xtel.co.uk:rmta="UK.CO.XTEL",rpsap='"594"/LOCAL-ETHER=lancaster',rpass="pimms" +italy-system-wizards:rmta="sw",rpass="sw",rpsap='"1"/Janet=000010695899' diff --git a/examples/xtel/ch.x400out88 b/examples/xtel/ch.x400out88 new file mode 100644 index 0000000..2c7730e --- /dev/null +++ b/examples/xtel/ch.x400out88 @@ -0,0 +1,24 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Tue Oct 15 11:16:14 BST 1991 +############## on host lancaster +############## +################################################## +################################################## +# X.400 88 connections - outbound +default:lpass=pimms,lmta="UK.CO.XTEL",type=1988 + +cs.ucl.ac.uk:rmta="UK.AC.UCL.CS",rpass=" ",rpsap='"592"/Janet=00000511160080' +bells.cs.ucl.ac.uk:rmta="UK.AC.UCL.CS",rpass=" ",rpsap='"592"/Janet=00000511160080' +cs.nott.ac.uk:rmta="UK.AC.NOTT.CS",rpsap='"593"/LOCAL-ETHER=trellis',rpass="pimms" +xtel.co.uk:rmta="UK.CO.XTEL",rpsap='"597"/LOCAL-ETHER=lancaster',rpass="pimms" +mel.dit.csiro.au:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rpsap='"597"/LOCAL-ETHER=128.250.90.100' +#mel.dit.csiro.au:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rpsap='"597"/LOCAL-ETHER=144.110.64.15' +#andrew:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rpsap='"597"/LOCAL-ETHER=128.250.90.100' +#andrew:rmta="MANTA.MEL.DIT.CSIRO.AU",rpass=" ",rpsap='"597"/LOCAL-ETHER=144.110.64.15' +talisker.cs.ucl.ac.uk:rpsap='"592"/Janet=00000511160010',rmta="UK.AC.UCL.CS",rpass=" " +#atlas.arc.nasa.gov:rpsap='"597"/Internet=128.102.128.50',rmta="atlas.arc.nasa.gov",rpass=" " +atlas.arc.nasa.gov:rpsap='"597"/LOCAL-ETHER=128.102.128.50',rmta="atlas.arc.nasa.gov",rpass=" " diff --git a/examples/xtel/channel b/examples/xtel/channel new file mode 100644 index 0000000..0ed22f6 --- /dev/null +++ b/examples/xtel/channel @@ -0,0 +1,500 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Wed Dec 18 08:34:21 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +a.gec-epl.co.uk:a.gec-epl.co.uk(gb-pss) +a.gec-mrc.co.uk:a.gec-mrc.co.uk(gb-pss) +a.mssl.ucl.ac.uk:a.mssl.ucl.ac.uk(gb-janet) +a.oxpoly.ac.uk:prime-a.oxford-poly.ac.uk(gb-janet) +a.plym.ac.uk:prime-a.plymouth.ac.uk(gb-janet) +a.prime.esrc.ac.uk:a.prime.esrc.ac.uk(gb-janet) +a.salf.ac.uk:sysa.salford.ac.uk(gb-janet) +a.salford-software-services.co.uk:a.salford-software-services.co.uk(gb-janet),a.salford-software-services.co.uk(gb-pss) +a.sss.co.uk:a.salford-software-services.co.uk(gb-janet),a.salford-software-services.co.uk(gb-pss) +a.wolves.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +aad.amtp.cam.ac.uk:alias-atmos-dynamics.damtp.cambridge.ac.uk(gb-janet) +aba.phy.hw.ac.uk:abacus.physics.heriot-watt.ac.uk(gb-janet) +abacu.strath.ac.uk:abacus.strathclyde.ac.uk(gb-janet),abacus.strathclyde.ac.uk(gb-pss) +abacus.physics.heriot-watt.ac.uk:abacus.physics.heriot-watt.ac.uk(gb-janet) +abacus.strathclyde.ac.uk:abacus.strathclyde.ac.uk(gb-janet),abacus.strathclyde.ac.uk(gb-pss) +abcl.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +abdn.ac.uk:aberdeen.ac.uk(gb-janet) +abekas-video-systems.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +abekrd.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aber.ac.uk:aberystwyth.ac.uk(gb-janet) +aberdeen.ac.uk:aberdeen.ac.uk(gb-janet) +aberystwyth.ac.uk:aberystwyth.ac.uk(gb-janet) +abstract-hardware-ltd.co.uk:brunel.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +acfd.bris.ac.uk:bristol.ac.uk(gb-janet) +acorn.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +acrc.bris.ac.uk:acrc.bristol.ac.uk(gb-janet) +acrc.bristol.ac.uk:acrc.bristol.ac.uk(gb-janet) +acrunm.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +acse.shef.ac.uk:sunc.sheffield.ac.uk(gb-janet) +acse.sheffield.ac.uk:sunc.sheffield.ac.uk(gb-janet) +acsvax.ou.ac.uk:vax.acs.open.ac.uk(gb-janet),vax.acs.open.ac.uk(gb-pss) +active-book-co.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +acu.rl.ac.uk:acu.rutherford.ac.uk(gb-janet) +acu.rutherford.ac.uk:acu.rutherford.ac.uk(gb-janet) +acvax.ulst.ac.uk:acvax.ulster.ac.uk(gb-janet) +acvax.ulster.ac.uk:acvax.ulster.ac.uk(gb-janet) +adg.mono.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +adg.monotype.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +adm.kl.ac.uk:admin.keele.ac.uk(gb-janet) +adm1.bris.ac.uk:adm1.bristol.ac.uk(gb-janet) +adm1.bristol.ac.uk:adm1.bristol.ac.uk(gb-janet) +admin.abdn.ac.uk:admin.aberdeen.ac.uk(gb-janet) +admin.aberdeen.ac.uk:admin.aberdeen.ac.uk(gb-janet) +admin.bbk.ac.uk:admin.bbk.ac.uk(gb-janet) +admin.cam.ac.uk:central-administration.cambridge.ac.uk(gb-janet) +admin.hull.ac.uk:admin.hull.ac.uk(gb-janet) +admin.keele.ac.uk:admin.keele.ac.uk(gb-janet) +admin.liv.ac.uk:admin.liverpool.ac.uk(gb-janet) +admin.liverpool.ac.uk:admin.liverpool.ac.uk(gb-janet) +admin.salf.ac.uk:admin.salford.ac.uk(gb-janet) +admin.salford.ac.uk:admin.salford.ac.uk(gb-janet) +admin.sussex.ac.uk:syma.sussex.ac.uk(gb-janet) +admin.susx.ac.uk:syma.sussex.ac.uk(gb-janet) +admin.thames.ac.uk:admin.thames.ac.uk(gb-janet) +admin.west-london-institute.ac.uk:admin.west-london-institute.ac.uk(gb-janet) +admin.wlihe.ac.uk:admin.west-london-institute.ac.uk(gb-janet) +admin1.leeds.ac.uk:mailer.leeds.ac.uk(gb-janet) +admin2.newcastle-poly.ac.uk:admin2.newcastle-poly.ac.uk(gb-janet) +admin2.npy.ac.uk:admin2.newcastle-poly.ac.uk(gb-janet) +advanced-risc-machines.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +advanced-robotics-research-centre.salford.ac.uk:advanced-robotics-research-centre.salford.ac.uk(gb-janet) +advax3.york.ac.uk:advax3.york.ac.uk(gb-janet) +ae.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +ae.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +aer.bris.ac.uk:aero.bristol.ac.uk(gb-janet) +aero-comp-fluids.bristol.ac.uk:bristol.ac.uk(gb-janet) +aero.bristol.ac.uk:aero.bristol.ac.uk(gb-janet) +aero.qmw.ac.uk:aero.qmw.ac.uk(gb-janet) +afe.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +afrcco.afrc.ac.uk:afrcco.afrc.ac.uk(gb-janet) +ag.phy.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +agri.afrc.ac.uk:agri.afrc.ac.uk(gb-janet) +agv1.qub.ac.uk:vax1.agriculture.queens-belfast.ac.uk(gb-janet) +ahl.co.uk:brunel.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +ai.co.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +ai.ed.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +ai.edinburgh.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +ai.leeds.ac.uk:ai.leeds.ac.uk(gb-janet) +aiai.ed.ac.uk:aiai.edinburgh.ac.uk(gb-janet) +aiai.edinburgh.ac.uk:aiai.edinburgh.ac.uk(gb-janet) +aiaitest.ed.ac.uk:aiaitest.edinburgh.ac.uk(gb-janet) +aiaitest.edinburgh.ac.uk:aiaitest.edinburgh.ac.uk(gb-janet) +aie.lloyds-register.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aie.lreg.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aifh.ed.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aifh.edinburgh.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aiil.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aipna.ed.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aipna.edinburgh.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aisb.ed.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aisb.edinburgh.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aiva.ed.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aiva.edinburgh.ac.uk:aifh.edinburgh.ac.uk(gb-janet) +aivru.shef.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aivru.sheffield.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aixssc.ibm.co.uk:doc.imperial.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +akv.dsir.govt.nz:nsfnet-relay.ac.uk(gb-janet),nsfnet-relay.ac.uk(gb-pss) +al.nmrc.le.ac.uk:alliant.nmrc.leicester.ac.uk(gb-janet) +alex-technologies-ltd.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +alf.physics.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +alias-atmos-dynamics.damtp.cambridge.ac.uk:alias-atmos-dynamics.damtp.cambridge.ac.uk(gb-janet) +all.surr.ac.uk:alliant.surrey.ac.uk(gb-janet),alliant.surrey.ac.uk(gb-pss) +alliant.nmrc.leicester.ac.uk:alliant.nmrc.leicester.ac.uk(gb-janet) +alliant.surrey.ac.uk:alliant.surrey.ac.uk(gb-janet),alliant.surrey.ac.uk(gb-pss) +alsys.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +altair.technorth.rutherford.ac.uk:altair.technorth.rutherford.ac.uk(gb-janet) +altair.tn.rl.ac.uk:altair.technorth.rutherford.ac.uk(gb-janet) +amsta.leeds.ac.uk:amsta.leeds.ac.uk(gb-janet) +amtp.cam.ac.uk:lattice-field-theory.damtp.cambridge.ac.uk(gb-janet) +amv.dsir.govt.nz:nsfnet-relay.ac.uk(gb-janet),nsfnet-relay.ac.uk(gb-pss) +amv1.qub.ac.uk:vax1.app-maths.queens-belfast.ac.uk(gb-janet) +and.cs.liv.ac.uk:anduin.compsci.liverpool.ac.uk(gb-janet) +andrew-sykes-microelectronics.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +anduin.compsci.liverpool.ac.uk:anduin.compsci.liverpool.ac.uk(gb-janet) +ansa.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +anvil.co.uk:cs.qmw.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aom.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +aom.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +ap.co.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +ap1.ee.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +ap2.ee.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +apg.ph.ucl.ac.uk:apg.ph.ucl.ac.uk(gb-janet) +apg.phil.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +apg.philips.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +apl.bris.ac.uk:bristol.ac.uk(gb-janet) +apl.bristol.ac.uk:bristol.ac.uk(gb-janet) +apollo.computation.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +apollo.electeng.portsmouth.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +apollo.loughborough.ac.uk:loughborough.ac.uk(gb-janet) +apollo.lut.ac.uk:loughborough.ac.uk(gb-janet) +apollo.me.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +apollo.me.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +apollo1.electrical-engineering.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +apollo2.electrical-engineering.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +applied-telematics-group.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +apre.mod.uk:apre.mod.uk(gb-pss),ess.cs.ucl.ac.uk(gb-janet) +apricot.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +aq.mcs.dund.ac.uk:aqua.maths-and-cs.dundee.ac.uk(gb-janet) +aqua.maths-and-cs.dundee.ac.uk:aqua.maths-and-cs.dundee.ac.uk(gb-janet) +aquarius.ed.ac.uk:aquarius.edinburgh.ac.uk(gb-janet) +aquarius.edinburgh.ac.uk:aquarius.edinburgh.ac.uk(gb-janet) +arcb.afrc.ac.uk:arcb.afrc.ac.uk(gb-janet) +arcc.afrc.ac.uk:arcc.afrc.ac.uk(gb-janet) +arcd.afrc.ac.uk:arcd.afrc.ac.uk(gb-janet) +arch.bute.cardiff.ac.uk:arch.bute.cardiff.ac.uk(gb-janet) +arch.bute.cf.ac.uk:arch.bute.cardiff.ac.uk(gb-janet) +are-pn.mod.uk:are-pn.mod.uk(gb-pss),ess.cs.ucl.ac.uk(gb-janet) +aries.ed.ac.uk:aries.edinburgh.ac.uk(gb-janet),aries.edinburgh.ac.uk(gb-pss) +aries.edinburgh.ac.uk:aries.edinburgh.ac.uk(gb-janet),aries.edinburgh.ac.uk(gb-pss) +armltd.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +arpa:nsfnet-relay.ac.uk(gb-janet),nsfnet-relay.ac.uk(gb-pss) +arrc.salf.ac.uk:advanced-robotics-research-centre.salford.ac.uk(gb-janet) +artificial-intelligence-international.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +artificial-intelligence.computation.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +as1.ma.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +ash.cc.kcl.ac.uk:ash.cc.kcl.ac.uk(gb-janet) +ash.scp.ac.uk:ash.sheffield-city-poly.ac.uk(gb-janet) +ash.sheffield-city-poly.ac.uk:ash.sheffield-city-poly.ac.uk(gb-janet) +asmec.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +ast-star.cam.ac.uk:starlink.astronomy.cambridge.ac.uk(gb-janet) +ast.star.rl.ac.uk:astrophysics.starlink.rutherford.ac.uk(gb-janet) +ast.west.cam.ac.uk:astronomy.west.cambridge.ac.uk(gb-janet) +aster.cu.bbk.ac.uk:aster.cu.bbk.ac.uk(gb-janet) +aston.ac.uk:aston.ac.uk(gb-janet) +astra-clinical.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +astra.ed.ac.uk:astra.edinburgh.ac.uk(gb-janet),astra.edinburgh.ac.uk(gb-pss) +astra.edinburgh.ac.uk:astra.edinburgh.ac.uk(gb-janet),astra.edinburgh.ac.uk(gb-pss) +astro.gla.ac.uk:udcf.glasgow.ac.uk(gb-janet) +astro.glasgow.ac.uk:udcf.glasgow.ac.uk(gb-janet) +astro.ox.ac.uk:astrophysics.oxford.ac.uk(gb-janet) +astro.rl.ac.uk:astrophysics.rutherford.ac.uk(gb-janet) +astronomy.physics.southampton.ac.uk:astronomy.physics.southampton.ac.uk(gb-janet) +astronomy.west.cambridge.ac.uk:astronomy.west.cambridge.ac.uk(gb-janet) +astrophysics.oxford.ac.uk:astrophysics.oxford.ac.uk(gb-janet) +astrophysics.rutherford.ac.uk:astrophysics.rutherford.ac.uk(gb-janet) +astrophysics.starlink.rutherford.ac.uk:astrophysics.starlink.rutherford.ac.uk(gb-janet) +astrosun-1.mathematics.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +at:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +atg.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +athro.cardiff.ac.uk:cardiff.ac.uk(gb-janet) +athro.cf.ac.uk:cardiff.ac.uk(gb-janet) +atlas.arc.nasa.gov:atlas.arc.nasa.gov(x40088) +atm.amtp.cam.ac.uk:atmos-dynamics.damtp.cambridge.ac.uk(gb-janet) +atm.ch.cam.ac.uk:atmos-modelling.chemistry.cambridge.ac.uk(gb-janet) +atmos-dynamics.damtp.cambridge.ac.uk:atmos-dynamics.damtp.cambridge.ac.uk(gb-janet) +atmos-modelling.chemistry.cambridge.ac.uk:atmos-modelling.chemistry.cambridge.ac.uk(gb-janet) +atmos.physics.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +atsr-ground-segment.rutherford.ac.uk:atsr-ground-segment.rutherford.ac.uk(gb-janet) +atsr-science.rutherford.ac.uk:atsr-science.rutherford.ac.uk(gb-janet) +atsr.rl.ac.uk:atsr-ground-segment.rutherford.ac.uk(gb-janet) +atsrsc.rl.ac.uk:atsr-science.rutherford.ac.uk(gb-janet) +att-unix-europe.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +au:nsfnet-relay.ac.uk(gb-janet),nsfnet-relay.ac.uk(gb-pss) +automation.university-library.cambridge.ac.uk:automation.university-library.cambridge.ac.uk(gb-janet) +avri.afrc.ac.uk:avri.afrc.ac.uk(gb-janet) +axion.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +axion.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +azit.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +azit.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +b.prg.ox.ac.uk:b.prg.oxford.ac.uk(gb-janet) +b.prg.oxford.ac.uk:b.prg.oxford.ac.uk(gb-janet) +b.salf.ac.uk:sysb.salford.ac.uk(gb-janet) +b.salford-software-services.co.uk:b.salford-software-services.co.uk(gb-janet),b.salford-software-services.co.uk(gb-pss) +b.sss.co.uk:b.salford-software-services.co.uk(gb-janet),b.salford-software-services.co.uk(gb-pss) +b.wolves.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +b29hp.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +b29hp.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +ba.strath.ac.uk:barra.strathclyde.ac.uk(gb-janet) +backup.loughborough.ac.uk:mailhost.loughborough.ac.uk(gb-janet) +backup.lut.ac.uk:mailhost.loughborough.ac.uk(gb-janet) +badger.pcl.ac.uk:badger.pcl.ac.uk(gb-janet) +balliol.ox.ac.uk:balliol.oxford.ac.uk(gb-janet) +balliol.oxford.ac.uk:balliol.oxford.ac.uk(gb-janet) +bangor.ac.uk:bangor.ac.uk(gb-janet) +barra.strathclyde.ac.uk:barra.strathclyde.ac.uk(gb-janet) +bartlett.ucl.ac.uk:bartlett.ucl.ac.uk(gb-janet) +basil.acs.bolton.ac.uk:basil.acs.bolton.ac.uk(gb-janet) +basil.bolton.ac.uk:basil.acs.bolton.ac.uk(gb-janet) +bath.ac.uk:bath.ac.uk(gb-janet) +bbc.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bc.rfhsm.lon.ac.uk:bc.rfhsm.lon.ac.uk(gb-janet) +be:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +bells.cs.ucl.ac.uk:bells.cs.ucl.ac.uk(x40084),bells.cs.ucl.ac.uk(x40088) +bgers.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bham.ac.uk:birmingham.ac.uk(gb-janet) +bilpin.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bio-medical-physics.aberdeen.ac.uk:bio-medical-physics.aberdeen.ac.uk(gb-janet) +bio.cam.ac.uk:biology.cambridge.ac.uk(gb-janet) +bio.ee.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +bio.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +bio.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +bioch.ox.ac.uk:biochemistry.oxford.ac.uk(gb-janet) +biochemistry.oxford.ac.uk:biochemistry.oxford.ac.uk(gb-janet) +biocomp.ed.ac.uk:biocomputing.edinburgh.ac.uk(gb-janet) +biocomputing.edinburgh.ac.uk:biocomputing.edinburgh.ac.uk(gb-janet) +biology.cambridge.ac.uk:biology.cambridge.ac.uk(gb-janet) +biomed.abdn.ac.uk:bio-medical-physics.aberdeen.ac.uk(gb-janet) +biomedical.ee.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +biop.ox.ac.uk:vax.molecular-biophysics.oxford.ac.uk(gb-janet) +biovax.ed.ac.uk:biovax.edinburgh.ac.uk(gb-janet) +biovax.edinburgh.ac.uk:biovax.edinburgh.ac.uk(gb-janet) +biovax.leeds.ac.uk:vax.bio.leeds.ac.uk(gb-janet) +birmingham.ac.uk:birmingham.ac.uk(gb-janet) +bitnet:earn-relay.ac.uk(gb-janet) +bj.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bl.uk:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +bmads.ucl.ac.uk:bmads.ucl.ac.uk(gb-janet) +bmth.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bnr.co.uk:bnr.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +boldon-james-limited.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +boo.cs.liv.ac.uk:compsci.liverpool.ac.uk(gb-janet) +boot.cr.bbk.ac.uk:boot.cr.bbk.ac.uk(gb-janet) +bootle.compsci.liverpool.ac.uk:compsci.liverpool.ac.uk(gb-janet) +bournemouth.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +br:earn-relay.ac.uk(gb-janet) +bradford.ac.uk:bradford.ac.uk(gb-janet) +bragg.ch.man.ac.uk:research1.computer-science.manchester.ac.uk(gb-janet) +bragg.chemistry.manchester.ac.uk:research1.computer-science.manchester.ac.uk(gb-janet) +brazier-systems-and-consultants.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bris.ac.uk:bristol.ac.uk(gb-janet) +bristol.ac.uk:bristol.ac.uk(gb-janet) +british-gas-ers.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +british-library.uk:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +british-national-corpus.oxford.ac.uk:convex.oxford.ac.uk(gb-janet) +brooktree.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +brunel.ac.uk:brunel.ac.uk(gb-janet) +bsa.bris.ac.uk:bsa.bristol.ac.uk(gb-janet) +bsa.bristol.ac.uk:bsa.bristol.ac.uk(gb-janet) +bscdev.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bsec.abcy.cardiff.ac.uk:bsec.abcy.cardiff.ac.uk(gb-janet) +bsec.abcy.cf.ac.uk:bsec.abcy.cardiff.ac.uk(gb-janet) +bsm.bioc.ucl.ac.uk:bsm.biochemistry.ucl.ac.uk(gb-janet) +bsm.biochemistry.ucl.ac.uk:bsm.biochemistry.ucl.ac.uk(gb-janet) +bsu.qmw.ac.uk:bsu.qmw.ac.uk(gb-janet) +bt-web.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +bt-web.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btcase.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btcase.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btrcosmos.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btrcosmos.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btree.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +btrlc7.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btrlc7.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btrnmw.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +btrnmw.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +bttelex.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +bttelex.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +buck.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +buckingham.ac.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +bul.esc.cam.ac.uk:bullard-convex.earth-sciences.cambridge.ac.uk(gb-janet) +bullard-convex.earth-sciences.cambridge.ac.uk:bullard-convex.earth-sciences.cambridge.ac.uk(gb-janet) +bunny.ulcc.ac.uk:ncdlab.ulcc.ac.uk(gb-janet) +buzzard.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +buzzard.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +c.mssl.ucl.ac.uk:c.mssl.ucl.ac.uk(gb-janet) +c.plym.ac.uk:prime-c.plymouth.ac.uk(gb-janet) +c.salf.ac.uk:sysc.salford.ac.uk(gb-janet) +c.salford-software-services.co.uk:c.salford-software-services.co.uk(gb-pss) +c.sss.co.uk:c.salford-software-services.co.uk(gb-pss) +c.wolves.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +c01.csi.cam.ac.uk:comms01.computing-service-internal.cambridge.ac.uk(gb-janet) +c01.umds.lon.ac.uk:portia.umds.lon.ac.uk(gb-janet) +c1.nkw.ac.uk:convex1.nerc-keyworth.ac.uk(gb-janet) +c2a.cr.bbk.ac.uk:c2a.cr.bbk.ac.uk(gb-janet) +ca:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +caad.ed.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +caad.edinburgh.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +cad-cen.co.uk:computer-lab.cambridge.ac.uk(gb-janet) +cad-centre.strathclyde.ac.uk:cad-centre.strathclyde.ac.uk(gb-janet),cad-centre.strathclyde.ac.uk(gb-pss) +cad.computer-science.manchester.ac.uk:cad.computer-science.manchester.ac.uk(gb-janet) +cad.cs.man.ac.uk:cad.computer-science.manchester.ac.uk(gb-janet) +cad.engit.reading.ac.uk:reading.ac.uk(gb-janet) +cad.leeds.ac.uk:ai.leeds.ac.uk(gb-janet) +cad.rdg.ac.uk:reading.ac.uk(gb-janet) +cad.strath.ac.uk:cad-centre.strathclyde.ac.uk(gb-janet),cad-centre.strathclyde.ac.uk(gb-pss) +cad1.me.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cad1.me.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +cad2.me.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cad2.me.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +cad3.me.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cad3.me.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +cadcentre.co.uk:computer-lab.cambridge.ac.uk(gb-janet) +cadl.ee.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cadlab.ee.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +cae.eng.gla.ac.uk:cae.eng.glasgow.ac.uk(gb-janet) +cae.eng.glasgow.ac.uk:cae.eng.glasgow.ac.uk(gb-janet) +cae.leeds.ac.uk:ai.leeds.ac.uk(gb-janet) +caesa.wolverhampton.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +caesa.wolves.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +calisto.salf.ac.uk:europa.salford.ac.uk(gb-janet) +callisto.salford.ac.uk:europa.salford.ac.uk(gb-janet) +cam-ani.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cam-orl.co.uk:computer-lab.cambridge.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cam.anglia.ac.uk:cambridge-cluster.anglia-polytechnic.ac.uk(gb-janet) +camalg.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +camberley.sd-scicon.co.uk:camberley.sd-scicon.co.uk(gb-pss) +camborne-school-of-mines.ac.uk:camborne-school-of-mines.ac.uk(gb-janet) +cambridge-algorithmica-limited.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cambridge-animation.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cambridge-cluster.anglia-polytechnic.ac.uk:cambridge-cluster.anglia-polytechnic.ac.uk(gb-janet) +cambridge-consultants.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cambustion.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +camcon.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +camelot.icl.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +camscan.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +can.pmms.cam.ac.uk:canary.dpmms.cambridge.ac.uk(gb-janet) +canary.dpmms.cambridge.ac.uk:canary.dpmms.cambridge.ac.uk(gb-janet) +cancer-trials-office.mrc.ac.uk:cancer-trials-office.mrc.ac.uk(gb-janet) +canon-research-europe.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +canon.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +capell.tn.rl.ac.uk:capella.technorth.rutherford.ac.uk(gb-janet) +capella.technorth.rutherford.ac.uk:capella.technorth.rutherford.ac.uk(gb-janet) +capri.ed.ac.uk:capri.edinburgh.ac.uk(gb-janet),capri.edinburgh.ac.uk(gb-pss) +capri.edinburgh.ac.uk:capri.edinburgh.ac.uk(gb-janet),capri.edinburgh.ac.uk(gb-pss) +capricornia.edu.au:capricornia.edu.au(gb-pss) +cara.ma.hw.ac.uk:cara.maths.heriot-watt.ac.uk(gb-janet) +cara.maths.heriot-watt.ac.uk:cara.maths.heriot-watt.ac.uk(gb-janet) +cardiff-institute.ac.uk:cardiff-institute.ac.uk(gb-janet) +cardiff.ac.uk:cardiff.ac.uk(gb-janet) +cardio.gla.ac.uk:cardio.glasgow.ac.uk(gb-janet) +cardio.glasgow.ac.uk:cardio.glasgow.ac.uk(gb-janet) +care.leeds-poly.ac.uk:care.leeds-poly.ac.uk(gb-janet) +care.lsply.ac.uk:care.leeds-poly.ac.uk(gb-janet) +case.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +castle.ed.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +castle.edinburgh.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +cb.ac.uk:computer-board.ac.uk(gb-janet) +cbl.leeds.ac.uk:ai.leeds.ac.uk(gb-janet) +cc.brunel.ac.uk:brunel.ac.uk(gb-janet) +cc.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cc.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +cch.cov.ac.uk:coventry.ac.uk(gb-janet) +cch.coventry.ac.uk:coventry.ac.uk(gb-janet) +cci.stc.co.uk:bnr.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +cck.cov.ac.uk:cck.coventry.ac.uk(gb-janet) +cck.coventry.ac.uk:cck.coventry.ac.uk(gb-janet) +ccl.umist.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +ccn1.ccc.nottingham.ac.uk:dir.nott.ac.uk(smtp),directory.nottingham.ac.uk(gb-janet) +ccn1.nott.ac.uk:dir.nott.ac.uk(smtp),directory.nottingham.ac.uk(gb-janet) +ccn2.ccc.nottingham.ac.uk:dir.nott.ac.uk(smtp),directory.nottingham.ac.uk(gb-janet) +ccn2.nott.ac.uk:dir.nott.ac.uk(smtp),directory.nottingham.ac.uk(gb-janet) +ccr.bris.ac.uk:bristol.ac.uk(gb-janet) +ccrg.ox.ac.uk:child-cancer-research.oxford.ac.uk(gb-janet) +ccsun.strath.ac.uk:computer-centre-sun.strathclyde.ac.uk(gb-janet) +ccta.uk:ccta.uk(gb-janet) +cctuvax.bham.ac.uk:vax.cancer-clinical-trials-unit.birmingham.ac.uk(gb-janet) +ccua.wolverhampton.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +ccua.wolves.ac.uk:sysa.wolverhampton.ac.uk(gb-janet) +ccur.co.uk:concurrent.co.uk(gb-pss),brunel.ac.uk(gb-janet) +cd.psw.ac.uk:computing-department.poly-south-west.ac.uk(gb-janet) +cdn:ean-relay.ac.uk(gb-janet),ean-relay.ac.uk(gb-pss) +ce.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +cent.gla.ac.uk:udcf.glasgow.ac.uk(gb-janet) +cent.glasgow.ac.uk:udcf.glasgow.ac.uk(gb-janet) +cent.surr.ac.uk:central.surrey.ac.uk(gb-janet),central.surrey.ac.uk(gb-pss) +cent1.lancs.ac.uk:central1.lancaster.ac.uk(gb-janet) +central-administration.cambridge.ac.uk:central-administration.cambridge.ac.uk(gb-janet) +central-unix-service.cambridge.ac.uk:central-unix-service.cambridge.ac.uk(gb-janet) +central.surrey.ac.uk:central.surrey.ac.uk(gb-janet),central.surrey.ac.uk(gb-pss) +central.sussex.ac.uk:central.sussex.ac.uk(gb-janet) +central.susx.ac.uk:central.sussex.ac.uk(gb-janet) +central1.lancaster.ac.uk:central1.lancaster.ac.uk(gb-janet) +cerberus.man.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +cerberus.manchester.ac.uk:sun.central-services.umist.ac.uk(gb-janet) +cern:ean-relay.ac.uk(gb-janet),ean-relay.ac.uk(gb-pss) +cern.ch:ean-relay.ac.uk(gb-janet),ean-relay.ac.uk(gb-pss) +cernvm.cern.ch:cernvm.cern.ch(gb-janet) +cevax.bham.ac.uk:civ-eng-vax.birmingham.ac.uk(gb-janet) +cf.ac.uk:cardiff.ac.uk(gb-janet) +cged.co.uk:praxis.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +cgu.cs.man.ac.uk:graphics.computer-science.manchester.ac.uk(gb-janet) +cgu.mcc.ac.uk:graphics.manchester-computing-centre.ac.uk(gb-janet) +ch:mhs-relay.ac.uk(gb-janet),mhs-relay.ac.uk(x40084),mhs-relay.ac.uk(gb-pss) +ch.ic.ac.uk:cc.imperial.ac.uk(gb-janet) +chaplin.british-telecom.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +chaplin.bt.co.uk:axion.british-telecom.co.uk(gb-pss),uknet-relay.ac.uk(gb-janet) +charles-cross.poly-south-west.ac.uk:charles-cross.poly-south-west.ac.uk(gb-janet) +chcc.aeatech.uk:chcc.harwell.aea-technology.uk(gb-janet) +chcc.harwell.aea-technology.uk:chcc.harwell.aea-technology.uk(gb-janet) +chef.bristol-poly.ac.uk:chef.bristol-poly.ac.uk(gb-janet) +chekov.ee.hull.ac.uk:chekov.ee.hull.ac.uk(gb-janet) +chekov.hull.ac.uk:chekov.ee.hull.ac.uk(gb-janet) +chelgraph.co.uk:cs.nott.ac.uk(smtp),computer-science.nottingham.ac.uk(gb-janet) +chem-eng.cambridge.ac.uk:chem-eng.cambridge.ac.uk(gb-janet) +chem-eng.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +chem.leeds.ac.uk:mailer.leeds.ac.uk(gb-janet) +chem1.gla.ac.uk:chem1.glasgow.ac.uk(gb-janet) +chem1.glasgow.ac.uk:chem1.glasgow.ac.uk(gb-janet) +chema.pharm.lon.ac.uk:chema.pharm.lon.ac.uk(gb-janet) +chemcrys.cam.ac.uk:crystallography.chemistry.cambridge.ac.uk(gb-janet) +chemeng.ed.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +chemical-eng.edinburgh.ac.uk:castle.edinburgh.ac.uk(gb-janet),castle.edinburgh.ac.uk(gb-pss) +chemistry.imperial.ac.uk:cc.imperial.ac.uk(gb-janet) +chemistry.leeds.ac.uk:mailer.leeds.ac.uk(gb-janet) +cheng.cam.ac.uk:chem-eng.cambridge.ac.uk(gb-janet) +chern.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +chernikeeff.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +chf.brispoly.ac.uk:chef.bristol-poly.ac.uk(gb-janet) +child-cancer-research.oxford.ac.uk:child-cancer-research.oxford.ac.uk(gb-janet) +chunet:ean-relay.ac.uk(gb-janet),ean-relay.ac.uk(gb-pss) +chv.dsir.govt.nz:nsfnet-relay.ac.uk(gb-janet),nsfnet-relay.ac.uk(gb-pss) +cif.leeds.ac.uk:cif.leeds.ac.uk(gb-janet) +cihe.ac.uk:cardiff-institute.ac.uk(gb-janet) +cil.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cim.cran.ac.uk:cim.cranfield.ac.uk(gb-janet) +cim.cranfield.ac.uk:cim.cranfield.ac.uk(gb-janet) +cim.leeds.ac.uk:ai.leeds.ac.uk(gb-janet) +citi.cran.ac.uk:citi.cranfield.ac.uk(gb-janet) +citi.cranfield.ac.uk:citi.cranfield.ac.uk(gb-janet) +city-poly.ac.uk:city-poly.ac.uk(gb-janet) +city.ac.uk:city.ac.uk(gb-janet) +civ-eng-vax.birmingham.ac.uk:civ-eng-vax.birmingham.ac.uk(gb-janet) +civeng.swansea.ac.uk:civeng.swansea.ac.uk(gb-janet) +civil.leeds.ac.uk:mailer.leeds.ac.uk(gb-janet) +civil.novell.leeds.ac.uk:mailer.leeds.ac.uk(gb-janet) +cix.clink.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cix.compulink.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +cl.cam.ac.uk:computer-lab.cambridge.ac.uk(gb-janet) +clink.co.uk:uknet-relay.ac.uk(gb-janet),uknet-relay.ac.uk(gb-pss) +clp.ac.uk:city-poly.ac.uk(gb-janet) +clss1.bangor.ac.uk:clss1.bangor.ac.uk(gb-janet) +clstr.pnl.ac.uk:cluster.poly-north-london.ac.uk(gb-janet) +clu.abcy.cardiff.ac.uk:clu.abcy.cardiff.ac.uk(gb-janet) +clu.abcy.cf.ac.uk:clu.abcy.cardiff.ac.uk(gb-janet) +club.eng.cam.ac.uk:teaching.engineering.cambridge.ac.uk(gb-janet) +clus1.ulcc.ac.uk:clus1.ulcc.ac.uk(gb-janet) +clust.aston.ac.uk:cluster.vax.aston.ac.uk(gb-janet) +clust.ch.cam.ac.uk:cluster.chemistry.cambridge.ac.uk(gb-janet) +clust.hw.ac.uk:cluster.heriot-watt.ac.uk(gb-janet) +cluster.chemistry.cambridge.ac.uk:cluster.chemistry.cambridge.ac.uk(gb-janet) +cluster.heriot-watt.ac.uk:cluster.heriot-watt.ac.uk(gb-janet) +cluster.middlesex.ac.uk:cluster.middlesex.ac.uk(gb-janet) +cluster.mx.ac.uk:cluster.middlesex.ac.uk(gb-janet) +cluster.poly-north-london.ac.uk:cluster.poly-north-london.ac.uk(gb-janet) +cluster.sussex.ac.uk:cluster.sussex.ac.uk(gb-janet) +cluster.susx.ac.uk:cluster.sussex.ac.uk(gb-janet) +cluster.trent-poly.ac.uk:cluster.trent-poly.ac.uk(gb-janet) +cluster.vax.aston.ac.uk:cluster.vax.aston.ac.uk(gb-janet) +clustr.trent.ac.uk:cluster.trent-poly.ac.uk(gb-janet) +cm.cf.ac.uk:computing-maths.cardiff.ac.uk(gb-janet) +cms.am.cc.reading.ac.uk:cms.am.cc.reading.ac.uk(gb-janet) +cms.am.rdg.ac.uk:cms.am.cc.reading.ac.uk(gb-janet) +cms.bris.ac.uk:cms.bristol.ac.uk(gb-janet) +cms.bristol.ac.uk:cms.bristol.ac.uk(gb-janet) +cms.gla.ac.uk:cms.glasgow.ac.uk(gb-janet) +cms.glasgow.ac.uk:cms.glasgow.ac.uk(gb-janet) +cms.manchester-computing-centre.ac.uk:cms.manchester-computing-centre.ac.uk(gb-janet) +cms.mcc.ac.uk:cms.manchester-computing-centre.ac.uk(gb-janet) +cms.scp.ac.uk:computing-and-management-sciences.sheffield-city-poly.ac.uk(gb-janet) +cms.ulcc.ac.uk:cms.ulcc.ac.uk(gb-janet) diff --git a/examples/xtel/config.h b/examples/xtel/config.h new file mode 100644 index 0000000..38798d9 --- /dev/null +++ b/examples/xtel/config.h @@ -0,0 +1,47 @@ +/* config.h: compile time configuration parameters */ + +/* + * @(#) $Header$ + * + * $Log$ + * + */ + + +#ifndef _H_CONFIG +#define _H_CONFIG + + +/* +Define the type of system you are running on. Beware - most of these have +no effect what so ever! Only one should be defined. +*/ + +/* +Choose DBM (-ldbm stuff) or NDBM (berkeley4.3/sun standard & better) +*/ +#define NDBM +#undef DBM +#undef GDBM + +/* define the following if you require BIND nameserver support for SMTP */ +/* #define NAMESERVER */ + +#define PP_DEBUG_ALL 2 +#define PP_DEBUG_SOME 1 +#define PP_DEBUG_NONE 0 + +#define PP_DEBUG PP_DEBUG_ALL + +/* + * define the following if you require user tools to use uk domain ordering + * by default + * #define UKORDER + */ + +/* +Add after this anything specific to your host. +*/ + +#define VAT /* extra stuff */ +#endif diff --git a/examples/xtel/domain b/examples/xtel/domain new file mode 100644 index 0000000..669ca6a --- /dev/null +++ b/examples/xtel/domain @@ -0,0 +1,500 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Wed Dec 18 08:34:19 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +bigears.concurrent.co.zz:local +uk:valid +# us +xtel.co.uk:norm+mta=xtel.co.uk local +xtel.co:norm+mta=xtel.co.uk local +xtel:norm+mta=xtel.co.uk local +xtel.uucp:norm+mta=xtel.co.uk local +lancaster.xtel.co.uk:norm+mta=xtel.co.uk local +lancaster.xtel.co:norm+mta=xtel.co.uk local +lancaster.xtel:norm+mta=xtel.co.uk local +lancaster:norm+mta=xtel.co.uk local +vulcan.xtel.co.uk:synonym=xtel.co.uk +vulcan.xtel.co:synonym=xtel.co.uk +vulcan.xtel:synonym=xtel.co.uk +vulcan:synonym=xtel.co.uk +spitfire.xtel.co.uk:synonym=xtel.co.uk +spitfire.xtel.co:synonym=xtel.co.uk +spitfire.xtel:synonym=xtel.co.uk +spitfire:synonym=xtel.co.uk +hurricane.xtel.co.uk:synonym=xtel.co.uk +hurricane.xtel.co:synonym=xtel.co.uk +hurricane.xtel:synonym=xtel.co.uk +hurricane:synonym=xtel.co.uk +vampire.xtel.co.uk:synonym=xtel.co.uk +vampire.xtel.co:synonym=xtel.co.uk +vampire.xtel:synonym=xtel.co.uk +vampire:synonym=xtel.co.uk +meteor.xtel.co.uk:synonym=xtel.co.uk +meteor.xtel.co:synonym=xtel.co.uk +meteor.xtel:synonym=xtel.co.uk +meteor:synonym=xtel.co.uk +lightning.xtel.co.uk:synonym=xtel.co.uk +lightning.xtel.co:synonym=xtel.co.uk +lightning.xtel:synonym=xtel.co.uk +lightning:synonym=xtel.co.uk +typhoon.xtel.co.uk:synonym=xtel.co.uk +typhoon.xtel.co:synonym=xtel.co.uk +typhoon.xtel:synonym=xtel.co.uk +typhoon:synonym=xtel.co.uk +tornado.xtel.co.uk:synonym=xtel.co.uk +tornado.xtel.co:synonym=xtel.co.uk +tornado.xtel:synonym=xtel.co.uk +tornado:synonym=xtel.co.uk +dornier.xtel.co.uk:norm+mta=dornier.xtel.co.uk +dornier.xtel.co:norm+mta=dornier.xtel.co.uk +dornier.xtel:norm+mta=dornier.xtel.co.uk +dornier:norm+mta=dornier.xtel.co.uk +x400.xtel.co.uk:norm+mta local=x400-developers +x400.xtel.co:norm+mta=x400.xtel.co.uk local=x400-developers +x400.xtel:norm+mta=x400.xtel.co.uk local=x400-developers +x400:norm+mta=x400.xtel.co.uk local=x400-developers +fax.xtel.co.uk:norm+mta=fax.xtel.co.uk +fax.xtel.co:norm+mta=fax.xtel.co.uk +fax.xtel:norm+mta=fax.xtel.co.uk +fax:norm+mta=fax.xtel.co.uk +cs-nott:synonym=cs.nott.ac.uk +nottcs:synonym=cs.nott.ac.uk +csnott:synonym=cs.nott.ac.uk +nott-cs:synonym=cs.nott.ac.uk +uucp.cs:synonym=cs.nott.ac.uk +computer-science:synonym=cs.nott.ac.uk +compsci:synonym=cs.nott.ac.uk +crg.cs.nott.ac.uk:synonym=cs.nott.ac.uk +crg.cs.nott.ac:synonym=cs.nott.ac.uk +crg.cs.nott:synonym=cs.nott.ac.uk +crg.cs:synonym=cs.nott.ac.uk +crg.computer-science.nottingham.ac.uk:synonym=cs.nott.ac.uk +crg.computer-science.nottingham.ac:synonym=cs.nott.ac.uk +crg.computer-science.nottingham:synonym=cs.nott.ac.uk +# other local people +much.cs.nott.ac.uk:synonym=cs.nott.ac.uk +much.cs.nott.ac:synonym=cs.nott.ac.uk +much.cs.nott:synonym=cs.nott.ac.uk +much.cs:synonym=cs.nott.ac.uk +much:synonym=cs.nott.ac.uk +little:synonym=cs.nott.ac.uk +marian:synonym=cs.nott.ac.uk +dir.nott.ac.uk:norm+mta=dir.nott.ac.uk +dir.nott.ac:norm+mta=dir.nott.ac.uk +dir.nott:norm+mta=dir.nott.ac.uk +dir:norm+mta=dir.nott.ac.uk +dir1.xtel.co.uk:norm+mta=dir1.xtel.co.uk +dir1.xtel.co:norm+mta=dir1.xtel.co.uk +dir1.xtel:norm+mta=dir1.xtel.co.uk +dir1:norm+mta=dir1.xtel.co.uk +# psychology +rpsyc.nott.ac.uk:norm+mta=rpsyc.nott.ac.uk +rpsyc.nott.ac:norm+mta=rpsyc.nott.ac.uk +rpsyc.nott:norm+mta=rpsyc.nott.ac.uk +rpsyc:norm+mta=rpsyc.nott.ac.uk +tpsyc.nott.ac.uk:norm+mta=tpsyc.nott.ac.uk +tpsyc.nott.ac:norm+mta=tpsyc.nott.ac.uk +tpsyc.nott:norm+mta=tpsyc.nott.ac.uk +tpsyc:norm+mta=tpsyc.nott.ac.uk +# others +*.uucp:mta=uucp +bells.cs.ucl.ac.uk:norm+mta=bells.cs.ucl.ac.uk +bells.cs.ucl.ac:norm+mta=bells.cs.ucl.ac.uk +bells.cs.ucl:norm+mta=bells.cs.ucl.ac.uk +talisker.cs.ucl.ac.uk:norm+mta=talisker.cs.ucl.ac.uk +talisker.cs.ucl.ac:norm+mta=talisker.cs.ucl.ac.uk +talisker.cs.ucl:norm+mta=talisker.cs.ucl.ac.uk + +# +*.hk:mta=hk +*.jp:mta=jp +*.il:mta=il +*.is:mta=is +#*.cs:mta=cs +*.br:mta=br +*.in:mta=in +*.gr:mta=gr +#*.mel.dit.csiro.au:norm+mta=mel.dit.csiro.au +mel.dit.csiro.au:valid +#*.au:valid + + +capricornia.edu.au:norm+mta=capricornia.edu.au +capricornia.edu.au:norm+mta=capricornia.edu.au +flinders.edu.au:norm+mta=flinders.edu.au +flinders.edu.au:norm+mta=flinders.edu.au +qut.edu.au:norm+mta=qut.edu.au +qut.edu.au:norm+mta=qut.edu.au +uq.edu.au:norm+mta=uq.edu.au +uq.edu.au:norm+mta=uq.edu.au +uqkl10.uq.edu.au:norm+mta=uqkl10.uq.edu.au +uqkl10.uq.edu.au:norm+mta=uqkl10.uq.edu.au +uqvax.uq.edu.au:norm+mta=uqvax.uq.edu.au +uqvax.uq.edu.au:norm+mta=uqvax.uq.edu.au +wombat.uq.edu.au:norm+mta=wombat.uq.edu.au +wombat.uq.edu.au:norm+mta=wombat.uq.edu.au +utas.edu.au:norm+mta=utas.edu.au +utas.edu.au:norm+mta=utas.edu.au +ibm.cern.ch:norm+mta=ibm.cern.ch +ibm.cern.ch:norm+mta=ibm.cern.ch +index.cern.ch:norm+mta=index.cern.ch +index.cern.ch:norm+mta=index.cern.ch +pad3.cern.ch:norm+mta=pad3.cern.ch +pad3.cern.ch:norm+mta=pad3.cern.ch +uxnmc.cern.ch:norm+mta=uxnmc.cern.ch +uxnmc.cern.ch:norm+mta=uxnmc.cern.ch +vxisol.cern.ch:norm+mta=vxisol.cern.ch +vxisol.cern.ch:norm+mta=vxisol.cern.ch +vxalfb.cern.ch:norm+mta=vxalfb.cern.ch +vxalfb.cern.ch:norm+mta=vxalfb.cern.ch +vxbssy.cern.ch:norm+mta=vxbssy.cern.ch +vxbssy.cern.ch:norm+mta=vxbssy.cern.ch +vxcrnb.cern.ch:norm+mta=vxcrnb.cern.ch +vxcrnb.cern.ch:norm+mta=vxcrnb.cern.ch +vxcrna.cern.ch:norm+mta=vxcrna.cern.ch +vxcrna.cern.ch:norm+mta=vxcrna.cern.ch +vxgift.cern.ch:norm+mta=vxgift.cern.ch +vxgift.cern.ch:norm+mta=vxgift.cern.ch +vxl3.cern.ch:norm+mta=vxl3.cern.ch +vxl3.cern.ch:norm+mta=vxl3.cern.ch +vxmerl.cern.ch:norm+mta=vxmerl.cern.ch +vxmerl.cern.ch:norm+mta=vxmerl.cern.ch +cernvm.cern.ch:norm+mta=cernvm.cern.ch +cernvm.cern.ch:norm+mta=cernvm.cern.ch +cithex.cern.ch:norm+mta=cithex.cern.ch +cithex.cern.ch:norm+mta=cithex.cern.ch +cmuhep.cern.ch:norm+mta=cmuhep.cern.ch +cmuhep.cern.ch:norm+mta=cmuhep.cern.ch +huhepl.cern.ch:norm+mta=huhepl.cern.ch +huhepl.cern.ch:norm+mta=huhepl.cern.ch +jhuphep.cern.ch:norm+mta=jhuphep.cern.ch +jhuphep.cern.ch:norm+mta=jhuphep.cern.ch +mich.cern.ch:norm+mta=mich.cern.ch +mich.cern.ch:norm+mta=mich.cern.ch +mitlns.cern.ch:norm+mta=mitlns.cern.ch +mitlns.cern.ch:norm+mta=mitlns.cern.ch +norhep.cern.ch:norm+mta=norhep.cern.ch +norhep.cern.ch:norm+mta=norhep.cern.ch +vxl3mu.cern.ch:norm+mta=vxl3mu.cern.ch +vxl3mu.cern.ch:norm+mta=vxl3mu.cern.ch +vxl3td.cern.ch:norm+mta=vxl3td.cern.ch +vxl3td.cern.ch:norm+mta=vxl3td.cern.ch +vxna31.cern.ch:norm+mta=vxna31.cern.ch +vxna31.cern.ch:norm+mta=vxna31.cern.ch +vxp173.cern.ch:norm+mta=vxp173.cern.ch +vxp173.cern.ch:norm+mta=vxp173.cern.ch +prinhep.cern.ch:norm+mta=prinhep.cern.ch +prinhep.cern.ch:norm+mta=prinhep.cern.ch +ndua6.cern.ch:norm+mta=ndua6.cern.ch +ndua6.cern.ch:norm+mta=ndua6.cern.ch +cernvmp.cern.ch:norm+mta=cernvmp.cern.ch +cernvmp.cern.ch:norm+mta=cernvmp.cern.ch +cernvmlm.cern.ch:norm+mta=cernvmlm.cern.ch +cernvmlm.cern.ch:norm+mta=cernvmlm.cern.ch +cernvmfs.cern.ch:norm+mta=cernvmfs.cern.ch +cernvmfs.cern.ch:norm+mta=cernvmfs.cern.ch +padp.desy:norm+mta=padp.desy +padp.desy:norm+mta=padp.desy +wnv.dsir.govt.nz:norm+mta=wnv.dsir.govt.nz +wnv.dsir.govt.nz:norm+mta=wnv.dsir.govt.nz +wmv.dsir.govt.nz:norm+mta=wmv.dsir.govt.nz +wmv.dsir.govt.nz:norm+mta=wmv.dsir.govt.nz +akv.dsir.govt.nz:norm+mta=akv.dsir.govt.nz +akv.dsir.govt.nz:norm+mta=akv.dsir.govt.nz +amv.dsir.govt.nz:norm+mta=amv.dsir.govt.nz +amv.dsir.govt.nz:norm+mta=amv.dsir.govt.nz +pnv.dsir.govt.nz:norm+mta=pnv.dsir.govt.nz +pnv.dsir.govt.nz:norm+mta=pnv.dsir.govt.nz +pmv.dsir.govt.nz:norm+mta=pmv.dsir.govt.nz +pmv.dsir.govt.nz:norm+mta=pmv.dsir.govt.nz +grv.dsir.govt.nz:norm+mta=grv.dsir.govt.nz +grv.dsir.govt.nz:norm+mta=grv.dsir.govt.nz +gfv.dsir.govt.nz:norm+mta=gfv.dsir.govt.nz +gfv.dsir.govt.nz:norm+mta=gfv.dsir.govt.nz +gmv.dsir.govt.nz:norm+mta=gmv.dsir.govt.nz +gmv.dsir.govt.nz:norm+mta=gmv.dsir.govt.nz +chv.dsir.govt.nz:norm+mta=chv.dsir.govt.nz +chv.dsir.govt.nz:norm+mta=chv.dsir.govt.nz +cmv.dsir.govt.nz:norm+mta=cmv.dsir.govt.nz +cmv.dsir.govt.nz:norm+mta=cmv.dsir.govt.nz +aberdeen.ac.uk:norm+mta=aberdeen.ac.uk +aberdeen.ac:norm+mta=aberdeen.ac.uk +aberdeen:norm+mta=aberdeen.ac.uk +abdn.ac.uk:norm+mta=aberdeen.ac.uk +abdn.ac:norm+mta=aberdeen.ac.uk +abdn:norm+mta=aberdeen.ac.uk +admin.aberdeen.ac.uk:norm+mta=admin.aberdeen.ac.uk +admin.aberdeen.ac:norm+mta=admin.aberdeen.ac.uk +admin.aberdeen:norm+mta=admin.aberdeen.ac.uk +admin.abdn.ac.uk:norm+mta=admin.aberdeen.ac.uk +admin.abdn.ac:norm+mta=admin.aberdeen.ac.uk +admin.abdn:norm+mta=admin.aberdeen.ac.uk +bio-medical-physics.aberdeen.ac.uk:norm+mta=bio-medical-physics.aberdeen.ac.uk +bio-medical-physics.aberdeen.ac:norm+mta=bio-medical-physics.aberdeen.ac.uk +bio-medical-physics.aberdeen:norm+mta=bio-medical-physics.aberdeen.ac.uk +biomed.abdn.ac.uk:norm+mta=bio-medical-physics.aberdeen.ac.uk +biomed.abdn.ac:norm+mta=bio-medical-physics.aberdeen.ac.uk +biomed.abdn:norm+mta=bio-medical-physics.aberdeen.ac.uk +computing-science.aberdeen.ac.uk:norm+mta=computing-science.aberdeen.ac.uk +computing-science.aberdeen.ac:norm+mta=computing-science.aberdeen.ac.uk +computing-science.aberdeen:norm+mta=computing-science.aberdeen.ac.uk +csd.abdn.ac.uk:norm+mta=computing-science.aberdeen.ac.uk +csd.abdn.ac:norm+mta=computing-science.aberdeen.ac.uk +csd.abdn:norm+mta=computing-science.aberdeen.ac.uk +comp-science.aberdeen.ac.uk:norm+mta=comp-science.aberdeen.ac.uk +comp-science.aberdeen.ac:norm+mta=comp-science.aberdeen.ac.uk +comp-science.aberdeen:norm+mta=comp-science.aberdeen.ac.uk +cs.abdn.ac.uk:norm+mta=comp-science.aberdeen.ac.uk +cs.abdn.ac:norm+mta=comp-science.aberdeen.ac.uk +cs.abdn:norm+mta=comp-science.aberdeen.ac.uk +erg.aberdeen.ac.uk:norm+mta=erg.aberdeen.ac.uk +erg.aberdeen.ac:norm+mta=erg.aberdeen.ac.uk +erg.aberdeen:norm+mta=erg.aberdeen.ac.uk +erg.abdn.ac.uk:norm+mta=erg.aberdeen.ac.uk +erg.abdn.ac:norm+mta=erg.aberdeen.ac.uk +erg.abdn:norm+mta=erg.aberdeen.ac.uk +kc.aberdeen.ac.uk:norm+mta=kc.aberdeen.ac.uk +kc.aberdeen.ac:norm+mta=kc.aberdeen.ac.uk +kc.aberdeen:norm+mta=kc.aberdeen.ac.uk +kc.abdn.ac.uk:norm+mta=kc.aberdeen.ac.uk +kc.abdn.ac:norm+mta=kc.aberdeen.ac.uk +kc.abdn:norm+mta=kc.aberdeen.ac.uk +library.aberdeen.ac.uk:norm+mta=library.aberdeen.ac.uk +library.aberdeen.ac:norm+mta=library.aberdeen.ac.uk +library.aberdeen:norm+mta=library.aberdeen.ac.uk +lib.abdn.ac.uk:norm+mta=library.aberdeen.ac.uk +lib.abdn.ac:norm+mta=library.aberdeen.ac.uk +lib.abdn:norm+mta=library.aberdeen.ac.uk +maths.aberdeen.ac.uk:norm+mta=maths.aberdeen.ac.uk +maths.aberdeen.ac:norm+mta=maths.aberdeen.ac.uk +maths.aberdeen:norm+mta=maths.aberdeen.ac.uk +maths.abdn.ac.uk:norm+mta=maths.aberdeen.ac.uk +maths.abdn.ac:norm+mta=maths.aberdeen.ac.uk +maths.abdn:norm+mta=maths.aberdeen.ac.uk +sysa.aberdeen.ac.uk:norm+mta=sysa.aberdeen.ac.uk +sysa.aberdeen.ac:norm+mta=sysa.aberdeen.ac.uk +sysa.aberdeen:norm+mta=sysa.aberdeen.ac.uk +sysa.abdn.ac.uk:norm+mta=sysa.aberdeen.ac.uk +sysa.abdn.ac:norm+mta=sysa.aberdeen.ac.uk +sysa.abdn:norm+mta=sysa.aberdeen.ac.uk +sysb.aberdeen.ac.uk:norm+mta=sysb.aberdeen.ac.uk +sysb.aberdeen.ac:norm+mta=sysb.aberdeen.ac.uk +sysb.aberdeen:norm+mta=sysb.aberdeen.ac.uk +sysb.abdn.ac.uk:norm+mta=sysb.aberdeen.ac.uk +sysb.abdn.ac:norm+mta=sysb.aberdeen.ac.uk +sysb.abdn:norm+mta=sysb.aberdeen.ac.uk +mail.aberdeen.ac.uk:norm+mta=mail.aberdeen.ac.uk +mail.aberdeen.ac:norm+mta=mail.aberdeen.ac.uk +mail.aberdeen:norm+mta=mail.aberdeen.ac.uk +mail.abdn.ac.uk:norm+mta=mail.aberdeen.ac.uk +mail.abdn.ac:norm+mta=mail.aberdeen.ac.uk +mail.abdn:norm+mta=mail.aberdeen.ac.uk +sysc.aberdeen.ac.uk:norm+mta=sysc.aberdeen.ac.uk +sysc.aberdeen.ac:norm+mta=sysc.aberdeen.ac.uk +sysc.aberdeen:norm+mta=sysc.aberdeen.ac.uk +sysc.abdn.ac.uk:norm+mta=sysc.aberdeen.ac.uk +sysc.abdn.ac:norm+mta=sysc.aberdeen.ac.uk +sysc.abdn:norm+mta=sysc.aberdeen.ac.uk +aberystwyth.ac.uk:norm+mta=aberystwyth.ac.uk +aberystwyth.ac:norm+mta=aberystwyth.ac.uk +aberystwyth:norm+mta=aberystwyth.ac.uk +aber.ac.uk:norm+mta=aberystwyth.ac.uk +aber.ac:norm+mta=aberystwyth.ac.uk +aber:norm+mta=aberystwyth.ac.uk +test.aberystwyth.ac.uk:norm+mta=test.aberystwyth.ac.uk +test.aberystwyth.ac:norm+mta=test.aberystwyth.ac.uk +test.aberystwyth:norm+mta=test.aberystwyth.ac.uk +test.aber.ac.uk:norm+mta=test.aberystwyth.ac.uk +test.aber.ac:norm+mta=test.aberystwyth.ac.uk +test.aber:norm+mta=test.aberystwyth.ac.uk +deca.central.aberystwyth.ac.uk:norm+mta=deca.central.aberystwyth.ac.uk +deca.central.aberystwyth.ac:norm+mta=deca.central.aberystwyth.ac.uk +deca.central.aberystwyth:norm+mta=deca.central.aberystwyth.ac.uk +a.aber.ac.uk:norm+mta=deca.central.aberystwyth.ac.uk +a.aber.ac:norm+mta=deca.central.aberystwyth.ac.uk +a.aber:norm+mta=deca.central.aberystwyth.ac.uk +decb.central.aberystwyth.ac.uk:norm+mta=decb.central.aberystwyth.ac.uk +decb.central.aberystwyth.ac:norm+mta=decb.central.aberystwyth.ac.uk +decb.central.aberystwyth:norm+mta=decb.central.aberystwyth.ac.uk +b.aber.ac.uk:norm+mta=decb.central.aberystwyth.ac.uk +b.aber.ac:norm+mta=decb.central.aberystwyth.ac.uk +b.aber:norm+mta=decb.central.aberystwyth.ac.uk +info.central.aberystwyth.ac.uk:norm+mta=info.central.aberystwyth.ac.uk +info.central.aberystwyth.ac:norm+mta=info.central.aberystwyth.ac.uk +info.central.aberystwyth:norm+mta=info.central.aberystwyth.ac.uk +info.aber.ac.uk:norm+mta=info.central.aberystwyth.ac.uk +info.aber.ac:norm+mta=info.central.aberystwyth.ac.uk +info.aber:norm+mta=info.central.aberystwyth.ac.uk +vax.central.aberystwyth.ac.uk:norm+mta=vax.central.aberystwyth.ac.uk +vax.central.aberystwyth.ac:norm+mta=vax.central.aberystwyth.ac.uk +vax.central.aberystwyth:norm+mta=vax.central.aberystwyth.ac.uk +v.aber.ac.uk:norm+mta=vax.central.aberystwyth.ac.uk +v.aber.ac:norm+mta=vax.central.aberystwyth.ac.uk +v.aber:norm+mta=vax.central.aberystwyth.ac.uk +compsci.aberystwyth.ac.uk:norm+mta=compsci.aberystwyth.ac.uk +compsci.aberystwyth.ac:norm+mta=compsci.aberystwyth.ac.uk +compsci.aberystwyth:norm+mta=compsci.aberystwyth.ac.uk +cs.aber.ac.uk:norm+mta=compsci.aberystwyth.ac.uk +cs.aber.ac:norm+mta=compsci.aberystwyth.ac.uk +cs.aber:norm+mta=compsci.aberystwyth.ac.uk +library.aberystwyth.ac.uk:norm+mta=library.aberystwyth.ac.uk +library.aberystwyth.ac:norm+mta=library.aberystwyth.ac.uk +library.aberystwyth:norm+mta=library.aberystwyth.ac.uk +lib.aber.ac.uk:norm+mta=library.aberystwyth.ac.uk +lib.aber.ac:norm+mta=library.aberystwyth.ac.uk +lib.aber:norm+mta=library.aberystwyth.ac.uk +netman.central.aberystwyth.ac.uk:norm+mta=netman.central.aberystwyth.ac.uk +netman.central.aberystwyth.ac:norm+mta=netman.central.aberystwyth.ac.uk +netman.central.aberystwyth:norm+mta=netman.central.aberystwyth.ac.uk +netman.aber.ac.uk:norm+mta=netman.central.aberystwyth.ac.uk +netman.aber.ac:norm+mta=netman.central.aberystwyth.ac.uk +netman.aber:norm+mta=netman.central.aberystwyth.ac.uk +arcc.afrc.ac.uk:norm+mta=arcc.afrc.ac.uk +arcc.afrc.ac:norm+mta=arcc.afrc.ac.uk +arcc.afrc:norm+mta=arcc.afrc.ac.uk +arcc.afrc.ac.uk:norm+mta=arcc.afrc.ac.uk +arcc.afrc.ac:norm+mta=arcc.afrc.ac.uk +arcc.afrc:norm+mta=arcc.afrc.ac.uk +arcb.afrc.ac.uk:norm+mta=arcb.afrc.ac.uk +arcb.afrc.ac:norm+mta=arcb.afrc.ac.uk +arcb.afrc:norm+mta=arcb.afrc.ac.uk +arcb.afrc.ac.uk:norm+mta=arcb.afrc.ac.uk +arcb.afrc.ac:norm+mta=arcb.afrc.ac.uk +arcb.afrc:norm+mta=arcb.afrc.ac.uk +arcd.afrc.ac.uk:norm+mta=arcd.afrc.ac.uk +arcd.afrc.ac:norm+mta=arcd.afrc.ac.uk +arcd.afrc:norm+mta=arcd.afrc.ac.uk +arcd.afrc.ac.uk:norm+mta=arcd.afrc.ac.uk +arcd.afrc.ac:norm+mta=arcd.afrc.ac.uk +arcd.afrc:norm+mta=arcd.afrc.ac.uk +afrcco.afrc.ac.uk:norm+mta=afrcco.afrc.ac.uk +afrcco.afrc.ac:norm+mta=afrcco.afrc.ac.uk +afrcco.afrc:norm+mta=afrcco.afrc.ac.uk +afrcco.afrc.ac.uk:norm+mta=afrcco.afrc.ac.uk +afrcco.afrc.ac:norm+mta=afrcco.afrc.ac.uk +afrcco.afrc:norm+mta=afrcco.afrc.ac.uk +agri.afrc.ac.uk:norm+mta=agri.afrc.ac.uk +agri.afrc.ac:norm+mta=agri.afrc.ac.uk +agri.afrc:norm+mta=agri.afrc.ac.uk +agri.afrc.ac.uk:norm+mta=agri.afrc.ac.uk +agri.afrc.ac:norm+mta=agri.afrc.ac.uk +agri.afrc:norm+mta=agri.afrc.ac.uk +lars.afrc.ac.uk:norm+mta=lars.afrc.ac.uk +lars.afrc.ac:norm+mta=lars.afrc.ac.uk +lars.afrc:norm+mta=lars.afrc.ac.uk +lars.afrc.ac.uk:norm+mta=lars.afrc.ac.uk +lars.afrc.ac:norm+mta=lars.afrc.ac.uk +lars.afrc:norm+mta=lars.afrc.ac.uk +nvrs.afrc.ac.uk:norm+mta=nvrs.afrc.ac.uk +nvrs.afrc.ac:norm+mta=nvrs.afrc.ac.uk +nvrs.afrc:norm+mta=nvrs.afrc.ac.uk +nvrs.afrc.ac.uk:norm+mta=nvrs.afrc.ac.uk +nvrs.afrc.ac:norm+mta=nvrs.afrc.ac.uk +nvrs.afrc:norm+mta=nvrs.afrc.ac.uk +frir.afrc.ac.uk:norm+mta=frir.afrc.ac.uk +frir.afrc.ac:norm+mta=frir.afrc.ac.uk +frir.afrc:norm+mta=frir.afrc.ac.uk +frir.afrc.ac.uk:norm+mta=frir.afrc.ac.uk +frir.afrc.ac:norm+mta=frir.afrc.ac.uk +frir.afrc:norm+mta=frir.afrc.ac.uk +frira.afrc.ac.uk:norm+mta=frira.afrc.ac.uk +frira.afrc.ac:norm+mta=frira.afrc.ac.uk +frira.afrc:norm+mta=frira.afrc.ac.uk +frira.afrc.ac.uk:norm+mta=frira.afrc.ac.uk +frira.afrc.ac:norm+mta=frira.afrc.ac.uk +frira.afrc:norm+mta=frira.afrc.ac.uk +resa.afrc.ac.uk:norm+mta=resa.afrc.ac.uk +resa.afrc.ac:norm+mta=resa.afrc.ac.uk +resa.afrc:norm+mta=resa.afrc.ac.uk +resa.afrc.ac.uk:norm+mta=resa.afrc.ac.uk +resa.afrc.ac:norm+mta=resa.afrc.ac.uk +resa.afrc:norm+mta=resa.afrc.ac.uk +jii.afrc.ac.uk:norm+mta=jii.afrc.ac.uk +jii.afrc.ac:norm+mta=jii.afrc.ac.uk +jii.afrc:norm+mta=jii.afrc.ac.uk +jii.afrc.ac.uk:norm+mta=jii.afrc.ac.uk +jii.afrc.ac:norm+mta=jii.afrc.ac.uk +jii.afrc:norm+mta=jii.afrc.ac.uk +frin.afrc.ac.uk:norm+mta=frin.afrc.ac.uk +frin.afrc.ac:norm+mta=frin.afrc.ac.uk +frin.afrc:norm+mta=frin.afrc.ac.uk +frin.afrc.ac.uk:norm+mta=frin.afrc.ac.uk +frin.afrc.ac:norm+mta=frin.afrc.ac.uk +frin.afrc:norm+mta=frin.afrc.ac.uk +frind.afrc.ac.uk:norm+mta=frind.afrc.ac.uk +frind.afrc.ac:norm+mta=frind.afrc.ac.uk +frind.afrc:norm+mta=frind.afrc.ac.uk +frind.afrc.ac.uk:norm+mta=frind.afrc.ac.uk +frind.afrc.ac:norm+mta=frind.afrc.ac.uk +frind.afrc:norm+mta=frind.afrc.ac.uk +nfl.afrc.ac.uk:norm+mta=nfl.afrc.ac.uk +nfl.afrc.ac:norm+mta=nfl.afrc.ac.uk +nfl.afrc:norm+mta=nfl.afrc.ac.uk +nfl.afrc.ac.uk:norm+mta=nfl.afrc.ac.uk +nfl.afrc.ac:norm+mta=nfl.afrc.ac.uk +nfl.afrc:norm+mta=nfl.afrc.ac.uk +niaea.afrc.ac.uk:norm+mta=niaea.afrc.ac.uk +niaea.afrc.ac:norm+mta=niaea.afrc.ac.uk +niaea.afrc:norm+mta=niaea.afrc.ac.uk +niaea.afrc.ac.uk:norm+mta=niaea.afrc.ac.uk +niaea.afrc.ac:norm+mta=niaea.afrc.ac.uk +niaea.afrc:norm+mta=niaea.afrc.ac.uk +emrs.afrc.ac.uk:norm+mta=emrs.afrc.ac.uk +emrs.afrc.ac:norm+mta=emrs.afrc.ac.uk +emrs.afrc:norm+mta=emrs.afrc.ac.uk +emrs.afrc.ac.uk:norm+mta=emrs.afrc.ac.uk +emrs.afrc.ac:norm+mta=emrs.afrc.ac.uk +emrs.afrc:norm+mta=emrs.afrc.ac.uk +avri.afrc.ac.uk:norm+mta=avri.afrc.ac.uk +avri.afrc.ac:norm+mta=avri.afrc.ac.uk +avri.afrc:norm+mta=avri.afrc.ac.uk +avri.afrc.ac.uk:norm+mta=avri.afrc.ac.uk +avri.afrc.ac:norm+mta=avri.afrc.ac.uk +avri.afrc:norm+mta=avri.afrc.ac.uk +gcri.afrc.ac.uk:norm+mta=gcri.afrc.ac.uk +gcri.afrc.ac:norm+mta=gcri.afrc.ac.uk +gcri.afrc:norm+mta=gcri.afrc.ac.uk +gcri.afrc.ac.uk:norm+mta=gcri.afrc.ac.uk +gcri.afrc.ac:norm+mta=gcri.afrc.ac.uk +gcri.afrc:norm+mta=gcri.afrc.ac.uk +iapc.afrc.ac.uk:norm+mta=iapc.afrc.ac.uk +iapc.afrc.ac:norm+mta=iapc.afrc.ac.uk +iapc.afrc:norm+mta=iapc.afrc.ac.uk +iapc.afrc.ac.uk:norm+mta=iapc.afrc.ac.uk +iapc.afrc.ac:norm+mta=iapc.afrc.ac.uk +iapc.afrc:norm+mta=iapc.afrc.ac.uk +irad.afrc.ac.uk:norm+mta=irad.afrc.ac.uk +irad.afrc.ac:norm+mta=irad.afrc.ac.uk +irad.afrc:norm+mta=irad.afrc.ac.uk +irad.afrc.ac.uk:norm+mta=irad.afrc.ac.uk +irad.afrc.ac:norm+mta=irad.afrc.ac.uk +irad.afrc:norm+mta=irad.afrc.ac.uk +wpbs.afrc.ac.uk:norm+mta=wpbs.afrc.ac.uk +wpbs.afrc.ac:norm+mta=wpbs.afrc.ac.uk +wpbs.afrc:norm+mta=wpbs.afrc.ac.uk +wpbs.afrc.ac.uk:norm+mta=wpbs.afrc.ac.uk +wpbs.afrc.ac:norm+mta=wpbs.afrc.ac.uk +wpbs.afrc:norm+mta=wpbs.afrc.ac.uk +nw.afrc.ac.uk:norm+mta=nw.afrc.ac.uk +nw.afrc.ac:norm+mta=nw.afrc.ac.uk +nw.afrc:norm+mta=nw.afrc.ac.uk +nw.afrc.ac.uk:norm+mta=nw.afrc.ac.uk +nw.afrc.ac:norm+mta=nw.afrc.ac.uk +nw.afrc:norm+mta=nw.afrc.ac.uk +iape.afrc.ac.uk:norm+mta=iape.afrc.ac.uk +iape.afrc.ac:norm+mta=iape.afrc.ac.uk +iape.afrc:norm+mta=iape.afrc.ac.uk +iape.afrc.ac.uk:norm+mta=iape.afrc.ac.uk +iape.afrc.ac:norm+mta=iape.afrc.ac.uk +iape.afrc:norm+mta=iape.afrc.ac.uk +iapep.afrc.ac.uk:norm+mta=iapep.afrc.ac.uk +iapep.afrc.ac:norm+mta=iapep.afrc.ac.uk +iapep.afrc:norm+mta=iapep.afrc.ac.uk +iapep.afrc.ac.uk:norm+mta=iapep.afrc.ac.uk +iapep.afrc.ac:norm+mta=iapep.afrc.ac.uk diff --git a/examples/xtel/make b/examples/xtel/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/examples/xtel/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/examples/xtel/or b/examples/xtel/or new file mode 100644 index 0000000..4725f6e --- /dev/null +++ b/examples/xtel/or @@ -0,0 +1,248 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Thu Nov 28 15:39:21 GMT 1991 +############## on host tornado +############## +################################################## +################################################## +# -*** xtel ***- +OU$x400.O$XTEL.PRMD$X-Tel Services.ADMD$ .C$GB:local x400-developers +PRMD$X-Tel Ltd.ADMD$ .C$GB:synonym PRMD$X-Tel\ Services.ADMD$\ .C$GB +PRMD$X-Tel Services Ltd.ADMD$ .C$GB:synonym PRMD$X-Tel\ Services.ADMD$\ .C$GB +PRMD$X-Tel Services.ADMD$ .C$GB:valid +O$XTEL.PRMD$X-Tel Services.ADMD$ .C$GB:local +O$X-Tel.PRMD$X-Tel Services.ADMD$ .C$GB:synonym O$XTEL.PRMD$X-Tel\ Services.ADMD$\ .C$GB +OU$CS.O$NOTT.PRMD$UK\.AC.ADMD$ .C$GB:mta cs.nott.ac.uk +O$NOTT.PRMD$UK\.AC.ADMD$ .C$GB:valid +#ADMD$GOLD 400.C$GB:synonym ADMD$\ .C$GB +PRMD$SUBSL.ADMD$ .C$GB:mta e.sss.co.uk +O$UCL.PRMD$UK\.AC.ADMD$ .C$GB:mta cs.ucl.ac.uk +O$UCL.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +OU$cs.O$UCL.PRMD$UK\.AC.ADMD$ .C$GB:valid +OU$talisker.OU$cs.O$UCL.PRMD$UK\.AC.ADMD$ .C$GB:mta talisker.cs.ucl.ac.uk +#Andrew +#S$worsley.OU$mel.O$dit.PRMD$CSIRO.ADMD$ .C$AU:mta andrew +OU$mel.O$dit.PRMD$CSIRO.ADMD$ .C$AU:mta mel.dit.csiro.au +O$dit.PRMD$CSIRO.ADMD$ .C$AU:valid +PRMD$CSIRO.ADMD$ .C$AU:valid +ADMD$ .C$AU:valid +ADMD$PPMAIL.C$AU:synonym ADMD$\ .C$AU +C$AU:mta au +PRMD$Level-7 Ltd.ADMD$ .C$gb:mta cs.ucl.ac.uk + +C$ZZ:valid +ADMD$ATTMAIL.C$ZZ:valid +PRMD$CCUR.ADMD$ATTMAIL.C$ZZ:local +O$Concurrent Computer Corporation.PRMD$CCUR.ADMD$ATTMAIL.C$ZZ:valid +OU$bigears.O$Concurrent Computer Corporation.PRMD$CCUR.ADMD$ATTMAIL.C$ZZ:local + +#ADMD$*.C$GB:valid +#PRMD$UK\.AC.ADMD$*.C$GB:mta cs.ucl.ac.uk + +PRMD$ARC.ADMD$telemail.C$US:valid +O$nasa.ADMD$telemail.C$US:mta atlas.arc.nasa.gov +# Test stuff - bogus.. +UA-ID$123456.ADMD$ .C$GB:mta cs.ucl.ac.uk +C$234:valid +ADMD$ .C$234:valid +X121$123456.ADMD$ .C$234:mta cs.ucl.ac.uk +X121$123456:valid +T-ID$123456.X121$123456:mta cs.ucl.ac.uk + +# temp fix +admd$ .c$se:mta cs.ucl.ac.uk +############################################################################## +# +# --- *** --- +# The OR master table +# --- *** --- +# +############################################################################## +# +# +# +# -*** gb & admd ***- +# Note: if prmd not found in this (or) table but the admd & +# country have as their values "admd$gold 400.c$gb" +# then automatic routing occurs to +# British Telecom Gold - as seen below. +# -*****************- +# +C$GB:valid +C$UK:alias C$GB +C$US:valid +C$SE:valid +ADMD$BTMHS.C$GB:valid +ADMD$ .C$GB:valid +ADMD$GOLD 400.C$GB:valid +ADMD$GOLD-400.C$GB:alias ADMD$GOLD\ 400.C$GB +# +# Mirroring what bells does here. This will then go through bt-gold +# +#ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +ADMD$ATTMAIL.C$US:mta cs.ucl.ac.uk +ADMD$DIALCOM.C$US:mta cs.ucl.ac.uk +ADMD$TELEDELTA.C$SE:mta cs.ucl.ac.uk +# +# -*** U.K. Academic Community ***- +# +PRMD$UK\.AC.ADMD$ .C$GB:valid +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:valid +PRMD$AC\.UK.ADMD$GOLD 400.C$GB:alias PRMD$UK\\\.AC.ADMD$GOLD\ 400.C$GB +PRMD$UK\.AC.ADMD$BTMHS.C$GB:alias PRMD$UK\\\.AC.ADMD$GOLD\ 400.C$GB +# +# -*** mhs-relay ***- +# +O$MHS-RELAY.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:alias O$MHS-RELAY.PRMD$UK\\\.AC.ADMD$\ .C$GB +# +# +# -*** THOSE PRMD CONNECTIONS ***- +# +# -*** uk-gosip ***- +# +PRMD$HMG.ADMD$GOLD 400.C$GB:valid +O$GOSIP UK.PRMD$HMG.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** dtiied ***- +#PRMD$DTIIED.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** dec (alternative route via BT Gold) ***- +PRMD$DIGITAL.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** data general ***- +PRMD$DGC.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +PRMD$DGC.ADMD$BTMHS.C$GB:mta cs.ucl.ac.uk +# +# -*** hewlett packard ***- +#PRMD$HP.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** icl (Temporary route via STC) ***- +#PRMD$ICL.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +PRMD$ICL.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +PRMD$ICLEXPO.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +PRMD$STC-T.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** STC in Harlow (pp) ***- +PRMD$STC Plc.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** Interspan (alternative route via BT Gold) ***- +PRMD$INTERSPAN.ADMD$ .C$GB:mta cs.ucl.ac.uk +PRMD$INTERSPAN.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +ADMD$INTERSPAN.C$GB:mta cs.ucl.ac.uk +# +# -*** itl ***- +#PRMD$ITL.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# +# -*** jmtc ***- +PRMD$JMTC.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** net-tel ***- +PRMD$NET-TEL.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# -*** telemail ***- +ADMD$TELEMAIL.C$US:mta cs.ucl.ac.uk +ADMD$TMAILUK.C$GB:mta cs.ucl.ac.uk +PRMD$UK\.AC.ADMD$TMAILUK.C$GB:alias PRMD$UK\.AC.ADMD$GOLD\ 400.C$GB +# +# THE R and D MHS WEPS +# +# -*** france ***- +C$FR:valid +ADMD$PTT.C$FR:mta cs.ucl.ac.uk +ADMD$ATLAS.C$FR:mta cs.ucl.ac.uk +PRMD$REUNIR.ADMD$ATLAS.C$FR:mta cs.ucl.ac.uk +# +# +# -*** at ***- +# +C$AT:mta cs.ucl.ac.uk +# +# -*** be ***- +# +C$BE:mta cs.ucl.ac.uk +# +# -*** br ***- +# +C$BR:mta cs.ucl.ac.uk +# +# -*** ca ***- +# +C$CA:mta cs.ucl.ac.uk +C$CDN:mta cs.ucl.ac.uk +# +# -*** ch ***- +# +C$CH:valid +ADMD$ARCOM.C$CH:mta cs.ucl.ac.uk +# +# -*** itu (in ch) ***- +# +PRMD$ITU.ADMD$ARCOM.C$CH:mta cs.ucl.ac.uk +# +# -*** de ***- +# +C$DD:mta cs.ucl.ac.uk +C$DE:mta cs.ucl.ac.uk +# +# -*** es ***- +# +C$ES:mta cs.ucl.ac.uk +# +# -*** fi ***- +# +C$FI:mta cs.ucl.ac.uk +# +# +# -*** gr ***- +# +C$GR:mta cs.ucl.ac.uk +# +# -*** it ***- +# +C$IT:mta cs.ucl.ac.uk +# +# -*** ie ***- +# +C$IE:mta cs.ucl.ac.uk +# +# -*** nl ***- +# +C$NL:mta cs.ucl.ac.uk +# +# -*** no ***- +# +C$NO:mta cs.ucl.ac.uk +C$UNINETT:mta cs.ucl.ac.uk +# +# -*** pt ***- +# +C$PT:mta cs.ucl.ac.uk +# +# -*** yu ***- +# +C$YU:mta cs.ucl.ac.uk +# +# -*** xnren.us ***- +# +ADMD$ .C$US:valid +ADMD$Telemail.C$US:mta cs.ucl.ac.uk +PRMD$xnren.ADMD$ .C$US:mta cs.ucl.ac.uk +# +# -*** ucl ***- +# +# O$UCL.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:valid +# O$UCL-CS.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# OU$CS.O$UCL.PRMD$UK\.AC.ADMD$GOLD 400.C$GB:mta cs.ucl.ac.uk +# +# +############################################################################## +# +# --- *** --- +# End of master OR table +# --- *** --- +# +############################################################################## diff --git a/examples/xtel/or2rfc b/examples/xtel/or2rfc new file mode 100644 index 0000000..3c02b71 --- /dev/null +++ b/examples/xtel/or2rfc @@ -0,0 +1,500 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Fri Nov 22 12:02:31 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +O$XTEL.PRMD$X-Tel Services.ADMD$ .C$GB:xtel.co.uk +O$XTEL.PRMD$X-Tel Services Ltd.ADMD$ .C$GB:xtel.co.uk +PRMD$SUBSL.ADMD$ .C$GB:sss.co.uk +ADMD$atlas.C$fr:fr +PRMD$ESSO.ADMD$TMAILUK.C$GB:esso.tmailuk.gb +OU$mel.O$dit.PRMD$CSIRO.ADMD$ .C$AU:mel.dit.csiro.au +O$Concurrent Computer Corporation.PRMD$CCUR.ADMD$ATTMAIL.C$ZZ:concurrent.co.zz +############################################################################## +# +# +# --- *** --- +# Automatically generated entries from the +# RFC-987 Gateway Conversion Tables +# --- *** --- +# +# +############################################################################## +# +# +# +#H DOC=PROCEDURES/RFC987-MAPPING1; RES=RARE MHS Project Team; DAT=90.08.13; +# +# INTERNATIONAL TABLE 1 +# ================================== +# RFC-987 GATEWAY CONVERSION TABLE +# - as a result of coordination in the +# R&D MHS Service. +# +# MAPPING 1: From X.400 Standard Attributes +# to RFC-822 format +# +# This table is a concatenation of different +# national conversion tables, and should be used +# in whole, - and by every operational RFC-987 +# gateway within the R&D MHS Service. +# +# Responsible: RARE MHS Project Team +# MHS-Project-Team@rare.no +# C=NO;PRMD=uninett;O=rare;S=MHS-Project-Team; +# +#============================================================== Austria ====== +# Last update: 89.11.21 +# Responsible: Franz Haselbacher +# C=at;A=ada;P=tu-graz;O=edvz;S=haselbacher +# +PRMD$ac.ADMD$ada.C$at:ac.at +PRMD$acd.ADMD$ada.C$at:acd.at +PRMD$cod.ADMD$ada.C$at:cod.at +# +#============================================================================= +#============================================================== Belgium ====== +# Last update: 90.08.02 +# Responsible: Bernard Detrembleur +# +# +# +# X400 Sites +# +PRMD$fundp.ADMD$rtt.C$be:fundp.rtt.be +PRMD$dgc.ADMD$rtt.C$be:dgc.rtt.be +PRMD$iihe.ADMD$rtt.C$be:iihe.rtt.be +O$informabel.PRMD$informabel.ADMD$rtt.C$be:informabel.informabel.rtt.be +O$stesud.PRMD$informabel.ADMD$rtt.C$be:stesud.informabel.rtt.be +O$@.PRMD$jrc.ADMD$rtt.C$be:jrc.rtt.be +PRMD$cenclcbel.ADMD$rtt.C$be:cenclcbel.rtt.be +PRMD$alcatel-etb.ADMD$rtt.C$be:etb-alcatel.rtt.be +# +# Non-X400 Domains +# +# +# Non-X.400 Domains carried by uucp +# +# +# UUCP sites under .be domain +# +PRMD$ac.ADMD$rtt.C$be:ac.be +PRMD$agfa.ADMD$rtt.C$be:agfa.be +PRMD$att.ADMD$rtt.C$be:att.be +PRMD$bbl.ADMD$rtt.C$be:bbl.be +PRMD$bbri.ADMD$rtt.C$be:bbri.be +PRMD$buug.ADMD$rtt.C$be:buug.be +PRMD$camme.ADMD$rtt.C$be:camme.be +PRMD$capgsb.ADMD$rtt.C$be:capgsb.be +PRMD$cec.ADMD$rtt.C$be:cec.be +PRMD$e2s.ADMD$rtt.C$be:e2s.be +PRMD$imec.ADMD$rtt.C$be:imec.be +PRMD$intecsi.ADMD$rtt.C$be:intecsi.be +PRMD$oma.ADMD$rtt.C$be:oma.be +PRMD$pgsgent.ADMD$rtt.C$be:pgsgent.be +PRMD$philips.ADMD$rtt.C$be:philips.be +PRMD$repko.ADMD$rtt.C$be:repko.be +PRMD$retime.ADMD$rtt.C$be:retime.be +PRMD$rubens.ADMD$rtt.C$be:rubens.be +PRMD$sema.ADMD$rtt.C$be:sema.be +PRMD$siemens.ADMD$rtt.C$be:siemens.be +PRMD$sunbim.ADMD$rtt.C$be:sunbim.be +PRMD$sydes.ADMD$rtt.C$be:sydes.be +PRMD$syteke.ADMD$rtt.C$be:syteke.be +# +#============================================================================= +#============================================================== Brazil ======= +# Date: 89.06.22 +# Responsible: Peter Kaufmann +# +# +# +#============================================================================= +#============================================================== Canada ======= +# Last update: 90.07.25 +# Responsible: John Demco +# C=ca;A=telecom.canada;P=cdn;O=cdnnet;S=demco +# +O$bc.PRMD$cdn.ADMD$telecom\.canada.C$ca:bc.ca +OU$gov.O$bc.PRMD$cdn.ADMD$telecom\.canada.C$ca:gov.bc.ca +OU$bcsystems.OU$gov.O$bc.PRMD$bcgovt.ADMD$telecom\.canada.C$ca:bcsystems.gov.bc.ca +PRMD$osiware.ADMD$telecom\.canada.C$ca:osiware.bc.ca +# +#============================================================================= +#========================================================== Switzerland ====== +# Last update: 90.08.02 +# Responsible: Urs Eppenberger +# +# +#----------------------------------------------------------- ch general ------ +ADMD$ARCOM.C$CH:arcom.ch +#--------------------------------------------------------- ch education ------ +#---------------------------------------------------------- ch research ------ +O$CERN.PRMD$CERN.ADMD$ARCOM.C$CH:cern.ch +PRMD$ABB.ADMD$ARCOM.C$CH:abb.ch +PRMD$SANDOZ.ADMD$ARCOM.C$CH:sandoz.ch +#--------------------------------------------------------- int networks ------ +# +#============================================================================= +#============================================================== Germany ====== +# TITLE: RFC-987 Reverse Conversion Table. Temporary +# Long Version. NOT Human Readable (X400 --> RFC822) +# Date: 90.07.24 +# Responsible: Peter Kaufmann +# Gabriele v. Siebert +# +#*************************************************************** +# +# A) German mapping rules for DFN-installations +# +# Weak syntax +# +# +# Strong syntax +# +# A=; C=de +# A=dbp; C=de +# O=; A=dbp; C=de +# P=mpg; A=dbp; C=de +# P=fhg; A=dbp; C=de +# P=danet; A=dbp; C=de +# P=ibm-deutschland; A=dbp; C=de +# P=nixdorf; A=dbp; C=de +# +# Installations without "Organizational Name" +# +# A.1) Universities +# +O$@.PRMD$rwth-aachen.ADMD$dbp.C$de:rwth-aachen.dbp.de +O$@.PRMD$fh-aalen.ADMD$dbp.C$de:fh-aalen.dbp.de +O$@.PRMD$uni-augsburg.ADMD$dbp.C$de:uni-augsburg.dbp.de +O$@.PRMD$fh-augsburg.ADMD$dbp.C$de:fh-augsburg.dbp.de +O$@.PRMD$uni-bamberg.ADMD$dbp.C$de:uni-bamberg.dbp.de +O$@.PRMD$uni-bayreuth.ADMD$dbp.C$de:uni-bayreuth.dbp.de +O$@.PRMD$fh-dbp-berlin.ADMD$dbp.C$de:fh-dbp-berlin.dbp.de +O$@.PRMD$fu-berlin.ADMD$dbp.C$de:fu-berlin.dbp.de +O$@.PRMD$tu-berlin.ADMD$dbp.C$de:tu-berlin.dbp.de +O$@.PRMD$uni-bielefeld.ADMD$dbp.C$de:uni-bielefeld.dbp.de +O$@.PRMD$uni-bochum.ADMD$dbp.C$de:uni-bochum.dbp.de +O$@.PRMD$ruhr-uni-bochum.ADMD$dbp.C$de:ruhr-uni-bochum.dbp.de +O$@.PRMD$uni-bonn.ADMD$dbp.C$de:uni-bonn.dbp.de +O$@.PRMD$tu-braunschweig.ADMD$dbp.C$de:tu-braunschweig.dbp.de +O$@.PRMD$uni-bremen.ADMD$dbp.C$de:uni-bremen.dbp.de +O$@.PRMD$tu-clausthal.ADMD$dbp.C$de:tu-clausthal.dbp.de +O$@.PRMD$fh-coburg.ADMD$dbp.C$de:fh-coburg.dbp.de +O$@.PRMD$fh-darmstadt.ADMD$dbp.C$de:fh-darmstadt.dbp.de +O$@.PRMD$th-darmstadt.ADMD$dbp.C$de:th-darmstadt.dbp.de +O$@.PRMD$uni-dortmund.ADMD$dbp.C$de:uni-dortmund.dbp.de +O$@.PRMD$uni-duisburg.ADMD$dbp.C$de:uni-duisburg.dbp.de +O$@.PRMD$uni-duesseldorf.ADMD$dbp.C$de:uni-duesseldorf.dbp.de +O$@.PRMD$ku-eichstaett.ADMD$dbp.C$de:ku-eichstaett.dbp.de +O$@.PRMD$uni-erlangen.ADMD$dbp.C$de:uni-erlangen.dbp.de +O$@.PRMD$uni-essen.ADMD$dbp.C$de:uni-essen.dbp.de +O$@.PRMD$fht-esslingen.ADMD$dbp.C$de:fht-esslingen.dbp.de +O$@.PRMD$uni-frankfurt.ADMD$dbp.C$de:uni-frankfurt.dbp.de +O$@.PRMD$uni-freiburg.ADMD$dbp.C$de:uni-freiburg.dbp.de +O$@.PRMD$fh-furtwangen.ADMD$dbp.C$de:fh-furtwangen.dbp.de +O$@.PRMD$uni-giessen.ADMD$dbp.C$de:uni-giessen.dbp.de +O$@.PRMD$uni-goettingen.ADMD$dbp.C$de:uni-goettingen.dbp.de +O$@.PRMD$fernuni-hagen.ADMD$dbp.C$de:fernuni-hagen.dbp.de +O$@.PRMD$uni-hamburg.ADMD$dbp.C$de:uni-hamburg.dbp.de +O$@.PRMD$fh-hamburg.ADMD$dbp.C$de:fh-hamburg.dbp.de +O$@.PRMD$uni-hannover.ADMD$dbp.C$de:uni-hannover.dbp.de +O$@.PRMD$tu-harburg.ADMD$dbp.C$de:tu-harburg.dbp.de +O$@.PRMD$uni-heidelberg.ADMD$dbp.C$de:uni-heidelberg.dbp.de +O$@.PRMD$fh-heilbronn.ADMD$dbp.C$de:fh-heilbronn.dbp.de +O$@.PRMD$uni-hildesheim.ADMD$dbp.C$de:uni-hildesheim.dbp.de +O$@.PRMD$uni-hohenheim.ADMD$dbp.C$de:uni-hohenheim.dbp.de +O$@.PRMD$uni-kaisersltrn.ADMD$dbp.C$de:uni-kl.dbp.de +O$@.PRMD$uni-kl.ADMD$dbp.C$de:uni-kl.dbp.de +O$@.PRMD$fh-karlsruhe.ADMD$dbp.C$de:fh-karlsruhe.dbp.de +O$@.PRMD$uni-karlsruhe.ADMD$dbp.C$de:uni-karlsruhe.dbp.de +O$@.PRMD$uni-kassel.ADMD$dbp.C$de:uni-kassel.dbp.de +O$@.PRMD$fh-kempten.ADMD$dbp.C$de:fh-kempten.dbp.de +O$@.PRMD$uni-kiel.ADMD$dbp.C$de:uni-kiel.dbp.de +O$@.PRMD$fh-kiel.ADMD$dbp.C$de:fh-kiel.dbp.de +O$@.PRMD$uni-konstanz.ADMD$dbp.C$de:uni-konstanz.dbp.de +O$@.PRMD$fh-koeln.ADMD$dbp.C$de:fh-koeln.dbp.de +O$@.PRMD$uni-koeln.ADMD$dbp.C$de:uni-koeln.dbp.de +O$@.PRMD$fh-landshut.ADMD$dbp.C$de:fh-landshut.dbp.de +O$@.PRMD$uni-mainz.ADMD$dbp.C$de:uni-mainz.dbp.de +O$@.PRMD$uni-mannheim.ADMD$dbp.C$de:uni-mannheim.dbp.de +O$@.PRMD$uni-marburg.ADMD$dbp.C$de:uni-marburg.dbp.de +O$@.PRMD$tu-muenchen.ADMD$dbp.C$de:tu-muenchen.dbp.de +O$@.PRMD$fh-muenchen.ADMD$dbp.C$de:fh-muenchen.dbp.de +O$@.PRMD$lmu-muenchen.ADMD$dbp.C$de:lmu-muenchen.dbp.de +O$@.PRMD$uni-muenchen.ADMD$dbp.C$de:uni-muenchen.dbp.de +O$@.PRMD$uni-muenster.ADMD$dbp.C$de:uni-muenster.dbp.de +O$@.PRMD$fh-muenster.ADMD$dbp.C$de:fh-muenster.dbp.de +O$@.PRMD$fh-nuernberg.ADMD$dbp.C$de:fh-nuernberg.dbp.de +O$@.PRMD$uni-oldenburg.ADMD$dbp.C$de:uni-oldenburg.dbp.de +O$@.PRMD$uni-osnabrueck.ADMD$dbp.C$de:uni-osnabrueck.dbp.de +O$@.PRMD$fh-osnabrueck.ADMD$dbp.C$de:fh-osnabrueck.dbp.de +O$@.PRMD$uni-paderborn.ADMD$dbp.C$de:uni-paderborn.dbp.de +O$@.PRMD$uni-passau.ADMD$dbp.C$de:uni-passau.dbp.de +O$@.PRMD$fh-regensburg.ADMD$dbp.C$de:fh-regensburg.dbp.de +O$@.PRMD$uni-regensburg.ADMD$dbp.C$de:uni-regensburg.dbp.de +O$@.PRMD$fh-rosenheim.ADMD$dbp.C$de:fh-rosenheim.dbp.de +O$@.PRMD$uni-saarland.ADMD$dbp.C$de:uni-saarland.dbp.de +O$@.PRMD$uni-siegen.ADMD$dbp.C$de:uni-siegen.dbp.de +O$@.PRMD$uni-stuttgart.ADMD$dbp.C$de:uni-stuttgart.dbp.de +O$@.PRMD$uni-trier.ADMD$dbp.C$de:uni-trier.dbp.de +O$@.PRMD$uni-tuebingen.ADMD$dbp.C$de:uni-tuebingen.dbp.de +O$@.PRMD$uni-ulm.ADMD$dbp.C$de:uni-ulm.dbp.de +O$@.PRMD$fh-ulm.ADMD$dbp.C$de:fh-ulm.dbp.de +O$@.PRMD$fh-weihenstephan.ADMD$dbp.C$de:fh-weihenstephan.dbp.de +O$@.PRMD$fh-wiesbaden.ADMD$dbp.C$de:fh-wiesbaden.dbp.de +O$@.PRMD$uni-witten-h.ADMD$dbp.C$de:uni-witten-h.dbp.de +O$@.PRMD$uni-wuerzburg.ADMD$dbp.C$de:uni-wuerzburg.dbp.de +O$@.PRMD$fh-wuerzburg.ADMD$dbp.C$de:fh-wuerzburg.dbp.de +O$@.PRMD$uni-wuppertal.ADMD$dbp.C$de:uni-wuppertal.dbp.de +# +# A.2) Research laboratories/institutions +# +O$@.PRMD$bessy.ADMD$dbp.C$de:bessy.dbp.de +O$@.PRMD$bgr.ADMD$dbp.C$de:bgr.dbp.de +O$@.PRMD$dfg.ADMD$dbp.C$de:dfg.dbp.de +O$@.PRMD$dfn.ADMD$dbp.C$de:dfn.dbp.de +O$@.PRMD$dlr.ADMD$dbp.C$de:dlr.dbp.de +O$@.PRMD$desy.ADMD$dbp.C$de:desy.dbp.de +O$@.PRMD$embl.ADMD$dbp.C$de:embl.dbp.de +O$@.PRMD$ffm.ADMD$dbp.C$de:ffm.dbp.de +O$@.PRMD$gmd.ADMD$dbp.C$de:gmd.dbp.de +O$@.PRMD$gsi.ADMD$dbp.C$de:gsi.dbp.de +O$@.PRMD$hmi.ADMD$dbp.C$de:hmi.dbp.de +O$@.PRMD$kfk.ADMD$dbp.C$de:kfk.dbp.de +O$@.PRMD$gwdg.ADMD$dbp.C$de:gwdg.dbp.de +O$@.PRMD$belwue.ADMD$dbp.C$de:belwue.dbp.de +O$@.PRMD$wiko-berlin.ADMD$dbp.C$de:wiko-berlin.dbp.de +O$@.PRMD$zib-berlin.ADMD$dbp.C$de:zib-berlin.dbp.de +O$@.PRMD$diw-berlin.ADMD$dbp.C$de:diw-berlin.dbp.de +O$@.PRMD$gbf-braunschweig.ADMD$dbp.C$de:gbf-braunschweig.dbp.de +O$@.PRMD$awi-bremerhaven.ADMD$dbp.C$de:awi-bremerhaven.dbp.de +O$@.PRMD$gtt-duisburg.ADMD$dbp.C$de:gtt-duisburg.dbp.de +O$@.PRMD$dkrz-hamburg.ADMD$dbp.C$de:dkrz-hamburg.dbp.de +O$@.PRMD$dkfz-heidelberg.ADMD$dbp.C$de:dkfz-heidelberg.dbp.de +O$@.PRMD$kfa-juelich.ADMD$dbp.C$de:kfa-juelich.dbp.de +O$@.PRMD$augustinum-m.ADMD$dbp.C$de:augustinum-m.dbp.de +O$@.PRMD$badw-muenchen.ADMD$dbp.C$de:badw-muenchen.dbp.de +# +# A.3) Companies +# +O$@.PRMD$basf-ag.ADMD$dbp.C$de:basf-ag.dbp.de +O$@.PRMD$hoechst-ag.ADMD$dbp.C$de:hoechst-ag.dbp.de +O$@.PRMD$datageneral.ADMD$dbp.C$de:datageneral.dbp.de +O$@.PRMD$decde.ADMD$dbp.C$de:decde.dbp.de +O$@.PRMD$pcs.ADMD$dbp.C$de:pcs.dbp.de +O$@.PRMD$siemens-mchp02.ADMD$dbp.C$de:siemens-mchp02.dbp.de +O$@.PRMD$siemens-mchp04.ADMD$dbp.C$de:siemens-mchp04.dbp.de +O$@.PRMD$siemens.ADMD$dbp.C$de:siemens.dbp.de +O$@.PRMD$sel-rc.ADMD$dbp.C$de:sel-rc.dbp.de +# +# A.4 and A.5 are not necessary +# +# +# +# B) German mapping rules for German UUCP Domains +# +# Installations without "ADMD=DBP" and without "Organizational Name" +# +# B.1) Universities +# +O$@.PRMD$fu-berlin.ADMD$ .C$de:fu-berlin.de +O$@.PRMD$uni-bochum.ADMD$ .C$de:uni-bochum.de +O$@.PRMD$uni-bonn.ADMD$ .C$de:uni-bonn.de +O$@.PRMD$uni-bremen.ADMD$ .C$de:uni-bremen.de +O$@.PRMD$uni-dortmund.ADMD$ .C$de:uni-dortmund.de +O$@.PRMD$uni-erlangen.ADMD$ .C$de:uni-erlangen.de +O$@.PRMD$uni-freiburg.ADMD$ .C$de:uni-freiburg.de +O$@.PRMD$uni-hamburg.ADMD$ .C$de:uni-hamburg.de +O$@.PRMD$uni-kl.ADMD$ .C$de:uni-kl.de +O$@.PRMD$uni-koeln.ADMD$ .C$de:uni-koeln.de +O$@.PRMD$uni-mainz.ADMD$ .C$de:uni-mainz.de +O$@.PRMD$tu-muenchen.ADMD$ .C$de:tu-muenchen.de +O$@.PRMD$uni-paderborn.ADMD$ .C$de:uni-paderborn.de +O$@.PRMD$uni-passau.ADMD$ .C$de:uni-passau.de +O$@.PRMD$uni-saarland.ADMD$ .C$de:uni-saarland.de +O$@.PRMD$uni-stuttgart.ADMD$ .C$de:uni-stuttgart.de +# +# B.2) Research laboratories/institutions +# +O$@.PRMD$kfa-juelich.ADMD$ .C$de:kfa-juelich.de +O$@.PRMD$gmd.ADMD$ .C$de:gmd.de +# +# +# +# C) German mapping rules for Non-X.400 Top-Domains +# +PRMD$cern.ADMD$dbp.C$de:cern.ch +PRMD$junet.ADMD$dbp.C$de:junet.utokyo-relay.csnet +PRMD$oz.ADMD$dbp.C$de:oz.au +# +#============================================================================= +#============================================================= Denmark ======= +# Last update: 90-03-20 +# Responsible: Klaus Hansen +# C=DK;ADMD= ;PRMD=;O=diku;S=khan; +# +# +#============================================================================= +#=============================================================== Spain ======= +# Last update: 90.06.01 +# Responsible: Ignacio Martinez +# C=es;A=" ";P=iris;O=iris-dcp;S=martinez +# +# +# Consider also these two mappings. One is coming, the other is nasty. +# +# +#------------------------------------------------------------ companies ------ +# +# Companies are exceptions to the general rule as they subscribe to their +# own PRMD (other than IRIS) +# +O$asicom.PRMD$asicom.ADMD$ .C$es:asicom.es +O$atimdr.PRMD$atimdr.ADMD$ .C$es:atimdr.es +O$ccs.PRMD$ccs.ADMD$ .C$es:ccs.es +O$correa.PRMD$correa.ADMD$ .C$es:correa.es +O$crisa.PRMD$crisa.ADMD$ .C$es:crisa.es +O$cuac.PRMD$cuac.ADMD$ .C$es:cuac.es +O$data-general.PRMD$dgsa.ADMD$ .C$es:data-general.es +O$dsd.PRMD$dsd.ADMD$ .C$es:dsd.es +O$easa.PRMD$easa.ADMD$ .C$es:easa.es +O$entel.PRMD$entel.ADMD$ .C$es:entel.es +O$eria.PRMD$eria.ADMD$ .C$es:eria.es +O$expo92.PRMD$expo92.ADMD$ .C$es:expo92.es +O$fesa.PRMD$fujitsu.ADMD$ .C$es:fesa.es +O$foro.PRMD$foro.ADMD$ .C$es:foro.es +O$gapd.PRMD$gapd.ADMD$ .C$es:gapd.es +O$gmv.PRMD$gmv.ADMD$ .C$es:gmv.es +O$intelsa.PRMD$intelsa.ADMD$ .C$es:intelsa.es +O$iss.PRMD$iss.ADMD$ .C$es:iss.es +O$lsi.PRMD$lsi.ADMD$ .C$es:lsi.es +O$menarini.PRMD$menarini.ADMD$ .C$es:menarini.es +O$mopu.PRMD$mopu.ADMD$ .C$es:mopu.es +O$nsi.PRMD$nexus.ADMD$ .C$es:nsi.es +O$nte.PRMD$nte.ADMD$ .C$es:nte.es +O$proa.PRMD$proa.ADMD$ .C$es:proa.es +O$px86.PRMD$px86.ADMD$ .C$es:px86.es +O$rebu.PRMD$repsol.ADMD$ .C$es:rebu.es +O$scyt.PRMD$scyt.ADMD$ .C$es:scyt.es +O$sicyd.PRMD$sicyd.ADMD$ .C$es:sicyd.es +O$sema.PRMD$sema.ADMD$ .C$es:sema.es +O$sesa.PRMD$alcatel.ADMD$ .C$es:sesa.es +O$teice.PRMD$teice-control.ADMD$ .C$es:teice.es +O$telefonica.PRMD$telefonica.ADMD$ .C$es:telefonica.es +O$telettra.PRMD$telettra.ADMD$ .C$es:telettra.es +O$tid.PRMD$tidsa.ADMD$ .C$es:tid.es +O$tifsa.PRMD$tifsa.ADMD$ .C$es:tifsa.es +O$ts.PRMD$ts.ADMD$ .C$es:ts.es +# +#---------------------------------------------------- NON-X.400 domains ------ +# +# +# +# +#---------------------------------------------------- NON-X.400 domains ------ +# +# The nasty ADMD=ptt forces repetion of the above mappings. +# It is not my fault, kick the suppliers ... +# +# +# +# +#============================================================================= +#============================================================== Finland ====== +# +# X.400 --> RFC.822 +# +# Last update 90.07.23 +# Responsible: Marko Kaittola +# c=fi;ADMD=fumail;PRMD=funet;S=Kaittola;G=Marko +# +ADMD$fumail.C$fi:fumail.fi +# +# elisa and mailnet should not appear in RARE +# tables, but here they go ... +# +ADMD$elisa.C$fi:elisa.fi +ADMD$mailnet.C$fi:mailnet.fi +# +# +# To make life easyer ... +# +# +#============================================================================= +#============================================ France REUNIR + Aristote ======= +# Last update: 90.07.20 +# Responsibles: +# REUNIR: Serge Aumont C=FR;ADMD=ATLAS;PRMD=REUNIR;S=Aumont +# ARISTOTE: Paul Andre Pays C=FR;ADMD=ATLAS;PRMD=EMSE;O=EMSESMC;S=pays +# +PRMD$@.ADMD$atlas.C$FR:atlas.fr +# +O$cea.PRMD$cea.ADMD$atlas.C$FR:cea.fr +O$@.PRMD$cicb.ADMD$atlas.C$FR:cicb.fr +O$@.PRMD$cirad.ADMD$atlas.C$FR:cirad.fr +O$@.PRMD$circe.ADMD$atlas.C$FR:circe.fr +O$@.PRMD$ciril.ADMD$atlas.C$FR:ciril.fr +O$@.PRMD$citilille.ADMD$atlas.C$FR:citilille.fr +O$@.PRMD$cnam.ADMD$atlas.C$FR:cnam.fr +O$@.PRMD$cnusc.ADMD$atlas.C$FR:cnusc.fr +O$@.PRMD$ensm.ADMD$atlas.C$FR:ensm.fr +O$@.PRMD$ens-cachan.ADMD$atlas.C$FR:ens-cachan.fr +O$@.PRMD$glvt-cnrs.ADMD$atlas.C$FR:glvt-cnrs.fr +O$@.PRMD$lmcp.ADMD$atlas.C$FR:lmcp.fr +O$@.PRMD$matups.ADMD$atlas.C$FR:matups.fr +O$@.PRMD$ill.ADMD$atlas.C$FR:ill.fr +O$@.PRMD$inra.ADMD$atlas.C$FR:inra.fr +O$@.PRMD$irisa.ADMD$atlas.C$FR:irisa.fr +O$uhb.PRMD$cicb.ADMD$atlas.C$FR:uhb.fr +O$@.PRMD$unicaen.ADMD$atlas.C$FR:unicaen.fr +O$@.PRMD$unice.ADMD$atlas.C$FR:unice.fr +O$@.PRMD$unilim.ADMD$atlas.C$FR:unilim.fr +O$@.PRMD$univ-lyon1.ADMD$atlas.C$FR:univ-lyon1.fr +O$@.PRMD$univ-pau.ADMD$atlas.C$FR:univ-pau.fr +O$@.PRMD$u-strasbg.ADMD$atlas.C$FR:u-strasbg.fr +O$@.PRMD$u-paris10.ADMD$atlas.C$FR:u-paris10.fr +O$@.PRMD$u-paris13.ADMD$atlas.C$FR:u-paris13.fr +O$@.PRMD$reunir.ADMD$atlas.C$FR:reunir.fr +# +# +# +#============================================================================= +#======================================================= United Kingdom ====== +# Last update: 90.08.06 +# Responsible: Tony Bates +# +# Beware of the quoted dots in this table! +# +PRMD$UK\.AC.ADMD$ .C$GB:ac.uk +PRMD$UK\.AC.ADMD$GOLD 400.C$GB:ac.uk +PRMD$UK\.AC.ADMD$TMAILUK.C$GB:ac.uk +ADMD$GOLD 400.C$GB:gold-400.gb +ADMD$TMAILUK.C$GB:tmailuk.gb +ADMD$BTMHS.C$GB:btmhs.gb +O$GOSIP UK.PRMD$HMG.ADMD$GOLD 400.C$GB:gosip-uk.hmg.gold-400.gb +O$NET-TEL COMPUTER SYSTEMS LTD.PRMD$NET-TEL.ADMD$GOLD 400.C$GB:net-tel.gold-400.gb +O$TELECOM GOLD.PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB:telecom-gold.telecom-gold.gold-400.gb +PRMD$BP EXPLORATION.ADMD$GOLD 400.C$GB:bp-exploration.gold-400.gb +PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB:telecom-gold.gold-400.gb +O$LOGITEK PLC.PRMD$LOGITEK.ADMD$GOLD 400.C$GB:logitek-plc.logitek.gold-400.gb +PRMD$BP RESEARCH.ADMD$GOLD 400.C$GB:bp-research.gold-400.gb +PRMD$GEC AVIONICS.ADMD$GOLD 400.C$GB:gec-avionics.gold-400.gb +PRMD$LOGITEK.ADMD$GOLD 400.C$GB:logitek.gold-400.gb +PRMD$@.ADMD$TMAILUK.C$GB:tmailuk.gb +PRMD$STC Plc.ADMD$GOLD 400.C$GB:stc-plc.gold-400.gb +OU$HAL0200.O$STC Technology Ltd.PRMD$STC Plc.ADMD$GOLD 400.C$GB:stl.stc.co.uk +OU$pdmrep.O$International Computers Ltd.PRMD$STC Plc.ADMD$GOLD 400.C$GB:pdmrep.icl.stc-plc.gold-400.gb +# +#============================================================================= +#============================================================== Italy ====== +# Last update: 90.07.26 +# C=it; ADMD=garr; PRMD=infn; OU=elettra-ts; S=Allocchio; G=Claudio; +# Claudio.Allocchio@elettra-ts.infn.it +# diff --git a/examples/xtel/rfc1148gate b/examples/xtel/rfc1148gate new file mode 100644 index 0000000..cdada87 --- /dev/null +++ b/examples/xtel/rfc1148gate @@ -0,0 +1,10 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Tue May 21 15:37:35 BST 1991 +############## on host lancaster +############## +################################################## +################################################## diff --git a/examples/xtel/rfc2or b/examples/xtel/rfc2or new file mode 100644 index 0000000..c956d0a --- /dev/null +++ b/examples/xtel/rfc2or @@ -0,0 +1,500 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Fri Nov 22 12:02:31 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +xtel.co.uk:O$XTEL.PRMD$X-Tel Services.ADMD$ .C$GB +sss.co.uk:PRMD$SUBSL.ADMD$ .C$GB +esso.tmailuk.gb:PRMD$ESSO.ADMD$TMAILUK.C$GB +mel.dit.csiro.au:OU$mel.O$dit.PRMD$CSIRO.ADMD$ .C$AU +############################################################################## +# +# +# --- *** --- +# Automatically generated entries from the +# RFC-987 Gateway Conversion Tables +# --- *** --- +# +# +############################################################################## +# +# +# +#H DOC=PROCEDURES/RFC987-MAPPING2; RES=RARE MHS Project Team; DAT=90.08.13; +# +# INTERNATIONAL TABLE 2 +# ================================== +# RFC-987 GATEWAY CONVERSION TABLE +# - as a result of coordination in the +# R&D MHS Service. +# +# MAPPING 2: From RFC-822 format +# to X.400 Standard Attributes +# +# This table is a concatenation of different +# national conversion tables. +# +# It does not contain ambiguous left hand sides. Local +# mappings are specifically excluded from this table, +# and must be added by each RFC-987 gateway operator. +# +# With this modification, it should be used by every operator +# of an RFC-987 gateway within the R&D MHS Service. +# +# Responsible: RARE MHS Project Team +# MHS-Project-Team@rare.no +# C=NO;PRMD=uninett;O=rare;S=MHS-Project-Team; +# +#============================================================== Austria ====== +# Last update: 90.03.21 +# Responsible: Franz Haselbacher +# C=at;A=ada;P=tu-graz;O=edvz;S=haselbacher +# +ada.at:ADMD$ada.C$at +radaus.ada.at:O$radaus.PRMD$@.ADMD$ada.C$at +# +#============================================================================= +#============================================================== Belgium ====== +# Last update: 90.08.02 +# Responsible: Bernard Detrembleur +# +# +fundp.rtt.be:PRMD$fundp.ADMD$rtt.C$be +dgc.rtt.be:PRMD$dgc.ADMD$rtt.C$be +iihe.rtt.be:PRMD$iihe.ADMD$rtt.C$be +informabel.informabel.rtt.be:O$informabel.PRMD$informabel.ADMD$rtt.C$be +stesud.informabel.rtt.be:O$stesud.PRMD$informabel.ADMD$rtt.C$be +jrc.rtt.be:O$@.PRMD$jrc.ADMD$rtt.C$be +cenclcbel.rtt.be:PRMD$cenclcbel.ADMD$rtt.C$be +alcatel-etb.rtt.be:PRMD$alcatel-etb.ADMD$rtt.C$be +# +# UUCP site under .be domain +# +ac.be:PRMD$ac.ADMD$rtt.C$be +ac.rtt.be:PRMD$ac.ADMD$rtt.C$be +agfa.be:PRMD$agfa.ADMD$rtt.C$be +att.be:PRMD$att.ADMD$rtt.C$be +bbl.be:PRMD$bbl.ADMD$rtt.C$be +bbri.be:PRMD$bbri.ADMD$rtt.C$be +buug.be:PRMD$buug.ADMD$rtt.C$be +camme.be:PRMD$camme.ADMD$rtt.C$be +capgsb.be:PRMD$capgsb.ADMD$rtt.C$be +cec.be:PRMD$cec.ADMD$rtt.C$be +e2s.be:PRMD$e2s.ADMD$rtt.C$be +imec.be:PRMD$imec.ADMD$rtt.C$be +intecsi.be:PRMD$intecsi.ADMD$rtt.C$be +oma.be:PRMD$oma.ADMD$rtt.C$be +pgsgent.be:PRMD$pgsgent.ADMD$rtt.C$be +philips.be:PRMD$philips.ADMD$rtt.C$be +repko.be:PRMD$repko.ADMD$rtt.C$be +retime.be:PRMD$retime.ADMD$rtt.C$be +rubens.be:PRMD$rubens.ADMD$rtt.C$be +sema.be:PRMD$sema.ADMD$rtt.C$be +siemens.be:PRMD$siemens.ADMD$rtt.C$be +sunbim.be:PRMD$sunbim.ADMD$rtt.C$be +sydes.be:PRMD$sydes.ADMD$rtt.C$be +syteke.be:PRMD$syteke.ADMD$rtt.C$be +# +#============================================================================= +#============================================================== Brazil ======= +# Date: 89.06.22 +# Responsible: Peter Kaufmann +# +# +# +#============================================================================= +#============================================================== Canada ======= +# Last update: 90.07.25 +# Responsible: John Demco +# C=ca;A=telecom.canada;P=cdn;O=cdnnet;S=demco +# +bc.ca:O$bc.PRMD$cdn.ADMD$telecom\.canada.C$ca +gov.bc.ca:OU$gov.O$bc.PRMD$cdn.ADMD$telecom\.canada.C$ca +bcsystems.gov.bc.ca:OU$bcsystems.OU$gov.O$bc.PRMD$bcgovt.ADMD$telecom\.canada.C$ca +osiware.bc.ca:PRMD$osiware.ADMD$telecom\.canada.C$ca +# +#============================================================================= +#========================================================== Switzerland ====== +# Last update: 90.08.02 +# Responsible: Urs Eppenberger +# +# +#----------------------------------------------------------- ch general ------ +arcom.ch:ADMD$ARCOM.C$CH +#--------------------------------------------------------- ch education ------ +#---------------------------------------------------------- ch research ------ +abb.ch:PRMD$ABB.ADMD$ARCOM.C$CH +sandoz.ch:PRMD$SANDOZ.ADMD$ARCOM.C$CH +cern.ch:O$CERN.PRMD$CERN.ADMD$ARCOM.C$CH +#--------------------------------------------------------- int networks ------ +# local mappings must be added before this table can be +# used for CH RFC987 gateways +# +#============================================================================= +#============================================================== Germany ====== +# TITLE: RFC-987 Conversion Tables. Temporary. NOT Human Readable. +# Long Version/ FR Germany (RFC822 --> X.400) +# Date: 90.07.24 +# Responsible: Peter Kaufmann +# Gabriele v. Siebert +# +#***************************************************************** +# +# A) German mapping rules for DFN-installations +# +# Defaults (strong syntax) +#de +#dbp.de +# +# +# Defaults (weak syntax) +dbp.de:ADMD$dbp.C$de +# +# Installations without "Organizational Name" +# +# A.1) Universities +# +rwth-aachen.dbp.de:O$@.PRMD$rwth-aachen.ADMD$dbp.C$de +fh-aalen.dbp.de:O$@.PRMD$fh-aalen.ADMD$dbp.C$de +uni-augsburg.dbp.de:O$@.PRMD$uni-augsburg.ADMD$dbp.C$de +fh-augsburg.dbp.de:O$@.PRMD$fh-augsburg.ADMD$dbp.C$de +uni-bamberg.dbp.de:O$@.PRMD$uni-bamberg.ADMD$dbp.C$de +uni-bayreuth.dbp.de:O$@.PRMD$uni-bayreuth.ADMD$dbp.C$de +fh-dbp-berlin.dbp.de:O$@.PRMD$fh-dbp-berlin.ADMD$dbp.C$de +fu-berlin.dbp.de:O$@.PRMD$fu-berlin.ADMD$dbp.C$de +tu-berlin.dbp.de:O$@.PRMD$tu-berlin.ADMD$dbp.C$de +uni-bielefeld.dbp.de:O$@.PRMD$uni-bielefeld.ADMD$dbp.C$de +uni-bochum.dbp.de:O$@.PRMD$uni-bochum.ADMD$dbp.C$de +ruhr-uni-bochum.dbp.de:O$@.PRMD$ruhr-uni-bochum.ADMD$dbp.C$de +uni-bonn.dbp.de:O$@.PRMD$uni-bonn.ADMD$dbp.C$de +tu-braunschweig.dbp.de:O$@.PRMD$tu-braunschweig.ADMD$dbp.C$de +uni-bremen.dbp.de:O$@.PRMD$uni-bremen.ADMD$dbp.C$de +tu-clausthal.dbp.de:O$@.PRMD$tu-clausthal.ADMD$dbp.C$de +fh-coburg.dbp.de:O$@.PRMD$fh-coburg.ADMD$dbp.C$de +fh-darmstadt.dbp.de:O$@.PRMD$fh-darmstadt.ADMD$dbp.C$de +th-darmstadt.dbp.de:O$@.PRMD$th-darmstadt.ADMD$dbp.C$de +uni-dortmund.dbp.de:O$@.PRMD$uni-dortmund.ADMD$dbp.C$de +uni-duisburg.dbp.de:O$@.PRMD$uni-duisburg.ADMD$dbp.C$de +uni-duesseldorf.dbp.de:O$@.PRMD$uni-duesseldorf.ADMD$dbp.C$de +ku-eichstaett.dbp.de:O$@.PRMD$ku-eichstaett.ADMD$dbp.C$de +uni-erlangen.dbp.de:O$@.PRMD$uni-erlangen.ADMD$dbp.C$de +uni-essen.dbp.de:O$@.PRMD$uni-essen.ADMD$dbp.C$de +fht-esslingen.dbp.de:O$@.PRMD$fht-esslingen.ADMD$dbp.C$de +uni-frankfurt.dbp.de:O$@.PRMD$uni-frankfurt.ADMD$dbp.C$de +uni-freiburg.dbp.de:O$@.PRMD$uni-freiburg.ADMD$dbp.C$de +fh-furtwangen.dbp.de:O$@.PRMD$fh-furtwangen.ADMD$dbp.C$de +uni-giessen.dbp.de:O$@.PRMD$uni-giessen.ADMD$dbp.C$de +uni-goettingen.dbp.de:O$@.PRMD$uni-goettingen.ADMD$dbp.C$de +fernuni-hagen.dbp.de:O$@.PRMD$fernuni-hagen.ADMD$dbp.C$de +uni-hamburg.dbp.de:O$@.PRMD$uni-hamburg.ADMD$dbp.C$de +fh-hamburg.dbp.de:O$@.PRMD$fh-hamburg.ADMD$dbp.C$de +uni-hannover.dbp.de:O$@.PRMD$uni-hannover.ADMD$dbp.C$de +tu-harburg.dbp.de:O$@.PRMD$tu-harburg.ADMD$dbp.C$de +uni-heidelberg.dbp.de:O$@.PRMD$uni-heidelberg.ADMD$dbp.C$de +fh-heilbronn.dbp.de:O$@.PRMD$fh-heilbronn.ADMD$dbp.C$de +uni-hildesheim.dbp.de:O$@.PRMD$uni-hildesheim.ADMD$dbp.C$de +uni-hohenheim.dbp.de:O$@.PRMD$uni-hohenheim.ADMD$dbp.C$de +uni-kaisersltrn.dbp.de:O$@.PRMD$uni-kl.ADMD$dbp.C$de +uni-kl.dbp.de:O$@.PRMD$uni-kl.ADMD$dbp.C$de +fh-karlsruhe.dbp.de:O$@.PRMD$fh-karlsruhe.ADMD$dbp.C$de +uni-karlsruhe.dbp.de:O$@.PRMD$uni-karlsruhe.ADMD$dbp.C$de +uni-kassel.dbp.de:O$@.PRMD$uni-kassel.ADMD$dbp.C$de +fh-kempten.dbp.de:O$@.PRMD$fh-kempten.ADMD$dbp.C$de +uni-kiel.dbp.de:O$@.PRMD$uni-kiel.ADMD$dbp.C$de +fh-kiel.dbp.de:O$@.PRMD$fh-kiel.ADMD$dbp.C$de +uni-konstanz.dbp.de:O$@.PRMD$uni-konstanz.ADMD$dbp.C$de +fh-koeln.dbp.de:O$@.PRMD$fh-koeln.ADMD$dbp.C$de +uni-koeln.dbp.de:O$@.PRMD$uni-koeln.ADMD$dbp.C$de +fh-landshut.dbp.de:O$@.PRMD$fh-landshut.ADMD$dbp.C$de +uni-mainz.dbp.de:O$@.PRMD$uni-mainz.ADMD$dbp.C$de +uni-mannheim.dbp.de:O$@.PRMD$uni-mannheim.ADMD$dbp.C$de +uni-marburg.dbp.de:O$@.PRMD$uni-marburg.ADMD$dbp.C$de +tu-muenchen.dbp.de:O$@.PRMD$tu-muenchen.ADMD$dbp.C$de +fh-muenchen.dbp.de:O$@.PRMD$fh-muenchen.ADMD$dbp.C$de +lmu-muenchen.dbp.de:O$@.PRMD$lmu-muenchen.ADMD$dbp.C$de +uni-muenchen.dbp.de:O$@.PRMD$uni-muenchen.ADMD$dbp.C$de +uni-muenster.dbp.de:O$@.PRMD$uni-muenster.ADMD$dbp.C$de +fh-muenster.dbp.de:O$@.PRMD$fh-muenster.ADMD$dbp.C$de +fh-nuernberg.dbp.de:O$@.PRMD$fh-nuernberg.ADMD$dbp.C$de +uni-oldenburg.dbp.de:O$@.PRMD$uni-oldenburg.ADMD$dbp.C$de +uni-osnabrueck.dbp.de:O$@.PRMD$uni-osnabrueck.ADMD$dbp.C$de +fh-osnabrueck.dbp.de:O$@.PRMD$fh-osnabrueck.ADMD$dbp.C$de +uni-paderborn.dbp.de:O$@.PRMD$uni-paderborn.ADMD$dbp.C$de +uni-passau.dbp.de:O$@.PRMD$uni-passau.ADMD$dbp.C$de +fh-regensburg.dbp.de:O$@.PRMD$fh-regensburg.ADMD$dbp.C$de +uni-regensburg.dbp.de:O$@.PRMD$uni-regensburg.ADMD$dbp.C$de +fh-rosenheim.dbp.de:O$@.PRMD$fh-rosenheim.ADMD$dbp.C$de +uni-saarland.dbp.de:O$@.PRMD$uni-saarland.ADMD$dbp.C$de +uni-siegen.dbp.de:O$@.PRMD$uni-siegen.ADMD$dbp.C$de +uni-stuttgart.dbp.de:O$@.PRMD$uni-stuttgart.ADMD$dbp.C$de +uni-trier.dbp.de:O$@.PRMD$uni-trier.ADMD$dbp.C$de +uni-tuebingen.dbp.de:O$@.PRMD$uni-tuebingen.ADMD$dbp.C$de +uni-ulm.dbp.de:O$@.PRMD$uni-ulm.ADMD$dbp.C$de +fh-ulm.dbp.de:O$@.PRMD$fh-ulm.ADMD$dbp.C$de +fh-weihenstephan.dbp.de:O$@.PRMD$fh-weihenstephan.ADMD$dbp.C$de +fh-wiesbaden.dbp.de:O$@.PRMD$fh-wiesbaden.ADMD$dbp.C$de +uni-witten-h.dbp.de:O$@.PRMD$uni-witten-h.ADMD$dbp.C$de +uni-wuerzburg.dbp.de:O$@.PRMD$uni-wuerzburg.ADMD$dbp.C$de +fh-wuerzburg.dbp.de:O$@.PRMD$fh-wuerzburg.ADMD$dbp.C$de +uni-wuppertal.dbp.de:O$@.PRMD$uni-wuppertal.ADMD$dbp.C$de +# +# A.2) Research laboratories/institutions +# +bessy.dbp.de:O$@.PRMD$bessy.ADMD$dbp.C$de +bgr.dbp.de:O$@.PRMD$bgr.ADMD$dbp.C$de +dfg.dbp.de:O$@.PRMD$dfg.ADMD$dbp.C$de +dfn.dbp.de:O$@.PRMD$dfn.ADMD$dbp.C$de +dlr.dbp.de:O$@.PRMD$dlr.ADMD$dbp.C$de +desy.dbp.de:O$@.PRMD$desy.ADMD$dbp.C$de +embl.dbp.de:O$@.PRMD$embl.ADMD$dbp.C$de +ffm.dbp.de:O$@.PRMD$ffm.ADMD$dbp.C$de +gmd.dbp.de:O$@.PRMD$gmd.ADMD$dbp.C$de +gsi.dbp.de:O$@.PRMD$gsi.ADMD$dbp.C$de +hmi.dbp.de:O$@.PRMD$hmi.ADMD$dbp.C$de +kfk.dbp.de:O$@.PRMD$kfk.ADMD$dbp.C$de +gwdg.dbp.de:O$@.PRMD$gwdg.ADMD$dbp.C$de +belwue.dbp.de:O$@.PRMD$belwue.ADMD$dbp.C$de +wiko-berlin.dbp.de:O$@.PRMD$wiko-berlin.ADMD$dbp.C$de +zib-berlin.dbp.de:O$@.PRMD$zib-berlin.ADMD$dbp.C$de +diw-berlin.dbp.de:O$@.PRMD$diw-berlin.ADMD$dbp.C$de +gbf-braunschweig.dbp.de:O$@.PRMD$gbf-braunschweig.ADMD$dbp.C$de +awi-bremerhaven.dbp.de:O$@.PRMD$awi-bremerhaven.ADMD$dbp.C$de +gtt-duisburg.dbp.de:O$@.PRMD$gtt-duisburg.ADMD$dbp.C$de +dkrz-hamburg.dbp.de:O$@.PRMD$dkrz-hamburg.ADMD$dbp.C$de +dkfz-heidelberg.dbp.de:O$@.PRMD$dkfz-heidelberg.ADMD$dbp.C$de +kfa-juelich.dbp.de:O$@.PRMD$kfa-juelich.ADMD$dbp.C$de +augustinum-m.dbp.de:O$@.PRMD$augustinum-m.ADMD$dbp.C$de +badw-muenchen.dbp.de:O$@.PRMD$badw-muenchen.ADMD$dbp.C$de +# +# A.3) Companies +# +basf-ag.dbp.de:O$@.PRMD$basf-ag.ADMD$dbp.C$de +hoechst-ag.dbp.de:O$@.PRMD$hoechst-ag.ADMD$dbp.C$de +datageneral.dbp.de:O$@.PRMD$datageneral.ADMD$dbp.C$de +decde.dbp.de:O$@.PRMD$decde.ADMD$dbp.C$de +pcs.dbp.de:O$@.PRMD$pcs.ADMD$dbp.C$de +siemens-mchp02.dbp.de:O$@.PRMD$siemens-mchp02.ADMD$dbp.C$de +siemens-mchp04.dbp.de:O$@.PRMD$siemens-mchp04.ADMD$dbp.C$de +siemens.dbp.de:O$@.PRMD$siemens.ADMD$dbp.C$de +sel-rc.dbp.de:O$@.PRMD$sel-rc.ADMD$dbp.C$de +# +# +# +# Installations with "Organizational Name" +# +# A.4) Research labaratories/institutions +# +esa.dbp.de:PRMD$esa.ADMD$dbp.C$de +fhg.dbp.de:PRMD$fhg.ADMD$dbp.C$de +mpg.dbp.de:PRMD$mpg.ADMD$dbp.C$de +ptb.dbp.de:PRMD$ptb.ADMD$dbp.C$de +# +# A.5) Companies +# +danet.dbp.de:PRMD$danet.ADMD$dbp.C$de +gtc.dbp.de:PRMD$gtc.ADMD$dbp.C$de +ibm-deutschland.dbp.de:PRMD$ibm-deutschland.ADMD$dbp.C$de +nixdorf.dbp.de:PRMD$nixdorf.ADMD$dbp.C$de +softlab.dbp.de:PRMD$softlab.ADMD$dbp.C$de +unisys-de.dbp.de:PRMD$unisys-de.ADMD$dbp.C$de +# +# +# +# B) German mapping rules for German UUCP Domains +# +# Installations without "ADMD=DBP" and without "Organizational Name" +# +# B.1) Universities +# +fu-berlin.de:O$@.PRMD$fu-berlin.ADMD$ .C$de +uni-bochum.de:O$@.PRMD$uni-bochum.ADMD$ .C$de +uni-bonn.de:O$@.PRMD$uni-bonn.ADMD$ .C$de +uni-bremen.de:O$@.PRMD$uni-bremen.ADMD$ .C$de +uni-dortmund.de:O$@.PRMD$uni-dortmund.ADMD$ .C$de +uni-erlangen.de:O$@.PRMD$uni-erlangen.ADMD$ .C$de +uni-freiburg.de:O$@.PRMD$uni-freiburg.ADMD$ .C$de +uni-hamburg.de:O$@.PRMD$uni-hamburg.ADMD$ .C$de +uni-kl.de:O$@.PRMD$uni-kl.ADMD$ .C$de +uni-koeln.de:O$@.PRMD$uni-koeln.ADMD$ .C$de +uni-mainz.de:O$@.PRMD$uni-mainz.ADMD$ .C$de +tu-muenchen.de:O$@.PRMD$tu-muenchen.ADMD$ .C$de +uni-paderborn.de:O$@.PRMD$uni-paderborn.ADMD$ .C$de +uni-passau.de:O$@.PRMD$uni-passau.ADMD$ .C$de +uni-saarland.de:O$@.PRMD$uni-saarland.ADMD$ .C$de +uni-stuttgart.de:O$@.PRMD$uni-stuttgart.ADMD$ .C$de +# +# B.2) Research laboratories/institutions +# +kfa-juelich.de:O$@.PRMD$kfa-juelich.ADMD$ .C$de +gmd.de:O$@.PRMD$gmd.ADMD$ .C$de +# +# Installations without "ADMD=DBP" but with "Organizational Name" +# +fhg.de:PRMD$fhg.ADMD$ .C$de +# +# +# +# C) German mapping rules for Non-X.400 Top-Domains +# +# - deleted - +# +#============================================================================= +#============================================================= Denmark ======= +# Last update: 90-03-20 +# Responsible: Klaus Hansen +# C=DK;ADMD= ;PRMD=;O=diku;S=khan; +# +# +#============================================================================= +#=============================================================== Spain ======= +# Last update: 90.06.01 +# Responsible: Ignacio Martinez +# C=es;A=" ";P=iris;O=iris-dcp;S=martinez +# +# Default mapping (according to CEN/CENELEC ENV 41201): +# +# +# Bloody mappings for those who still not accept ADMD=" " +# (namely CDC, Data General and HP) +# +santiago.usc.es:OU$santiago.O$usc.PRMD$iris.ADMD$ptt.C$es +seins.usc.es:OU$seins.O$usc.PRMD$iris.ADMD$ptt.C$es +cc.unican.es:OU$cc.O$unican.PRMD$iris.ADMD$ptt.C$es +laro.unican.es:OU$laro.O$unican.PRMD$iris.ADMD$ptt.C$es +ucma.es:O$ucma.PRMD$iris.ADMD$ptt.C$es +inia.es:O$inia.PRMD$iris.ADMD$ptt.C$es +fltq.es:O$fltq.PRMD$iris.ADMD$ptt.C$es +git.upv.es:OU$git.O$upv.PRMD$iris.ADMD$ptt.C$es +# +#------------------------------------------------------------ companies ------ +# +# Companies are exceptions to the general rule as they subscribe to their +# own PRMD (other than IRIS) +# +asicom.es:O$asicom.PRMD$asicom.ADMD$ .C$es +atimdr.es:O$atimdr.PRMD$atimdr.ADMD$ .C$es +ccs.es:O$ccs.PRMD$ccs.ADMD$ .C$es +correa.es:O$correa.PRMD$correa.ADMD$ .C$es +crisa.es:O$crisa.PRMD$crisa.ADMD$ .C$es +cuac.es:O$cuac.PRMD$cuac.ADMD$ .C$es +data-general.es:O$data-general.PRMD$dgsa.ADMD$ptt.C$es +dsd.es:O$dsd.PRMD$dsd.ADMD$ .C$es +easa.es:O$easa.PRMD$easa.ADMD$ .C$es +entel.es:O$entel.PRMD$entel.ADMD$ .C$es +eria.es:O$eria.PRMD$eria.ADMD$ .C$es +expo92.es:O$expo92.PRMD$expo92.ADMD$ .C$es +fesa.es:O$fesa.PRMD$fujitsu.ADMD$ .C$es +foro.es:O$foro.PRMD$foro.ADMD$ .C$es +gapd.es:O$gapd.PRMD$gapd.ADMD$ .C$es +gmv.es:O$gmv.PRMD$gmv.ADMD$ .C$es +intelsa.es:O$intelsa.PRMD$intelsa.ADMD$ .C$es +iss.es:O$iss.PRMD$iss.ADMD$ .C$es +lsi.es:O$lsi.PRMD$lsi.ADMD$ .C$es +menarini.es:O$menarini.PRMD$menarini.ADMD$ .C$es +mopu.es:O$mopu.PRMD$mopu.ADMD$ .C$es +nsi.es:O$nsi.PRMD$nexus.ADMD$ .C$es +nte.es:O$nte.PRMD$nte.ADMD$ .C$es +proa.es:O$proa.PRMD$proa.ADMD$ .C$es +px86.es:O$px86.PRMD$px86.ADMD$ .C$es +rebu.es:O$rebu.PRMD$repsol.ADMD$ .C$es +scyt.es:O$scyt.PRMD$scyt.ADMD$ .C$es +sicyd.es:O$sicyd.PRMD$sicyd.ADMD$ .C$es +sema.es:O$sema.PRMD$sema.ADMD$ .C$es +sesa.es:O$sesa.PRMD$alcatel.ADMD$ .C$es +teice.es:O$teice.PRMD$teice-control.ADMD$ .C$es +telefonica.es:O$telefonica.PRMD$telefonica.ADMD$ .C$es +telettra.es:O$telettra.PRMD$telettra.ADMD$ .C$es +tid.es:O$tid.PRMD$tidsa.ADMD$ .C$es +tifsa.es:O$tifsa.PRMD$tifsa.ADMD$ .C$es +ts.es:O$ts.PRMD$ts.ADMD$ .C$es +# +#============================================================================= +#============================================================== Finland ====== +# +# RFC.822 --> X.400 +# +# Last update 90.07.23 +# Responsible: Marko Kaittola +# c=fi;ADMD=fumail;PRMD=funet;S=Kaittola;G=Marko +# +# +fumail.fi:ADMD$fumail.C$fi +mailnet.fi:ADMD$mailnet.C$fi +elisa.fi:ADMD$elisa.C$fi +# +#============================================================================= +#============================================ France REUNIR + Aristote ======= +# Last update: 90.07.20 +# Responsibles: +# REUNIR: Serge Aumont C=FR;ADMD=ATLAS;PRMD=REUNIR;S=Aumont +# ARISTOTE: Paul Andre Pays C=FR;ADMD=ATLAS;PRMD=EMSE;O=EMSESMC;S=pays +# +atlas.fr:PRMD$@.ADMD$atlas.C$FR +# +cea.fr:O$cea.PRMD$cea.ADMD$atlas.C$FR +cicb.fr:O$@.PRMD$cicb.ADMD$atlas.C$FR +cirad.fr:O$@.PRMD$cirad.ADMD$atlas.C$FR +circe.fr:O$@.PRMD$circe.ADMD$atlas.C$FR +ciril.fr:O$@.PRMD$ciril.ADMD$atlas.C$FR +citilille.fr:O$@.PRMD$citilille.ADMD$atlas.C$FR +cnam.fr:O$@.PRMD$cnam.ADMD$atlas.C$FR +cnusc.fr:O$@.PRMD$cnusc.ADMD$atlas.C$FR +ensm.fr:O$@.PRMD$ensm.ADMD$atlas.C$FR +ens-cachan.fr:O$@.PRMD$ens-cachan.ADMD$atlas.C$FR +glvt-cnrs.fr:O$@.PRMD$glvt-cnrs.ADMD$atlas.C$FR +lmcp.fr:O$@.PRMD$lmcp.ADMD$atlas.C$FR +matups.fr:O$@.PRMD$matups.ADMD$atlas.C$FR +ill.fr:O$@.PRMD$ill.ADMD$atlas.C$FR +inra.fr:O$@.PRMD$inra.ADMD$atlas.C$FR +irisa.fr:O$@.PRMD$irisa.ADMD$atlas.C$FR +uhb.fr:O$uhb.PRMD$cicb.ADMD$atlas.C$FR +unicaen.fr:O$@.PRMD$unicaen.ADMD$atlas.C$FR +unice.fr:O$@.PRMD$unice.ADMD$atlas.C$FR +unilim.fr:O$@.PRMD$unilim.ADMD$atlas.C$FR +univ-lyon1.fr:O$@.PRMD$univ-lyon1.ADMD$atlas.C$FR +univ-pau.fr:O$@.PRMD$univ-pau.ADMD$atlas.C$FR +u-strasbg.fr:O$@.PRMD$u-strasbg.ADMD$atlas.C$FR +u-paris10.fr:O$@.PRMD$u-paris10.ADMD$atlas.C$FR +u-paris13.fr:O$@.PRMD$u-paris13.ADMD$atlas.C$FR +reunir.fr:O$@.PRMD$reunir.ADMD$atlas.C$FR +# +#============================================================================= +#======================================================= United Kingdom ====== +# Last update: 90.08.06 +# Responsible: Tony Bates +# +# Beware of the quoted dots in this table! +# +ac.uk:PRMD$UK\.AC.ADMD$ .C$GB +gold-400.gb:ADMD$GOLD 400.C$GB +btmhs.gb:ADMD$BTMHS.C$GB +tmailuk.gb:PRMD$@.ADMD$TMAILUK.C$GB +gosip-uk.hmg.gold-400.gb:O$GOSIP UK.PRMD$HMG.ADMD$GOLD 400.C$GB +bp-exploration.gold-400.gb:PRMD$BP EXPLORATION.ADMD$GOLD 400.C$GB +bp-research.gold-400.gb:PRMD$BP RESEARCH.ADMD$GOLD 400.C$GB +btg.gold-400.gb:O$BTG.PRMD$@.ADMD$GOLD 400.C$GB +dialcom-ltd.telecom-gold.gold-400.gb:O$DIALCOM LTD.PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB +gec-avionics.gold-400.gb:PRMD$GEC AVIONICS.ADMD$GOLD 400.C$GB +logitek-plc.logitek.gold-400.gb:O$LOGITEK PLC.PRMD$LOGITEK.ADMD$GOLD 400.C$GB +mhs.gold-400.gb:O$MHS.PRMD$@.ADMD$GOLD 400.C$GB +telecom-gold.gold-400.gb:PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB +telecom-gold.telecom-gold.gold-400.gb:O$TELECOM GOLD.PRMD$TELECOM GOLD.ADMD$GOLD 400.C$GB +stc-plc.gold-400.gb:PRMD$STC Plc.ADMD$GOLD 400.C$GB +net-tel.gold-400.gb:O$Net-Tel Computer Systems Ltd.PRMD$NET-TEL.ADMD$GOLD 400.C$GB +# +#============================================================================= +#============================================================== Italy ====== +# Last update: 90.07.26 +# Responsible: Claudio Allocchio +# C=it; ADMD=garr; PRMD=infn; OU=elettra-ts; S=Allocchio; G=Claudio; +# Claudio.Allocchio@elettra-ts.infn.it +# +# ******* Note: ADMD$ HAS TURNED INTO ADMD$garr ************* +# +# +infn.it:O$@.PRMD$infn.ADMD$garr.C$it diff --git a/examples/xtel/tailor b/examples/xtel/tailor new file mode 100644 index 0000000..0ddfe35 --- /dev/null +++ b/examples/xtel/tailor @@ -0,0 +1,439 @@ +############################################################ +# +# Tailor file for PP +# +# This version for sites with local smtp +# +############################################################ + +############################################################ +# +# The following variables will need tailoring +# +############################################################ +# +# The loc_dom_mta is the host that the MTA will reside on and execute from +# It is a fully qualified domain name and represent the physical machine +# Examples might be +# cheetah.nyser.net +# violet.berkeley.edu +# john.cs.nott.ac.uk +# +loc_dom_mta lancaster.xtel.co.uk +# +# The Sitename is what the rest of the world sees you as. This is typically +# a domain shorter than the full domain name. It is the name used to represent +# your site or group as a whole. This name normally hides the individual +# machine names +# Examples might be +# berkeley.edu +# nyser.net +# cs.nott.ac.uk +# +loc_dom_site xtel.co.uk +# +# The postmaster should include the local site name +# e.g. postmaster@berkeley.edu or postmaster@cs.nott.ac.uk +# +postmaster postmaster@xtel.co.uk + +#adminstration_assigned_alternate_recipient pac + +# +# The pplogin should be the username of the owner of pp. +# +pplogin pp +# +# The qmgrhost should be the same as the name found in isoentities file. +# This can be the same as loc_dom_mta name +# +pptsapd_addr LOCAL-ETHER=lancaster+20001 +qmgrhost lancaster +# +# The local or name should be the name of your site in X.400 terms. +# This is attribute value based, and starts with organisational units and +# works up to country. If you are unsure, leave it with just a country +# component, e.g. "/C=GB/" +# +loc_or "/o=xtel/prmd=X-Tel Services/admd= /c=GB/" +############################################################ +# +# That is the end of the things you must tailor - the rest are +# probably ok - but you should check. +# +############################################################ + +delim1 "\1\1\1\1\12" +delim2 "\1\1\1\1\12" +#returntime 36 +#queuestruct 100 +dap_user "c=GB@o=X-Tel Services Ltd@cn=lancaster@cn=pp qmgr" + + +authchannel free +authloglevel high +wrndfldir warnings +#submit_addr lancaster:pp-submit + +# Body types + +headertype 822 822-jnt 822-us p2 822-uk p22 ipn g3fax ps +bodypart encrypted g3fax ia5 ipm national sfd tif0 tif1 +bodypart tlx undefined videotex voice odif iso6937 +bodypart bilateral external +bodypart dmd ia5-dk ps ms +bodypart oid.0.9.2342.60200172.99.1.4 + + + +# **-- Mapping tables --** +# +# All of these table MUST have the names given here +tbl aliases show="Aliases: mapping -> local id", + flags=dbm +tbl users show="Users: mapping local id -> disposition", + flags=dbm +tbl x400-developers-aliases show="Aliases: mapping -> local id", + flags=linear +tbl x400-developers-users show="Users: mapping local id -> disposition", + flags=linear +tbl domain show="Mapping domain key ->full domain/MTA", + flags=dbm +tbl or show="Mapping O/R Address -> MTA",flags=dbm +tbl channel show="Binding MTA -> Channels",flags=dbm +tbl or2rfc show="RFC 987: X.400 -> RFC 822",flags=dbm +tbl rfc2or show="RFC 987: RFC 822 -> X.400",flags=dbm +tbl rfc1148gate show="Gateways that perform RFC 1148 conversions", + flags=dbm +tbl auth.channel show="Authorisation: channel policy",flags=dbm +tbl auth.mta show="Authorisation: mta based",flags=dbm +tbl auth.user show="Authorisation: user based",flags=dbm +tbl auth.qmgr show="Authorisation: qmgr control",flags=dbm +# **-- Channel tables --** +# +# Needed by individual channels, not submit +tbl local file="ch.local", + show="local id -> user id + home directory", + flags=dbm + +tbl x400in84 file="ch.x400in84", + show="MTA -> connect info",flags=linear +tbl x400out84 file="ch.x400out84", + show="X.400(84) connect info -> MTA + other info", + flags=linear +tbl x400in88 file="ch.x400in88", + show="MTA -> connect info",flags=linear +tbl x400out88 file="ch.x400out88", + show="X.400(88) connect info -> MTA + other info", + flags=linear +tbl shell file="ch.shell", + show="info for shell chan" + flags=dbm +tbl list file="ch.list", + show="Lists: distribution lists", + flags=dbm +tbl uucp file="ch.uucp" + show="UUCP: rfc822 -> uucp", + flags=dbm +tbl fax file="ch.fax", + show="FAX: mappings and info", + flags=linear +tbl mslocal file="ch.mslocal", + show="Message Store:local id -> user id,home directory", + flags=linear + +chan 822-local prog=local, + show="Local Delivery channel",type=both, + sort="user time",adr=822,adr-order=usapref, + hdrin=822,hdrout=822-us, + bptin=ia5,bptout=ia5, + content-out=822,outtable=local,access=mts,drchan=dr2rfc + +chan slocal prog=slocal, + show="via Structured Local Delivery channel", + type=both, + sort="user time",adr=822,adr-order=ukpref, + hdrin=822,hdrout=822-uk, + bptin="ia5,odif", + bptout="ia5,odif", + content-out=822,outtable=local,access=mts, + drchan=dr2rfc + +chan bugs-local prog=local, + show="Local Delivery channel for Bug Reports",type=both, + sort="user time",adr=822,adr-order=usapref, + hdrin=822,hdrout=822-us, + bptin=ia5,bptout=ia5, + content-out=822,outtable=local,access=mts,drchan=dr2rfc + +chan x40088 show="X400 (1988)", type=both, adr=x400, adr-order=ukpref, + key=x400in88, content-in=p22, intable=x400in88, prog=x400out88, + content-out=p22, hdrout="p22,ipn", + bptout="ia5,g3fax,voice,odif,iso6937,oid.0.9.2342.60200172.99.1.4", + outtable=x400out88,probe=y + +chan x40084 show="X400 (1984)", type=both, adr=x400,probe=y + adr-order=ukpref, key=x400in84, content-in=p2, + intable=x400in84, prog=x400out84, content-out=p2, + hdrout=p2, bptout="ia5,g3fax,odif", outtable=x400out84 + +chan xua show="XUA Submission Channel",type=in, + access=mts,adr-order=ukpref, + adr=x400, access=mts, + +chan mslocal prog=mslocal,show="MS local delivery",type=out, + hdrout="p22,p2,ipn", + bptout="encrypted,g3fax,ia5,ipm,national,sfd,tif0,tif1,tlx,undefined,videotex,voice,odif,iso6937,bilateral,external", + outtable=mslocal, + sort="user time",access=mts + +chan mslocal-beta prog=mslocalbeta,show="MS local delivery",type=out, + hdrout="p22,p2,ipn", + bptout="encrypted,g3fax,ia5,ipm,national,sfd,tif0,tif1,tlx,undefined,videotex,voice,odif,iso6937,bilateral,external,oid.0.9.2342.60200172.99.1.4", + outtable=mslocal, + sort="user time",access=mts + +chan smtp prog=smtp,show="with SMTP (PP)",type=both, + adr=822,adr-order=usapref,drchan=dr2rfc, + bptout=ia5,hdrout=822-us,content-out=822, +# bad-sender-policy=address, +# bad-sender-addr=pac + +chan pac-janet prog="greyout -P",show="via JANET with NIFTP (PP)", + type=in, adr=822, + hdrin=822-us,bad-sender-policy=sloppy, + out-info=janet + +chan gb-janet prog="greyout -P",show="via JANET with NIFTP (PP)", + type=both, adr=822,adr-order=ukpref, + hdrout=822-jnt, + bptout=ia5,drchan=dr2rfc, + content-out=822,out-info=janet +# mta=much.cs.nott.ac.uk, + +chan gb-pss prog=smtp,key=ipss, + show="via PSS with NIFTP (PP)",type=both, + adr=822,adr-order=ukpref,drchan=dr2rfc, + bptout=ia5,hdrout=822-jnt, + content-out=822,mta=much.cs.nott.ac.uk + +chan fax prog=ps250, show="Fax channel",type=both, + content-in=p22, hdrin=p22, bptin=g3fax, + hdrout=g3fax, bptout=g3fax, maxproc=1, + drchan=dr2rfc,outtable=fax, sort="user time", + out-info="out=/dev/faxout,confirm=always,softcar=used", + in-info="in=/dev/faxout,softcar=used,master=gal@xtel.co.uk" + +chan dirlist prog=dirlist,show="Directory List channel",type=both, + adr=x400,adr-order=usapref, + sort="user time", out-info="dn=C=GB@O=X-Tel Services Ltd@CN=lancaster" + +chan list prog=list,show="List channel",type=both, + adr-order=usapref,out-info="linked", + outtable=list,sort="user time" + +chan uucp prog=uucp-out,key="uucp-out,rmail", + show="UUCP channel",type=both, + adr=822,adr-order=ukpref,outtable=uucp + out-info="uux=/tmp/uux,host=nott-cs",drchan=dr2rfc + +chan dr2rfc prog=dr2rfc,show="Dr2rfc channel",type=both, + adr=822,adr-order=ukpref, + bptin=ia5,hdrin=822, + out-info="return=all order=uk", + content-out=822 + +chan shell prog=shell,type=out,access=mts + show="Shell channel", + outtable=shell,sort="user time", + bptout="ia5,ps",hdrout=822-uk + +# QMGR special channels (load/manage/clean) + +chan qmgr-load prog=qmgr-load,show="Loading the QMGR", + type=qmgrload,out-info="5"; + +chan msg-clean prog=msg-clean,show="Removing finished message" + type=delete + +chan trash prog=trash,show="Removing trash" + type=debris,out-info=3h + +chan timeout prog=timeout,show="Timeout messages" + type=timeout + +chan warning prog=warnings,show="Send warning messages", + type=warn, out-info="copy-to" + +chan splitter prog=splitter,type=split, + show="Divide message into single" +recipient messages +# **-- shaper channels --** + +# Flatteners + +chan p2flatten prog=p2flatten,show="Structured message -> P2", + type=shaper,content-out=p2 + +chan 822flatten prog=rfc934,type=shaper,content-out=822 + +chan p22flatten prog=p2flatten,show="Structured Message -> P22", + type=shaper,content-out=p22 + +# Unflatteners + +chan p2explode prog=p2explode,type=shaper,content-in=p2 + +chan p22explode prog=p2explode,type=shaper,content-in=p22 + + +# Header Filters +chan 822tofax prog=fcontrol,type=shaper, + hdrin=822-us,hdrout=g3fax,n + out-info="hdr2fax -from $(400sender) -to $(400recip) -subject $(ua-id) -table $(outtable) -outmta $(outmta)",outtable=fax, + cost=20,solo-proc=yes +chan 822touk prog=fcontrol,type=shaper, + hdrin=822, + hdrout=822-uk, + out-info="rfc822norm -jnt -bigend" +chan 822tojnt prog=fcontrol,type=shaper, + hdrin=822,hdrout=822-jnt, + out-info="rfc822norm -jnt -bigend -jntsender $(822SENDER)" +chan 822tous prog=fcontrol,type=shaper,hdrin=822, + hdrout=822-us, + out-info="rfc822norm -822 -littleend" +chan 822top22 prog=RFCtoP2,type=shaper,hdrin=822-us,conv=1148 + hdrout=p22,cost=10, + show="RFC1148 RFC 822 -> P22" +chan 822top2 prog=RFCtoP2,type=shaper,hdrin=822-us,conv=1148 + hdrout=p2,cost=15, + show="RFC1148 RFC 822 -> P2" +chan p2to822 prog=P2toRFC,type=shaper,hdrout=822,conv=1148, + hdrin="p2,ipn",cost=10, + show="RFC1148 P2 -> RFC 822" +chan p22to822 prog=P2toRFC,type=shaper,hdrout=822,conv=1148 + hdrin="p22,ipn",cost=10, + show="RFC1148 P22 -> RFC 822" +chan p22top2 prog=fcontrol,type=shaper,hdrout=p2,hdrin=p22, + show="P22 to P2 downgrade", + conv=conv,cost=10,out-info="p2norm -downgrade" +#identity map +chan p2top22 prog=fcontrol,type=shaper,hdrout=p22,hdrin=p2, + show="P2 to P22 upgrade",cost=1, + out-info="/bin/cat" + +# Body part filters + +chan ia5-dk2ia5 prog=fcontrol,type=shaper,bptin=ia5-dk, + bptout=ia5,show="Danish ia5 to ia5", + conv=loss,out-info="charset DK 38 UK 29" + +chan iso6937totxt prog=fcontrol,type=shaper,bptin=iso6937, + bptout=ia5,conv=loss,cost=15, + out-info="asn -inchar iso_6937-2-add -outchar irv -inasn motis-86-6937 -outasn ia5", + show="ISO6937 -> IA5" + +chan g3faxtotxt prog=fcontrol,type=shaper,bptin=g3fax, + bptout=ia5,out-info="removebp G3Fax", + show="Fax -> Text mapper",cost=100,conv=loss +chan tif0totxt prog=fcontrol,type=shaper,bptin=tif0, + bptout=ia5,out-info="removebp Tif0", + show="Tif0 -> Text mapper",cost=100,conv=loss +chan txttofax prog=fcontrol,type=shaper,bptin=ia5, + bptout=g3fax, + out-info="ia52fax -table $(outtable)",outtable=fax, + show="ia5 -> g3fax mapper" + +chan faxtops prog=fcontrol,type=shaper,bptin=g3fax, + bptout=ps,out-info="fax2ps",show="fax -> postscript" + +chan mstops prog=fcontrol,type=shaper,bptin=ms, + bptout=ps,out-info="/usr/local/bin/psroff -ms -t", + show="ms macros -> postscript" + +chan mstoia5 prog=fcontrol,type=shaper,bptin=ms, + bptout=ia5,out-info="/bin/cat", + show="MS->Text mapper",cost=100,conv=loss + +chan xxtotxt prog=fcontrol,type=shaper,bptin=oid.0.9.2342.60200172.99.1.4, + bptout=ia5,out-info="removebp oid.0.9.2342.60200172.99.1.4" + show="XXX -> Text mapper",cost=100,conv=loss + +chan voicetotxt prog=fcontrol,type=shaper,bptin=voice, + bptout=ia5,out-info="removebp Voice" + show="Voice -> Text mapper",cost=100,conv=loss + +# **-- Logging for the rest of the prog --** +# +authlog level=notice, size=-1 +operlog level=notice, size=400 +normlog level=notice, size=400, sflags=zero + +822flatten normlog file=filter +p2flatten normlog file=filter +822touk normlog file=filter +822tous normlog file=filter +dr2rfc normlog file=filter +fcontrol normlog file=filter +odif2txt normlog file=filter +p2explode normlog file=filter +rfc822norm normlog file=filter +trash normlog file=filter + +822top2 normlog file=rfc987 +p2to822 normlog file=rfc987 + +list normlog file=lists + +qmgr normlog file=qmgr +qmgr-load normlog file=qmgr + +smtp normlog file=smtp +smtpsrvr normlog file=smtp + +greyout normlog file=greyout +gb-janet normlog file=greyin +submit normlog file=submit dflags=close + +local normlog file=local level=trace +msg-clean normlog file=msg-clean + +x400in84 normlog file=x400in84,level=pdus +x400in84 isodelog rtsaplevel file=rts,level=all +x400in84 isodelog ssaplevel file=ssap,level=all +x400out84 normlog file=x400out84 + +x400in88 normlog file=x400in88 level=pdus,level=trace +x400out88 normlog file=x400out88 #level=all + +p7server normlog file=p7server level=all + +xfax normlog file=fax level=debug +xfaxd normlog file=fax #level=debug +G3Fax normlog file=fax +ps250 normlog file=fax +hdr2fax normlog file=fax +ia52fax normlog file=fax +fax normlog file=fax +txttofax normlog file=fax +822tofax normlog file=fax + +#x400out88 isodelog rtsaplevel file=rts-out level=all +#x400out88 isodelog acsaplevel file=acsap-out level=all +#x400out88 isodelog psap2level file=psap2-out level=all +#x400out88 isodelog ssaplevel file=ssap-out level=all + + +#x400in88 isodelog rtsaplevel file=proto-in level=all +#x400in88 isodelog acsaplevel file=proto-in level=all +#x400in88 isodelog psap2level file=proto-in level=all + +pptsapd normlog file=pptsapd, dlevel=notice +dirlist normlog file=dirlist +mslocal normlog file=mslocal +xprobe normlog file=probe level=trace,level=pdus level=all +p7server isode ns_enable off +xua isode ns_enable off +libmsattr isode ns_enable off +#xckadr normlog level=all file=ckadr +xt-rdmsg normlog file=rdmsg diff --git a/examples/xtel/users b/examples/xtel/users new file mode 100644 index 0000000..b2dce5c --- /dev/null +++ b/examples/xtel/users @@ -0,0 +1,88 @@ +################################################## +################################################## +############## +############## WARNING +############## This file is automatically generated +############## at date Tue Dec 3 16:20:39 GMT 1991 +############## on host lancaster +############## +################################################## +################################################## +#x-tel members +#default-user:shell lancaster.xtel.co.uk +a.young:822-local + +lynx:shell lancaster.xtel.co.uk +fred:822-local trellis.xtel.co.uk +j.onions:822-local lancaster.xtel.co.uk + +#g.lunt:822-local lancaster.xtel.co.uk +g.lunt:list lancaster.xtel.co.uk +g.a.lunt:822-local lancaster.xtel.co.uk +ms-g.a.lunt:mslocal-beta lancaster.xtel.co.uk + +#a.roadknight:822-local lancaster.xtel.co.uk +a.roadknight:list lancaster.xtel.co.uk +a.v.roadknight:822-local lancaster.xtel.co.uk +ms-a.v.roadknight:mslocal-beta lancaster.xtel.co.uk + +#p.hennessy:822-local lancaster.xtel.co.uk +p.hennessy:list lancaster.xtel.co.uk +p.a.hennessy:822-local lancaster.xtel.co.uk +ms-p.a.hennessy:mslocal lancaster.xtel.co.uk + +#j.kitchen:822-local lancaster.xtel.co.uk +j.kitchen:list lancaster.xtel.co.uk +j.p.kitchen:822-local lancaster.xtel.co.uk +ms-j.p.kitchen:mslocal lancaster.xtel.co.uk + +#n.cook:822-local lancaster.xtel.co.uk +n.cook:list lancaster.xtel.co.uk +n.l.cook:822-local lancaster.xtel.co.uk +ms-n.l.cook:mslocal lancaster.xtel.co.uk + +hugh:list lancaster.xtel.co.uk +ms-hugh:mslocal lancaster.xtel.co.uk +hts:822-local lancaster.xtel.co.uk + +c.robbins:822-local lancaster.xtel.co.uk +a.whitaker:822-local lancaster.xtel.co.uk +p.cowen:822-local lancaster.xtel.co.uk +p.pat:822-local lancaster.xtel.co.uk +a.worsley:822-local lancaster.xtel.co.uk + +pactest:mslocal lancaster.xtel.co.uk +adam:822-local lancaster.xtel.co.uk, mslocal lancaster.xtel.co.uk + +a.shepherd:822-local + +#pp-course:dirlist lancaster.xtel.co.uk +#xtel:list lancaster.xtel.co.uk +xtel:dirlist lancaster.xtel.co.uk +XUA-support:dirlist lancaster.xtel.co.uk +xua-users:dirlist +#directory-pilot:dirlist lancaster.xtel.co.uk +ontos-users:dirlist +eurocoop:dirlist + +jnt-pp:dirlist lancaster.xtel.co.uk +jnt-quipu:dirlist lancaster.xtel.co.uk +gb-dir-pilot:dirlist lancaster.xtel.co.uk +x500:dirlist lancaster.xtel.co.uk +xconfer:dirlist lancaster.xtel.co.uk +dl-test:dirlist lancaster.xtel.co.uk +isode-steering:dirlist lancaster.xtel.co.uk +wp3:dirlist lancaster.xtel.co.uk +bug-isode:list lancaster.xtel.co.uk +isode-beta:list lancaster.xtel.co.uk +isode-dist:list lancaster.xtel.co.uk + +isode-bugs:bugs-local lancaster.xtel.co.uk +quipu-bugs:bugs-local lancaster.xtel.co.uk +pp-bugs:bugs-local lancaster.xtel.co.uk + +fax:fax lancaster.xtel.co.uk + +test-list:list lancaster.xtel.co.uk +dev-null:822-local lancaster.xtel.co.uk +activitymonitor:mslocal lancaster.xtel.co.uk diff --git a/examples/xtel/warning.1 b/examples/xtel/warning.1 new file mode 100644 index 0000000..5091b66 --- /dev/null +++ b/examples/xtel/warning.1 @@ -0,0 +1,16 @@ +Your message, + ID $(p1-id) + UA-ID $(ua-id) +has not yet been delivered to the following recipients: + +$(822recips) + +The message is queued for processing on $(locmta). + +Delays are usually created by hosts being down, less often by network +outages. + +Delivery attempts will continue and no action on your part is +required. If the message cannot be delivered in the next $(hours-left) hours +it will be returned to you. + diff --git a/examples/xtel/warning.2 b/examples/xtel/warning.2 new file mode 100644 index 0000000..a45c2da --- /dev/null +++ b/examples/xtel/warning.2 @@ -0,0 +1,15 @@ +Your message, + ID $(p1-id) + UA-ID $(ua-id) +has still not yet been delivered to the following recipients: + +$(822recips) + +The message is queued for processing on $(locmta). + +Delays are usually created by hosts being down, less often by network +outages. + +Delivery attempts will continue and no action on your part is +required. If the message cannot be delivered in the next $(hours-left) hours +it will be returned to you. diff --git a/h/adr.h b/h/adr.h new file mode 100644 index 0000000..95c0c1d --- /dev/null +++ b/h/adr.h @@ -0,0 +1,241 @@ +/* adr.h: address structure definition */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/adr.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: adr.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_ADR +#define _H_ADR + + +#include "list_rchan.h" +#include "extension.h" +#include "mta.h" +#include "aparse.h" +#include + +typedef struct ad_redirection { + struct ad_redirection *rd_next; + char *rd_addr; /* O/R Name */ + char *rd_dn; /* Distinguished Name */ + UTC rd_time; + int rd_reason; +#define RDR_RECIP_ASSIGNED 0 +#define RDR_ORIG_ASSIGNED 1 +#define RDR_MD_ASSIGNED 2 +} Redirection; + +/* Address-types */ + +#define AD_ORIGINATOR 1 +#define AD_RECIPIENT 2 + +typedef struct adr_struct { + int ad_no; /* recipient number */ + /* PP's key to this adr */ + + /* Next 3 parms may be modfiied */ + /* in Q. Fixed text encoding */ + int ad_status; /* recipient status */ +#define AD_STAT_UNKNOWN 0 +#define AD_STAT_PEND 1 +#define AD_STAT_DRREQUIRED 2 /* DR required */ +#define AD_STAT_DRWRITTEN 3 /* DR written */ +#define AD_STAT_DONE 4 + int ad_rcnt; /* reformatters done count */ + + /* -- MTS Service Parms */ + + char *ad_value; /* address-original */ + char *ad_dn; /* Directory Distinguished Name */ + /* QUIPU string encoding */ + + int ad_usrreq; /* user-report-request bit */ +#define AD_USR_NOREPORT 0 +#define AD_USR_BASIC 1 +#define AD_USR_CONFIRM 2 +#define AD_USR_NONE 3 + int ad_explicitconversion; /* explicit conversion */ +#define AD_EXP_NONE -1 +#define AD_EXP_IA5_TEXT_TO_TELETEX 0 +#define AD_EXP_TELETEX_TO_TELEX 1 +#define AD_EXP_TELEX_TO_IA5_TEXT 2 +#define AD_EXP_TELEX_TO_TELETEX 3 +#define AD_EXP_TELEX_TO_G4_CLASS_1 4 +#define AD_EXP_TELEX_TO_VIDEOTEX 5 +#define AD_EXP_IA5_TEXT_TO_TELEX 6 +#define AD_EXP_TELEX_TO_G3_FACSIMILE 7 +#define AD_EXP_IA5_TEXT_TO_G3_FACSIMILE 8 +#define AD_EXP_IA5_TEXT_TO_G4_CLASS_1 9 +#define AD_EXP_IA5_TEXT_TO_VIDEOTEX 10 +#define AD_EXP_TELETEX_TO_IA5_TEXT 11 +#define AD_EXP_TELETEX_TO_G3_FACSIMILE 12 +#define AD_EXP_TELETEX_TO_G4_CLASS_1 13 +#define AD_EXP_TELETEX_TO_VIDEOTEX 14 +#define AD_EXP_VIDEOTEX_TO_TELEX 15 +#define AD_EXP_VIDEOTEX_TO_IA5_TEXT 16 +#define AD_EXP_VIDEOTEX_TO_TELETEX 17 + + int ad_type; /* address-type */ +#define AD_X400_TYPE 1 +#define AD_822_TYPE 2 +#define AD_ANY_TYPE 3 + + char *ad_orig_req_alt; /* originator requested alternate */ + /* recipient - std encoded */ + char ad_orig_req_alt_crit; + +#define AD_RDM_MAX 4 + int ad_req_del[AD_RDM_MAX]; /* requested delivery method */ +#define AD_RDM_NOTUSED -1 +#define AD_RDM_ANY 0 +#define AD_RDM_MHS 1 +#define AD_RDM_PD 2 +#define AD_RDM_TLX 3 +#define AD_RDM_TTX 4 +#define AD_RDM_G3 5 +#define AD_RDM_G4 6 +#define AD_RDM_TTY 7 +#define AD_RDM_VTX 8 + char ad_req_del_crit; + + char ad_phys_forward; /* boolean - is physical */ + /* forwarding allowed */ + char ad_phys_forward_crit; + + char ad_phys_fw_ad_req; + char ad_phys_fw_ad_crit; + /* boolean - request for phys */ + /* foward address */ + + int ad_phys_modes; + char ad_phys_modes_crit; +#define AD_PM_ORD 0x1 +#define AD_PM_SPEC 0x2 +#define AD_PM_EXPR 0x4 +#define AD_PM_CNT 0x8 +#define AD_PM_CNT_PHONE 0x10 +#define AD_PM_CNT_TLX 0x20 +#define AD_PM_CNT_TTX 0x40 +#define AD_PM_CNT_BUREAU 0x80 +#define AD_PM_MAX 0x80 + + int ad_reg_mail_type; + char ad_reg_mail_type_crit; +#define AD_RMT_UNSPECIFIED -1 +#define AD_RMT_NON_REG 0 +#define AD_RMT_REG 1 +#define AD_RMT_PERSON 2 + + char *ad_recip_number_for_advice; + char ad_recip_number_for_advice_crit; + + OID ad_phys_rendition_attribs; + char ad_phys_rendition_attribs_crit; + + int ad_pd_report_request; + char ad_pd_report_request_crit; +#define AD_PRR_UNSPECIFIED -1 +#define AD_PRR_UNDELIV_PDS 0 +#define AD_NTF_PDS 1 +#define AD_NTF_MHS 2 +#define AD_NTF_BOTH 3 + Redirection *ad_redirection_history; + char ad_redirection_history_crit; + + struct qbuf *ad_message_token; + char ad_message_token_crit; + + struct qbuf *ad_content_integrity; + char ad_content_integrity_crit; + + int ad_proof_delivery; + char ad_proof_delivery_crit; + /* boolean. Is proof of delivery */ + /* requested */ + + /* -- MTA Service Params (calculated for MTS AS) */ + + int ad_extension; /* extension-id */ + int ad_resp; /* responsibility bit */ + int ad_mtarreq; /* mta-report-request bit */ +#define AD_MTA_NONE 0 +#define AD_MTA_BASIC 1 +#define AD_MTA_CONFIRM 2 +#define AD_MTA_AUDIT_CONFIRM 3 + + /* -- This may be supplied as a hint but might get changed */ + + int ad_subtype; /* address-subtype */ +#define AD_NOSUBTYPE 0 +#define AD_JNT 1 +#define AD_REAL733 2 +#define AD_REAL822 3 +#define AD_X400_84 4 /* Use this if compatible */ +#define AD_X400_88 5 + + + X400_Extension *ad_per_recip_ext_list; + /* bucket for new and private */ + /* odds and sods */ + + /* -- parameters calculated by PP -- */ + /* -- Note: the outbound mta is held in ad_outchan -- */ + + char *ad_r400adr; /* x400-addr */ + char *ad_r822adr; /* rfc-addr */ + + /* -- should only be set for inbound x400 channels -- */ + char *ad_r400orig; /* original form of x400 address */ + + /* -- next two should only be set for -- */ + /* -- unroutable originator addresses -- */ + char *ad_r400DR; /* x400 address for DRs */ + char *ad_r822DR; /* 822 address for DRs */ + + char *ad_content; /* outgoing content type */ + + LIST_RCHAN *ad_fmtchan; /* reformatting channels */ + LIST_RCHAN *ad_outchan; /* outbound channel structure */ + LIST_BPT *ad_eit; /* outgoing eit's */ + + + /* -- from here onwards extra PP specific info -- */ + /* -- Diagnostics for any address parsing failures -- */ + + int ad_parse_stat; /* address parsing err status */ + char *ad_parse_message; /* address parsing err message */ + int ad_reason; /* DR reason failure */ + int ad_diagnostic; /* DR diagnostic code */ + char *ad_add_info; /* DR supplementary info */ + + Aparse *aparse; /* parsing bucket */ + + /* -- Address Control File offsets for fixed length variables -- */ + + off_t ad_no_offset; /* offset param for recip number */ + off_t ad_stat_offset; /* offset param for recip status */ + off_t ad_rcnt_offset; /* offset param for reformat next */ + + + struct adr_struct *ad_next; +} ADDR; + +#define NULLADDR ((ADDR *)0) + +extern ADDR *adr_new (); +extern void adr_init (); +extern void adr_free (); +extern void adr_tfree (); +extern void adr_add (); +extern void redirection_free (); + +#endif diff --git a/h/alias.h b/h/alias.h new file mode 100644 index 0000000..7901c64 --- /dev/null +++ b/h/alias.h @@ -0,0 +1,35 @@ +/* alias.h: alias structure definition (man page ALIASES(5)) */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/alias.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: alias.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_ALIAS +#define _H_ALIAS + +#define ALIAS_EXTERNAL 3 + +typedef struct alias_struct { + int alias_type; +#define ALIAS_SYNONYM 1 +#define ALIAS_PROPER 2 + char alias_user[LINESIZE]; + int alias_external; + int alias_ad_type; +} ALIAS; + + +#define NULLALIAS ((ALIAS *)0) + + + + +#endif diff --git a/h/ap.h b/h/ap.h new file mode 100644 index 0000000..364e2a7 --- /dev/null +++ b/h/ap.h @@ -0,0 +1,140 @@ +/* ap.h: RFC-822 address parser definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/ap.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: ap.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_AP +#define _H_AP + + +#include "util.h" + + +struct ap_node +{ + char ap_obtype; /* parsing type of this object */ + +#define AP_NIL 0 +#define AP_COMMENT 1 /* comment (...) */ +#define AP_DATA_TYPE 2 /* "data-type" (e.g., :include:...,) */ +#define AP_DOMAIN 3 /* host-part of address */ +#define AP_DOMAIN_LITERAL 4 /* domain literal */ +#define AP_GENERIC_WORD 5 /* generic word */ +#define AP_GROUP_END 6 /* end of group list */ +#define AP_GROUP_NAME 7 /* name of group */ +#define AP_GROUP_START 8 /* start of group address list x:.. ; */ +#define AP_MAILBOX 9 /* mailbox-part of address */ +#define AP_PERSON_END 10 /* end of personal address list */ +#define AP_PERSON_NAME 11 /* name of perrson */ +#define AP_PERSON_START 12 /* start of personal addr list <...> */ + + + char ap_ptrtype; /* next node is continuation of this */ + /* address, start of new, or null */ +#define AP_PTR_NIL 0 /* there is no next node */ +#define AP_PTR_NXT 1 /* next is start of new address */ +#define AP_PTR_MORE 2 /* next is part of this address */ + + char *ap_obvalue; /* ptr to str value of object */ + +/* new fields added for efficiency during parsing */ + int ap_normalised; /* boolean indicate whether domain */ + /* has been normalised */ + int ap_recognised; /* boolean indicate whether domain */ + /* was recognised by normalisation */ + int ap_islocal; /* boolean indicate whether domain */ + /* is local */ + char *ap_localhub; /* name of local hub */ + char *ap_chankey; /* key to use in look up of chan table */ + char *ap_error; /* error from look up */ + struct ap_node *ap_next; /* pointer to next node */ +}; + + + +typedef struct ap_node *AP_ptr; +#define NULLAP ((AP_ptr)0) +#define NULLAPP ((AP_ptr *)0) +#define BADAP ((AP_ptr) -1) + + + +/* +Environment for the address parser +*/ + +#define AP_TYPE_MASK (~0003) + +#define AP_PARSE_SAME 0000 /* do not transorm the address */ +#define AP_PARSE_733 0001 /* follow RFC #733 rules */ +#define AP_PARSE_822 0002 /* follow RFC #822 rules */ +#define AP_PARSE_BIG 0010 /* Use Big-endian domains, FLAG */ + +/* +For use when getting indirect input +*/ + +struct ap_prevstruct +{ + FILE *ap_curfp; /* handle on current file input */ + int (*ap_prvgfunc) (); /* getchar function for that input */ + int ap_opeek; /* with this as peek-ahead char for it*/ + int ap_ogroup; /* nesting level of group list */ + int ap_operson; /* nesting level of personal list */ + struct ap_prevstruct *ap_next; +}; + + + +extern AP_ptr ap_1delete(); +extern AP_ptr ap_add(); +extern AP_ptr ap_alloc(); +extern AP_ptr ap_append(); +extern AP_ptr ap_move(); +extern AP_ptr ap_new(); +extern AP_ptr ap_normalize(); +extern AP_ptr ap_pcur; +extern AP_ptr ap_pinit(); +extern AP_ptr ap_pstrt; +extern AP_ptr ap_s2t(); +extern AP_ptr ap_sqdelete(); +extern AP_ptr ap_sqinsert(); +extern AP_ptr ap_sqmove(); +extern AP_ptr ap_t2p(); +extern AP_ptr ap_t2s(); +extern char ap_llex; +extern char* ap_dmflip(); +extern char* ap_p2s(); +extern char* ap_p2s_nc(); +extern char* ap_s2p(); +extern int ap_1adr(); +extern int ap_dmnormalize(); +extern int ap_flget(); +extern int ap_fpush(); +extern int ap_lex(); +extern int ap_ppush(); +extern void ap_7to8 (); +extern void ap_ninit (); +extern void ap_palloc (); +extern void ap_pfill (); +extern void ap_clear (); +extern void ap_pappend (); +extern void ap_sqtfix (); +extern void ap_insert (); +extern void ap_fllnode (); +extern void ap_free (); +extern void ap_iinit (); +extern void ap_delete (); +extern void ap_pnsrt (); +extern void ap_val2str (); +extern void ap_use_percent(); +#endif diff --git a/h/ap_lex.h b/h/ap_lex.h new file mode 100644 index 0000000..a334494 --- /dev/null +++ b/h/ap_lex.h @@ -0,0 +1,54 @@ +/* ap_lex.h: lexical symbols for address parser */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/ap_lex.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: ap_lex.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_AP_LEX +#define _H_AP_LEX + + +#define LT_EOL 0 /* New-Line */ +#define LT_SPC 0 /* Space and tab */ +#define LT_ERR 1 /* Illegal chars (control chars) */ +#define LT_EOD 2 /* End of Data (null) */ +#define LT_COM 3 /* , */ +#define LT_AT 4 /* @ */ +#define LT_COL 5 /* : */ +#define LT_SEM 6 /* ; */ +#define LT_LES 7 /* < */ +#define LT_GTR 8 /* > */ +#define LT_SQT 9 /* \ (only in quoted strings) */ +#define LT_LTR 10 /* alphabetics, numbers, and others */ +#define LT_XTR 10 /* alphabetics, numbers, and others */ +#define LT_NUM 10 /* alphabetics, numbers, and others */ +#define LT_LPR 11 /* ( */ +#define LT_RPR 12 /* ) */ +#define LT_QOT 13 /* " */ +#define LT_LSQ 14 /* [ */ +#define LT_RSQ 15 /* ] */ + + +#define LV_EOD 0 /* End of Data */ +#define LV_ERROR 1 /* These Values go with the above Types */ +#define LV_COMMA 2 /* , */ +#define LV_AT 3 /* @ */ +#define LV_COLON 4 /* : */ +#define LV_SEMI 5 /* ; */ +#define LV_COMMENT 6 /* (text text text) */ +#define LV_LESS 7 /* < */ +#define LV_GRTR 8 /* > */ +#define LV_WORD 9 /* atom / string */ +#define LV_FROM 10 /* << */ +#define LV_DLIT 11 /* [text text text] */ + + +#endif diff --git a/h/aparse.h b/h/aparse.h new file mode 100644 index 0000000..b4894bb --- /dev/null +++ b/h/aparse.h @@ -0,0 +1,96 @@ +/* aparse.h: holdall structure for various parsing entities for one address */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/aparse.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: aparse.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + +#ifndef _H_APARSE +#define _H_APARSE + +#include "ap.h" +#include "or.h" +#include "chan.h" +#include "auth.h" +#include "list_rchan.h" + +typedef struct _bindings { + LIST_RCHAN *outchan; + LIST_RCHAN *fmtchans; + LIST_BPT *bpts; + int cost; + struct _bindings *next; +} Bindings; + +typedef struct _aliasList { + char *alias; + struct _aliasList *next; +} aliasList; + +typedef struct a_parse { + + int ad_type; + +/*-- rfc 822 entities --*/ + + AP_ptr ap_tree, /* complete tree */ + ap_group, /* start of 822 group */ + ap_name, /* start of 822 name */ + ap_local, /* start of 822 local */ + ap_domain, /* start of 822 domain */ + ap_route; /* start of 822 route */ + + int normalised; /* degree of normalisation done */ +#define APARSE_NORM_NONE 0 +#define APARSE_NORM_NEXTHOP 1 +#define APARSE_NORM_ALL 2 + + int dmnorder; /* order required for domain ordering */ + int full; /* boolean indicating whether to parse fully */ + int percents; /* boolean indicating whether percents */ + /* are recognised as having routing properties */ + + char *r822_str, /* string representation of address */ + *r822_local, /* string representation of local part of address */ + *r822_error; /* error message from 822 parse and validate */ +/*-- x400 entities --*/ + ORName *orname; /* OR tree and DN representation of x400 address */ + OR_ptr lastMatch; /* where we matched to in or table */ + char *x400_dn, /* string representation of DN */ + *x400_str, /* string representation of ORaddress */ + *x400_local, /* string representation of local part of ORaddress */ + *x400_error; /* error message from x400 parse and validate */ +/*-- authorisation related entities --*/ + + AUTH *auth; + +/*-- delivery related entities --*/ + aliasList *aliases; /* list of aliases unwound so far */ + char *local_hub_name; /* name of local hub */ + int recurse_count; /* number of times have recursed */ + int dont_use_aliases; /* whether to use aliases table or not */ + /* set after an external entry */ + int internal; /* used in header address normalisation */ + /* to specify whether to follow external entries */ + + Bindings *channels; /* all possible channels that can */ + /* be used to delivery to the address */ +} Aparse, *Aparse_ptr; + +extern Aparse_ptr aparse_new(); +extern void aparse_rewindr822(); +extern void aparse_rewindx400(); +extern void aparse_rewindlocal(); +extern void aparse_free(); +extern void aparse_copy_for_recursion(); + +extern void aparse_addToAliasList(); +extern int aparse_inAliasList(); +extern void aparse_freeAliasList(); +extern aliasList *aparse_aliasDup(); +#endif diff --git a/h/argh.h b/h/argh.h new file mode 100644 index 0000000..0db32ae --- /dev/null +++ b/h/argh.h @@ -0,0 +1,104 @@ +/* argh.h: Used by the mu program */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/argh.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: argh.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_ARGH +#define _H_ARGH + + + +#define ARGHVER "argh v. 1.1" /* Version number */ +#define MAXARGS 100 /* Maximum argument instances provided for */ +#define MAXFLAGS 50 /* Maximum number of flags + needed to size sorting array argsort[] */ +#define FLAGCHAR '-' /* introduces a flag on command line */ +#define EQUCHAR '=' /* to separate a partial but + unambiguous flag from its value */ +#define MAXFLAGLEN 30 /* max flag length */ +#define VALIDTYPES "0123456789amnz?" /* allowed flag types */ +#define ADJARGS TRUE /* allow adjacent args */ +#define ONECHARARGS FALSE /* allow unambiguous one-byte flags without EQUCHAR */ +#define ZEROCHECK FALSE /* test type '0' against next arg */ + +int flagcount; /* Count from calling-program-specific table */ +int argcpi; /* Current parameter index */ +int argsource; /* Current argument source */ + +void add_link(); +void take_next(); +void arg_error(); +void show_args(); +void call_args(); +void list_args(); +void quick_string(); +void qs_string(); + +int scan_args(); +int prep_args(); +int count_to_flag(); + +char *next_arg(); +char *nextc_arg(); +char *digit_word(); + +struct arginst { /* instance of one argument type */ + char *argcp; /* character pointer */ + int argci; /* argument counter e.g. argv[ai->argci] */ + int argoi; /* offset e.g. argv[ai->argci][ai->argoi] */ + int argn; /* instance in this run */ + int argof; /* ... of total instances in this run */ + int argsrc; /* source - i.e. which call to scan_args */ + int argused; /* used marker TRUE -> has been used */ + struct arginst *next; /* linked list */ +}; + +struct argdef { /* user supplied flag list */ + char *flag; /* see below */ + void (*function)(); + char type; + int match; +}; + +struct argfull { /* argument ( flag ) definitions */ + +/* char flag[MAXFLAGLEN]; character(s) to follow '-' */ + char *flag; /* character(s) to follow '-' */ + + void (*function)(); /* to hold pointer to function */ + + char type; /* a : valued : adjacent to flag + n : valued : next argument + 0 : lone ( no assoc. value ) + 1 : valued : adjacent or next + 2 : as v but takes 2 args + 3 : as v but takes 3 args + ... etc. (up to 9) + m : 1 or more ( up to next flag ) + z : as m but zero args allowed */ + + int match; /* Minimum length for unambiguous + matching. These can be calculated + >0 indicates length to use + 0 indicates calculation reqd. + -1 indicates exact match reqd. + If matching allowed, type a is not. + nor v(adjacent) less than + strlen(flag) unless EQUCHAR used */ + + int length; /* length of flag */ + int count; /* how many instances */ + struct arginst *first,*last; /* pointers to first, last instance */ +}; + + +#endif diff --git a/h/auth.h b/h/auth.h new file mode 100644 index 0000000..90c2d4c --- /dev/null +++ b/h/auth.h @@ -0,0 +1,147 @@ +/* auth.h: authorisation */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/auth.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: auth.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_AUTH +#define _H_AUTH + +#include "list_bpt.h" + + +#define MAX_AUTH_ARGS 100 +#define AUTH_SEPERATOR '|' + + +/* command table values */ +#define AUTH_LOGLEVEL_LOW 1 +#define AUTH_LOGLEVEL_MEDIUM 2 +#define AUTH_LOGLEVEL_HIGH 3 + + +typedef struct list_regex { + char *li_regex; + struct list_regex *li_next; + } LIST_REGEX; + +#define NULLIST_REGEX (LIST_REGEX *)0 + + + +typedef struct list_chan_rights { + CHAN *li_chan; + int li_rights; + struct list_chan_rights *li_next; + } LIST_CHAN_RIGHTS; + +#define NULLIST_CHAN_RIGHTS (LIST_CHAN_RIGHTS *)0 + + + + +typedef struct list_auth_chan { + CHAN *li_chan; + int li_found; + + int policy; +#define AUTH_CHAN_FREE 1 +#define AUTH_CHAN_NEGATIVE 2 +#define AUTH_CHAN_BLOCK 3 +#define AUTH_CHAN_NONE 4 +#define AUTH_CHAN_WARNS 5 +#define AUTH_CHAN_WARNR 6 +#define AUTH_CHAN_SIZELIMIT 7 +#define AUTH_CHAN_TEST 8 + + char *warnsender; + char *warnrecipient; + long sizelimit; + int test; + struct list_auth_chan *li_next; + + } LIST_AUTH_CHAN; + + +#define NULLIST_AUTHCHAN (LIST_AUTH_CHAN *)0 + + + + + +typedef struct list_auth_mta { + char *li_mta; + int li_found; + int rights; + LIST_REGEX *requires; + LIST_REGEX *excludes; + LIST_BPT *content_excludes; + LIST_CHAN_RIGHTS *li_cr; + long sizelimit; + struct list_auth_mta *li_next; + } LIST_AUTH_MTA; + +#define NULLIST_AUTHMTA (LIST_AUTH_MTA *)0 + + + +typedef struct auth_user { + int found; + int rights; + LIST_BPT *content_excludes; + LIST_CHAN_RIGHTS *li_cr; + long sizelimit; + } AUTH_USER; + +#define NULL_AUTHUSR (AUTH_USER *)0 + + + +typedef struct auth { /* holds all details for each channel, mta and user */ + + int status; +#define AUTH_OK 0 +#define AUTH_FAILED 1 +#define AUTH_DR_OK 2 +#define AUTH_DR_FAILED 3 +#define AUTH_FAILED_TEST 4 + + int stage; +#define AUTH_STAGE_1 1 /* stage 1 tests performed */ +#define AUTH_STAGE_2 2 /* stage 2 tests performed */ + + int warnings; +#define AUTH_NOTWARNED 0 /* msg not generated yet */ +#define AUTH_WARNED 1 /* msg has been generated */ +#define AUTH_WARNERROR 2 /* msg could not be generated */ + + char *reason; + + LIST_AUTH_CHAN *chan; + LIST_AUTH_MTA *mta; + AUTH_USER *user; + + + int mta_inrights; + int mta_outrights; + int user_inrights; + int user_outrights; +#define AUTH_RIGHTS_IN 1 +#define AUTH_RIGHTS_OUT 2 +#define AUTH_RIGHTS_BOTH 3 +#define AUTH_RIGHTS_NONE 4 +#define AUTH_RIGHTS_UNSET 5 + + } AUTH; + +#define NULL_AUTH (AUTH *)0 + +#endif diff --git a/h/ch_bind.h b/h/ch_bind.h new file mode 100644 index 0000000..668dbed --- /dev/null +++ b/h/ch_bind.h @@ -0,0 +1,48 @@ +/* ch_bind.h: channel binding types */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/ch_bind.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: ch_bind.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_CH_BIND +#define _H_CH_BIND + +/* SEK - someone must document this !! */ + +typedef struct list { + struct list *li_next; + char *li_name; +} LIST; + +typedef struct { + int m_int; + LIST *m_list; +} MAT; + +typedef struct types { + struct types *ty_next; + int ty_number; + char *ty_name; +} TYPES; + +typedef struct flat { + struct flat *flt_next; + char *flt_name; + char *flt_type; +} FLAT; + +typedef struct fillist { + struct fillist *fil_next; + char *fil_name; + char *fil_from; + char *fil_to; +} FILTER; +#endif diff --git a/h/chan.h b/h/chan.h new file mode 100644 index 0000000..b3dc3b7 --- /dev/null +++ b/h/chan.h @@ -0,0 +1,126 @@ +/* chan.h: the description of a channel structure */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/chan.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: chan.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_CHAN +#define _H_CHAN + +#include "table.h" +#include "list_bpt.h" + + + +#define CH_MAX_SORT 10 + + +typedef struct chan_struct { + char *ch_name; /* channel name */ + char *ch_progname; /* prog name referencing this chan */ + char *ch_show; /* Display field of the chan title */ + LIST_BPT *ch_key; /* The key to this chan */ + + int ch_chan_type; /* What kind of channel is this */ +#define CH_SHAPER 0 +#define CH_IN 1 +#define CH_OUT 2 +#define CH_BOTH 3 +#define CH_WARNING 4 +#define CH_DELETE 5 +#define CH_QMGR_LOAD 6 +#define CH_DEBRIS 7 +#define CH_TIMEOUT 8 +#define CH_POSTMASTER 9 +#define CH_SPLITTER 10 + + char *ch_drchan; /* Channel for DRs */ + + int ch_cost; /* How expensive to run */ + + char ch_sort[CH_MAX_SORT]; /* How to sort the msgs */ +#define CH_SORT_USR 01 +#define CH_SORT_MTA 02 +#define CH_SORT_PRIORITY 03 +#define CH_SORT_TIME 04 +#define CH_SORT_SIZE 05 +#define CH_SORT_NONE 06 + + char *ch_in_info; /* Info locally interpreted by chan */ + char *ch_out_info; /* Info locally interpreted by chan */ + char *ch_content_in; /* Incoming content of a message */ + char *ch_content_out; /* Outgoing content of a message */ + + int ch_in_ad_type; /* Address in types */ + int ch_out_ad_type; /* Address out types */ + int ch_in_ad_subtype; /* Address subtypes */ + /* Used outbound */ + /* on inbound to turn on percentages */ + /* as routing */ + int ch_out_ad_subtype; /* address subtype outbound */ + + int ch_ad_order; /* Ordering of the incoming domain */ + /* for submit to interpret */ +#define CH_USA_ONLY 00 +#define CH_USA_PREF 01 +#define CH_UK_ONLY 02 +#define CH_UK_PREF 03 + + + LIST_BPT *ch_hdr_in; /* Incoming header types */ + LIST_BPT *ch_hdr_out; /* Outgoing header types */ + LIST_BPT *ch_bpt_in; /* Incoming body part types */ + LIST_BPT *ch_bpt_out; /* Outgoing body part types */ + Table *ch_mta_table; /* MTA matching table */ + Table *ch_table; /* outbound table */ + Table *ch_in_table; /* inbound table */ + + Table *ch_auth_tbl; /* Table of authentication stuff */ + char *ch_mta; /* Mta to route through */ + unsigned int + ch_probe:1, /* Does the channel support probes */ + ch_domain_norm:1, /* parse all domains or just next hop */ +#define CH_DOMAIN_NORM_PARTIAL 0 +#define CH_DOMAIN_NORM_ALL 1 + ch_conversion:2, /* what sort of conversion this does */ +#define CH_CONV_NONE 0 +#define CH_CONV_1148 1 +#define CH_CONV_CONVERT 2 +#define CH_CONV_WITHLOSS 3 + ch_access:1, /* The type of channel access */ +#define CH_MTS 00 +#define CH_MTA 01 + ch_trace_type:2, /* Text type of trace for messages */ + /* interpreted by submit */ +#define CH_TRACE_RECEIVED 1 +#define CH_TRACE_VIA 2 +#define CH_TRACE_X400 3 + ch_solo_proc:1, + /* what to do with DRs for unroutable senders */ +#define CH_BADSENDER_STRICT 0 +#define CH_BADSENDER_SLOPPY 1 + ch_badSenderPolicy:2, +#define CH_STRICT_CHECK 0 +#define CH_SLOPPY_CHECK 1 + ch_strict_mode:1; + + int ch_maxproc; /* Max instances of channel qmgr */ + /* can run */ +} CHAN; + + +#define NULLCHAN ((CHAN *)0) + +extern CHAN *ch_nm2struct(); +extern CHAN *ch_mta2struct(); +extern CHAN **ch_all; /* all chans from tailor file */ + +#endif diff --git a/h/charset.h b/h/charset.h new file mode 100644 index 0000000..dbafa3b --- /dev/null +++ b/h/charset.h @@ -0,0 +1,69 @@ +/* charset.h */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/charset.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: charset.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + +#ifndef _H_CHARSET +#define _H_CHARSET + + +/* -***- +The character set conversion filter is written by Keld Simonsen (keld@dkuug.dk). +Please refer to the PP documentation Volume 1 on more information +about its modification. +-***- */ + + + +/* --- the following 3 parameters may need modifying --- */ +typedef unsigned char CHAR8U; /* must be able to hold values 0-255 */ +typedef short int INT16S; /* Must be able to hold 16 bits signed int */ +#define DEFAULT_ESCAPE 29 /* ASCII GS */ + + +#define LOW_LINE 64 /* LOW LINE '_' */ + /* if menmonics are required */ +#define QUESTION_MARK 32 /* QUESTION MARK '?' */ + /* if X.408 conv is required */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FLASE +#define FALSE 0 +#endif + + +#define IN_CH INT16S +#define OUT_CH CHAR8U + + +typedef struct charset CHARSET; +#define C256L 256L +#define C256 256 /* max val of any char encoded as one byte */ +#define LSIZE 256 /* max byte chars on a line, in a file name */ + + +struct charset +{ + CHARSET *next; + INT16S ecma; + char *name; + IN_CH *in; + OUT_CH *out; + INT16S esc; +}; + + +extern CHARSET *getchset(); + +#endif diff --git a/h/dbase.h b/h/dbase.h new file mode 100644 index 0000000..ed72942 --- /dev/null +++ b/h/dbase.h @@ -0,0 +1,73 @@ +/* dbase.h: Definitions for the dbm database */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/dbase.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: dbase.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_DBASE +#define _H_DBASE + +#include "config.h" + +/* most pcc based compilers screw up the return of structures. + * They actually return a pointer to a static struct, which is copied. + * Here is a HACK to get such a pcc version of the library to work with the + * gnu structure returning convention. NB: need a cpp which allows recursive + * definitions (such as gcc) + */ + +#ifdef GDBM +#include "gdbm.h" + +#else +#ifdef NDBM + +#ifndef GCC_DBM_OK +#ifdef __GNUC__ +#define dbm_fetch *dbm_fetch +#define dbm_firstkey *dbm_firstkey +#define dbm_nextkey *dbm_nextkey +#endif /* __GNUC__ */ +#endif /* !GCC_DBM_OK */ + +#include "ndbm.h" + +#else + +#ifndef GCC_DBM_OK +#ifdef __GNUC__ +#define fetch *fetch +#define makdatum *makdatum +#define firstkey *firstkey +#define nextkey *nextkey +#define firsthash *firsthash +#endif /* __GNUC__ */ +#endif /* !GCC_DBM_OK */ + +#include +#endif +#endif + +#define MAXDBENTRIES 32 +#define FS '\034' /* the dbm seperator character */ +#define ENTRYSIZE 1024 /* maximum database entry size */ + + +typedef struct { + char *db_table; + char *db_value; +} + Dbvalue [MAXDBENTRIES], + *Dbptr; + + + +#endif diff --git a/h/dl.h b/h/dl.h new file mode 100644 index 0000000..5bba1f8 --- /dev/null +++ b/h/dl.h @@ -0,0 +1,44 @@ +/* distlist.h: distribution list structure definition */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/dl.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: dl.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_DL +#define _H_DL + +typedef struct namelist_struct { + char *name; + char *file; /* file this name comes from */ + /* NULL => in string name */ + struct namelist_struct *next; +} Name; + +typedef struct distlist_struct { + char *dl_listname, + *dl_desc, + *dl_file; + char *dl_moderator; + Name *dl_uids; /* uids allowed to modify */ + Name *dl_list; +} dl; + + +#define NULLDL ((dl *)0) + +/* list acceess modes */ +#define FREEMODE 0666 +#define PUBMODE 0744 +#define PRIVMODE 0644 +#define SECRMODE 0600 +#define TOPMODE 0000 + +#endif diff --git a/h/dlist.h b/h/dlist.h new file mode 100644 index 0000000..5b8e517 --- /dev/null +++ b/h/dlist.h @@ -0,0 +1,62 @@ +/* dlist.h: */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/dlist.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: dlist.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_DIRLIST_DLIST +#define _H_DIRLIST_DLIST + +#include "util.h" +#include +#include "or.h" +#include "DL-types.h" +#include "MD-types.h" + +typedef struct dl_policy { + char dp_expand; + + int dp_convert; +#define DP_ORIGINAL 1 /* default */ +#define DP_FALSE 2 +#define DP_TRUE 3 + + int dp_priority; +/* #define DP_ORIGINAL 1 */ +#define DP_LOW 2 /* default */ +#define DP_NORMAL 3 +#define DP_HIGH 4 + +} dl_policy; + + + +typedef struct dl_permit { + + int dp_type; +#define DP_INDIVIDUAL 1 +#define DP_MEMBER 2 +#define DP_PATTERN 3 +#define DP_GROUP 4 + + union { + ORName * dp_un_or; + DN dp_un_dn; + } dp_un; + +#define dp_or dp_un.dp_un_or +#define dp_dn dp_un.dp_un_dn + +} dl_permit; + + + +#endif diff --git a/h/dr.h b/h/dr.h new file mode 100644 index 0000000..750c30c --- /dev/null +++ b/h/dr.h @@ -0,0 +1,170 @@ +/* dr.h: delivery report definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/dr.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: dr.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_DR +#define _H_DR +#include "extension.h" +#include "mta.h" + +typedef struct DeliveredInfo { + UTC del_time; + int del_type; +#define DRT_PUBLIC 0 +#define DRT_PRIVATE 1 +#define DRT_MS 2 +#define DRT_DL 3 +#define DRT_PDAU 4 +#define DRT_PHYSICAL_RECIPIENT 5 +#define DRT_OTHER 6 +} Delinfo; + + +typedef struct NonDeliveredInfo { + int nd_rcode; +#define DRR_NO_REASON -1 +#define DRR_TRANSFER_FAILURE 0 +#define DRR_UNABLE_TO_TRANSFER 1 +#define DRR_CONVERSION_NOT_PERFORMED 2 +#define DRR_PHYS_RENDITION_NOT_PERFORMED 3 +#define DRR_PHYS_DELIVERY_NOT_PERFORMED 4 +#define DRR_RESTRICTED_DELIVERY 5 +#define DRR_DIRECTORY_OP_UNSUCCESSFUL 6 + + int nd_dcode; +#define DRD_UNRECOGNISED_OR 0 +#define DRD_AMBIGUOUS_OR 1 +#define DRD_MTA_CONGESTION 2 +#define DRD_LOOP_DETECTED 3 +#define DRD_UA_UNAVAILABLE 4 +#define DRD_MAX_TIME_EXPIRED 5 +#define DRD_ENCINFOTYPES_NOTSUPPORTED 6 +#define DRD_CONTENT_TOO_LONG 7 +#define DRD_CONVERSION_IMPRACTICAL 8 +#define DRD_CONVERSION_PROHIBITED 9 +#define DRD_IMPLICITCONV_NOTREGISTERED 10 +#define DRD_INVALID_PARAMETERS 11 +#define DRD_CONTENT_SYNTAX_ERROR 12 +#define DRD_SIZE_CONSTRAINT_VIOLATION 13 +#define DRD_PROTOCOL_VIOLATION 14 +#define DRD_CONTENT_TYPE_NOT_SUPPORTED 15 +#define DRD_TOO_MANY_RECIPIENTS 16 +#define DRD_NO_BILATERAL_AGREEMENT 17 +#define DRD_UNSUPPORTED_CRITICAL_FUNCTION 18 +#define DRD_CONVERSION_WITH_LOSS_PROHIBITED 19 +#define DRD_LINE_TOO_LONG 20 +#define DRD_PAGE_SPLIT 21 +#define DRD_PICTORIAL_SYMBOL_LOSS 22 +#define DRD_PUNCTUATION_SYMBOL_LOSS 23 +#define DRD_ALPHABETIC_CHARACTER_LOSS 24 +#define DRD_MULTIPLE_INFORMATION_LOSS 25 +#define DRD_RECIPIENT_REASSIGNMENT_PROHIBITED 26 +#define DRD_REDIRECTION_LOOP_DETECTED 27 +#define DRD_DL_EXPANSION_PROHIBITED 28 +#define DRD_NO_DL_SUBMIT_PERMISSION 29 +#define DRD_DL_EXPANSION_FAILURE 30 +#define DRD_PHYSICAL_RENDITION_ATTRIBUTES_NOT_SUPPORTED 31 +#define DRD_UNDLIV_PD_ADDRESS_INCORRECT 32 +#define DRD_UNDLIV_PD_OFFICE_INCORRECT_OR_INVALID 33 +#define DRD_UNDLIV_PD_ADDRESS_INCOMPLETE 34 +#define DRD_UNDLIV_RECIPIENT_UNKNOWN 35 +#define DRD_UNDLIV_RECIPIENT_DECEASED 36 +#define DRD_UNDLIV_ORGANIZATION_EXPIRED 37 +#define DRD_UNDLIV_RECIPIENT_REFUSED_TO_ACCEPT 38 +#define DRD_UNDLIV_RECIPIENT_DID_NOT_CLAIM 39 +#define DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_PERMANENTLY 40 +#define DRD_UNDLIV_RECIPIENT_CHANGED_ADDRESS_TEMPORARILY 41 +#define DRD_UNDLIV_RECIPIENT_CHANGED_TEMPORARY_ADDRESS 42 +#define DRD_UNDLIV_NEW_ADDRESS_UNKNOWN 43 +#define DRD_UNDLIV_RECIPIENT_DID_NOT_WANT_FORWARDING 44 +#define DRD_UNDLIV_ORIGINATOR_PROHIBITED_FORWARDING 45 +#define DRD_SECURE_MESSAGING_ERROR 46 +#define DRD_UNABLE_TO_DOWNGRADE 47 + } NonDelinfo; + + +typedef struct report { + char rep_type; +#define DR_REP_SUCCESS 0 +#define DR_REP_FAILURE 1 + union { + Delinfo rep_dinfo; + NonDelinfo rep_ndinfo; + } rep; + } Report; + + + +typedef struct ReportedRecipientInfo { + struct ReportedRecipientInfo *rr_next; + int rr_recip; /* reference to adr struct */ + Report rr_report; + EncodedIT *rr_converted; + FullName *rr_originally_intended_recip; + char *rr_supplementary; + + Redirection *rr_redirect_history; + char rr_redirect_history_crit; + + FullName *rr_physical_fwd_addr; + char rr_physical_fwd_addr_crit; + + struct qbuf *rr_recip_certificate; + char rr_recip_certificate_crit; + + struct qbuf *rr_report_origin_authentication_check; + char rr_report_origin_authentication_check_crit; + + UTC rr_arrival; + X400_Extension *rr_per_recip_extensions; + } Rrinfo; + + + + /* Originator, MPDU ID, content id */ + /* Content correlator, EITs */ + /* be stored in associated addr */ + /* structure - no repeat */ +typedef struct DeliveryReportMPDU { + MPDUid *dr_mpduid; /* envelope mpdu id */ + Trace *dr_trace; /* envelope trace */ + Trace *dr_subject_intermediate_trace; /* content trace */ + + DLHistory *dr_dl_history; + char dr_dl_history_crit; + + FullName *dr_reporting_dl_name; + char dr_reporting_dl_name_crit; + + struct qbuf *dr_security_label; + char dr_security_label_crit; + + struct qbuf *dr_reporting_mta_certificate; + char dr_reporting_mta_certificate_crit; + + struct qbuf *dr_report_origin_auth_check; + char dr_report_origin_auth_check_crit; + + X400_Extension *dr_per_envelope_extensions; + X400_Extension *dr_per_report_extensions; + Rrinfo *dr_recip_list; +} DRmpdu; + +/* couple of useful defines */ +#define DR_FILENO_DEFAULT 1 + +extern void dr_init (); +extern void dr_free (); +extern void rrinfo_free (); + +#endif diff --git a/h/expand.h b/h/expand.h new file mode 100644 index 0000000..093e837 --- /dev/null +++ b/h/expand.h @@ -0,0 +1,25 @@ +/* expand.h: macro expansion structure */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/expand.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: expand.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_EXPAND +#define _H_EXPAND + +typedef struct Expand { + char *macro; + char *expansion; +} Expand; + +char *expand (); +char *expand_dyn (); +#endif diff --git a/h/extension.h b/h/extension.h new file mode 100644 index 0000000..fb74650 --- /dev/null +++ b/h/extension.h @@ -0,0 +1,139 @@ +/* extension.h: extension attributes */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/extension.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: extension.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_EXTENSION +#define _H_EXTENSION + + +#include + +typedef struct mt_extension { + int ext_int; +#define EXT_OID_FORM -1 + OID ext_oid; + struct qbuf *ext_value; + int ext_criticality; + struct mt_extension *ext_next; +} X400_Extension; + +extern void extensions_free (); + +#define CRITICAL_NONE 0 +#define CRITICAL_SUBMISSION 0x1 +#define CRITICAL_TRANSFER 0x2 +#define CRITICAL_DELIVERY 0x4 + + +#define EXT_RECIPIENT_REASSIGNMENT_PROHIBITED 1 +#define EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC CRITICAL_DELIVERY +#define EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT 2 +#define EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT_DC CRITICAL_NONE +#define EXT_DL_EXPANSION_PROHIBITED 3 +#define EXT_DL_EXPANSION_PROHIBITED_DC CRITICAL_DELIVERY +#define EXT_CONVERSION_WITH_LOSS_PROHIBITED 4 +#define EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC CRITICAL_DELIVERY +#define EXT_LATEST_DELIVERY_TIME 5 +#define EXT_LATEST_DELIVERY_TIME_DC CRITICAL_DELIVERY +#define EXT_REQUESTED_DELIVERY_METHOD 6 +#define EXT_REQUESTED_DELIVERY_METHOD_DC CRITICAL_DELIVERY +#define EXT_PHYSICAL_FORWARDING_PROHIBITED 7 +#define EXT_PHYSICAL_FORWARDING_PROHIBITED_DC CRITICAL_DELIVERY +#define EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST 8 +#define EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC CRITICAL_DELIVERY +#define EXT_PHYSICAL_DELIVERY_MODES 9 +#define EXT_PHYSICAL_DELIVERY_MODES_DC CRITICAL_DELIVERY +#define EXT_REGISTERED_MAIL 10 +#define EXT_REGISTERED_MAIL_DC CRITICAL_DELIVERY +#define EXT_RECIPIENT_NUMBER_FOR_ADVICE 11 +#define EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC CRITICAL_DELIVERY +#define EXT_PHYSICAL_RENDITION_ATTRIBUTES 12 +#define EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC CRITICAL_DELIVERY +#define EXT_ORIGINATOR_RETURN_ADDRESS 13 +#define EXT_ORIGINATOR_RETURN_ADDRESS_DC CRITICAL_DELIVERY +#define EXT_PHYSICAL_DELIVERY_REPORT_REQUEST 14 +#define EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC CRITICAL_DELIVERY +#define EXT_ORIGINATOR_CERTIFICATE 15 +#define EXT_ORIGINATOR_CERTIFICATE_DC CRITICAL_DELIVERY +#define EXT_MESSAGE_TOKEN 16 +#define EXT_MESSAGE_TOKEN_DC CRITICAL_NONE +#define EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER 17 +#define EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC CRITICAL_NONE +#define EXT_CONTENT_INTEGRITY_CHECK 18 +#define EXT_CONTENT_INTEGRITY_CHECK_DC CRITICAL_NONE +#define EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK 19 +#define EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC CRITICAL_DELIVERY +#define EXT_MESSAGE_SECURITY_LABEL 20 +#define EXT_MESSAGE_SECURITY_LABEL_DC CRITICAL_DELIVERY +#define EXT_PROOF_OF_SUBMISSION_REQUEST 21 +#define EXT_PROOF_OF_SUBMISSION_REQUEST_DC CRITICAL_SUBMISSION +#define EXT_FORWARDING_REQUEST 36 +#define EXT_FORWARDING_REQUEST_DC CRITICAL_SUBMISSION +#define EXT_PROOF_OF_DELIVERY_REQUEST 22 +#define EXT_PROOF_OF_DELIVERY_REQUEST_DC CRITICAL_DELIVERY +#define EXT_CONTENT_CORRELATOR 23 +#define EXT_CONTENT_CORRELATOR_DC CRITICAL_NONE +#define EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK 24 +#define EXT_PROBE_ORIGIN_AUTHENTICATION_CHECK_DC CRITICAL_DELIVERY +#define EXT_REDIRECTION_HISTORY 25 +#define EXT_REDIRECTION_HISTORY_DC CRITICAL_NONE +#define EXT_DL_EXPANSION_HISTORY 26 +#define EXT_DL_EXPANSION_HISTORY_DC CRITICAL_NONE +#define EXT_PHYSICAL_FORWARDING_ADDRESS 27 +#define EXT_PHYSICAL_FORWARDING_ADDRESS_DC CRITICAL_NONE +#define EXT_RECIPIENT_CERTIFICATE 28 +#define EXT_RECIPIENT_CERTIFICATE_DC CRITICAL_NONE +#define EXT_PROOF_OF_DELIVERY 29 +#define EXT_PROOF_OF_DELIVERY_DC CRITICAL_NONE +#define EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY 30 +#define EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY_DC CRITICAL_NONE +#define EXT_REPORT_DL_NAME 31 +#define EXT_REPORT_DL_NAME_DC CRITICAL_NONE +#define EXT_REPORTING_MTA_CERTIFICATE 32 +#define EXT_REPORTING_MTA_CERTIFICATE_DC CRITICAL_DELIVERY +#define EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK 33 +#define EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK_DC CRITICAL_DELIVERY +#define EXT_ORIGINATING_MTA_CERTIFICATE 34 +#define EXT_ORIGINATING_MTA_CERTIFICATE_DC CRITICAL_NONE +#define EXT_PROOF_OF_SUBMISSION 35 +#define EXT_PROOF_OF_SUBMISSION_DC CRITICAL_NONE +#define EXT_INTERNAL_TRACE_INFORMATION 38 +#define EXT_INTERNAL_TRACE_INFORMATION_DC CRITICAL_NONE + +/* ADDRESS EXTENSIONS */ + +#define AEXT_CN 1 /* common-name */ +#define AEXT_TTXCN 2 /* teletex-common-name */ +#define AEXT_TTXORG 3 /* teletex-organization */ +#define AEXT_TTXPN 4 /* teletex-personal-name */ +#define AEXT_TTXOU 5 /* teletex-organizational-unit-names */ +#define AEXT_TTXDD 6 /* teletex-domain-defined-attributes */ +#define AEXT_PDSNAME 7 /* pds-name */ +#define AEXT_PDCN 8 /* physical-delivery-country-name */ +#define AEXT_POSTCODE 9 /* postal-code */ +#define AEXT_PDONAME 10 /* physical-delivery-office-name */ +#define AEXT_PDONUMB 11 /* physical-delivery-office-number */ +#define AEXT_ORAC 12 /* extension-OR-address-components */ +#define AEXT_PDPN 13 /* physical-delivery-personal-name */ +#define AEXT_PDORG 14 /* physical-delivery-organization-name */ +#define AEXT_EPDAC 15 /* extension-physical-delivery-address-components */ +#define AEXT_UNFPA 16 /* unformatted-postal-address */ +#define AEXT_STREET 17 /* street-address */ +#define AEXT_POBOX 18 /* post-office-box-address */ +#define AEXT_POSTERES 19 /* poste-restante-address */ +#define AEXT_UNIQPA 20 /* unique-postal-address */ +#define AEXT_LPA 21 /* local-postal-attribute */ +#define AEXT_NETADDR 22 /* extended-network-address */ +#define AEXT_TT 23 /* terminal-type */ + +#endif diff --git a/h/head.h b/h/head.h new file mode 100644 index 0000000..842f1bb --- /dev/null +++ b/h/head.h @@ -0,0 +1,39 @@ +/* head.h: header file */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/head.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: head.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_HEAD +#define _H_HEAD + + +#include "util.h" +#include "retcode.h" + + +/* + * PP - An MTA + * + * Copyright (C) 1989, University College London + Nottingham University + * + * Acquisition, use, and distribution of this module and its listings + * are subject restricted to the terms of a license agreement. + * Documents describing systems using this module must cite its source. + * + * The above statements must be retained with all copies of this + * program and may not be removed without the consent of + * University College London and Nottingham University. + * + */ + + +#endif diff --git a/h/list_bpt.h b/h/list_bpt.h new file mode 100644 index 0000000..89ea64e --- /dev/null +++ b/h/list_bpt.h @@ -0,0 +1,37 @@ +/* list_bpt.h: A definition of a List structure for Body Part Types */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/list_bpt.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: list_bpt.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_LIST_BPT +#define _H_LIST_BPT + + +typedef struct list_bpt { + char *li_name; + struct list_bpt *li_next; +} LIST_BPT; + + + +#define NULLIST_BPT ((LIST_BPT *)0) + + +extern LIST_BPT *list_bpt_dup(); +extern LIST_BPT *list_bpt_find(); +extern LIST_BPT *list_bpt_nfind(); +extern LIST_BPT *list_bpt_malloc(); +extern LIST_BPT *list_bpt_new(); +extern void list_bpt_add (); +extern void list_bpt_free (); + +#endif diff --git a/h/list_rchan.h b/h/list_rchan.h new file mode 100644 index 0000000..db96d52 --- /dev/null +++ b/h/list_rchan.h @@ -0,0 +1,52 @@ +/* list_rchan.h: a definition of a Reformatter Channel List struct */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/list_rchan.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: list_rchan.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_LIST_RCHAN +#define _H_LIST_RCHAN + +#include "chan.h" +#include "auth.h" + +/* +li_mta - is the remote site/mta e.g "stl.stc.co.uk" or "DLCMHS" etc +li_chan - is the channel pointer for that site e.g "PSS" "x400out84" etc + + +Note: + That though this list structure is used both for the reformatting + and the outgoing channels, Only the outgoing channels have the + li_name array set. +*/ + +typedef struct list_rchan { + char *li_mta; /* the MTA */ + CHAN *li_chan; /* the channel its on */ + union { + AUTH *li_un_auth; /* auth stuff used in submit */ + char *li_un_dir; /* the directory associated */ + } list_rchan_un; + struct list_rchan *li_next; /* next in the chain */ +} LIST_RCHAN; +#define li_auth list_rchan_un.li_un_auth +#define li_dir list_rchan_un.li_un_dir + +#define NULLIST_RCHAN ((LIST_RCHAN *)0) + +extern LIST_RCHAN *list_rchan_new(); +extern LIST_RCHAN *list_rchan_malloc(); +extern void list_rchan_free (); +extern int list_rchan_ssite (); +extern int list_rchan_schan (); +extern void list_rchan_add (); +#endif diff --git a/h/ll_log.h b/h/ll_log.h new file mode 100644 index 0000000..d798096 --- /dev/null +++ b/h/ll_log.h @@ -0,0 +1,128 @@ +/* ll_log.h: logging definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/ll_log.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: ll_log.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_LOG_ +#define _H_LOG_ + + + +#include + + +extern LLog *pp_log_norm, + *pp_log_stat, + *pp_log_oper; + + +/* can't leave spaces in macro definitions... PP_LOG ( blows up! */ + +#define PP_LOG(level, args) SLOG (pp_log_norm, level, NULLCP, args) +#define PP_SLOG(level, str, args) \ + SLOG (pp_log_norm, level, str, args) +#define PP_OPER(what, args) if (pp_log_oper -> ll_events & (LLOG_FATAL)) { \ + (void) ll_log (pp_log_oper, LLOG_FATAL, what, "%s", ll_preset args); \ + (void) ll_log (pp_log_norm, LLOG_FATAL, what, "%s", ll_preset args); \ + } \ + else +#define PP_STAT(args) SLOG (pp_log_stat, LLOG_NOTICE, NULLCP, args) +#define PP_NOTICE(args) SLOG(pp_log_norm, LLOG_NOTICE, NULLCP, args) + +/* Tracing of PP PDUS */ +#define PDU_READ (1) +#define PDU_WRITE (0) + +#if PP_DEBUG > 0 + +#ifdef PEPSY_VERSION +#ifdef __STDC__ + +#define PP_PDUP(fnx,pe,text,rw) \ + if (pp_log_norm -> ll_events & LLOG_PDUS) { \ + pvpdu (pp_log_norm, print_##fnx##_P, pe, text, rw); \ +} \ +else + +#define PP_PDU(fnx,pe,text,rw) \ + if (pp_log_norm -> ll_events & LLOG_PDUS) { \ + pvpdu (pp_log_norm, fnx##_P, pe, text, rw); \ +} \ +else + +#else /* !STDC */ + +#define PP_PDUP(fnx,pe,text,rw) \ + if (pp_log_norm -> ll_events & LLOG_PDUS) { \ + pvpdu (pp_log_norm, print_/**/fnx/**/_P, pe, text, rw); \ +} \ +else + +#define PP_PDU(fnx,pe,text,rw) \ + if (pp_log_norm -> ll_events & LLOG_PDUS) { \ + pvpdu (pp_log_norm, fnx/**/_P, pe, text, rw); \ +} \ +else + +#endif /* STDC */ + +#else /* !PEPSY_VERSION */ + +#ifdef __STDC__ + +#define PP_PDUP(fnx,pe,text,rw)\ + if (pp_log_norm -> ll_events & LLOG_PDUS) {\ + vpdu (pp_log_norm, print_##fnx, pe, text, rw);\ +}\ +else + +#else /* !__STDC__ */ + +#define PP_PDUP(fnx,pe,text,rw)\ + if (pp_log_norm -> ll_events & LLOG_PDUS) {\ + vpdu (pp_log_norm, print_/**/fnx, pe, text, rw);\ +}\ +else + +#endif /* __STDC__ */ + +#define PP_PDU(fnx,pe,text,rw) \ + if (pp_log_norm -> ll_events & LLOG_PDUS) { \ + vpdu (pp_log_norm, fnx, pe, text, rw); \ +} \ +else + +#endif /* PEPSY_VERSION */ + +#else /* !DEBUG */ + +#define PP_PDU(fnx,pe,text,rw) +#define PP_PDUP(fnx,pe,text,rw) + +#endif + +/* general PP Tracing */ +#if PP_DEBUG > 0 +#define PP_TRACE(args) SLOG (pp_log_norm, LLOG_TRACE, NULLCP, args) +#else +#define PP_TRACE(args) +#endif + + +/* Low level PP Tracing */ +#if PP_DEBUG > 1 +#define PP_DBG(args) SLOG (pp_log_norm, LLOG_DEBUG, NULLCP, args) +#else +#define PP_DBG(args) +#endif + +#endif diff --git a/h/loc_user.h b/h/loc_user.h new file mode 100644 index 0000000..8f1f468 --- /dev/null +++ b/h/loc_user.h @@ -0,0 +1,42 @@ +/* loc_user.h: information about a local user*/ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/loc_user.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: loc_user.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_LOC_USER +#define _H_LOC_USER + +typedef struct loc_user { + int uid; + int gid; + + char *username; + + char *directory; + char *mailbox; + char *shell; + char *home; + int mailformat; +#define MF_UNIX 1 /* sendmail format */ +#define MF_PP 2 /* pp/mmdf format */ +#define MF_AUTO 3 /* ??? */ + int restricted; + char *mailfilter; + char *sysmailfilter; + char *searchpath; + char *opts; +} LocUser; + +extern LocUser *tb_getlocal (); +extern void free_loc_user (); + +#endif diff --git a/h/mta.h b/h/mta.h new file mode 100644 index 0000000..965b239 --- /dev/null +++ b/h/mta.h @@ -0,0 +1,112 @@ +/* mta.h: various structure definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/mta.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: mta.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_MTA +#define _H_MTA + + +#include "adr.h" +#include "list_bpt.h" +#include + +/* -- MTS papameters */ + +typedef struct GlobalDomainidentifier { + char *global_Country; + char *global_Admin; + char *global_Private; + } GlobalDomId; + +void GlobalDomId_new (); +void GlobalDomId_free (); + +typedef struct MPDUidentifier { + GlobalDomId mpduid_DomId; + char *mpduid_string; + } MPDUid; + +void MPDUid_new (); +void MPDUid_free (); + +typedef struct EncodedInformationTypes { + LIST_BPT *eit_types; /* subset of BodyPartTypes + -- also contains OID's */ + long eit_g3parms; + long eit_tTXparms; + long eit_presentation; +} EncodedIT; + + +/* -- MTA parameters */ + +typedef struct DomainSuppliedInfo { + UTC dsi_time; + UTC dsi_deferred; + int dsi_action; +#define ACTION_RELAYED 0 +#define ACTION_ROUTED 1 + int dsi_other_actions; +#define ACTION_REDIRECTED 0x1 +#define ACTION_EXPANDED 0x2 + EncodedIT dsi_converted; + GlobalDomId dsi_attempted_md; + char *dsi_attempted_mta; +} DomSupInfo; + +void DomSupInfo_free (); + + /* No need to distinguish types of trace in PP */ + /* Just see if MTA is present */ +typedef struct TraceInformation { + char *trace_mta; + GlobalDomId trace_DomId; + DomSupInfo trace_DomSinfo; + struct TraceInformation *trace_next; +} Trace; + +Trace *trace_new (); +Trace *trace_dup(); +void trace_add (); +void trace_free (); + +typedef struct full_name { + char *fn_addr; /* O/R Adress */ + char *fn_dn; /* DN */ +} FullName; + +FullName *fn_new (); +FullName *fn_dup (); +void fn_free (); + +typedef struct dl_history { + struct dl_history *dlh_next; + char *dlh_addr; /* O/R Adress */ + char *dlh_dn; /* DN */ + UTC dlh_time; +} DLHistory; + +DLHistory *dlh_new(); +void dlh_add (); +DLHistory *dlh_dup (); +void dlh_free (); + +typedef struct p3params { + MPDUid mpduid; + UTC submit_time; + char *content_type; + struct qbuf *originating_mta_certificate; + struct qbuf *proof_of_submission; +} P3params; + +#endif diff --git a/h/or.h b/h/or.h new file mode 100644 index 0000000..9ee937c --- /dev/null +++ b/h/or.h @@ -0,0 +1,248 @@ +/* or.h: o/r name package */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/or.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: or.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_OR +#define _H_OR + +#include +#include +#include +/* +Definitions for OR Name structure + +NOTE - that the trees are strucutred with the MOST significant part at the top +*/ + +/* SEK temp notes: + + OR/STD will have a matrix of or_part/valid encodings. + If a Char* is present, this identifies the valid key + + 84/88 distinction will be done as address subtyping. + std2or needs to have a flag to reflect this. + + Needs to be a routine to downgrade addresses 88 -> 84. + First cut can work by discard. +*/ + +/* upperbound on number of organizational units allowed in an address */ +#define MAX_OU 4 + +/* upperbound on number of domain defined attributes allowed in an address */ +#define MAX_DDA 4 + +struct or_part +{ +int or_type; +#define OR_C 1 +#define OR_ADMD 2 +#define OR_PRMD 3 +#define OR_O 4 +#define OR_OU 5 +#define OR_OU1 6 +#define OR_OU2 7 +#define OR_OU3 8 +#define OR_OU4 9 +#define OR_X121 10 +#define OR_TID 11 +#define OR_UAID 12 +#define OR_S 13 +#define OR_G 14 +#define OR_I 15 +#define OR_GQ 16 +#define OR_CN 17 +#define OR_PDSNAME 18 +#define OR_PD_C 19 +#define OR_POSTCODE 20 +#define OR_PDO_NAME 21 +#define OR_PDO_NUM 22 +#define OR_OR_COMPS 23 +#define OR_PD_PN 24 +#define OR_PD_O 25 +#define OR_PD_COMPS 26 +#define OR_UPA_PA 27 +#define OR_STREET 28 +#define OR_PO_BOX 29 +#define OR_PRA 30 +#define OR_UPN 31 +#define OR_LPA 32 +#define OR_ENA_N 33 +#define OR_ENA_S 34 +#define OR_ENA_P 35 +#define OR_TT 36 +#define OR_DD 99 +int or_encoding; +#define OR_ENC_PS 1 +#define OR_ENC_TTX 2 +#define OR_ENC_NUM 3 +#define OR_ENC_TTX_AND_OR_PS 4 /* use 987 string encoding */ +#define OR_ENC_INT 5 +#define OR_ENC_PSAP 6 /* ISODE/SEK string form */ +#define OR_ENC_PP 7 /* internal PP encoding used for */ + /* missing OR components in rfc1148 */ + /* conversion tables */ +char *or_ddname; +char *or_value; +struct or_part *or_prev; +struct or_part *or_next; +}; + +#define or_or2rfc(a,b) or_or2rfc_aux ((a), (b), 0) /* backwards compat */ +#define or_rfc2or(a,b) or_rfc2or_aux ((a), (b), 1) + +#define OR_ISLOCAL 01 +#define OR_ISMTA 02 + +#define CHR_PS 01 /* Printable String */ +#define CHR_NS 02 /* Numeric String */ + +typedef struct or_part *OR_ptr; + +#define NULLOR ((OR_ptr)0) + +typedef struct ORName { + OR_ptr on_or; + DN on_dn; +} ORName; + +#define NULLORName ((ORName *) 0) + +ORName *pe2orn (); +ORName *orname2orn (); +OR_ptr oradr2ora (); +PE orn2pe (); +PE orname2pe (); +OR_ptr pe2ora (); +PE ora2pe (); +PE oradr2pe (); +void ORName_free (); + +extern char _pstable[]; + +#define or_isps(c) (_pstable[c]&CHR_PS) +#define or_isns(c) (_pstable[c]&CHR_NS) + +typedef struct tpstruct { + char *ty_string; + int ty_int; + int ty_charset; +} typestruct; + +typedef struct or_upperbound { + int or_type; + int or_upperbound; +/* 0 == not valid, -1 == no upperbound */ +} OR_upperbound; + +/* upperbounds as defined in x.411 */ +#define OR_UB_C_ALPHA 2 +#define OR_UB_C_NUM 3 +#define OR_UB_MD 16 +#define OR_UB_O 64 +#define OR_UB_OU 32 +#define OR_UB_X121 15 +#define OR_UB_TID 24 +#define OR_UB_UAID 32 +#define OR_UB_S 40 +#define OR_UB_G 16 +#define OR_UB_I 5 +#define OR_UB_GQ 3 +#define OR_UB_CN 64 +#define OR_UB_PDSNAME 16 +#define OR_UB_PDS_PARAM 30 +#define OR_UB_POSTCODE 16 +#define OR_UB_OR_COMPS 256 +#define OR_UB_UPA_PA 180 +#define OR_UB_ENA_N 15 +#define OR_UB_ENA_S 40 +#define OR_UB_INT_OPTS 246 +#define OR_UB_DDA_VALUE 128 +#define OR_UB_DDA_TYPE 8 + +extern typestruct typetab[]; +extern typestruct typetab88[]; + +/* valid DD's */ +#define OR_DDVALID_RFC822 1 +#define OR_DDVALID_JNT 2 +#define OR_DDVALID_UUCP 3 +#define OR_DDVALID_LIST 4 +#define OR_DDVALID_ROLE 5 +#define OR_DDVALID_FAX 6 +#define OR_DDVALID_ATTN 7 +#define OR_DDVALID_X40088 8 + +/* forms of address */ +#define OR_FORM_NONE 0 +#define OR_FORM_MNEM 1 +#define OR_FORM_NUMR 2 +#define OR_FORM_POST 3 +#define OR_FORM_TERM 4 + +extern CMD_TABLE ortbl_ddvalid[]; +extern OR_ptr loc_ortree; + +extern OR_ptr pe2or(); /* convert PE to OR struct */ +extern PE or2pe(); /* convert OR struct to PE */ +extern OR_ptr or_add(); /* add or_part to place in tree */ +extern OR_ptr or_add_t61 (); /* add in a T61 address attribute */ +extern OR_ptr or_default(); /* add def vals to partial OR Name */ +extern OR_ptr or_default_aux(); /* add given vals to partial OR Name */ +extern OR_ptr or_dmn2or(); /* OR dmn string -> structure */ +extern OR_ptr or_dup(); /* duplicate or_part */ +extern OR_ptr or_tdup(); /* duplicate or tree */ +extern OR_ptr or_find(); /* find or_part of type in tree */ +extern OR_ptr or_lastpart(); /* point to last component */ +extern OR_ptr or_locate(); /* find 1st part of any component */ +extern OR_ptr or_new(); /* create and fill new or_part */ +extern OR_ptr or_new_aux(); /* create and fill new or_part */ +extern OR_ptr or_std2or(); /* OR std string -> structure */ +extern char *or_value(); /* find a type and return it's val */ +extern char* or_type2name(); /* get string of part type */ +extern int or_cmp(); /* test if two or_parts are equal */ +extern void or_free(); /* free structure recursively */ +extern int or_init(); /* various global inits */ +extern void or_myinit(); /* various global inits */ +extern int or_name2type(); /* get type of string */ +extern void or_or2dmn(); /* structure to OR dmn string */ +extern int or_or2rfc_aux (); +extern int or_rfc2or_aux (); /* map 822 form to tree */ +extern void or_or2std(); /* structure to OR std string */ +extern int or_utilinit(); /* various global inits */ +extern int or_blank (); +extern OR_ptr or_buildpn (); /* construct a personal name */ +extern int or_getpn (); +extern void qstrcat (); +extern void dstrcat (); +extern void or_myinit (); +extern void or_t61encode (); +extern struct qbuf *or_t61decode (); +extern int or_ddname_chk (); +extern int or_ddvalid_chk (); +extern int or_gettoken (); +extern int or_isdomsyntax (); +extern void or_ps2asc (); +extern void or_downgrade(); /* downgrades 88 to 84 */ +extern int or_or2rbits (); +extern int rfc_space (); +extern int or_domain2or(); +extern int or_local2or(); +extern int or_asc2ps (); +extern int or_append (); +extern struct qbuf *or_getps (); +extern struct qbuf *or_getttx (); +extern void or_chk_admd (); +extern int or_check_upper(); +extern int or_chk_ubs(); +#endif diff --git a/h/ppp.h b/h/ppp.h new file mode 100644 index 0000000..124f7de --- /dev/null +++ b/h/ppp.h @@ -0,0 +1,30 @@ +/* ppp.h: ppp interface */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/ppp.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: ppp.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_PPP +#define _H_PPP + +#define PPP_STATUS_DONE 1 +#define PPP_STATUS_CONNECT_FAILED 2 +#define PPP_STATUS_PERMANENT_FAILURE 3 +#define PPP_STATUS_TRANSIENT_FAILURE 4 + +int ppp_init (); +int ppp_getnextmessage (); +int ppp_getdata (); +int ppp_status (); +void ppp_terminate (); + + +#endif diff --git a/h/prm.h b/h/prm.h new file mode 100644 index 0000000..cb8c733 --- /dev/null +++ b/h/prm.h @@ -0,0 +1,39 @@ +/* prm.h: submit parameter structure */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/prm.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: prm.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_PRM +#define _H_PRM + + +/* +When talking to submit this is the initial structure that is passed down. +All the work should be done by mm_winit() to which is passed the relevent +structure +*/ + +struct prm_vars { + char *prm_logfile; /* log file */ + int prm_loglevel; /* level of logging */ + int prm_opts; /* various options*/ +/* prm_opts is a bit field: (more to follow) */ +#define PRM_OPTS_TOTAL 2 +#define PRM_NONE 0x0 +#define PRM_ACCEPTALL 0x1 +#define PRM_NOTRACE 0x2 + char *prm_passwd; +}; + +extern void prm_init (); +extern void prm_free (); +#endif diff --git a/h/q.h b/h/q.h new file mode 100644 index 0000000..a5058e2 --- /dev/null +++ b/h/q.h @@ -0,0 +1,134 @@ +/* q.h - The QUEUE/ADDR Control File structure */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/q.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: q.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_Q +#define _H_Q + + +#include "adr.h" +#include "mta.h" + +typedef struct Qstruct { + + int msgtype; /* Type of message */ +#define MT_UMPDU 1 +#define MT_DMPDU 2 +#define MT_PMPDU 3 + +/* -- MTS Parameters */ + + long msgsize; /* Size of message */ + UTC defertime; /* Deffered time */ + UTC latest_time; + char latest_time_crit; + + char nwarns; /* Number of warning msgs to send */ + int warninterval; /* Interval between warning msgs */ + int retinterval; /* Interval after which return mail */ + char *cont_type; /* Content type of message */ + EncodedIT orig_encodedinfo; /* Original Encoded Info Types */ + int priority; /* Priority of message */ +#define PRIO_NORMAL 0 +#define PRIO_NONURGENT 1 +#define PRIO_URGENT 2 + + char disclose_recips; + char implicit_conversion_prohibited; + char alternate_recip_allowed; + char content_return_request; + + char recip_reassign_prohibited; + char recip_reassign_crit; + + char dl_expansion_prohibited; + char dl_expansion_crit; + + char conversion_with_loss_prohibited; + char conversion_with_loss_crit; + + char *ua_id; /* UA content id */ + char *pp_content_correlator; + /* PP preferred string form */ + struct qbuf *general_content_correlator; + char content_correlator_crit; + /* ASN.1 uninterpreted */ + + FullName *originator_return_address; + char originator_return_address_crit; + + int forwarding_request; + char forwarding_request_crit; + + struct qbuf *originator_certificate; + char originator_certificate_crit; + + struct qbuf *algorithm_identifier; + char algorithm_identifier_crit; + /* content confidentiality */ + + struct qbuf *message_origin_auth_check; + /* also for Probe */ + char message_origin_auth_check_crit; + + struct qbuf *security_label; + char security_label_crit; + + int proof_of_submission_request; /* boolean */ + char proof_of_submission_crit; + + X400_Extension *per_message_extensions; + + + + ADDR *Oaddress; /* Orig addr - linked list */ + ADDR *Raddress; /* Recip addrs - linked list */ + + + +/* -- MTA AS Parameters */ + + LIST_RCHAN *inbound; /* Inbound MTA/Channel */ + MPDUid msgid; /* Message ID */ + Trace *trace; /* Trace info */ + DLHistory *dl_expansion_history; + char dl_expansion_history_crit; + + + +/* -- PP calculated parameters */ + + EncodedIT encodedinfo; /* Encoded information types */ + UTC queuetime; /* Time that message was enqueued */ + UTC departime; /* Time that message left the queue */ + int n_bodyparts; + int n_forwarded; + + /* -- Queue Control File offsets for fixed length variables -- */ + + off_t nwarns_offset; /* offset param for nwarns */ +} Q_struct; + +extern void q_init (); +extern void q_free (); +extern void encodedinfo_free (); +extern void MPDUid_free (); + +#define RDMSG_RDONLY 1 +#define RDMSG_RDONLYLCK 2 +#define RDMSG_RDWR 3 + + +#define rd_msg(file,prm,que,sndr,recip,rcount) \ + rd_msg_file((file),(prm),(que),(sndr),(recip),(rcount),RDMSG_RDWR) +#endif diff --git a/h/qmgr-int.h b/h/qmgr-int.h new file mode 100644 index 0000000..9746ba5 --- /dev/null +++ b/h/qmgr-int.h @@ -0,0 +1,188 @@ +/* qmgr-int.h: interface to qmgr for consoles */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/qmgr-int.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: qmgr-int.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + +typedef struct bindResult { + int access; +#define FULL_ACCESS 1 +#define LIMITED_ACCESS 2 + + char *info; + char *version; +} BindResult; +void free_BindResult (); + +typedef struct qmgrStatus { + time_t boottime; + int messagesIn; + int messagesOut; + int addrIn; + int addrOut; + int opsPerSec; + int runnableChans; + int msgsInPerSec; + int msgsOutPerSec; + int maxChans; + int currChans; + int totalMsgs; + int totalVolume; + int totalDRs; +} QmgrStatus; + +#define free_QmgrStatus(x) free((char *)x) + +typedef struct procStatus { + char enabled; /* boolean TRUE or FALSE */ + time_t lastAttempt, + cachedUntil, + lastSuccess; +} ProcStatus; + +extern ProcStatus *convert_ProcStatus(); +#define free_ProcStatus(x) free((char *)x) + +typedef struct channelinfo_struct { + struct channelinfo_struct *next; + + int priority; + + char *channelname, + *channeldescrip; + time_t oldestMessage; + int numberMessages; + int volumeMessages; + int numberActiveProcesses; + ProcStatus *status; + int numberReports; + + int inbound; + int outbound; + + int chantype; + + int maxprocs; + int numberMtas; +} ChannelInfo; + +typedef struct mtainfo_struct { + struct mtainfo_struct *next; + + int priority; + + char *channel; + char *mta; + time_t oldestMessage; + int numberMessages; + int volumeMessages; + ProcStatus *status; + int numberReports; + int active; + char *info; +} MtaInfo; + +typedef struct strlist_struct { + struct strlist_struct *next; + + char *str; +} Strlist; + + +typedef struct recipinfo_struct { + struct recipinfo_struct *next; + + char *user; + int id; + char *mta; + Strlist *channels; + int channelsDone; + ProcStatus *status; + char *info; +} RecipInfo; + +typedef struct permsginfo_struct { + char *qid; + + /* mpduid */ + char *country; + char *admd; + char *prmd; + char *local; + + char *originator; + char *contenttype; + Strlist *eits; + int priority; + int size; + time_t age; + int warnInterval; + int numberWarningsSent; + time_t expiryTime; + time_t deferredTime; + char *uaContentId; + int errorCount; + char *inChannel; +} PerMessageInfo; + +typedef struct msginfo_struct { + struct msginfo_struct *next; + + PerMessageInfo *permsginfo; + + RecipInfo *recips; +} MsgInfo; + +typedef struct msglist_struct { + MsgInfo *msgs; + Strlist *deleted; +} MsgList; + + +typedef struct measureInfo { + struct measureInfo *next; + + char *key; + double ub_number, + ub_volume, + ub_age, + ub_last; +} MeasureInfo; + +#define CTRL_ENABLE "enable" +#define CTRL_DISABLE "disable" +#define CTRL_CACHECLEAR "cacheclear" +#define CTRL_CACHEADD "cacheadd" + +#define QCTRL_ABORT "abort" +#define QCTRL_GRACEFUL "graceful" +#define QCTRL_RESTART "restart" +#define QCTRL_REREAD "reread" +#define QCTRL_DISSUB "disablesubmission" +#define QCTRL_ENASUB "enablesubmission" +#define QCTRL_DISALL "disableall" +#define QCTRL_ENAALL "anableall" +#define QCTRL_INCMAX "increasemax" +#define QCTRL_DECMAX "decreasemax" + +#define QFILTER_CONTENT "contenttype" +#define QFILTER_EIT "eits" +#define QFILTER_PRIO "priority" +#define QFILTER_MORERECENT "morerecentthan" +#define QFILTER_EARLIER "earlierthan" +#define QFILTER_MAXSIZE "maxsize" +#define QFILTER_ORIG "originator" +#define QFILTER_RECIP "recipient" +#define QFILTER_CHANNEL "channel" +#define QFILTER_MTA "mta" +#define QFILTER_QUEUEID "queueid" +#define QFILTER_MPDU "mpduidentifier" +#define QFILTER_UA "uacontentid" + +extern time_t convert_time (); diff --git a/h/qmgr.h b/h/qmgr.h new file mode 100644 index 0000000..e147d3f --- /dev/null +++ b/h/qmgr.h @@ -0,0 +1,43 @@ +/* qmgr.h: basic qmgr library definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/qmgr.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: qmgr.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_QMGR_DEFS +#define _H_QMGR_DEFS + +#include "Qmgr-types.h" +#include "Qmgr-ops.h" + +extern struct type_Qmgr_DeliveryStatus *deliverystate; + +extern struct type_Qmgr_DeliveryStatus *delivery_setstate (), + *delivery_init (), + *delivery_setallstate (); + +#define delivery_set(x,y) delivery_setstate((x),(y),NULLCP) +#define delivery_setall(x) delivery_setallstate ((x), NULLCP) + + +#define CHANNEL_CTX_OID "0.9.2342.60200172.200.1" +#define CHANNEL_PCI_OID "0.9.2342.60200172.200.2" +#define QMGR_CTX_OID "0.9.2342.60200172.201.1" +#define QMGR_PCI_OID "0.9.2342.60200172.201.2" + +#define CHANNEL_AC str2oid(CHANNEL_CTX_OID) +#define CHANNEL_PCI str2oid(CHANNEL_PCI_OID) +#define QMGR_AC str2oid(QMGR_CTX_OID) +#define QMGR_PCI str2oid(QMGR_PCI_OID) + +extern char *dap_user, *dap_passwd; + +#endif diff --git a/h/retcode.h b/h/retcode.h new file mode 100644 index 0000000..dc9e729 --- /dev/null +++ b/h/retcode.h @@ -0,0 +1,250 @@ +/* retcode.h: reply & status codes used throughout pp */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/retcode.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: retcode.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_RETCODE +#define _H_RETCODE + + + +/* +------------------------------------------------------------------------------ + + Reply Codes for PP + + Based on: "Revised FTP Reply Codes", by Jon Postel & Nancy Neigus Arpanet + RFC 640 / NIC 30843, in the "Arpanet Protocol Handbook", E. Feinler + and J. Postel (eds.), NIC 7104, Network Information Center, SRI + International: Menlo Park, CA. (NTIS AD-A0038901) + + Basic format: + + 0yz: positive completion; entire action done + 1yz: positive intermediate; only part done + 2yz: Transient negative completion; may work later + 3yz: Permanent negative completion; you lose forever + + x0z: syntax + x1z: general; doesn't fit any other category + x2z: connections; truly transfer-related + x3z: user/authentication/account + x4x: mail + x5z: file system + + 3-bit z field is unique to the reply. In the following, + the RP_xVAL defines are available for masking to obtain a field. + +------------------------------------------------------------------------------ +*/ + + +/* ++++++++++++++ Field Definitions & Basic Values +++++++++++++++++++++ */ + + +/* +Field 1: Basic degree of success (2-bits) +*/ + +#define RP_BTYP 0200 /* good vs. bad; on => bad */ + +#define RP_BVAL 0300 /* basic degree of success */ + +#define RP_BOK 0000 /* went fine; all done */ +#define RP_BPOK 0100 /* only the first part got done */ +#define RP_BTNO 0200 /* temporary failure; try later */ +#define RP_BNO 0300 /* not now, nor never; you lose */ + + +/* +Field 2: Basic domain of discourse (3-bits) +*/ + +#define RP_CVAL 0070 /* basic category (domain) of reply */ + +#define RP_CSYN 0000 /* purely a matter of form */ +#define RP_CGEN 0010 /* couldn't find place for it */ +#define RP_CCON 0020 /* data-transfer-related issue */ +#define RP_CUSR 0030 /* pertaining to the user */ +#define RP_CMAI 0040 /* specific to mail semantics */ +#define RP_CFIL 0050 /* file system */ +#define RP_CLIO 0060 /* local i/o system */ + +/* +Field 3: Specific value for this reply (3-bits) +*/ + +#define RP_SVAL 0007 /* specific value of reply */ + + +/* ++++++++++++++++++++ Specific Success Values ++++++++++++++++++++++++ */ + + +/* +Complete Success +*/ + +#define RP_DONE (RP_BOK | RP_CGEN | 0000) + /* done (e.g., w/transaction) */ +#define RP_OK (RP_BOK | RP_CGEN | 0001) + /* general-purpose OK */ +#define RP_MOK (RP_BOK | RP_CMAI | 0000) + /* message is accepted (w/text) */ +#define RP_DOK (RP_BOK | RP_CGEN | 0003) + /* accepted for the delayed submission channel */ + + +/* +Partial Success +*/ + +#define RP_MAST (RP_BPOK| RP_CGEN | 0000) + /* you are the requestor */ +#define RP_SLAV (RP_BPOK| RP_CGEN | 0001) + /* you are the requestee */ +#define RP_AOK (RP_BPOK| RP_CMAI | 0000) + /* message address is accepted */ +#define RP_HOK (RP_BPOK| RP_CMAI | 0001) + /* host processing completed */ + + +/* ++++++++++++++++++++ Specific Failure Values ++++++++++++++++++++++++ */ + + +/* +Partial Failure +*/ + +#define RP_AGN (RP_BTNO | RP_CGEN | 0000) + /* not now; maybe later */ +#define RP_TIME (RP_BTNO | RP_CGEN | 0001) + /* timeout */ +#define RP_NOOP (RP_BTNO | RP_CGEN | 0002) + /* no-op; nothing done, this time */ +#define RP_EOF (RP_BTNO | RP_CGEN | 0003) + /* encountered an end of file */ +#define RP_NET (RP_BTNO | RP_CCON | 0000) + /* channel went bad */ +#define RP_BHST (RP_BTNO | RP_CCON | 0001) + /* foreign host screwed up */ +#define RP_DHST (RP_BTNO | RP_CCON | 0002) + /* host went away */ +#define RP_NIO (RP_BTNO | RP_CCON | 0004) + /* general net i/o problem */ +#define RP_NS (RP_BTNO | RP_CCON | 0005) + /* temporary nameserver failure */ +#define RP_FIO (RP_BTNO | RP_CFIL | 0000) + /* error reading/writing file */ +#define RP_FCRT (RP_BTNO | RP_CFIL | 0001) + /* unable to create file */ +#define RP_FOPN (RP_BTNO | RP_CFIL | 0002) + /* unable to open file */ +#define RP_LIO (RP_BTNO | RP_CLIO | 0000) + /* general local i/o problem */ +#define RP_LOCK (RP_BTNO | RP_CLIO | 0001) + /* resource currently locked */ + + +/* +Complete Failure +*/ + +#define RP_MECH (RP_BNO | RP_CGEN | 0000) + /* bad mechanism/path; try alternate? */ +#define RP_NO (RP_BNO | RP_CGEN | 0001) + /* general-purpose NO */ +#define RP_BAD (RP_BNO | RP_CGEN | 0002) + /* another general purpose NO */ +#define RP_PROT (RP_BNO | RP_CCON | 0000) + /* general prototocol error */ +#define RP_RPLY (RP_BNO | RP_CCON | 0001) + /* bad reply code (PERMANENT ERROR) */ +#define RP_NAUTH (RP_BNO | RP_CUSR | 0001) + /* bad authorisation */ + /* SEK this will be used for user checks*/ +#define RP_NDEL (RP_BNO | RP_CMAI | 0000) + /* couldn't deliver */ +#define RP_HUH (RP_BNO | RP_CSYN | 0000) + /* couldn't parse the request */ +#define RP_NCMD (RP_BNO | RP_CSYN | 0001) + /* no such command defined */ +#define RP_PARM (RP_BNO | RP_CSYN | 0002) + /* bad parameter */ +#define RP_UCMD (RP_BNO | RP_CSYN | 0003) + /* command not implemented */ +#define RP_PARSE (RP_BNO| RP_CSYN | 0004) + /* address parse error */ +#define RP_USER (RP_BNO | RP_CUSR | 0000) + /* unknown user */ + + +/* +Structure of a Reply String +*/ + + +struct rp_construct /* for constant reply conditions */ +{ + unsigned char rp_cval; + char rp_cline[50]; +}; + + +struct rp_bufstruct /* for reading reply strings */ +{ + unsigned char rp_val; + char rp_line[256]; +}; + + +typedef struct rp_bufstruct RP_Buf; + +#define rp_conlen(bufnam) (strlen (bufnam.rp_cline) + sizeof (bufnam.rp_cval)) + + + +/* +Pseudo-functions to access reply info +*/ + +#define rp_gval(val) ((val) & 0377) + /* get the value of the return code */ +/* +The next three give the field's bits, within the whole value +*/ + +#define rp_gbval(val) ((val) & RP_BVAL) + /* get the basic part of return value */ +#define rp_gcval(val) ((val) & RP_CVAL) + /* get the domain part of value */ +#define rp_gsval(val) ((val) & RP_SVAL) + /* get the specific part of value */ + +/* +The next three give the numeric value withing the field +*/ + +#define rp_gbbit(val) (((val) >> 6) & 03) + /* get the basic part right-shifted */ +#define rp_gcbit(val) (((val) >> 3 ) & 07) + /* get the domain part right-shifted */ +#define rp_gsbit(val) ((val) & 07) + /* get the specific part right-shifted */ +#define rp_isgood(val) (! rp_isbad(val)) + /* is return value positive? */ +#define rp_isbad(val) ((val) & 0200) + /* is return value negative? */ + +extern char *rp_valstr (); + + +#endif diff --git a/h/rtsparams.h b/h/rtsparams.h new file mode 100644 index 0000000..74386c1 --- /dev/null +++ b/h/rtsparams.h @@ -0,0 +1,53 @@ +/* RtsParams.h: RTS parameter structures */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/rtsparams.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: rtsparams.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_RTSPARAMS +#define _H_RTSPARAMS + +typedef struct RtsParams { + char *their_name; + char *their_passwd; + char *their_internal_ppname; + char *their_address; + + char *our_name; + char *our_passwd; + char *our_address; + + char *md_info; + char *try_next; + + char *info_mode; + char *info_undefined; + + int rts_mode; + + int type; +#define RTSP_1984 1 +#define RTSP_1988_X410MODE 2 +#define RTSP_1988_NORMAL 3 + + int trace_type; +#define RTSP_TRACE_ADMD 1 +#define RTSP_TRACE_NOINT 2 +#define RTSP_TRACE_LOCALINT 3 +#define RTSP_TRACE_ALL 4 + char *fix_orig; +} RtsParams; + + +RtsParams *tb_rtsparams(); +void RPfree(); + +#endif diff --git a/h/sys.file.h b/h/sys.file.h new file mode 100644 index 0000000..3195f65 --- /dev/null +++ b/h/sys.file.h @@ -0,0 +1,47 @@ +/* sys.file.h - system independent sys/file.h */ + +/* + * $Header: /xtel/pp/pp-beta/h/RCS/sys.file.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * + * $Log: sys.file.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + +#ifndef _PP_SYS_FILE_H +#define _PP_SYS_FILE_H + +#if ISODE > 68 + +#include + +#else + +#include +#include "util.h" + +/* Beware the ordering is important to aviod symbol clashes */ + +#ifndef SVR4_UCB +#include +#endif + +#ifdef BSD42 +#include +#else +#ifdef SYS5 +#include +#else +#include +#endif +#endif + +#ifdef SYS5 +#include +#endif + +#endif +#endif diff --git a/h/table.h b/h/table.h new file mode 100644 index 0000000..8c4af3c --- /dev/null +++ b/h/table.h @@ -0,0 +1,55 @@ +/* table.h: table structures */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/table.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: table.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TABLE +#define _H_TABLE + + +/* +Information kept for all tables +*/ + +typedef struct TableOverride { + char *tbo_key; + char *tbo_value; + struct TableOverride *tbo_next; +} TableOverride; + +typedef struct tb_struct { + char *tb_name; /* internal name of table */ + char *tb_show; /* displayable human-oriented string */ + char *tb_file; /* name of file containing table */ + FILE *tb_fp; /* stdio file pointer */ + int tb_flags; /* various bits (type of table, etc) */ + TableOverride *tb_override; + /* overridden tables */ +} Table; + + +#define NULLTBL ((Table *)0) + +#define TB_SRCMASK 07 +#define TB_SRC(x) ((x) & TB_SRCMASK) /* Source of table data */ +#define TB_DBM 01 /* Read from DBM database */ +#define TB_NS 02 /* Read from Nameserver */ +#define TB_LINEAR 04 /* Read from linear file */ + + +extern Table *tb_nm2struct(); +extern Table **tb_all; +extern int tb_getdomain (); +extern int tb_k2val (); +extern int tb_dbmk2val (); +extern int tab_fetch (); +#endif diff --git a/h/tb_a.h b/h/tb_a.h new file mode 100644 index 0000000..7d32b22 --- /dev/null +++ b/h/tb_a.h @@ -0,0 +1,77 @@ +/* tb_a.h: definitions used for I/O Address Lines in queues */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_a.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_a.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_A +#define _H_TB_A + + + + +/* Address-Lines */ + +#define AD_822 1 +#define AD_ADDTYPE 2 +#define AD_DR_NO 3 +#define AD_END 4 +#define AD_EXPLICITCONVERSION 5 +#define AD_EXTENSION_ID 6 +#define AD_MTA_REP_REQ 7 +#define AD_ORIG 8 +#define AD_OUTCHAN 9 +#define AD_OUTHOST 10 +#define AD_RECIP_NO 11 +#define AD_REFORM_LIST 12 +#define AD_REFORM_DONE 13 +#define AD_RESPONSIBILITY 14 +#define AD_STATUS 15 +#define AD_SUBTYPE 16 +#define AD_USR_REP_REQ 17 +#define AD_X400 18 +#define AD_CONTENT 19 +#define AD_EITS 20 +#define AD_DN 21 +#define AD_ORIG_REQ_ALT 22 +#define AD_ORIG_REQ_ALT_CRIT 23 +#define AD_PHYS_FORWARD 24 +#define AD_PHYS_FORWARD_CRIT 25 +#define AD_PHYS_FW_AD 26 +#define AD_PHYS_FW_AD_CRIT 27 +#define AD_PHYS_MODES 28 +#define AD_PHYS_MODES_CRIT 29 +#define AD_REG_MAIL 30 +#define AD_REG_MAIL_CRIT 31 +#define AD_RECIP_NUMBER_ADVICE 32 +#define AD_RECIP_NUMBER_ADVICE_CRIT 33 +#define AD_PHYS_RENDITION 34 +#define AD_PHYS_RENDITION_CRIT 35 +#define AD_PD_REPORT_REQUEST 36 +#define AD_PD_REPORT_REQUEST_CRIT 37 +#define AD_REDIRECTION_HISTORY 38 +#define AD_REDIRECTION_HISTORY_CRIT 39 +#define AD_MESSAGE_TOKEN 40 +#define AD_MESSAGE_TOKEN_CRIT 41 +#define AD_CONTENT_INTEGRITY 42 +#define AD_CONTENT_INTEGRITY_CRIT 43 +#define AD_PROOF_DELIVERY 44 +#define AD_PROOF_DELIVERY_CRIT 45 +#define AD_EXTENSION 46 +#define AD_REQ_DEL 47 +#define AD_REQ_DEL_CRIT 48 +#undef AD_AEXT +#define AD_X400DR 50 +#define AD_822DR 51 +#define AD_X400ORIG 52 +/* ------------------------------------------------------------------------ */ + +#endif diff --git a/h/tb_auth.h b/h/tb_auth.h new file mode 100644 index 0000000..969089d --- /dev/null +++ b/h/tb_auth.h @@ -0,0 +1,33 @@ +/* tb_auth.h: auth definitions of tables used by submit*/ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_auth.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_auth.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_AUTH +#define _H_TB_AUTH + +#define AUR_UNKNOWN 1 +#define AUR_CH_NONE 2 +#define AUR_CH_FREE 3 +#define AUR_IMTA_MISSING_SNDR 4 +#define AUR_IMTA_EXCLUDES_SNDR 5 +#define AUR_OMTA_MISSING_RECIP 6 +#define AUR_OMTA_EXCLUDES_RECIP 7 +#define AUR_MSGSIZE_FOR_CHAN 8 +#define AUR_MSGSIZE_FOR_MTA 9 +#define AUR_MSGSIZE_FOR_USR 10 +#define AUR_MTA_BPT 11 +#define AUR_USR_BPT 12 +#define AUR_CHBIND 13 +#define AUR_DUPLICATE_REMOVED 14 + +#endif diff --git a/h/tb_bpt84.h b/h/tb_bpt84.h new file mode 100644 index 0000000..885cdf7 --- /dev/null +++ b/h/tb_bpt84.h @@ -0,0 +1,45 @@ +/* tb_bpt84.h: Body part definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_bpt84.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_bpt84.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_BP +#define _H_TB_BP + + +/* -- Unique Body Part types -- */ + +#define BPT_HDR_P2 20 +#define BPT_HDR_822 21 + +#define BPT_ODIF 22 + +#define BPT_P2_DLIV_TXT 23 + +#define BPT_HDR_IPN 24 + +/* -- Repeated Body Part types -- */ + +#define BPT_UNDEFINED -1 +#define BPT_IA5 0 +#define BPT_TLX 1 +#define BPT_VOICE 2 +#define BPT_G3FAX 3 +#define BPT_TIF0 4 +#define BPT_TTX 5 +#define BPT_VIDEOTEX 6 +#define BPT_NATIONAL 7 +#define BPT_ENCRYPTED 8 +#define BPT_IPM 9 +#define BPT_SFD 10 +#define BPT_TIF1 11 +#endif diff --git a/h/tb_bpt88.h b/h/tb_bpt88.h new file mode 100644 index 0000000..6658bf1 --- /dev/null +++ b/h/tb_bpt88.h @@ -0,0 +1,48 @@ +/* tb_bpt88.h: Body part definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_bpt88.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_bpt88.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_BP +#define _H_TB_BP + + +/* -- Unique Body Part types -- */ + +#define BPT_HDR_P2 20 +#define BPT_HDR_822 21 + +#define BPT_P2_DLIV_TXT 23 + +#define BPT_HDR_IPN 24 +#define BPT_HDR_P22 25 + +/* -- Repeated Body Part types -- */ + +#define BPT_UNDEFINED -1 +#define BPT_IA5 0 +#define BPT_TLX 1 +#define BPT_VOICE 2 +#define BPT_G3FAX 3 +#define BPT_TIF0 4 +#define BPT_TTX 5 +#define BPT_VIDEOTEX 6 +#define BPT_NATIONAL 7 +#define BPT_ENCRYPTED 8 +#define BPT_IPM 9 +#define BPT_SFD 10 +#define BPT_TIF1 11 +#define BPT_ODIF 12 +#define BPT_ISO6937TEXT 13 +#define BPT_BILATERAL 14 +#define BPT_EXTERNAL 15 +#endif diff --git a/h/tb_com.h b/h/tb_com.h new file mode 100644 index 0000000..b490b67 --- /dev/null +++ b/h/tb_com.h @@ -0,0 +1,33 @@ +/* tb_com.h: common definitions used in the tb_tables ... */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_com.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_com.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_COMM +#define _H_TB_COMM + + +extern char* Bf_put(); +extern char* Bf_app(); + +/* +Used in sequencing +*/ + +#define EOU -9 +#define EOB -99 +#define EOUNIT "End-of-unit" +#define EOBLOCK "End-of-block" +#define EMPTY "empty" + + +#endif diff --git a/h/tb_dr.h b/h/tb_dr.h new file mode 100644 index 0000000..05d3ccc --- /dev/null +++ b/h/tb_dr.h @@ -0,0 +1,48 @@ +/* tb_dr.h: definitions used in I/O for Delivery Reports */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_dr.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_dr.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_DR +#define _H_TB_DR + +#define DR_MSGID 1 +#define DR_TRACE 2 +#define DR_SI_TRACE 3 +#define DR_DL_EXP_HIST 4 +#define DR_DL_EXP_HIST_CRIT 5 +#define DR_REPORTING_DL_NAME 6 +#define DR_SECURITY_LABEL 7 +#define DR_REPORTING_MTA_CERTIFICATE 8 +#define DR_REPORT_ORIGIN_AUTH_CHECK 9 +#define DR_PER_ENVELOPE_EXTENSIONS 10 +#define DR_PER_REPORT_EXTENSIONS 11 +#define DR_END_HDR 12 +#define DR_END 13 + +#define RR_RECIP 1 +#define RR_SUCCESS 2 +#define RR_FAILURE 3 +#define RR_CONVERTED 4 +#define RR_ORIGINALLY_INTENDED_RECIP 5 +#define RR_SUPPLEMENTARY 6 +#define RR_REDIRECT_HISTORY 7 +#define RR_REDIRECT_HISTORY_CRIT 8 +#define RR_PHYSICAL_FWD 9 +#define RR_RECIP_CERTIFICATE 10 +#define RR_REPORT_ORIGIN_CHECK 11 +#define RR_ARRIVAL 12 +#define RR_PER_RECIP_EXTENSIONS 13 +#define RR_END_RECIP 14 +#define RR_END 15 + +#endif diff --git a/h/tb_p1.h b/h/tb_p1.h new file mode 100644 index 0000000..e6e139c --- /dev/null +++ b/h/tb_p1.h @@ -0,0 +1,56 @@ +/* tb_p1.h: definitions used in I/O Queue Lines */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_p1.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_p1.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_P1 +#define _H_TB_P1 + + +/* MsgId */ +#define MPDUID_STRING 1 + +/* Trace */ +#define TRACE_MTA 1 + + +/* GlobalId */ +#define GLOBAL_COUNTRY 1 +#define GLOBAL_ADMIN 2 +#define GLOBAL_PRIVATE 3 + + +/* DomainSuppliedInfo */ +#define DSI_TIME 1 +#define DSI_DEFERRED 2 +#define DSI_ACTION 3 +#define DSI_CONVERTED 4 +#define DSI_ATTEMPTED 5 + + +/* DomainSuppliedInfo - Action */ +#define ACTION_RELAYED 0 +#define ACTION_ROUTED 1 + + +/* EncodedInformationTypes - Set */ +#define EI_BIT_STRING 1 +#define EI_G3NONBASIC 2 +#define EI_TELETEXNONBASIC 3 +#define EI_PRESENTATION 4 + + +/* EncodedInformationTypes - Bit string */ +#define EI_TOTAL 10 + + +#endif diff --git a/h/tb_p3prm.h b/h/tb_p3prm.h new file mode 100644 index 0000000..8d6efe2 --- /dev/null +++ b/h/tb_p3prm.h @@ -0,0 +1,26 @@ +/* tb_p3p.h: submit return information */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_p3prm.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_p3prm.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_P3PRM +#define _H_TB_P3PRM + + +#define P3PRM_MPDUID 1 +#define P3PRM_STIME 2 +#define P3PRM_CONTENT 3 +#define P3PRM_ORIG_MTA_CERT 4 +#define P3PRM_PROOF_OF_SUB 5 +#define P3PRM_END 6 + +#endif diff --git a/h/tb_prm.h b/h/tb_prm.h new file mode 100644 index 0000000..140c359 --- /dev/null +++ b/h/tb_prm.h @@ -0,0 +1,26 @@ +/* prm.h: submit parameter structure definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_prm.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_prm.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_PRM +#define _H_TB_PRM + + +#define PRM_LOGFILE 1 +#define PRM_LOGLEVEL 2 +#define PRM_OPTS 3 +#define PRM_PASSWD 4 +#define PRM_END 5 + + +#endif diff --git a/h/tb_q.h b/h/tb_q.h new file mode 100644 index 0000000..b794eff --- /dev/null +++ b/h/tb_q.h @@ -0,0 +1,59 @@ +/* tb_q.h: definitions used for I/O QUEUE/ADDR Control Files */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tb_q.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tb_q.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TB_Q +#define _H_TB_Q + + +/* MessageEnvelopeParameters */ +#define Q_MSGTYPE 1 +#define Q_MSGSIZE 2 +#define Q_QUEUETIME 3 +#define Q_DEPARTIME 4 +#define Q_DEFERREDTIME 5 +#define Q_INCHANNEL 6 +#define Q_INHOST 7 +#define Q_NWARNS 8 +#define Q_WARNINTERVAL 9 +#define Q_RETINTERVAL 10 +#define Q_CONTENT_TYPE 11 +#define Q_ENCODED_INFO 12 +#define Q_PRIORITY 13 +#define Q_UA_ID 14 +#define Q_MSGID 16 +#define Q_TRACE 17 +#define Q_DISCLOSE_RECIPS 18 +#define Q_IMPICIT_CONVERSION 19 +#define Q_ALTERNATE_RECIP_ALLOWED 20 +#define Q_CONTENT_RETURN_REQUEST 21 +#define Q_LATESTTIME 22 +#define Q_RECIP_REASSIGN_PROHIBITED 23 +#define Q_DL_EXP_PROHIBITIED 24 +#define Q_PP_CONT_CORR 25 +#define Q_GEN_CONT_CORR 26 +#define Q_END 27 +#define Q_IMPLICIT_CONVERSION 28 +#define Q_CONV_WITH_LOSS 29 +#define Q_ORIG_RETURN_ADDRESS 30 +#define Q_FORWARDING_REQUEST 31 +#define Q_ORIGINATOR_CERT 32 +#define Q_ALGORITHM_ID 33 +#define Q_MESSAGE_ORIGIN_AUTH_CHECK 34 +#define Q_SECURITY_LABEL 35 +#define Q_PROOF_OF_SUB 36 +#define Q_MESSAGE_EXTENSIONS 37 +#define Q_DL_EXP_HISTORY 38 +#define Q_DL_EXP_HIST_CRIT 39 +#define Q_ORIG_ENCODED_INFO 40 +#endif diff --git a/h/tjoin.h b/h/tjoin.h new file mode 100644 index 0000000..9bf9f48 --- /dev/null +++ b/h/tjoin.h @@ -0,0 +1,77 @@ +/* tjoin.h: used to build the PP tables */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/tjoin.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: tjoin.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_TJOIN +#define _H_TJOIN + +#include /* for bzero */ + + +#define LOADS 1000 +#define STRINGSTORESIZE 1000 +#define MTASTORESIZE 1000 +#define CHANSTORESIZE 1000 + +typedef struct print { + struct print *pr_next; + int pr_cost; + char *pr_chan; + char *pr_nexthop; + char pr_relay [LOADS]; + } PRINT; + +typedef struct string { + struct string *str_next; + int str_index; + char str_buffer [STRINGSTORESIZE]; + } SBUFF; + +typedef struct chan { + struct chan *ch_next; + union { + struct chan *chan; + struct mta *mta; + char *name; + } ch; + } CHAN; + +typedef struct mta { + char *mta_name; + struct mta *mta_left; + struct mta *mta_right; + struct chan *mta_chan; + struct chan *mta_arlist; + struct chan *mta_domain; + } MTA; + +typedef struct mtst { /* MTA Store */ + struct mtst *mts_next; + int mts_index; + MTA mts_buffer [MTASTORESIZE]; + } MTST; + +typedef struct chst { /* CHAN Store */ + struct chst *chs_next; + int chs_index; + CHAN chs_buffer [CHANSTORESIZE]; + } CHST; + +typedef struct host { + struct host *hst_next; + char *hst_name; + CHAN *hst_chan; + } HOST; + + +#endif diff --git a/h/util.h b/h/util.h new file mode 100644 index 0000000..51c8615 --- /dev/null +++ b/h/util.h @@ -0,0 +1,190 @@ +/* util.h: various useful utility definitions */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/util.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: util.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + + + +#ifndef _H_UTIL +#define _H_UTIL + + +/* -- various common defines -- */ + + +#include /* -- minus the ctype stuff -- */ +#include +#include +#include +#include +#include "config.h" +#include "ll_log.h" + +#define PP 60 + +/* -- declarations that should have been in the system files -- */ + +#ifdef SVR4 + +#include +#include + +#else +#include +#endif + +extern char *multcat (); +extern char *multcpy (); +extern char *smalloc (); + +/* -- some common logical values -- */ + + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef YES +#define YES 1 +#endif + +#ifndef NO +#define NO 0 +#endif + +#ifndef OK +#define OK 0 +#endif + +#ifndef DONE +#define DONE 1 +#endif + +#ifndef NOTOK +#define NOTOK -1 +#endif + +#ifndef MORE +#define MORE 2 +#endif + +#ifndef MAYBE +#define MAYBE 1 +#endif + + +/* -- stdio extensions -- */ + +#ifndef lowtoup +#define lowtoup(chr) (islower (chr) ? toupper (chr) : chr) +#endif + +#ifndef uptolow +#define uptolow(chr) (isupper (chr) ? tolower (chr) : chr) +#endif + +#ifndef MIN +#define MIN(a,b) (( (b) < (a) ) ? (b) : (a) ) +#endif + +#ifndef MAX +#define MAX(a,b) (( (b) > (a) ) ? (b) : (a) ) +#endif + +#ifndef isstr +#define isstr(ptr) ((ptr) != 0 && *(ptr) != '\0') +#endif +#ifndef isnull +#define isnull(chr) ((chr) == '\0') +#endif + + + +/* -- provide a timeout facility -- */ + + +extern jmp_buf _timeobuf; + +#ifndef timeout +#define timeout(val) (setjmp(_timeobuf) ? 1 : (_timeout(val), 0)) +#endif + + +/* -- some common extensions -- */ + +#ifndef LINESIZE +#define LINESIZE 512 /* -- max line length -- */ +#endif + +#ifndef FILNSIZE +#ifdef MAXNAMLEN +#define FILNSIZE MAXNAMLEN +#else +#define FILNSIZE 256 /* -- max filename length -- */ +#endif +#endif + +#ifndef MAXPATHLENGTH +#ifdef MAXPATHLEN +#define MAXPATHLENGTH MAXPATHLEN +#else +#define MAXPATHLENGTH 1024 +#endif +#endif + +#ifndef MAXFORK +#define MAXFORK 10 /* -- no. of times to try a fork() -- */ +#endif + +#ifndef NULLCP +#define NULLCP ((char *)0) +#define NULLVP ((char **)0) +#endif + +#ifndef NULLFILE +#define NULLFILE ((FILE *)0) +#endif + +/* utctime stuff */ + +extern UTC time_t2utc (); +extern time_t utc2time_t (); +extern UTC utcdup (); +extern UTC utcnow (); + +#define LOCK_FLOCK 0 +#define LOCK_FCNTL 1 +#define LOCK_FILE 2 +#define LOCK_LOCKF 3 + +extern FILE *flckopen (); +extern int flckclose (); + +/* tailoring */ +#define TAI_NONE 0000 +#define TAI_LOGS 0001 +#define TAI_SIGNALS 0002 +#define TAI_ALL (TAI_LOGS|TAI_SIGNALS) + +#ifdef SYS5 +#define killpg(pid,sig) kill(-(pid), (sig)) +#endif + +#ifndef HAS_FSYNC +#if defined(BSD42) || defined(SVR4) +#define HAS_FSYNC +#endif +#endif + +#endif diff --git a/h/x400_ub.h b/h/x400_ub.h new file mode 100644 index 0000000..403d121 --- /dev/null +++ b/h/x400_ub.h @@ -0,0 +1,69 @@ +/* x400_ub.h: X.400 upper bounds on things */ + +/* + * @(#) $Header: /xtel/pp/pp-beta/h/RCS/x400_ub.h,v 6.0 1991/12/18 20:42:44 jpo Rel $ + * + * $Log: x400_ub.h,v $ + * Revision 6.0 1991/12/18 20:42:44 jpo + * Release 6.0 + * + * + */ + +#define UB_INTEGER_OPTIONS 256 +#define UB_QUEUE_SIZE 2147483647 +#define UB_CONTENT_LENGTH 2147483647 +#define UB_PASSWORD_LENGTH 62 +#define UB_BIT_OPTIONS 16 +#define UB_CONTENT_TYPES 1024 +#define UB_TSAP_ID_LENGTH 16 +#define UB_RECIPIENTS 32767 +#define UB_CONTENT_ID_LENGTH 16 +#define UB_X121_ADDRESS_LENGTH 15 +#define UB_MTS_USER_TYPES 256 +#define UB_REASON_CODES 32767 +#define UB_DIAGNOSTIC_CODES 32767 +#define UB_SUPPLEMENTARY_INFO_LENGTH 256 +#define UB_EXTENSION_TYPES 256 +#define UB_RECIPIENT_NUMBER_FOR_ADVICE_LENGTH 32 +#define UB_CONTENT_CORRELATOR_LENGTH 512 +#define UB_REDIRECTIONS 512 +#define UB_DL_EXPANSIONS 512 +#define UB_BUILT_IN_CONTENT_TYPE 32767 +#define UB_LOCAL_ID_LENGTH 32 +#define UB_MTA_NAME_LENGTH 32 +#define UB_COUNTRY_NAME_NUMERIC_LENGTH 3 +#define UB_COUNTRY_NAME_ALPHA_LENGTH 2 +#define UB_DOMAIN_NAME_LENGTH 16 +#define UB_TERMINAL_ID_LENGTH 24 +#define UB_ORGANIZATION_NAME_LENGTH 64 +#define UB_NUMERIC_USER_ID_LENGTH 32 +#define UB_SURNAME_LENGTH 40 +#define UB_GIVEN_NAME_LENGTH 16 +#define UB_INITIALS_LENGTH 5 +#define UB_GENERATION_QUALIFIER_LENGTH 3 +#define UB_ORGANIZATIONAL_UNITS 4 +#define UB_ORGANIZATIONAL_UNIT_NAME_LENGTH 32 +#define UB_DOMAIN_DEFINED_ATTRIBUTES 4 +#define UB_DOMAIN_DEFINED_ATTRIBUTE_TYPE_LENGTH 8 +#define UB_DOMAIN_DEFINED_ATTRIBUTE_VALUE_LENGTH 128 +#define UB_EXTENSION_ATTRIBUTES 256 +#define UB_COMMON_NAME_LENGTH 64 +#define UB_PDS_NAME_LENGTH 16 +#define UB_POSTAL_CODE_LENGTH 16 +#define UB_PDS_PARAMETER_LENGTH 30 +#define UB_PDS_PHYSICAL_ADDRESS_LINES 6 +#define UB_UNFORMATTED_ADDRESS_LENGTH 180 +#define UB_E163_4_NUMBER_LENGTH 15 +#define UB_E163_4_SUB_ADDRESS_LENGTH 40 +#define UB_BUILT_IN_ENCODED_INFORMATION_TYPES 32 +#define UB_TELETEX_PRIVATE_USE_LENGTH 128 +#define UB_ENCODED_INFORMATION_TYPES 1024 +#define UB_SECURITY_LABELS 256 +#define UB_LABELS_AND_REDIRECTIONS 256 +#define UB_SECURITY_PROBLEMS 256 +#define UB_PRIVACY_MARK_LENGTH 128 +#define UB_SECURITY_CATEGORIES 64 +#define UB_TRANSFERS 512 +#define UB_BILATERAL_INFO 1024 +#define UB_ADDITIONAL_INFO 1024 diff --git a/make b/make new file mode 100755 index 0000000..ad41e2e --- /dev/null +++ b/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f Make.defs -f Makefile ${1+"$@"} diff --git a/man/Makefile b/man/Makefile new file mode 100644 index 0000000..ac9c9ac --- /dev/null +++ b/man/Makefile @@ -0,0 +1,46 @@ +# Manual page installation +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/man/RCS/Makefile,v 6.0 1991/12/18 20:43:36 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:43:36 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +SUBDIRS = man1 man3 man8 + + +############################################################ +# +# Building Rules +# +############################################################ + +default: + @for i in $(SUBDIRS); \ + do (echo "cd $$i; $(MAKE)"; cd $$i; $(MAKE) );\ + done + +install clean tidy: + @for i in $(SUBDIRS); \ + do (echo "cd $$i; $(MAKE) $@"; cd $$i; $(MAKE) $@);\ + done +lint:; + +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/man/inst-man.sh b/man/inst-man.sh new file mode 100755 index 0000000..eafdbb2 --- /dev/null +++ b/man/inst-man.sh @@ -0,0 +1,166 @@ +: run this script through /bin/sh + +# for a non standard base directory, set MANDIR + +# set MANOPTS in config/CONFIG.make -- may be one of: +# -bsd42 man/ +# -bsd44 cat/thing.0 +# -ros man/ -- using /etc/install +# -sys5 _man/man/ +# -aix _man/man/ +# -local manl/.l +# -l man/.l +# -hpux hpux + +BINDIR="/usr/local/bin/" +ETCDIR="/usr/local/etc/" +INCDIR="/usr/local/include/isode//" +LOGDIR="/usr/tmp/" +SBINDIR="/usr/local/etc/" + +M=BSD42 +if [ -f /usr/bin/make ]; then + MANDIR=${MANDIR-${INSTDIR}/usr/share/man} +else + MANDIR=${MANDIR-${INSTDIR}/usr/man} +fi + +if test ! -d ${MANDIR} +then + echo "inst-man: ${MANDIR} non-existant directory" 1>&2 + exit 0 +fi + +for A in $* +do + case $A in + -bsd42) M=BSD42 + ;; + + -bsd44) M=BSD44 + ;; + + -ros) M=ROS + ;; + + -local) M=LOCAL + ;; + + -l) M=L + ;; + + -sys5) M=SYS5 + ;; + + -aix) M=AIX + ;; + + -hpux) M=HPUX + ;; + + -*) echo "inst-man: $A unknown" 1>&2 + exit 1 + ;; + + *) if test ! -f $A + then + exit 0 + fi + F=`basename $A` + E=`echo $F | sed -e "s%^.*\.\([1-8]\).*%\1%"` + + X=/tmp/$F + rm -f $X + cat $A >> $X + + case $M in + BSD42) + echo install -m 0644 -c $X ${MANDIR}/man$E/$F + install -m 0644 -c $X ${MANDIR}/man$E/$F + ;; + + BSD44) + echo "nroff -man $X > ${MANDIR}/cat$E/$F" | \ + sed -e 's%\.\([1-8]\)[1-8cn]*$%.0%' | \ + sh -ve + ;; + + LOCAL) + (cd /tmp ; \ + echo $F | \ + sed -e "s%.*%install -m 0644 -c & ${MANDIR}/manl/&%" | \ + sed -e 's%\.[1-8cn]*$%.l%' | \ + sh -ve) + ;; + + L) + (cd /tmp ; \ + echo "install -m 0644 -c $F ${MANDIR}/man$E/$F" | \ + sed -e 's%\.\([1-8]\)[1-8cn]*$%.\1l%' | \ + sh -ve) + ;; + + SYS5|AIX) + case $E in + 3) D=p_man ;; + 5) D=p_man E=4 ;; + 8) D=a_man E=1 ;; + *) D=u_man ;; + esac + echo /etc/install -m 0644 -f ${MANDIR}/$D/man$E $X + /etc/install -m 0644 -f ${MANDIR}/$D/man$E $X + case $D in + a_man) + F=`basename $A .8c`.1m + echo mv ${MANDIR}/$D/man$E/$A \ + ${MANDIR}/$D/man$E/$F + mv ${MANDIR}/$D/man$E/$A ${MANDIR}/$D/man$E/$F + ;; + + p_man) + if [ "$E" = "4" ]; then + F=`basename $A .5`.4 + echo mv ${MANDIR}/$D/man$E/$A \ + ${MANDIR}/$D/man$E/$F + mv ${MANDIR}/$D/man$E/$A \ + ${MANDIR}/$D/man$E/$F + fi + ;; + esac + ;; + + HPUX) + case $E in + 5) E=4 ;; + 8) E=1m ;; + esac + echo /etc/install -m 0644 -f ${MANDIR}/man$E $X + /etc/install -m 0644 -f ${MANDIR}/man$E $X + case $E in + 4) F=`basename $A .5`.4 + echo mv ${MANDIR}/man$E/$A ${MANDIR}/man$E/$F + mv ${MANDIR}/man$E/$A ${MANDIR}/man$E/$F + ;; + + 1m) F=`basename $A .8c`.1m + echo mv ${MANDIR}/man$E/$A ${MANDIR}/man$E/$F + mv ${MANDIR}/man$E/$A ${MANDIR}/man$E/$F + ;; + esac + ;; + + ROS) + echo /etc/install -m 0644 -c $X ${MANDIR}/man$E/$F + /etc/install -m 0644 -c $X ${MANDIR}/man$E/$F + ;; + + *) echo "inst-man: mode botch" 1>&2 + exit 1 + ;; + esac + rm -f $X + ;; + esac +done + +exit 0 diff --git a/man/make b/man/make new file mode 100755 index 0000000..78e7e36 --- /dev/null +++ b/man/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../Make.defs -f Makefile ${1+"$@"} diff --git a/man/man1/Makefile b/man/man1/Makefile new file mode 100644 index 0000000..641b305 --- /dev/null +++ b/man/man1/Makefile @@ -0,0 +1,56 @@ +# Manual page installation (section 1) +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/Makefile,v 6.0 1991/12/18 20:43:41 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:43:41 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +MANUALS = ckmail.1 \ + ckmf.1 \ + dl.1 \ + flagmail.1 \ + flock.1 \ + mail.1 \ + malias.1 \ + mlist.1 \ + ntail.1 \ + rcvtrip.1 \ + resend.1 \ + strip_addr.1 \ + ttyalert.1 \ + ttybiff.1 \ + xalert.1 + + +############################################################ +# +# Building Rules +# +############################################################ + +default:; + +install:; MANDIR=$(MANDIR) ../inst-man.sh $(MANOPTS) $(MANUALS) + +clean:; +tidy:; +lint:; +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/man/man1/ckmail.1 b/man/man1/ckmail.1 new file mode 100644 index 0000000..d32ac0a --- /dev/null +++ b/man/man1/ckmail.1 @@ -0,0 +1,36 @@ +.TH CHECKMAIL 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/ckmail.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: ckmail.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +checkmail \- message status checkup tool +.SH SYNOPSIS +.in +.5i +.ti -.5i +checkmail +\%[-a] \%[-h mtaname] +.in -.5i +.SH DESCRIPTION +The +.I checkmail +program is used to query local and remote mtas about the status of +messages related to the user. +.PP +\fIcheckmail\fP responds to the following flags: +.TP +\-a +This flag prompts \fIcheckmail\fP to enquire about messages to and +from the user. By default, \fIcheckmail\fP only enquires about +messages from the user. +.TP +\-h mtaname +This flags prompts \fIcheckmail\fP to connect to the named mta. +By default, \fIcheckmail\fP attempts to connect to an mta running on +the local machine. +.SH "SEE ALSO" +\fIThe PP Manual: Volume 3 \- Users Guide\fP diff --git a/man/man1/ckmf.1 b/man/man1/ckmf.1 new file mode 100644 index 0000000..6812586 --- /dev/null +++ b/man/man1/ckmf.1 @@ -0,0 +1,39 @@ +.TH CKMF 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/ckmf.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: ckmf.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ckmf \- check users .mailfilter file +.SH SYNOPSIS +.in +.5i +.ti -.5i +ckmf file +.in -.5i +.SH DESCRIPTION +\fICkmf\fP checks that the given .mailfilter is free from syntax +errors. This does not necessarily mean that the file will work, just +that it should be interpreted ok. Run time errors may still occur. +.PP +It runs with a single argument, the file to check. It expects a +message on the standard input to attempt to deliver. It will then +print out what actions it would take. An empty message (a.k.a. +/dev/null) may be given and the appropriate actons will be indicated. +.PP +It is \fBSTRONGLY\fP advised that you run this program after modifying +your \&\fB.mailfilter\fP file to check that you haven't made mistakes +in the syntax. +.SH FILES +.nf +.ta \w'/usr/local/lib/mailfilter\0\0'u +~/.mailfilter The users mailfilter file +/usr/local/lib/mailfilter The system mailfilter file +.fi +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP +.SH BUGS +Ought to check more (including the sanity of the user). diff --git a/man/man1/dl.1 b/man/man1/dl.1 new file mode 100644 index 0000000..f5c8c73 --- /dev/null +++ b/man/man1/dl.1 @@ -0,0 +1,106 @@ +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/dl.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: dl.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.TH DL 1 +.SH NAME +dl \- X.500 Directory Based Distribution List Management tool. +.SH SYNOPSIS +.in +.5i +.ti -.5i +dl +\%[\-u\0distinguished-name] +\%[\-c\0name-or-address] +\%[-m] +\%[-q] +\%[-p] +\%[-v] +\%[listname] +.br +.in -.5i +.SH DESCRIPTION +The +.I dl +program is used to modify the list specified on the command line. +If no list is specified, dl enters an +interactive mode prompting the user for lists to modify. +When modifying a list, \fIdl\fR allows the user to create, add, +remove, display, and check distribution lists via menu items. +.PP +Lists can also be created or converted from file based lists using +this tool. +.PP +The `\-u' flag is used to change the default distinguished name of the user +the specified name, the default is read from \fI.quipurc\fR. +.PP +The `\-c' flag is used to specify the name or address of the DSA to +call. +.PP +The `\-p' flag is used to ask for the list to be printed, then dl will exit. +.PP +The `\-q' flag put dl into "quiet" mode. This is particularly useful +when running with the `\-v' flag. +.PP +The `\-m' flag is used to persuade \fIdl\fR that the user bound does +have sufficient access rights to modify the directory based list. +This is useful for directory managers. +.PP +The `\-v' flag asks dl the verify the specified list (or all local lists in +none specified). If is useful to run with this option from cron(1) at +reqular intervals to detect any changed mail addresses. +If used with the `\-m' flag, out of date addresses are modified. +.SH ATTRIBUTE SYNTAXES +.PP +There are various attribute syntaxes defined in addition to the standard +syntaxes used by \fIdish\fR. +The most important of these is the \fIORName\fR syntax, used for the +\fImhsDLMembers\fR attribute. +.PP +An ORName consists of an optional directory name, and an ORAddress. +The two components are seperated by a `$' thus: +.sp +.in +.5i +.nf +ORName ::= [] [$ ] +.fi +.in -.5i +.sp +The DirectoryName is either a Quipu style Distinguished +Name, or a name in Steve Kille's user-friendly notation. +This notation is ordered but untyped, +with components separated by commas. +Typical names include: +.sp +.in +.5i +.nf +kille, cs, ucl +rose, psi, USA +L. Eagle, \*(lqSue, Grabbit and Runn\*(rq, GB +.fi +.in -.5i +.sp +The ORaddress is an X.400 style mail address. +If a DirectoryName is supplied, the the ORAdress can be omitted, +\fIdl\fR will fill it in by looking at the mail attributes of the entry for +`DirectoryName' in the X.500 directory. +.sp +.SH FILES +.nf +\*(EDdsaptailor system QUIPU tailoring file +$HOME/\&.quipurc user's QUIPU tailoring file +\*(EDufnrc system UFN runcom file +$HOME/\&.ufnrc user's UFN runcom file +.re +.fi +.SH "SEE ALSO" +The PP Manual: Volume 3 \- Users Guide, +.br +Using the OSI Directory to achieve User Friendly Naming, +.br +dish(1c). +.SH AUTHOR +Colin Robbins, +University College London diff --git a/man/man1/flagmail.1 b/man/man1/flagmail.1 new file mode 100644 index 0000000..2be6a7b --- /dev/null +++ b/man/man1/flagmail.1 @@ -0,0 +1,78 @@ +.TH FLAGMAIL 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/flagmail.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: flagmail.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +flagmail \- interface to xalert +.SH SYNOPSIS +.in +.5i +.ti -.5i +flagmail +\%[-d] \%[-e\ string] \%[-f\ format] \%[-h\ hostfile] \%[-p num] +\%[-s\ size] \%[-w\ width] \%[\-x] +.in -.5i +.SH DESCRIPTION +Flagmail is an interface to the \fIxalert\fP program, which runs under +the X windowing system. It's task is to build up a alert message from +a message read from the standard input and pass it to the \fIxalert\fP +for display. In actual fact, \fIflagmail\fP is not limited to talking +to \fIxalert\fP but can talk to any process that understands the +protocol and listens on the appropriate port. +.PP +If it can not contact such an X server, then it will attempt to locate +the users terminal line and notify that in the same manner as +\fIttyalert\fP. +.PP +It has several options to control the format. +.TP +\-d +Run in debug mode. This stops the process disappearing into the +background at the first opportunity. +.TP +\-e string +Set the \fIextra\fP variable. This is used in part of the display +string and defaults to \*(lqNEW: \*(rq. +.TP +\-f format +This allows overriding the default format of the message displayed. +.TP +\-h hostfile +This changes the file that is read to discover the host xalert is +running on. +.TP +\-p number +Change the default udp port that is sent to. +.TP +\-s size +This sets the \fIsize\fP variable which can be set in the +\&\fI.mailfilter\fP delivery script (typically using the +\*(lq$(size)\*(rq variable). +.TP +\-w width +This sets the maximum width of the output line. The string is +truncated to this width. +.TP +\-x +Force the use of protocol. +.PP +The default display string is the following +.sp +.ti +.5i +.nf +%extra(%size) %20from %subject << %50body +.fi +.sp +.SH FILES +.ta \w'~/.alert\0\0'u +~/.alert The default alert file. +.SH "SEE ALSO" +xalert(1), ttyalert(1) +.br +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +The formatting string ought to be more general. diff --git a/man/man1/flock.1 b/man/man1/flock.1 new file mode 100644 index 0000000..641b4fd --- /dev/null +++ b/man/man1/flock.1 @@ -0,0 +1,30 @@ +.TH FLOCK 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/flock.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: flock.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +flock \- run a process with a file locked +.SH SYNOPSIS +.in +.5i +.ti -.5i +flock \%file \%[command..] +.in -.5i +.SH DESCRIPTION +.I Flock +is a small utility that takes a file and a command to run. It firstly +locks the file using the current PP locking method, and then runs the +command as a subprocess. When the subprocess exits, \fIflock\fP exits +with the same value. +.PP +It has no options. +.SH FILES +None +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +None \- Hah! diff --git a/man/man1/mail.1 b/man/man1/mail.1 new file mode 100644 index 0000000..44ca19f --- /dev/null +++ b/man/man1/mail.1 @@ -0,0 +1,38 @@ +.TH MAIL 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/mail.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: mail.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +mail \- dumb mail interface +.SH SYNOPSIS +.in +.5i +.ti -.5i +mail \%[-t] \%[-c] \%[-s] \%[recipients..] +.in -.5i +.SH DESCRIPTION +\fIMail\fP is a very simple interface to PP. It takes a message on its +standard input and submits it to the given list of recipients. +.PP +It has the following options +.TP +\-t +Interpret the remaining arguments up to the next switch as +\*(lqTo:\*(rq recipients. +.TP +\-c +Interpret the recipients arguments up to the next switch as +\*(lqCc:\*(rq recipients. +.TP +\-s +Interpret the next argument as the subject string. Processing will revert to +the previous type after this argument (r.g. to or cc). Multiple subject +arguments may be given and will be concatenated. +.SH FILES +None +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP diff --git a/man/man1/make b/man/man1/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/man/man1/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/man/man1/malias.1 b/man/man1/malias.1 new file mode 100644 index 0000000..6a28dfa --- /dev/null +++ b/man/man1/malias.1 @@ -0,0 +1,28 @@ +.TH MALIAS 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/malias.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: malias.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +malias \- distribution list viewer +.SH SYNOPSIS +.in +.5i +.ti -.5i +malias +\%[listname ...] +.in -.5i +.SH DESCRIPTION +The +.I malias +program is used to show the expansion of the lists specified on the +command line. +If no lists are specified, malias enters an interactive mode prompting +the user for lists to show. +.SH "SEE ALSO" +mlist(1) +.sp +\fIThe PP Manual: Volume 3 \- Users Guide\fP diff --git a/man/man1/mlist.1 b/man/man1/mlist.1 new file mode 100644 index 0000000..7f89550 --- /dev/null +++ b/man/man1/mlist.1 @@ -0,0 +1,37 @@ +.TH MLIST 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/mlist.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: mlist.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +mlist \- distribution list manager +.SH SYNOPSIS +.in +.5i +.ti -.5i +mlist +\%[listname ...] +.br +malias +\%[listname ...] +.in -.5i +.SH DESCRIPTION +The +.I mlist +program is used to modify the lists specified on the command line. +If no lists are specified, mlist enters an +interactive mode prompting the user for lists to modify. +When modifying a list, \fImlist\fP allows the user to create, add, +remove, display, and check distribution lists via menu items. +.PP +The +.I malias +program is used to show the expansion of the lists specified on the +command line. +If no lists are specified, \fImalias\fP enters an interactive mode prompting +the user for lists to show. +.SH "SEE ALSO" +\fIThe PP Manual: Volume 3 \- Users Guide\fP diff --git a/man/man1/mu.1 b/man/man1/mu.1 new file mode 100644 index 0000000..52724e3 --- /dev/null +++ b/man/man1/mu.1 @@ -0,0 +1,151 @@ +.TH MU 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/mu.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: mu.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +mu \- message submission tool +.SH SYNOPSIS +.in +.5i +.ti -.5i +mu +\%[\-default\ file] \%[\-file\ file] \%[\-value\ value] \%[\-body\ file] +\%[\-tree\ directory] \%[\-logfile\ file] \%[\-confirm] \%[\-nofix] \%[\-help] +\%[\-\-] \%[\-0] \%[\-1] \%[\-2] \%[\-3] \%[\-4] \%[\-5] +.in -.5i +.SH DESCRIPTION +This is a special user interface, provided as a general tool to help +test \fIsubmit\fP and consequent operations in PP. It may be used to +re-submit a modified text-encoded file taken from the queue. + +The message submission tool \fImu\fP takes input from the command +line, a defaults file \fImu.defaults\fP if present in the working directory, +otherwise from the default command directory \fIcmddfldir\fP (as +specified in the top level Makefile & static.c) and then +any other files specified with \fI\-file\fP flags. +Any command line option may be placed on a +line within an input file. \fImu\fP calls its command line parser +recursively when it encounters a line starting with \fI`\-'\fP. +Any line starting with \fI`#'\fP is +ignored. Otherwise, all lines are offered to the various +\fIsubmit\fP input routines in turn for incorporation into PP's +internal message structures (\fIprm\_vars, Qstruct and ADDR\fP). +Any line which returns an error code (\fIrp_isbad\fP) +from all these routines is assumed to be in error. +Flags may be abbreviated to single letters. +.PP +The command line options are summarised below. +.TP +\-default +Use file instead of \fImu.defaults\fP for initial input. +.TP +\-file +Read input from file. +.TP +\-value +Assign message parameter value on command line (rather than within an +input file). +.TP +\-body +Specify message body part file. +.TP +\-tree +Specify directory containing tree-structured message. +.TP +\-logfile +Output progress and error messages to logfile instead of stdout. +.TP +\-confirm +Prompt user for y/n confirmation after interactive input. (See below.) +.TP +\-nofix +Ignore errors in user input. (See below.) +.TP +\-help or \-\- +Print summary of flag table entries. +.TP +Various debug and control flags : +.TP +\-0 +log progress messages, and PPLOG(LLOG\_TRACE ...) +.TP +\-1 +log command files as they are processed, and PPLOG(LLOG\_DEBUG ...) +.TP +\-2 +list body part files as they are io\_tdata'ed +.TP +\-3 +list message structures prior to submit io\_ calls +.TP +\-4 +abort prior to submit io\_ calls +.TP +\-5 +append to logfile rather than overwrite +.PP +The input lines which specify message parameter assignments may +be received in any sequence, and inputs may override earlier entries. +Any value may also be assigned on the (original) command line with +\fI\-value v1 v2 ... \fP up to the next flag. +.PP +If input files are nested, input lines from the nested file are +processed before the remainder of the file containing the \fI\-file\fP +specifier. The default file is parsed first (\fImu.defaults\fP +unless overridden with a \fI\-default\fP flag on the command line), +then any \fI\-file\fP specified files from the command line, finally +\fI\-value\fP specifications from the command line. Body part files +may be specified with \fI\-body\fP commands, either on the command +line or embedded as with other commands. +.PP +\fImu\fP uses PP's standard logging \- additional logging messages generated by +\-0 \-1 \-2 \-3 flags are output to a channel (\fImuout\fP) which defaults to \fIstdout\fP +unless flag \fI\-logfile\fP is specified. Note that output may be re-routed +in the course of processing input files. The flag \-5 allows +these messages to be appended to the nominated logfile, rather than +replacing it. +.PP +\fImu\fP allows interactive user input. +.sp +The reserved character \fI`$'\fP (TOKENCHAR) is used to indicate that +the user should input a value to replace the \fI`$'\fP, unless the +line is a comment line or the \fI`$'\fP is immediately followed by a +second to escape a real \fI$\fP symbol. The portion of the input +line up to and including the \fI`$'\fP is displayed on screen, then a +carriage return delimited string is input to replace the \fI`$'\fP. +The substituted line is scanned for further unpaired \fI`$'\fP +characters. When all have been replaced, if the flag \fI\-confirm\fP +has been specified, the user input will be re-displayed awaiting user +confirmation or cancellation with \fI`y'\fP or \fI`n'\fP. The line +is then offered to the \fIsubmit\fP input routines. Any error will +cause the input portions to be re-prompted \fIunless\fP the flag +\fI\-nofix\fP has been specified, in which case \fImu\fP will ignore +the error and continue. +.PP +To allow repeated user input, for example, of multiple recipient +lines, another reserved character \fI`*'\fP (REPEATCHAR) may be +placed at the start of a line to indicate repetition. If this +character appears at the start of a line which contains no unpaired +\fI`$'\fP characters, an error +.sp +error : no TOKENCHAR(s) in REPEAT line \- REPEATCHAR ignored +.sp +is reported. Otherwise, user input takes place as before, terminated +by a null input (just a carriage return) on any substitution field +in the line. Repeat lines are stripped of the \fI`*'\fP character +before passing to the \fIsubmit\fP input routines. +.sp +.SH FILES +.TP +mu.defaults +The default initial inputs file. +.SH "SEE ALSO" +mail(1) +.br +\fIPP Manual \- Volume 1: Installation and Operation\fP +.SH "BUGS" +Too complicated. diff --git a/man/man1/ntail.1 b/man/man1/ntail.1 new file mode 100644 index 0000000..e4af799 --- /dev/null +++ b/man/man1/ntail.1 @@ -0,0 +1,53 @@ +.TH NTAIL 1L +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/ntail.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: ntail.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ntaiL - Watch the growth of files. +.SH SYNTAX +.B ntail +entry ... +.SH DESCRIPTION +.I Ntail +monitors one or more files, and displays all data written to a file +since command invocation. It is very useful for monitoring multiple +logfiles simultaneously. +.P +If an +.I entry +given on the command line is a directory, all files in that directory +will be monitored, including those created after the +.I ntail +invocation. If an +.I entry +given on the command line doesn't exist, +.I ntail +will watch for it and monitor it once created. When switching files in +the display, a banner showing the pathname of the file is printed. +.P +An interrupt character (usually CTRL/C or DEL) will display a list of the +most recently modified files being watched. Send a quit signal +(usually CTRL/backslash) to stop +.IR ntail . +.SH SEE ALSO +tail(1) +.SH NOTES +.I Ntail +may be easily confused. For example, if a file is renamed, +.I ntail +may or may not continue to monitor it. If you ask it to monitor a file +multiple times, it probably will. If you misspell a filename, +.I ntail +will treat it as a nonexistent entry and happily wait for its creation. +.P +My favorite use is "ntail /usr/spool/uucp/.Log/*". +.br +Ntail was originally called xtail, and was changed for reasons you don't +want to know about... +.SH AUTHOR +Chip Rosenthal diff --git a/man/man1/rcvtrip.1 b/man/man1/rcvtrip.1 new file mode 100644 index 0000000..44d054d --- /dev/null +++ b/man/man1/rcvtrip.1 @@ -0,0 +1,75 @@ +.TH RCVTRIP 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/rcvtrip.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: rcvtrip.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +rcvtrip \- answerphone for mail +.SH SYNOPSIS +.in +.5i +.ti -.5i +rcvtrip \%[\-dF] \%[\-e\ exit] \%[\-f\ from] \%[\-l\ file] +\%[\-n\ file] \%[-s\ sigfile] \%[\-t\ text] \%[\-u\ user] +.in -.5i +.SH DESCRIPTION +.I Rcvtrip +is a process that is normally run from the user \fB.mailfilter\fP +file. It answers incoming mail with a user defined message usually +informing the sender that the recipient is on vacation or similar. +.PP +It normally checks to see if the message specifies the user in the To: +or Cc: lines and will not reply otherwise. It also checks and updates +a database file to see if this user has been replied to already. It +will normally only reply to a given user once. +.PP +It has several options to modify it's behaviour. +.TP +\-d +run in debug mode. +.TP +\-F +Always reply to the message, even if the message is not sent directly +to the user. +\-e\ value +set the exit code depending on this value. If the value is 0, the exit +code is always bad. If the value is 1, the exit code is always good. +An value of 2 will give an exit value of 1, 2, 3, 4 or 99 if the +message was sent; not sent because duplicate; not sent because not +sent to user; parse error; other; respectively. +.TP +\-f\ from +Set the free form text of the from address to this value (default is +MESSAGE AGENT). +.TP +\-l\ file +Set the database file to this file name. +.TP +\-n\ file +Use this file as the text of the message to send back after standard +preamble. +.TP +\-s\ file +Use this file to determine the users signature, which is appended to +the preamble. +.TP +\-t\ text +Modify the preamble with this line. There may be several of these +arguments in which case they are concatenated. +.TP +\-u\ user +Pretend to be this user when answering. +.SH FILES +.nf +.ta \w'.signature\0\0'u +\&.signature default signature file +tripnote default trip note file +triplog database of incoming messages +\&.mailfilter the mailfilter processing file +.fi +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" diff --git a/man/man1/resend.1 b/man/man1/resend.1 new file mode 100644 index 0000000..13e3414 --- /dev/null +++ b/man/man1/resend.1 @@ -0,0 +1,41 @@ +.TH RESEND 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/resend.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: resend.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +resend \- resubmit a message +.SH SYNOPSIS +.in +.5i +.ti -.5i +resend \%[\-u\ username] \%[\-t] \%[\-c] \%recipients... +.in -.5i +.SH DESCRIPTION +.I Resend +is a small utility that forwards a message to more recipients. It does +this by attaching extra fields to the original message of the form +Resent-To: and Resent-Cc:. +.PP +It has the following options: +.TP +\-t +Take the next arguments up to the next flag as recipients to place in +the Resent-To: field. +.TP +\-c +Take the next arguments up to the next flag as recipients to place in +the Resent-Cc: field. +.TP +\-u\ username +Pretend to this user when resubmitting. This is dependant on +authentication checks and non privelidged users will normally fail. +.SH FILES +None +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +Not many. diff --git a/man/man1/strip_addr.1 b/man/man1/strip_addr.1 new file mode 100644 index 0000000..4eb4202 --- /dev/null +++ b/man/man1/strip_addr.1 @@ -0,0 +1,37 @@ +.TH STRIP_ADDR 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/strip_addr.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: strip_addr.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +strip_addr \- reduce address to simple forms +.SH SYNOPSIS +.in +.5i +.ti -.5i +strip_addr \%[-pr] \%[addrs...] +.in -.5i +.SH DESCRIPTION +.I Strip_addr +is a small utility that takes address either from the command line or +from the standard input and removes extraneous features. In particular +it removes comments, lists names and other name components leaving +just the username, domain and any routes. +.PP +It has the following options +.TP +\-r +Remove any routes in the address leaving just user@domain style +addresses. +.TP +\-p +Take the percent character (%) as equivalent to an "@" character. +.SH FILES +None +.SH "SEE ALSO" +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +Who knows, the address parser is full of suprises... diff --git a/man/man1/ttyalert.1 b/man/man1/ttyalert.1 new file mode 100644 index 0000000..4b32c2e --- /dev/null +++ b/man/man1/ttyalert.1 @@ -0,0 +1,58 @@ +.TH TTYALERT 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/ttyalert.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: ttyalert.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ttyalert \- notification of new mail +.SH SYNOPSIS +.in +.5i +.ti -.5i +ttyalert +\%[-d] \%[-e\ string] \%[-f\ format] \%[-s\ size] \%[-w\ width] +.in -.5i +.SH DESCRIPTION +Ttyalert attempts to alert users of new mail. It's task is to build up +an alert message from a message and display it on the users terminal. +.PP +It has several options to control the format. +.TP +\-d +Run in debug mode. This stops the process disappearing into the +background at the first opportunity. +.TP +\-e string +Set the \fIextra\fP variable. This is used in part of the display +string and defaults to \*(lqNEW: \*(rq. +.TP +\-f format +This allows overriding the default format of the message displayed. +.TP +\-s size +This sets the \fIsize\fP variable which can be set in the +\&\fI.mailfilter\fP delivery script (typically using the +\*(lq$(size)\*(rq variable). +.TP +\-w width +This sets the maximum width of the output line. The string is +truncated to this width. +.PP +The default display string is the following +.sp +.ti +.5i +.nf +%extra(%size) %20from %subject << %50body +.fi +.sp +.SH FILES +none +.SH "SEE ALSO" +xalert(1), flagmail(1) +.br +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +The formatting string ought to be more general. diff --git a/man/man1/ttybiff.1 b/man/man1/ttybiff.1 new file mode 100644 index 0000000..fdf5c87 --- /dev/null +++ b/man/man1/ttybiff.1 @@ -0,0 +1,53 @@ +.TH TTYBIFF 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/ttybiff.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: ttybiff.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ttybiff \- display new mail alerts +.SH SYNOPSIS +.in +.5i +.ti -.5i +ttybiff \%[-f\ file] \%[-u\ user] \%[-p\ number] \%[-s] +.in -.5i +.SH DESCRIPTION +This program is subsimed by xalert and will probably disappear from +future releases. +.PP +Ttybiff is a simple program designed to display new message alerts on +a users terminal. It does very little else, relying on its client to +do all the hard work. It is normally run in the background. it +displays the message on all terminals the user is logged onto on the +current machine, or if that fails to the standard output. +.PP +It has the following options +.TP +\-f file set the alert filename that \fIttybiff\fP and +\fIflagmail\fP communicate via. This defaults to the file \fB.alert\fP +in your home directory. This file is created by \fIttybiff\fP and read +by \fIflagmail\fP +.TP +\-u username +Allows you to pretend to be the given user. This does not really do +much as you will generally only get notified of messages to you, but +it may be useful. +.TP +\-p number +Change the default udp port that \fIttybiff\fP and \fIflagmail\fP +communicate via (normally assigned by the system). +.TP +\-s +Only display on the standard output, not on all terminals that the +user is logged into. +.SH FILES +.ta \w'~/.alert\0\0'u +~/.alert The default alert file. +.SH "SEE ALSO" +flagmail(1), ttyalert(1) +.br +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" diff --git a/man/man1/xalert.1 b/man/man1/xalert.1 new file mode 100644 index 0000000..adaf540 --- /dev/null +++ b/man/man1/xalert.1 @@ -0,0 +1,82 @@ +.TH XALERT 1 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man1/RCS/xalert.1,v 6.0 1991/12/18 20:43:41 jpo Rel $ +.\" +.\" $Log: xalert.1,v $ +.\" Revision 6.0 1991/12/18 20:43:41 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +xalert \- display new mail alerts +.SH SYNOPSIS +.in +.5i +.ti -.5i +xalert \%[\-filename\ file] \%[\-user\ user] \%[\-port\ number] +\%[\-bell] \%[\-nobell] \%[\-autoraise] \%[\-noautoraise] +\%[\-photos] \%[\-nophotos] +\%[\-s] \%[\-t] \%[\-x] \%[\-w\ width] +\%[generic\ X\ options] +.in -.5i +.SH DESCRIPTION +Xalert is a simple program designed to display new message alerts on a +display running the X windowing system. it does very little else, +relying on its client to do all the hard work. The program normally +tries to start as an X client. If this fails it acceps new messages +from the client and displays them to the users terminal. +.PP +It has the following options +.TP +\-filename file set the alert filename that \fIxalert\fP and +\fIflagmail\fP communicate via. This defaults to the file \fB.alert\fP +in your home directory. This file is created by \fIxalert\fP and read +by \fIflagmail\fP. This is also settable via the X resource string fileName. +.TP +\-user username +Allows you to pretend to be the given user. This does not really do +much as you will generally only get notified of messages to you, but +it may be useful. This is settable by the X resource string userName. +.TP +\-port number +Change the default udp port that \fIxalert\fP and \fIflagmail\fP +communicate via (normally selected by the system). This is settable by +the X resource integer port. +.TP +\-bell / \-nobell +Ring or don't ring the bell when a new message arrives. This is settable by +the X resource boolean bell +.TP +\-autoraise / \-noautoraise Raise or don't raise the window to the top +of the stack on each new message. This is settable by the X resource +boolean autoRaise. +.TP +\-photos / \-nophotos +Display the senders photograph as retrieved from the directory on each +new message. This is settable by the X resource boolean photos. +.TP +\-s +Only attempt to print to the standard output - do not search for all +occurances of this user logged in. +.TP +\-t +Do not attempt to start as an X client. +.TP +\-x +Allow use of X. +.TP +\-w\ width +Truncate to this width when displaying on terminals. +.PP +It is also quite useful as a clipboard... +.SH FILES +.ta \w'~/.alert\0\0'u +~/.alert The default alert file. +.SH "SEE ALSO" +flagmail(1), ttyalert(1) +.br +\fIPP Manual \- Volume 3: User Manual\fP +.SH "BUGS" +Ought to sing, dance and make coffee. +.br +Sometimes searching for a photograph can take a while - especially if +the photo is big! diff --git a/man/man3/Makefile b/man/man3/Makefile new file mode 100644 index 0000000..cdc6a81 --- /dev/null +++ b/man/man3/Makefile @@ -0,0 +1,41 @@ +# Manual page installation (section 3) +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/man/man3/RCS/Makefile,v 6.0 1991/12/18 20:43:58 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:43:58 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +MANUALS = or.3 + +############################################################ +# +# Building Rules +# +############################################################ + +default:; + +install:; MANDIR=$(MANDIR) ../inst-man.sh $(MANOPTS) $(MANUALS) + +clean:; +tidy:; +lint:; +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/man/man3/make b/man/man3/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/man/man3/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/man/man3/or.3 b/man/man3/or.3 new file mode 100644 index 0000000..2e616b5 --- /dev/null +++ b/man/man3/or.3 @@ -0,0 +1,216 @@ +.TH OR 3 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man3/RCS/or.3,v 6.0 1991/12/18 20:43:58 jpo Rel $ +.\" +.\" $Log: or.3,v $ +.\" Revision 6.0 1991/12/18 20:43:58 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +or \- library of O/R-address routines. +.SH SYNOPSIS +cc [flags] files libpp.a [libraries] +.SH DESCRIPTION +The +.I or +library provids a set of routines for building, transforming and +manipulating X.400 O/R Names. Most routines work on a doubly linked list +of structures representing the elements of the O/R Name. The list is +kept in an ordered sequence of elements, with the "most significant" +elements at the top. +Significance is determined by "lowness" in the assocaited #defines. +This is an extension of the precedence defined in RFC 987. +Some of the choices are arbitrary, and do not really matter. +The basic type is the +.I OR_ptr +which is defined in the header file +.IR or.h . +The routines are provided to work at various levels of complexity. +.SS "PRIMITIVE ROUTINES" +.nf +#include "or.h" +.sp +or_init () +.sp +OR_ptr or_add (list, or, before) +OR_ptr list, or; +int before; +.sp +or_cmp (or1, or2) +OR_ptr or1, or2; +.sp +OR_ptr or_dup (or) +OR_ptr or; +.sp +OR_ptr or_find (tree, type, ddname) +OR_ptr tree; +int type; +char *ddname; +.sp +or_free (or) +OR_ptr or; +.sp +OR_ptr or_lastpart (or) +OR_ptr or; +.sp +OR_ptr or_locate (or, type) +OR_ptr or; +int type; +.sp +OR_ptr or_new (type, ddname, value) +int type; +char *ddname, *value; +.sp +char *or_value (or, type) +OR_ptr or; +int type; +.sp +.fi +These routines are the primitive interface to the +.I or +package. Most routines use symbolic values to refer to the different +components. These are the following +.sp +.nf +.in +4 +#define OR_C 1 +#define OR_ADMD 2 +#define OR_PRMD 3 +#define OR_O 4 +#define OR_OU 5 +#define OR_X121 6 +#define OR_TID 7 +#define OR_UAID 8 +#define OR_S 9 +#define OR_G 10 +#define OR_I 11 +#define OR_GQ 12 +#define OR_DD 99 +.fi +.sp +.in -4 +In general if a routine fails then it returns either +.I NOTOK +if the return value is an integer, +.I NULLOR +if the return value is an or element and +.I NULLCP +if the return value is a character string. +.I or_init +initialises the package. It should be called before any other routines +although more commonly a higher level initialising function is used. +.I or_new +creates a new element of the given type with the given value. If the +element is a domain defined attribute, then ddname is the name of the +attribute. All parameters are copied into allocated memory. +.I or_add +adds a new or element to the list, and inserts it in the correct place +in the hierarchy. +It will not allow duplicates, except for DDs and OUs. +If the flag before is set and the +element type is a recurring type, then the element is added before +other elements of the same type. +This flag is to cope with some of the oddities of EAN and RFC 987. +.I or_cmp +compares two elements. It returns true if the two elements are the +same. +.I or_dup +duplicates an or element. +Finally, +.I or_free +releases the storage associated with an element when finished with. +.I or_locate +locates an element of a specified type in a tree. +.I or_find +is a version generalised to acces domain defined. +.I or_lastpart +identifeis the last element of an or_tree. +.I or_value +returns the value of the first occurence of the specified type. +.SS "CONVERSION ROUTINES" +.nf +or_or2std (or, buf, nicepn) +OR_ptr or; +char *buf; +int nicepn; +.sp +OR_ptr or_std2or (str) +char *str; +.sp +or_or2dmn (first, last, buf) +OR_ptr first, last; +char *buf; +.sp +OR_ptr or_dmn2or (istr) +char *istr; +or_or2rfc (or, result) +OR_ptr or; +char *result; +.sp +or_rfc2or (rfc, or) +char *rfc; +OR_ptr *or; +.sp +PE or2pe (or) +OR_ptr or; +.sp +OR_ptr pe2or (pe) +PE pe; +.sp +.fi +These routines, in general, manipulate between OR_ptr trees +and various forms of string. +.I or_or2std +maps an OR_ptr into RFC 987 \%std-orname (for human consumption). +If nicepn is set, it produces a more readable, but illegal, version. +.I or_std2or +performs the reverse mapping. +.I or_or2dmn +and +.I or_dmn2or +do the same for the machine interpretable \%dmn-orname encodings of RFC +987. +For +.I or_or2dmn , +the first and list paramters enable specification of an (inclusive) +section of an OR_ptr tree to be encoded. +.I or_or2rfc +and +.I or_rfc2or +perform mappings between RFC 822 addresses and OR_ptr trees, according +to RFC 987. +.I or2pe +and +.I pe2or +perform mappings between OR_ptr trees and PE pointer ones. +They are PEPY generated routines. See the ISODE 5.0 documentation +for more details. +.SS "STRING ROUTINES" +.nf +or_asc2ps (ascii, ps) +char *ascii, *ps; +.sp +or_ps2asc (ps, ascii) +char *ps, *ascii; +.sp +.fi +The first two routines convert between ascii character strings and the +printable string encoding of the ascii string as specified in RFC-987. +.SS "OTHER ROUTINES" +.nf +OR_ptr or_default (or) +OR_ptr or; +.sp +.fi +.I or_default +inserts local default components into partially specified OR Names. +.SH "SEE ALSO" +ISODE 5.0 documentation. +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP +.SH FILES +Various tables, including: rfc2or/or2rfc (for 987 mappings); +or (for or_check). +.SH BUGS +Need to add an or_undefault function. diff --git a/man/man8/MTAconsole.8 b/man/man8/MTAconsole.8 new file mode 100644 index 0000000..c40e1e9 --- /dev/null +++ b/man/man8/MTAconsole.8 @@ -0,0 +1,69 @@ +.TH CONSOLE 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/MTAconsole.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: MTAconsole.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +console \- qmgr monitor and controller +.SH SYNOPSIS +.in +.5i +.ti -.5i +console +\%[-Q\ host] \%[-N] \%[-r\ time] \%[-c\ number] \%[-m\ number] +\%[-v\ number] \%[-o\ time] +.in -.5i +.SH DESCRIPTION +The +.I console +tool enables a user to connect to, monitor and control a qmgr. +The console runs on top of the X windowing system. +.PP +The \fIconsole\fP responds to various command line flags. +.TP +\-Q host +The default host. +The console attempts to automatically connect to the Qmgr on the given host. +WARNING this may take a lot of time! +.TP +\-N +Turn off confirmation popups for the quit and disconnect command buttons. +.TP +\-r time +The amount of time between automatic refreshes of the display. +By default, this time interval is five minutes. +The time should be a console time string with no whitespace between +elements of the string (i.e 5m or 5h3m2s). +.TP +\-c number +The number of colours used in the display. +The default is ten. +.PP +The following flags affect the heuristics used to determine the +comparitive states of different channels, mtas or messages. +.TP +\-m number +The highest number of messages on a channel or mta. +Any channel or mta with more than this number is deemed to be in +serious trouble. +The default value is 50. +.TP +\-v number +The largest volume of messages on a channel or mta. +Any channel or mta with a volume greater than this is deemed to be in +serious trouble. +The default value is 10000. +.TP +\-o time +The oldest message allowed. +Any message older than this time or channel or mta containing a +message older than this is deemed to be in serious trouble. +The time should be given as a console time string with no intervening +whitespace (e.g 2w5d). +The default age is four weeks. +.SH FILES +.SH "SEE ALSO" +.SH BUGS diff --git a/man/man8/Makefile b/man/man8/Makefile new file mode 100644 index 0000000..ab14acb --- /dev/null +++ b/man/man8/Makefile @@ -0,0 +1,62 @@ +# Manual page installation (section 8) +# +############################################################ +# +# @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/Makefile,v 6.0 1991/12/18 20:44:03 jpo Rel $ +# +# $Log: Makefile,v $ +# Revision 6.0 1991/12/18 20:44:03 jpo +# Release 6.0 +# +# +############################################################ +# +# Definitions +# +############################################################ + + + +MANUALS = MTAconsole.8 \ + abbrev.8 \ + ckadr.8 \ + ckchan.8 \ + ckconfig.8 \ + dbmbuild.8 \ + dbmedit.8 \ + dbmunbuild.8 \ + lconsole.8 \ + mpp84.8 \ + mpp88.8 \ + pp-gen.8 \ + pptsapd.8 \ + probe.8 \ + qmgr.8 \ + rmail.8 \ + sendmail.8 \ + smtpd.8 \ + smtpsrvr.8 \ + tjoin.8 + + + +############################################################ +# +# Building Rules +# +############################################################ + +default:; + +install:; MANDIR=$(MANDIR) ../inst-man.sh $(MANOPTS) $(MANUALS) + +clean:; +tidy:; +lint:; +depend:; + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/man/man8/abbrev.8 b/man/man8/abbrev.8 new file mode 100644 index 0000000..66dd6d0 --- /dev/null +++ b/man/man8/abbrev.8 @@ -0,0 +1,42 @@ +.TH ABBREV 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/abbrev.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: abbrev.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +abbrev \- Abbreviates host\/domain names +.SH SYNOPSIS +abbrev local-domain1 [local-domain2 ...] < input-file +.SH DESCRIPTION +.I Abbrev +is a program that is used to construct the +.I domain +table residing in the PP table directory (tbldfldir). +This is a useful tool as it allows a user an alternative +way of specifying an RFC822 address. +If +.I abbrev +is used, an abbreviated forms of domains may be specified +which will then get properly expanded by the PP mail system. +For example an address "Jim.Hacker@cs" could be expanded +to "Jim.Hacker@cs.ucl.ac.uk", depending on +.I abbrev's +parameters. +.PP +.I Abbrev +takes a number of command line arguments, which should be local domains. +It takes as input a typical domain table format. +.PP +For each entry specified in the input-file, +.I abbrev +recursively shortens the key until the domain specified on the command +line and the given entry share no common parts. Each entry is +abbreviated with respect to each command line option. +.PP +Blank lines and comments are passed though unchanged. +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/ckadr.8 b/man/man8/ckadr.8 new file mode 100644 index 0000000..a96f324 --- /dev/null +++ b/man/man8/ckadr.8 @@ -0,0 +1,58 @@ +.TH CKADR 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/ckadr.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: ckadr.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ckadr \- address checker +.SH SYNOPSIS +.in +.5i +.ti -.5i +ckadr \%[-rxanpbl0123] +\%[address..] +.in -.5i +.SH DESCRIPTION +The +.I ckadr +tool checks whether addresses are acceptable to the local mail system. +.PP +If \fIckadr\fP is invoked with command line arguments, it will +attempt to parse them as addresses and report back the +result. +.PP +If no command line arguments are given, \fIckadr\fP will read from +the standard input. +Each line read will be parsed as an address and the result reported back to +the user. +.PP +.I ckadr +has a growing number of flags. These are:- +.TP +\-r +Force the address type to be RFC-822 address. This is the default choice. +.TP +\-x +Force the address type to be X.400 style. +.TP +\-a +Normalise all domains within the address +.TP +\-n +No responsibility set, parse this like an originator address. +.TP +\-p +count percent characters (%) as routing constructs. +.TP +\-b +Parse in big-endian format first (UK form). +.TP +\-l +parse in little endian format (US and rest of world format) +.TP +.SH "SEE ALSO" +\fIThe PP Manual: Volume 3 \- Users Guide\fP + diff --git a/man/man8/ckchan.8 b/man/man8/ckchan.8 new file mode 100644 index 0000000..cbf846b --- /dev/null +++ b/man/man8/ckchan.8 @@ -0,0 +1,44 @@ +.TH CKCHAN 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/ckchan.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: ckchan.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ckchan \- channel status checker +.SH SYNOPSIS +.in +.5i +.ti -.5i +ckchan +\%[-s] \%[-v] \%[all | channelname...] +.in -.5i +.SH DESCRIPTION +The +.I ckchan +tool outputs information on the status of the specified channels. +Because it reads from the restricted access spool area, \fIckchan\fP +can only be run by privileged users. +If the key word \fIall\fP appears on the command line, \fIckchan\fP +output information on all active channels. +.PP +\fIckchan\fP behaviour is effect by the following flags +.TP +\-v +This flag prompts \fIckchan\fP to output a verbose form of information. +By default, the information consists of a summary of the mtas that are +queued on each channel. +The verbose output consists of detailed information about all the messages +queued on each channel. +.TP +\-s +Give a short summary of the queue. +.SH BUGS +\fIckchan\fP interrogates the model of the mail queue stored on disc. +For this reason, \fIckchan\fP must be run on a file system which +has access to the relevant disc partitions. + + + diff --git a/man/man8/ckconfig.8 b/man/man8/ckconfig.8 new file mode 100644 index 0000000..a05e9a5 --- /dev/null +++ b/man/man8/ckconfig.8 @@ -0,0 +1,69 @@ +.TH CKCONFIG 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/ckconfig.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: ckconfig.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +ckconfig \- configuration checker +.SH SYNOPSIS +.in +.5i +.ti -.5i +ckconfig +\%[\-f] \%[\-v] \%[\-n] \%[-t\ tailor] +.in -.5i +.SH DESCRIPTION +The +.I ckconfig +tool checks various configuration details of the PP message system. +.TP +1. +It checks that all the required directories are in place. +If a directory is missing, the user will be prompted for the creation +of the directory. +.TP +2. +It checks that all the channels mentioned in the tailor file +reference existing executables in the correct directory (\fIchndfldir\fP). +If a channel is the filtercontrol channel running a specified filter, +it checks that the channel references an existing executable filter in +the correct directory (\fIformdfldir\fP). +.TP +3. +It checks that all the tables mentioned in the tailor file +reference existing files in the correct directory (\fItbldfldir\fP). +.TP +4. +There are certain channels and tables that the PP system +refers to by explicit, known names. +\fIckconfig\fP checks to see if these names have an appropriate entry +in the tailor file. +.PP +\fIckconfig\fP responds to the following flags +.TP +\-v +Verbose Mode. +Switches the output to verbose mode, displaying correct +as well as incorrect configuration details. +By default, ckconfig only displays incorrect configuration details. +.TP +\-f +Force Mode. +Switches of any prompting to the user. +Thus able to run independent of a user. +.TP +\-n +No Execution Mode. +Displays incorrect configuration details and what can be done to +correct them, but does not attempt correction. +.TP +\-t tailor +check the given tailor file rather than the system default one. +.SH FILES +PP tailor file +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/dbmbuild.8 b/man/man8/dbmbuild.8 new file mode 100644 index 0000000..f2aa612 --- /dev/null +++ b/man/man8/dbmbuild.8 @@ -0,0 +1,49 @@ +.TH DBMBUILD 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/dbmbuild.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: dbmbuild.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +dbmbuild \- database builder for PP +.SH SYNOPSIS +.in +.5i +.ti -.5i +dbmbuild \%[-nvdk] \%[database\ [table ...]] +.in -.5i +.SH DESCRIPTION +.I Dbmbuild +reads the tables specified in the PP tailor file into a hashed +database for use in quickly verifying addresses and efficiently assigning +channels to submitted messages. If no database file is specified, the +default dbm filename is used from the PP tailor file. If no table files +are specified, all tables listed in the tailor file are used. +.PP +The options are: +.IP n +Don't create a new database, attempt to add to an existing database. +.IP v +Verbose mode. Print out each table as it is processed. +.IP d +Debug mode. Report everything that happens (verbose). +.IP k +Keep going. If a file is mentioned that doesn't exist, ignore it. +It might be appropriate to make this the default at some sites. +.PP +Appropriate locks are placed on the database so that +.I dbmbuild +can safely be run while PP is in operation. +.SH FILES +.nf +.ta \w'ppdbm.dir\0\0'u +ppdbm.dir database directory +ppdbm.pag database pages +ppdbm.lck database locking file +.fi +.SH "SEE ALSO" +dbm(3X), dbmedit(8), dbmunbuild(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/dbmedit.8 b/man/man8/dbmedit.8 new file mode 100644 index 0000000..30a7470 --- /dev/null +++ b/man/man8/dbmedit.8 @@ -0,0 +1,118 @@ +.TH DBMEDIT 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/dbmedit.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: dbmedit.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +dbmedit \- edit the pp database file +.SH SYNOPSIS +.in +.5i +.ti -.5i +dbmedit \%[-v] \%[-d\ database] \%[cmd ...] +.SH DESCRIPTION +.I Dbmedit +is a program to manually edit the \fIdbm\fR(3) database used by PP. +It is intended to be used by the system maintainer for quick +and simple changes to the database. +It can also be used by careful setuid programs to make controlled +changes on behalf of users. +For example, a \fIforwardmail\fR command might use +dbmedit to change a user's entry in the +dbm database after changing the mail forwarding alias file. +.PP +The \-v option may be used to get a verbose description of the +program's activities. +.PP +The \-d option may be used to specify an alternate database. The +default is given in the PP tailor file. +.PP +If no arguments are given to \fIdbmedit\fR then the program +goes into an interactive mode, and prompts the user for each +command. Otherwise the arguments are taken as one command. +.PP +Commands in \fIdbmedit\fR refer to keys, tables, and values. +Tables are hashed into the database using \fIdbmbuild\fR(8). +The keys appear on the LHS of the tables and the values on the RHS. +In general, only the first occurence of a value for a given +key/table pair is significant. +For example, the table entries: +.nf +.ta \w'table1:\0\0'u +table1: + key1: val1 + key2: val2 +table2: + key1: val3 + key1: val4 +.fi +get hashed into the following database entries: +.nf +key1 table1 val1 +key1 table2 val3 +key1 table2 val4 +key2 table1 val2 +.fi +.PP +The command lines in interactive mode are parsed using the standard +PP string-to-argument routines so the same quoting +and escape conventions are used. +For example, if you want double-quotes or spaces +in the value, they must be +escaped with a backslash or the string must be quoted (for spaces). +.PP +The commands are: +.RS +.TP 4 +.I print key [table] +Print the value of the key/table pair. +If the table is omitted, then print the value of any +table entry with this key. +.TP 4 +.I add key table value +Add a key/table entry with the given value. +In verbose mode, a warning message is printed if the given +key/table pair already has a value in the database. +.TP 4 +.I delete key [table [value]] +Delete the values for the specified key. If a table is specified, +delete only the values for the specified key/table pair. If a value +is also specified, delete only entries for the pair with that value. +It is an error to try to delete something which does not appear in +the database as specified. +.TP 4 +.I change key table [oldvalue] newvalue +Change the value of the specified key/table pair to +.I newvalue. +If +.I oldvalue +is specified, change the entry matching that value. Otherwise, +change the value of the first occurence or add a new key/table pair +if none already exists. +.TP 4 +.I help +Give a brief summary of the commands +.TP 4 +.I quit +Exit the program. +.RE +.PP +All commands may be shortened to their first character only. +If the wrong number of arguments is given to a command, a +``Usage:'' message will be printed. +All changes are made in real time. +This program may be used while PP processes are running. +There is no temporary copy of the database while editing. +.SH FILES +.nf +.ta \w'ppdbm.dir\0\0'u +ppdbm.dir The PP database +ppdbm.pag The PP database +.fi +.SH "SEE ALSO" +dbm(3x), dbmbuild(8), dbmunbuild(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/dbmunbuild.8 b/man/man8/dbmunbuild.8 new file mode 100644 index 0000000..975350e --- /dev/null +++ b/man/man8/dbmunbuild.8 @@ -0,0 +1,49 @@ +.TH DBMUNBUILD 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/dbmunbuild.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: dbmunbuild.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +dbmunbuild \- dump the PP database +.SH SYNOPSIS +.in +.5i +.ti -.5i +dbmunbuild \%[\-v] \%[\-d\ database] \%[\-t\ table] +\%[\-T\ table] directory +.in -.5i +.SH DESCRIPTION +.I Dbmunbuild +takes a PP database and recreates the files it was created from. +.PP +The options are: +.TP +\-v +verbose mode. Print out a few messages. Normally \fIdbmunbuild\fP does +it's work silently unless errors occur. +.TP +\-d database +Read from the given database. Normally the default database is found +from the tailor file. +.TP +\-t table +Dump only the given table. Multiple of these flags may be given. It +cannot be used with the \-T option. +.TP +\-T +Dump all tables with the exception of this table. Multiple of these +options may be given. It may not be used in conjunction with the \-t option. +.SH FILES +.nf +.ta \w'ppdbm.dir\0\0'u +ppdbm.dir database directory +ppdbm.pag database pages +ppdbm.lck database locking file +.fi +.SH "SEE ALSO" +dbm(3X), dbmedit(8), dbmbuild(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/lconsole.8 b/man/man8/lconsole.8 new file mode 100644 index 0000000..0dc1298 --- /dev/null +++ b/man/man8/lconsole.8 @@ -0,0 +1,77 @@ +.TH LCONSOLE 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/lconsole.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: lconsole.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +lconsole \- line based MTA console +.SH SYNOPSIS +.in +.5i +.ti -.5i +lconsole \%[\-Q\ mta] \%[\-u\ user] \%[\-p\ passwd] \%[\-b] \%[actions...] +.in -.5i +.SH DESCRIPTION +.I Lconsole +is a simple interface to the qmgr providing low functionality but +provides access to all the controlling and monitoring functions. +.PP +The options are: +.TP +\-Q mta +Connect to this mta by default on start up. +.TP +\-u user +Connect as this user to the mta, a password will be prompted for. +.TP +\-p passwd +Supply a password to connect to the mta. (This is not generally +recommended) +.TP +\-b +Run in batch mode (no prompting). +.PP +All other arguments on the command line are taken as an operation to +perform. If no actions are supplied the \fIlconsole\fP takes commands +from the standard input. +.PP +The possible commands are: +.nf +.sp +.ta \w'rereadqueue\0\0'u +? - provide help. +channel - display channels or one channel. +clear - clear the delay on a channel, mta or msg. +close - close the association with a qmgr. +decrease - decrease the number of runnable channels. +delay - add a deley to a channel, mta or msg. +disable - disable a channel, mta or message. +enable - enable a channel, mta or msg. +help - provide help. +increase - increase the number of runnable channels. +msg - show details of messages. +mta - show details of mtas. +open - open a connection to a qmgr. +quit - terminate the program. +rereadqueue - initiate a queue refresh. +restart - restart the qmgr. +show - show certain matching messages. +shutdown - shutdown the qmgr. +source - read in a file of commands. +status - show the status of the qmgr. +.sp +.fi +When displaying channels, messages and mtas, a regular expression is +used to choose the messages. Where a command takes a channel as an +argument, a regular expression resolving to a unique channel may be used. +.SH FILES +None +.SH "SEE ALSO" +MTAconsole(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP +.SH BUGS +Should have more defaulting. diff --git a/man/man8/make b/man/man8/make new file mode 100755 index 0000000..fe76849 --- /dev/null +++ b/man/man8/make @@ -0,0 +1,2 @@ +#! /bin/sh +PATH=/usr/ucb:/bin:/usr/bin exec ${MAKECMD-make} -f ../../Make.defs -f Makefile ${1+"$@"} diff --git a/man/man8/mpp84.8 b/man/man8/mpp84.8 new file mode 100644 index 0000000..2bddc85 --- /dev/null +++ b/man/man8/mpp84.8 @@ -0,0 +1,56 @@ +.TH MPP84 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/mpp84.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: mpp84.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +mpp84 \- message pretty printer +.SH +.in +.5i +.ti -.5i +mpp84 \%[-ps] \%[-pl] \%[-p1] \%[-p2] \%[-sfd] \%[-nounpack] \%[-p2hdr] \%[-p1hdr] +.in -.5i +.SH DESCRIPTION +.I Mpp84 +is a diagnostic tool for examining X.400 (1984) message structures. It +handles various types of structures either in raw asn.1 or in the +presentation list abstraction of ISODE. +.I Mpp84 +responds to the following flags: +.TP +\-ps +indicates that the input is from a presentation stream abstraction +(e.g raw ASN.1) +.TP +\-pl +indicates that the input is from a presentation list abstraction. +.TP +\-p1 +Interpret the data as a P1 envelope with P2 encapsualted within. +.TP +\-p2 +Interpret the data as a P2 header and body parts. +.TP +\-sfd +Interpret the data as a simple formatted document type. +.TP +\-nounpack +Any structures packed into OCTET STRINGs (such as p2 body or return +of contents) will not be examined. +.TP +\-p2hdr +Interpret the data as a p2 header (the p2.hdr queue format). +.TP +\-p1hdr +Interpret the data as a p1 header (pp hex dump format). +.SH FILES +none +.SH "SEE ALSO" +mpp88(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/mpp88.8 b/man/man8/mpp88.8 new file mode 100644 index 0000000..0c7e37c --- /dev/null +++ b/man/man8/mpp88.8 @@ -0,0 +1,52 @@ +.TH MPP88 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/mpp88.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: mpp88.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +mpp88 \- message pretty printer +.SH +.in +.5i +.ti -.5i +mpp88 \%[-ps] \%[-pl] \%[-p1] \%[-p2] \%[-ipn] \%[-nounpack] \%[-p2hdr] +.in -.5i +.SH DESCRIPTION +.I Mpp88 +is a diagnostic tool for examining X.4001988) message structures. It +handles various types of structures either in raw asn.1 or in the +presentation list abstraction of ISODE. +.I Mpp88 +responds to the following flags: +.TP +\-ps +indicates that the input is from a presentation stream abstraction +(e.g raw ASN.1) +.TP +\-pl +indicates that the input is from a presentation list abstraction. +.TP +\-p1 +Interpret the data as a P1 envelope with P2 encapsualted within. +.TP +\-p2 +Interpret the data as a P2 header and body parts. +.TP +\-ipn +Interpret the data as a IPN. +.TP +\-nounpack +Do not recursively unpack sub structures encoded as OCTET STRINGs. +.TP +\-p2hdr +Interpret the data as a p2 header sequence. +.SH FILES +none +.SH "SEE ALSO" +mpp84(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/pp-gen.8 b/man/man8/pp-gen.8 new file mode 100644 index 0000000..0219996 --- /dev/null +++ b/man/man8/pp-gen.8 @@ -0,0 +1,284 @@ +.TH PP-GEN 8 "25 Nov 1989" +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/pp-gen.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: pp-gen.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\"$ +.\" +.ds VD pp\-6.0/ +.ds VN 6.0 +.ds Iv 7.0 +.SH NAME +pp\-gen \- generating the PP message system +.PP +You should read over this entire document first, +before typing any commands. +.SH "READ THIS" +This documentation describes how to configure, generate, and install the +PP message system. It is intended only as a quick guide. The full +details are in the PP documentation set - \fIPP Manual$ +Installation and Operation\fP. This can be found in the +\fBdoc/manual/volume1\fP directory +.SH SYNOPSIS +make +.SH DESCRIPTION +This is a description of how one can bring up the PP message system. +It is assumed that you have super-user privileges in order to (re-)install +the software. +Super-user privileges are not required to configure or generate this +software. +.PP +PP is normally installed with most programs and directories owned by a +single user. Conventionally this username is \*(lqpp\*(rq and is not a +normal user id but this is not required. You should normally do most +of the compilation and configuration as this user. +.PP +The distribution tape contains the hierarchy for the \fB\*(VD\fR directory. +Bring the sources on-line by changing to a directory for local sources and +running tar as the pp username you have chosen, e.g.: +.sp +.in +.5i +.nf +% cd /usr/src/local/ +% tar xf \fItarfile\fP +% cd \*(VD +.fi +.in -.5i +.SH CONFIGURATION +First, go to the \fBconfig/\fR directory: +.sp +.in +.5i +.nf +% cd config +.fi +.in -.5i +.PP +Select the Makefile and include-file skeletons which most closely match +your system. +The current choices are: +.sp +.in +.5i +.nf +.ta \w'ultrix\0\0'u +sun Fairly standard sun configuration +vax Fairly standard vax configuration +s5r4 System Five, release 4 +hpux Hewlet Packard +.sp +\fImore samples welcome\fP +.re +.fi +.in -.5i +.sp +The makefile skeleton has the extension \fB.make\fR, +and the include-file skeleton has the extension \fB.h\fR. +.SS MAKEFILE +Copy the makefile skeleton of your choice to \fBpickle.make\fR, +where \*(lqpickle\*(rq is the name of your system. +Now edit this file to set the \fImake\fR variables. +There are many of these, please refer to \fIThe PP Manual: Volume 1 \- +Installation and Operation\fP. However, some of the more obvious +variables are documented in \fB./OPTIONS.make\fP. +.PP +Link \fBpickle.make\fR to \fBMake.defs\fR in the base directory. +.sp +.in +.5i +.nf +% ln pickle.make ../Make.defs +.re +.fi +.in -.5i +.sp +.SS INCLUDE\-FILE +Copy the include-file skeleton of your choice to \fBpickle.h\fR, +where \*(lqpickle\*(rq is the name of your system. +Now add any additional definitions you may need. +Consult the file \fB./OPTIONS.h\fR for a list. +.PP +Now, link \fBpickle.h\fR to \fB../h/config.h\fR. +.sp +.in +.5i +.nf +% ln pickle.h ../h/config.h +.re +.fi +.in -.5i +.SH GENERATION +It is assumed that you have ISODE \*(Iv installed on the machine in +question, including the X.500 libraries \fB\-ldsap \-lisode\fP. If you +wish to build the grey book channels for JANET mail, you should first +build and install the unix-niftp package. +.PP +Go to the \fB\*(VD\fR directory and generate the basic system: +.sp +.in +.5i +.nf +% cd .. +% ./make +.fi +.in -.5i +.sp +.PP +This will cause a complete generation of the system. If all goes +well, proceed with the installation. If not, complain, as there +\*(lqshould be no problems\*(rq at this step. It may be worth saving +the output of the make stage in a file in case things do go wrong. +.SH INSTALLATION +You will need to be the super-user to install the software. There are +two kinds of activities: once-only activities that you perform the +first time the software is installed; and each-time activities that +you perform every time the software is installed. +.PP +The first once-only activity is to create the necessary basic +directories to install the commands. This is done by issuing the +command as super-user: +.sp +.in +.5i +.nf +# su +# ./make dirs +.re +.fi +.in -.5i +.sp +Note that the pp user id needs to have been allocated at this point. +.PP +The second once-only activity is to make sure that PP will run when +when the machine goes multi-user. On Berkeley UNIX systems, add +something along these lines to the \fB/etc/rc.local\fR file: +.sp +.in +.5i +.nf +if [ \-f /usr/lib/pp/pp.start ]; then + /usr/lib/pp/pp.start & (echo \-n ' pp') > /dev/console +fi +.fi +.in -.5i +.sp +There are some examples of this start-up script in the config directory. +.SS NOTE +If you wish to use smtp then it may be appropriate to start the smtp +server for \fI/etc/inetd\fP by adding a suitable line to +\fB/etc/inetd.conf\fP. See Volume 1 for more details, but the basic +format is something like: +.sp +.in +.75i +.ti -.25i +smtp stream \%tcp \%nowait \%pp \%/usr/lib/pp/cmds/chans/smtpd \%smtpd +\%/usr/lib/pp/cmds/chans/smtpsrvr \%smtp +.in -.75i +.sp +.PP +To allow processes to contact the \fBqmgr\fP you must add a line to your +isoentities file, +.sp +.in +.5in +pickle "pp qmgr" 1.17.6.2.1 #1001/Internet=pickle+18000 +.in -.5in +.PP +You will need to replace \*(lqpickle\*(rq by your local host, and you +may need to change the isomacro \*(lqInternet\*(rq to something else +if you have a local ethernet or similar. +.PP +Alternatively you may add a suitable entry to the directory if this is +being used as a nameserver. Some samples are given below the +\fBexamples\fP directory. +.PP +Then to install the following each-time activity is: +.sp +.in +.5i +.nf +% su +Password: +# ./make install +.fi +.in -.5i +.PP +If you plan to run the \fBMTAconsole\fP program (and you should!) you +will need to install the application defaults file. This is in the +\fBMTAconsole\fP directory and it should be installed as +\fBMTAconsole\fP in the \fBapp-defaults\fP directory in your X +hierarchy. For instance: +.sp +.in +.5i +.nf +# cd Src/MTAconsole +# cp MTAconsole.ad /usr/lib/X11/app-defaults/MTAconsole +.fi +.in -.5i +.PP +The same is true of the user utility \fBxalert\fP. This has a similar +set of application defaults that should be installed. +.PP +That's about it. This will install everything. +To clean-up the source tree as well, +then use: +.sp +.in +.5i +.nf +% make clean +.fi +.in -.5i +.sp +at this point. (However, unless you are very tight for space save this +step until you are sure things are working.) +.PP +If this is the first time you have used PP it is worth picking one of +the example configurations in the \fBexamples/\fP directory. Choose a +sample that is close to your requirements as a starting point. The +available samples are +.sp +.in +.5i +.nf +.ta \w'LOCALSMTP\0\0'u +LOCALSMTP Very simple local smtp only +JANET A simple JANET configuration +INTERNET A simple Internet site +.re +.fi +.in -.5i +.sp +Change to one of these directories, and read the README there. This +will tell you to do various things, depending on what configuration +you have chosen. Remember, this is only an example and will not deal +with all your needs. +.PP +After all is set up, and at regular intervals, you should check all is +ok by running \fIckconfig\fP (found in the tools directory) which will +check things are installed correctly. +.PP +Finally, if you are interested in discussing PP with others running +the software, drop a note to the Janet mailbox +\*(lqpp\-people\-request@cs.ucl.ac.uk\*(rq, and ask to be added to the +\*(lqpp-people@cs.ucl.ac.uk\*(rq list. +.SH TAILORING +Tailoring is an essential part of running PP. This is somewhat complex +to achieve the correct setup and so is described in Volume 1 of the PP +manual. It is important that this is followed carefully. +.SH "GENERATING DOCUMENTATION" +The directory \fBdoc/\fR contains the documentation set for this +release. Consult the file \fBdoc/READ\-ME\fR for a description of +each document. The directory \fBdoc/ps/\fR contains PostScript +versions of each document. These can be used to generate standard +documentation on PostScript printers, but users who want to preview +the documentation should generate the .dvi files from the SLiTeX and +LaTeX sources. +.PP +If you received this distribution from the network, +then the directory \fBdoc/ps/\fR does not contain any PostScript files. +There should be a separate compressed \fItar\fR file, +containing only PostScript files, +available on the machine where you retrieved this distribution. +.SH "REPORTING PROBLEMS" +Comments concerning this release should be directed to the authors. +Consult the preface in the \fIUser's Manual\fR for a current postal +address. Alternately, if you have access to the Janet network, +comments may be sent to the mailbox +\*(lqpp\-support@cs.ucl.ac.uk\*(rq. Do \fBnot\fR send bug reports to +the pp-people discussion group. +.SH "SEE ALSO" +ckconfig(8), dbmbuild(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fR + diff --git a/man/man8/pptsapd.8 b/man/man8/pptsapd.8 new file mode 100644 index 0000000..6b347b4 --- /dev/null +++ b/man/man8/pptsapd.8 @@ -0,0 +1,40 @@ +.TH PPTSAPD 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/pptsapd.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: pptsapd.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +pptsapd \- server for PP channels. +.SH +.in +.5i +.ti -.5i +/usr/lib/pp/pptsapd +\%[-c\ address] \%[\-t\ tailor] +.in -.5i +(under rc.local) +.SH DESCRIPTION +.I Pptsapd +is a server that listens for requests from the \fIqmgr\fP to start up +particular channels. It is a PP specific version of the \fItsapd\fP(8) +in actuality. Once the channel is identified, the program part of the +channel is executed in standard ISODE style. +.PP +\fIPptsapd\fP responds to the following flag: +.TP +\-c address +Specifies a different presentation address to listen on. It defaults +to the value given in the PP tailor file. +.TP +\-t tailor +Use the given file as a tailor file rather than the default. +.SH FILES +The PP tailor file +.SH "SEE ALSO" +qmgr(8), tsapd(8) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/probe.8 b/man/man8/probe.8 new file mode 100644 index 0000000..d75849f --- /dev/null +++ b/man/man8/probe.8 @@ -0,0 +1,59 @@ +.TH PROBE 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/probe.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: probe.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +probe \- Generates a Probe +.SH SYNOPSIS +.in +.5i +.ti -.5i +probe +.in -.5i +.in +.4i +\%[-t [Recipients ...]] +.br +\%[-s Message-size] +.br +\%[-e Encoded-Information-Types] +.br +\%[-u UA-id] +.br +\%[-i] +.br +\%[-a] +.in -.4i +.SH DESCRIPTION +.I Probe, +generates a message probe which should always return either a +successful or a failed Delivery Report. +.PP +It has the following options +.TP +\-t +Interpret the remaining arguments up to the next switch as +\*(lqTo:\*(rq Recipients. +.TP +\-s +Specifies the size of the message that will be sent later on. +.TP +\-e +Specifies one or more encoded information types within the message +to be sent later. The list of types should be seperated +by a \*(lq,\*(rq and are found in the PP Documentation Volume 1. +.TP +\-u +Specifies a User id. This should be a maximum of 16 characters. +.TP +\-i +This option requests implicit conversion. +.TP +\-a +This option allows for alternate recipients. + +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/qmgr.8 b/man/man8/qmgr.8 new file mode 100644 index 0000000..2b4350e --- /dev/null +++ b/man/man8/qmgr.8 @@ -0,0 +1,79 @@ +.TH QMGR 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/qmgr.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: qmgr.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +qmgr \- the PP queue manager process +.SH SYNOPSIS +.in +.5i +.ti -.5i +/usr/lib/pp/qmgr +\%[\-D] \%[\-d\ debris_time] \%[\-l\ load_time] \%[\-c\ cache_time] +\%[\-t\ timeout_time] \%[\-m\ nchans] \%[\-s] \%[\-M] +.in -.5i +(under rc.local) +.SH DESCRIPTION +The +.I Qmgr +is the controlling process for the PP message system. It is +responsible for the scheduling of all the messages in the queue and is +also the information base for the knowledge about the PP queues. +.PP +.I Qmgr +is normally invoked at boot time from the file \fI/etc/rc.local\fP to +initialise the queue and start things running. +When invoked, the \fIqmgr\fP listens on an set of NSAP connections +awaiting queries and updates. At the same time it starts a channel +designed to load information into the qmgr. +.PP +The \fIQmgr\fP responds to the following flags +.TP +\-D +When initialising the channels, set all channels to disabled. If this +switch is set, then no channels will be run until they are enabled by +the \fIMTAconsole\fP or similar. +.TP +\-d time +The amount of time (in hours) between successive runs of the debris +cleanout channel. By default, this channel runs every 3 hours. +.TP +\-l time +The amount of time in hours between successive runs of the qmgr +loading channel. This channel is run every so often to check +consistency between the queue on disc and in memory. The default is +every 6 hours. +.TP +\-t time +The amount of time in hours between successive runs of the timeout +process. This is run every so often to check the queue for messages +that have timed out. The default is every 12 hours. +.TP +\-c time +Set the default cache time (in seconds) for channels. This defaults to +5 minutes. This is the time a channel will be cached for initially. +Multiple failures keep doubling this number up to a maximum 6 times. +.TP +\-m nchans +Sets the maximum number of channels that can be running at one time. +This should be greater than 0! The default is 6. +.TP +\-s +This sets the inhibit submission flag. If this is set, the \fIqmgr\fP +will still accept incoming submissions but will otherwise ignore them. +.TP +\-M +Allow the msg-clean process to run whilst the qmgr is loading. This +allows a possible race condition but is a big win for very large queues. +.SH FILES +/etc/rc.local +.SH "SEE ALSO" +MTAconsole(1) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP +.SH BUGS +Probably lots... diff --git a/man/man8/rmail.8 b/man/man8/rmail.8 new file mode 100644 index 0000000..e8f7c7f --- /dev/null +++ b/man/man8/rmail.8 @@ -0,0 +1,21 @@ +.TH RMAIl 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/rmail.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: rmail.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +rmail \- handle remote mail received via uucp +.SH SYNOPSIS +.in +.5i +.ti -.5i +rmail +\%[recipient...] +.in -.5i +.SH DESCRIPTION +\fIrmail\fP provides the gateway from uucp to the PP mail system. +It interprets incoming mail received via uucp and passes the +processed mail on to the \fIsubmit\fP process. diff --git a/man/man8/sendmail.8 b/man/man8/sendmail.8 new file mode 100644 index 0000000..1e7f116 --- /dev/null +++ b/man/man8/sendmail.8 @@ -0,0 +1,26 @@ +.TH SENDMAIL 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/sendmail.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: sendmail.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +sendmail \- pretend sendmail that talks to PP +.SH SYNOPSIS +.in +.5i +.ti -.5i +sendmail \%[sendmail args] +.in -.5i +.SH DESCRIPTION +.I Sendmail +is a forgery of the BSD \fIsendmail\fP program. It attempts to fool +programs that have built into them the idea that sendmail is the way +to send mail. It takes a range of standard sendmail options and passes +the message to PP. +.SH FILES +Various +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/man/man8/smtpd.8 b/man/man8/smtpd.8 new file mode 100644 index 0000000..7600347 --- /dev/null +++ b/man/man8/smtpd.8 @@ -0,0 +1,47 @@ +.TH SMTPD 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/smtpd.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: smtpd.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +smtpd \- Smtp protocol server front end process +.SH +.in +.5i +.ti -.5i +/usr/lib/pp/smtpd +\%[-p\ port] \%[-i\ maxcon] server channel +.in -.5i +(under rc.local or inetd) +.SH DESCRIPTION +.I Smtpd +is the front end to the smtp server provided with PP. +It provides a simple network listener service for smtp requests +similar to that provided by \fIinetd(8)\fP. However, the smtp server +it invokes can normally be run directly under inetd. +.PP +.I Smtpd +responds to the following flags. +.TP +\-p port +When running standalone, this overrides the default internet port that +\fIsmtpd\fP listens on. +.TP +\-i maxcon +When running standalone, this option limits the number of simultaneous +smtp connections that can be open. Once this limit is reached, +\fIsmtpd\fP will ignore further requests for connections until one of +the current connections terminates. +.PP +The two mandatory arguments to \fIsmtpd\fP are firstly the pathname of +the server that is to be executed to obey the smtp protocol, and +secondly the PP channel that the server should claim to originate from. +Neither of these values default and both must be specified. +.SH FILES +/etc/rc.local started from here +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/smtpsrvr.8 b/man/man8/smtpsrvr.8 new file mode 100644 index 0000000..b77ada7 --- /dev/null +++ b/man/man8/smtpsrvr.8 @@ -0,0 +1,41 @@ +.TH SMTPSRVR 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/smtpsrvr.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: smtpsrvr.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +smtpsrvr \- Smtp protocol server +.SH +.in +.5i +.ti -.5i +/usr/lib/pp/smtpsrvr +\%[-t\ timeout] \%[\-T\ tailor] \%channel +.in -.5i +(under smtpd or inetd) +.SH DESCRIPTION +.I Smtpsrvr +is the smtp protocol engine. It is responsible for interfacing between +PP and the smtp protocol. +.PP +.I Smtpsrvr +responds to the following flags. +.TP +\-t timeout +Sets the timeout for nameserver operations +.TP +\-T tailor +Use the given tailor file rather than the standard default. +.PP +The mandatory argument to \fIsmtpsrvr\fP is the channel to claim it is +coming from. There is no default for this. +.SH FILES +/etc/inetd.conf the inetd configuration file +.SH "SEE ALSO" +inetd(8), inetd.conf(5) +.br +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP + diff --git a/man/man8/tjoin.8 b/man/man8/tjoin.8 new file mode 100644 index 0000000..cd6414e --- /dev/null +++ b/man/man8/tjoin.8 @@ -0,0 +1,57 @@ +.TH TJOIN 8 +.\" @(#) $Header: /xtel/pp/pp-beta/man/man8/RCS/tjoin.8,v 6.0 1991/12/18 20:44:03 jpo Rel $ +.\" +.\" $Log: tjoin.8,v $ +.\" Revision 6.0 1991/12/18 20:44:03 jpo +.\" Release 6.0 +.\" +.\" +.\" +.SH NAME +tjoin \- Unrolls the Application Relays. +.SH SYNOPSIS +tjoin \%[-d] local-domain-name channel-names... < input-file +.SH DESCRIPTION +.I Tjoin +is a lexical program that is used to construct the +.I channel +table residing in the PP table directory. +.PP +.I Tjoin +performs a number of transformations on the data. +.PP +It firstly fills in all +missing channels. If mail to one host must first be sent to another +host, +.I tjoin +will expand this to the correct form and fill in the appropriate +channel. +.PP +Secondly, it removes references to the local domain name specified in +the first parameter. +.PP +Thirdly, it sorts the hosts with multiple channels into the preferred +order given on the command line. The order is the same order as the +channel-names parameters. +.PP +Tjoin responds to several flags. +.TP +\-d +Prefer direct routes to hosts over the ordering given on the command +line. E.g. if there are two channels to a host, and one is direct and +the other goes via an intermediary always prrefer the first one. This +should be the nromal setting. +.TP +\-c +Produce a more complex output, this may save a little space, but is +probably not worth while and is untested. +.TP +\-r +put route entries in the output. This option should not be used other +than for debuging +.PP +The normal procedure is to run with the \-d flag enabled. +.SH FILES +channel in the tbldfldir. +.SH "SEE ALSO" +\fIThe PP Manual: Volume 1 \- Installation and Operation\fP diff --git a/pp-changes.ms b/pp-changes.ms new file mode 100644 index 0000000..90d3e45 --- /dev/null +++ b/pp-changes.ms @@ -0,0 +1,306 @@ +.\" $Header: /xtel/pp/pp-beta/RCS/pp-changes.ms,v 6.0 1991/12/18 20:02:50 jpo Rel $ +.\" +.\" $Log: pp-changes.ms,v $ +.\" Revision 6.0 1991/12/18 20:02:50 jpo +.\" Release 6.0 +.\" +.\" +.\" +.ds Pv 6.0 +.ds Lv 5.2 +.ds Iv 7.0 +.ds Il 6.0 +.ds Ii 6.8 +.de Bu +.IP \(bu +.. +.de Ip +.IP "\fB\\$1\fP\0\0" +.. +.TL +Changes from PP version \*(Lv to \*(Pv +.NH +Overview +.LP +This short document is a description of the more user/administrator +visible changes that have taken place in PP between the last interim +version (\*(Lv) and the beta version (\*(Pv). This document is not +exhaustive or complete but is a guide to what to look out for. In +general the following may be assumed. +.Bu +The Queue files are compatible between \*(Lv and \*(Pv. +Note however that the Queue structure has changed. Old channels will +have to be recompiled to recognise the new format, but new channels +will read old queue files. +.Bu +The qmgr protocol is compatible between \*(Lv and \*(Pv +.Bu +The syntax of some of the table files has changed. Where appropriate +conversion scripts are provided. +.Bu +Some procedure calls have been changed or have different parameters. +.Bu +the libdsap.a library is now required for compilation. +.LP +In summary, you should be careful when upgrading to the \*(Pv release. +It will not work by just replacing the \*(Lv binaries with \*(Pv. For +definite the domain table will HAVE to be changed. +.NH +Detailed changes +.LP +This list is in no particular order of preference or importance. +.Ip "Domain Table" +The domain table syntax has been changed to be more explicit and has +been brought into line with the OR table syntax. We feel this is +clearer and more logical. Tools that process the domain table have +been taught the new format and there are scripts in +Tools/tables/compat to convert between the old and new formats. +There is \fBNO\fP backwards compatibility here. Old format tables will +just plain not work. +.Ip "Aliases Table" +The aliases table syntax has changed to a main choice of +synonym or alias with further qualifiers specifying +the address type of the synonym or alias. +The changes are +.sp +.in +5 +.nf +.ta +\w'x:x400-synonym y\0\0'u +x:alias y x:alias y +x:synonym y x:synonym y +x:822-synonym y x:synonym y 822 +x:x400-synonym y x:synonym y x400 +x:822 y x:alias y 822 +x:x400 y x:alias y x400 +.fi +.in -5 +where any white space in y must be quoted using a backslash +There is also a "external" qualifier. +This disables further lookups of synonyms and aliases and can be used +for a main site mail hub mapping from site_wide_name@localsite to +local_machine_name@localmachine and vice versa. +The use of external stops the looping alias problem which would +otherwise occur. +.Ip "Return of Contents" +Return of contents is now supported. This is a side effect and part of +the work on routing of delivery reports. +.Ip "Use of pepsy" +Use of the PEPSY ASN.1 compiler rather than PEPY/POSY is now used in +many places. This makes for smaller binaries and much quicker +compilation. +.Ip "ISODE \*(Iv" +PP \*(Pv is aligned to ISODE \*(Iv. It will not work under ISODE \*(Il. If +you are using the \*(Pv release you should be using ISODE \*(Iv. It should +however work under ISODE \*(Ii. +.Ip "Tailor file" +There have been many changes to the tailor file. The introduction of +several new variables and the splitting up of header and body part +types. These are +.sp +.in +5 +.nf +.ta +\w'queuestruct\0\0'u +dap_user Directory username for DS lookups +dap_passwd Directory Passwd for same +fsync disable use of fsync(2) +headertype list of headers c.f. bodypart +queuestruct use hierarchical queue structure +submit_addr call submit over network +diskuse limit the disk space consumed by PP +.fi +.in -5 +.sp +Channel tailoring also has a number of new variables +.sp +.in +5 +.nf +.\" .ta +\w'bad-sender-policy\0\0'u +drchan replaces old outchan +hdrin headers inbound +hdrout headers outbound +ininfo inbound channel info +inadr inbound channel addr type +insubadr inbound channel sub address type +intable inbound channel table +key give alternative names to channel +mtatable list of known mtas for channel binding +outinfo outbound channel info +outsubadr outbound channel sub address +outtable outbound channel table +solo-proc channel requires address one at a time +bad-sender-policy set the policy for unroutable senders +check set the checking mode of the channel +.fi +.in -5 +.Ip "Channel pairing" +Channels may now be explicitly paired together. This allows one +definition to specify both an inbound and an outbound channel. +It also allows several logical channels for one inbound protocol by +selecting a channel per MTA. +.Ip "Timezones" +Many more lettered timezones are recognised. This list is ambiguous at +best and numeric forms should really be used except at user +interfaces. +.Ip "Delivery Reports" +Delivery reports are now routed back to their originator. In \*(Lv they +were returned directly down the channel they arrived on. This allows +for one way links in general makes things easier. It also allows +protocol conversion so that, for instance, a delivery report on an +X.400 message may go back via an RFC-822 if that is the only option. +A side effect of this is the channel variable outchan has been renamed +drchan and has different semantics attached to it (see the manual). +.Ip "Header parts" +Separation of headers and bodyparts for each channel. This is mainly a +syntactic change but will allow more flexibility later. The upshot is +you may need both bptin/bptout and hdrin/hdrout types in channel definitions. +.Ip "Local delivery" +The local channel table (ch.local) has had a change of syntax. The old +format should still work, but the new format (which is key=value) +based allows much more flexibility and setting of options for mail +managers. +.Ip "MTA Console" +The MTA Console has been changed to show more statistics and has a new +heuristics for showing just channel and MTA summary information. This +is useful for very large queues. +.Ip "Line Console" +Two line based console programs have been provided. +These give some of the functionality of the MTA console for dumb terminals. +.Ip "Directory lists" +The directory list program has been improved more. It now has several +associated tools to convert file based lists into directory based +lists. There is also a checkup tool. +.Ip "Performance" +Some work has been done on general performance. In general the system +should run slightly faster and have less problems with large queues. +.Ip "X.400(88) OIDs" +One of the X.400(1988) object identifiers was incorrect. Originally +the code used the object identifier designated in the Blue Book. It now +uses the one given in the implementors guide. +.Ip "Mail 11" +Our thanks must go to Nigel Titley of British Telecom for the donation +of a Decnet Mail-11 channel. This allows interworking with DECNET and PP. +.Ip "G3Fax channel" +A skeleton outbound G3 Fax channel is included. +There are currently two drivers written using this skeleton, one for +the Fujitsu dexNet200 modem and one for the Panasonic SystemFax 250 machine. +These channels enable PP to send appropriately encoded messages via fax. +There are a couple of reformatter filters which convert an +hdr.822 to a fax coverpage and an ia5 bodypart to a g3fax bodypart. +These reformatters produce X.400 g3fax bodyparts and so are general +use and are not dependent on any fax machine. +.Ip "Splitter Channel" +A Splitter channel is included. +This channel together with the presence of solo-proc=yes in channel +entries in the tailor file enables exclusive processing for specified +recipients. This was introduced for the fax reformatter channels. +.Ip "Address Parsing" +The address parsing code has been restructured extensively. This +should be more efficient in many cases. +.Ip "X.400 Extensions" +X.400(88) address extensions are now recognised. +.Ip "X.400 addresses" +Address parsing recognises A as ADMD and P as PRMD in RFC1148 encoded +X.400 addresses. These are converted to the form given in RFC1148. +.Ip "Multi level queue" +For very large system (queues in excess of about 4000 messages) a +multi-level queue can be used. if this is in effect messages are +placed at random in subdirectories of the main queue to reduce the +time required by the system to locate files. +.Ip "Authorisation Warnings" +Authorisation warnings are now implemented. If a message fails +authorisation, a warning can be optionally sent to the originator +and/or the recipient. +.Ip "Delayed delivery warning" +Warnings of delays in delivery are now sent to the originator of the message +if the message cannot be delivered in a timely fashion. +.Ip "Submit daemon" +Submit can be run as a daemon in addition to its normal directly +executed form. This may give performance improvements for inbound +messages. +.Ip "administrator assigned alternate recipient" +The system manager can direct bad address to a default +mailbox, where numerous actions may be attempted (such as returning +helpful messages about approximate matchings etc.) +.Ip "X.400(88) downgrading" +A filter to downgrade X.400(88) P2 headers to X.400(84) P2 headers has +been provided. +Similarly downgrading of P1 is done in the appropriate channels. +This new filter may also be used to normalise OR addresses in these headers. +.Ip "Body part support" +Support of a number of different body types, including ISO-6937, +ISO-8859, and T.61 character sets. +.Ip "New queue format" +A new queue format has been introduced. We believe this will give +greater reliability and flexibility. There are now no special +subdirectories of the queue, everything is directly under the queue +directory. There is a utility to convert the old format into the new +format (Tools/tables/compat/que_o2n). +New format for the internal structure of the message queue has also +been added in a backwards compatible way. +.Ip "ckadr" +ckadr no longer guesses which format of addressing an address is (x400 +or rfc822). +Explicit choice should be made via the -x and -r flags (-r is default) +It also no longer checks for UK domain ordering by default i.e. will only +identify US domain ordering). +Checking for UK ordering can be done via the -b flag. +.Ip "Disk checking" +Submit can be tailored to check the amount of free space available +on disk and not submit messages if this is below some threshold. This +is not supported on all systems. +.Ip "Control of header type" +The specification of a nondefault header type in the inbound channel will +override the default header types such as hdr.822 and hdr.p2. +This will enable a site to minimise the header +manipulation/normalisation done. +.Ip "Bad senders" +The system manager can control the policy for dealing with bad senders +on an inbound channel basis. +.Ip "X.400(88) Extensions" +X.400(88) O/R Address extensions have been implemented and are useable +for routing. +.Ip "loc_dom_mta, loc_dom_site" +Previously these two values were magically recognised as local when +normalising and routing RFC 822 addresses. +This magic has been removed and now you need explicit entries for +these in the domain table +.Ip "redirection history" +X.400 redirection history is now supported. +This shows up a bug in PP 5.* which may cause PP 5.* MTA to break when +interworking over x400 with a PP 6.0 MTA. +Note that aliases are implemented as redirects. +.Ip "table overrides" +Tables may been overriden by explicit key/value pairs given in the +tailor file. +.NH +Upgrade path +.PP +This is the basics of how to upgrade from PP \*(Lv to \*(Pv. +.Ip "Compile" +Compile pp-\*(Pv and install. +.Ip "domain table" +Convert the domain table into the new format. There are some tools +under Tools/tables/compat to aid in this, but you may want to rethink +how you generate these a little. This is the major change in this +version. +Also check that the relevant entries for loc_dom_site and loc_dom_mta +are present in the domain table as they are no longer magically recognised. +.Ip "alias table" +This should be altered into the new format. The conversion routine in +Tools/tables/compat may help again. +.Ip "local table" +This should be backwards compatible, but you may want to change to the +new format anyway. +.Ip "Queue" +Any files in the queue should be converted to the new format. This can +be done by the following: +.DS +.../Tools/tables/compat/que_o2n ..../queue +.DE +.Ip "Tailoring" +Change the tailor file to use the new keys and values. +.Ip "Checkup" +Run ckconfig and see that everything is sensible. +.Ip "restart" +Rebuild the database and restart. + diff --git a/template/README b/template/README new file mode 100644 index 0000000..8046df7 --- /dev/null +++ b/template/README @@ -0,0 +1,32 @@ +Files in this directory are the preferred format for the pp system. +Add new file types as needed. The format is not particularly +important, but I think it looks ok and it has most of the essential +info in it. + +A brief note about some of the formats. + +template.py + Don't forget to set the comment leader for RCS, else you'll + get some funny results. Basically, the first time you co a .py + file - the following is the easiest way. + ci filename.py + rcs -c'-- ' filename.py + co [-l] filename.py + +template.mk + This should include the following targets so that recursive + things work properly. + default - the default things to build. + clean - clean out all the junk. + lint - lint the files. Should be a target for each separate + systm as well though. e.g. + lint: l-prog1 l-prog2 + so that they can be lint'd separately if needed. + install - installation method (one day! - leave blank for now) + depend - rebuild dependency list + +template.man + Use for -ms & -man macro - but remove the TH for ms. Also need + to set the comment string here. Use rcs -c'.\" ' file. + + diff --git a/template/template.bug-report b/template/template.bug-report new file mode 100755 index 0000000..b83026e --- /dev/null +++ b/template/template.bug-report @@ -0,0 +1,22 @@ +To: pp-support@cs.ucl.ac.uk +Subject: + +PP VERSION: 5.3 + +ISODE VERSION: 7.0 + +MACHINE: + +O/S: + +PROGRAM/CHANNEL: + +SYNOPSIS: + +DESCRIPTION: + +REPEAT BY: + +SAMPLE FIX: + +ORIGINAL REPORT: diff --git a/template/template.c b/template/template.c new file mode 100644 index 0000000..6054c32 --- /dev/null +++ b/template/template.c @@ -0,0 +1,12 @@ +/* program/subroutines name: brief description of what this is */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + diff --git a/template/template.chan b/template/template.chan new file mode 100644 index 0000000..1847251 --- /dev/null +++ b/template/template.chan @@ -0,0 +1,228 @@ +/* template.chan: template of a typical PP channel */ + +# ifndef lint +static char Rcsid[] = "@(#)$Header$"; +# endif + +/* + * $Header$ + * + * $Log$ + */ + + +#include "util.h" +#include "qmgr.h" +#include "q.h" +#include "prm.h" +#include "retcode.h" + +static void dirinit(); +static int initialise(); +static int endfunc(); +static struct type_Qmgr_DeliveryStatus *process(); +static ADDR *getnthrecip (); + +CHAN *mychan; +char *this_msg = NULLCP, *this_chan = NULLCP; +int first_successDR, first_failureDR; + +main (argc, argv) +int argc; +char **argv; +{ + sys_init (argv[0]); + dirinit(); + +#ifdef PP_DEBUG + if (argc > 1 && strcmp (argv[1], "debug") == 0) + debug_channel_control (argc,argv,initialise,process,endfunc); + else +#endif + channel_control (argc,argv,initialise,process,endfunc); +} + +/* */ +/* move to correct place in file system */ + +extern char *quedfldir; + +static void dirinit () +{ + if (chdir (quedfldir) < 0) + err_abrt (RP_LIO, + "Unable to change directory to '%s'", + quedfldir); +} + +/* */ +/* channel initialisation routine */ + +static void parse_ch_info(); + +static int initialise (arg) +struct type_Qmgr_Channel *arg; +{ + char *name; + name = qb2str (arg); + + if ((mychan = ch_nm2struct (name)) == NULLCHAN) { + PP_OPER (NULLCP, ("Channel '%s' not known", name)); + if (name != NULLCP) free(name); + return NOTOK; + } + + if (name != NULLCP) free(name); + + if (mychan->ch_out_info != NULLCP) + parse_ch_info (mychan->ch_out_info); + + return OK; +} + +/* parse the info string and set the global variables */ +static void parse_ch_info(info) +char *info; +{ + char *info_copy, *margv[20]; + int margc, ix; + + if (info == NULLCP) return; + + info_copy = strdup(info); + + if ((margc = sstr2arg (info_copy, 20, margv, ",")) > 0) { + for (ix = 0; ix < margc; ix++) { + /* check each entry in info string */ + } + } + free(info_copy); +} + +/* */ +/* channel termination routine */ + +static int endfunc (arg) +struct type_Qmgr_Channel *arg; +{ +} + +/* */ +/* channel work routine */ + +static int security_check (msg) +struct type_Qmgr_ProcMsg *msg; +{ + if (this_msg) free(this_msg); + this_msg = qb2str (msg->qid); + + if (this_chan) free(this_chan); + this_chan = qb2str (msg->channel); + + if (mychan == NULLCHAN + || strcmp (this_chan, mychan->ch_name) != 0) { + PP_LOG (LLOG_EXCEPTIONS, + ("channel error: '%s'", + this_chan)); + return FALSE; + } + + return TRUE; +} + +static struct type_Qmgr_DeliveryStatus *process (arg) +struct type_Qmgr_ProcMsg *arg; +{ + struct prm_vars prm; + Q_struct que; + ADDR *sender = NULLADDR; + ADDR *recips = NULLADDR; + ADDR *adr; + int rcount, retval; + struct type_Qmgr_UserList *ix; + + bzero ((char *)&prm, sizeof (prm)); + bzero ((char *)&que, sizeof (que)); + + delivery_init (arg->users); + delivery_setall (int_Qmgr_status_messageFailure); + first_failureDR = first_successDR = TRUE; + + if (security_check (arg) != TRUE) + return deliverystate; + + PP_LOG (LLOG_NOTICE, + ("processing msg '%s' through '%s'", + this_msg, this_chan)); + + /* read in message */ + if (rp_isbad (rd_msg (this_msg, &prm, &que, + &sender, &recips, &rcount))) { + PP_LOG (LLOG_EXCEPTIONS, + ("rd_msg error: '%s'", this_msg)); + rd_end(); + return delivery_setallstate(int_Qmgr_status_messageFailure, + "Can't read message"); + } + + /* process recipients individually */ + for (ix = arg->users; ix; ix = ix->next) { + if ((adr = getnthrecip (&que, ix->RecipientId->parm)) == NULLADDR) { + PP_LOG (LLOG_EXCEPTIONS, + ("failed to find recipient %d of msg '%s'", + ix->RecipientId->parm, this_msg)); + delivery_setstate (ix->RecipientId->parm, + int_Qmgr_status_messageFailure, + "Unable to find specified recipient"); + continue; + } + + switch (chan_acheck (adr, mychan, 1, (char **)NULL)) { + default: + case NOTOK: + break; + case OK: + processAddr (this_msg, &prm, &que, adr); + break; + } + } + + /* write results of processing */ + + if (rp_isbad (retval = wr_q2dr (&que, this_msg))) { + PP_LOG (LLOG_EXCEPTIONS, + ("%s wr_q2dr failure '%d'", + mychan->ch_name, retval)); + (void) delivery_resetDRs (int_Qmgr_status_messageFailure); + } + + rd_end (); + q_free(&que); + prm_free (&prm); + + return deliverystate; +} + +/* */ +/* do processing for specified recip */ + +static int processAddr (msg, prm, qp, recip) +char *msg; +struct prm_vars *prm; +Q_struct *qp; +ADDR *recip; +{ +} + +static ADDR *getnthrecip(que, num) +Q_struct *que; +int num; +{ + ADDR *ix = que->Raddress; + + if (num == 0) + return que->Oaddress; + while ((ix != NULL) && (ix->ad_no != num)) + ix = ix->ad_next; + return ix; +} diff --git a/template/template.h b/template/template.h new file mode 100644 index 0000000..acdc23f --- /dev/null +++ b/template/template.h @@ -0,0 +1,8 @@ +/* filename: brief description of the files purpose */ + +/* + * @(#) $Header$ + * + * $Log$ + * + */ diff --git a/template/template.man b/template/template.man new file mode 100644 index 0000000..e0ff4a1 --- /dev/null +++ b/template/template.man @@ -0,0 +1,5 @@ +.TH PROGNAME [1-8] +.\" @(#) $Header$ +.\" +.\" $Log$ +.\" diff --git a/template/template.mk b/template/template.mk new file mode 100644 index 0000000..688d8a1 --- /dev/null +++ b/template/template.mk @@ -0,0 +1,56 @@ +# Preliminary comments +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################ +# +# Definitions +# +############################################################ + +SRCS = +OBJS = + +HEADERS = ../../h +LIBPP = ../../Lib/libpp.a + +CFLAGS = $(CCOPTIONS) -I$(HEADERS) +LDFLAGS = $(LDOPTIONS) + +LLFLAGS = $(LINTFLAGS) -I$(HEADERS) +LINTLIBS = ../../Lib/llib-lpp.ln $(LINTISODE) + +############################################################ +# +# Building Rules +# +############################################################ + +default: default-targets + +install:; + +saber_src: $(SRCS) + #load -C $(CFLAGS) $(SRCS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +saber_obj: $(OBJS) + #load -C $(OBJS) $(LIBPP) $(LIBSYS) $(LIBX) $(LM) + +clean: tidy +tidy: + rm -f $(OBJS) core a.out Makefile.old + +lint: l-targets + +depend: + $(DEPEND) -I$(HEADERS) $(SRCS) + +############################################################ +# +# End of Building Rules +# +############################################################ diff --git a/template/template.py b/template/template.py new file mode 100644 index 0000000..d13b7d8 --- /dev/null +++ b/template/template.py @@ -0,0 +1,13 @@ +-- filename: brief description + +-- @(#) $Header$ +-- +-- $Log$ +-- + +MODULENAME DEFINITIONS ::= +%{ +#ifndef lint +static char *Rcsid = "@(#)$Header$"; +#endif lint +%} diff --git a/template/template.sh b/template/template.sh new file mode 100644 index 0000000..00d1317 --- /dev/null +++ b/template/template.sh @@ -0,0 +1,11 @@ +#! /bin/sh +# +# filename: purpose +# +############################################################ +# +# @(#) $Header$ +# +# $Log$ +# +############################################################